@oxy-hq/sdk 2.5.0 → 2.8.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.mts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { A as UseSemanticQueryOpts, B as CustomerAppErrorReport, C as UseProcedureRunInput, D as UseQueryOpts, E as UseQueryInput, F as useProcedureRun, G as OxyAppFunctionManifest, H as apiErrorFromResponse, I as useQuery, J as _resetCustomerAppManifestCacheForTest, K as OxyAppManifest, L as useResolvedManifest, M as useAgentRun, N as useFunction, O as UseQueryResult, P as useOxyApp, R as useSemanticQuery, S as UseFunctionResult, T as UseProcedureRunResult, U as interpretCustomerAppError, V as OxyApiError, W as LoadManifestOptions, Y as loadCustomerAppManifest, _ as SemanticFilter, a as AppFetcher, b as UseAgentRunInput, c as OxyAppProvider, d as OxyChatProps, f as ProcedureProgress, g as SemanticDateRangeOp, h as SemanticArrayOp, i as AgentSqlArtifact, j as UseSemanticQueryResult, k as UseSemanticQueryInput, l as OxyAppProviderProps, m as ProcedureRunState, n as AgentRunEvent, o as OxyAnswer, p as ProcedureResult, q as ResolvedCustomerAppManifest, r as AgentRunState, s as OxyAnswerProps, t as AgentArtifact, u as OxyChat, v as SemanticScalarOp, w as UseProcedureRunOpts, x as UseAgentRunResult, y as SemanticTimeDimension, z as useTrackEvent } from "./react-BnpR8VRJ.mjs";
2
+ import { A as UseSemanticQueryOpts, B as CustomAppErrorReport, C as UseProcedureRunInput, D as UseQueryOpts, E as UseQueryInput, F as useProcedureRun, G as OxyAppFunctionManifest, H as apiErrorFromResponse, I as useQuery, J as _resetCustomAppManifestCacheForTest, K as OxyAppManifest, L as useResolvedManifest, M as useAgentRun, N as useFunction, O as UseQueryResult, P as useOxyApp, R as useSemanticQuery, S as UseFunctionResult, T as UseProcedureRunResult, U as interpretCustomAppError, V as OxyApiError, W as LoadManifestOptions, Y as loadCustomAppManifest, _ as SemanticFilter, a as AppFetcher, b as UseAgentRunInput, c as OxyAppProvider, d as OxyChatProps, f as ProcedureProgress, g as SemanticDateRangeOp, h as SemanticArrayOp, i as AgentSqlArtifact, j as UseSemanticQueryResult, k as UseSemanticQueryInput, l as OxyAppProviderProps, m as ProcedureRunState, n as AgentRunEvent, o as OxyAnswer, p as ProcedureResult, q as ResolvedCustomAppManifest, r as AgentRunState, s as OxyAnswerProps, t as AgentArtifact, u as OxyChat, v as SemanticScalarOp, w as UseProcedureRunOpts, x as UseAgentRunResult, y as SemanticTimeDimension, z as useTrackEvent } from "./react-kHG5gkd-.mjs";
3
3
  //#region src/config.d.ts
4
4
  /**
5
5
  * Configuration for the Oxy SDK
@@ -141,15 +141,38 @@ interface ExplainNode {
141
141
  dimension_count?: number;
142
142
  children?: ExplainNode[];
143
143
  }
144
+ /** Whether a driver's observed move pushes the target the way it actually
145
+ * moved (`contributing`) or against it (`counteracting` — it offset part of
146
+ * the move rather than causing it). `unknown` when no signed claim is
147
+ * available: `direction: unknown` with no coefficient, or a flat
148
+ * driver/target. */
149
+ type DriverContribution = "contributing" | "counteracting" | "unknown";
150
+ /** A driver's move split into the part its base forced and the part its own
151
+ * ratio contributed. Emitted only when the driver genuinely tracks a sibling
152
+ * rather than moving on its own — presence is the claim.
153
+ * `base_driven_delta + ratio_driven_delta === driver_delta`. */
154
+ interface PassthroughSplit {
155
+ base_measure: string;
156
+ ratio_previous: number;
157
+ ratio_current: number;
158
+ base_driven_delta: number;
159
+ ratio_driven_delta: number;
160
+ }
144
161
  interface DriverAttribution {
145
162
  driver_measure: string;
146
163
  driver_previous: number;
147
164
  driver_current: number;
148
165
  driver_delta: number;
166
+ /** Both optional: an `explain_cache` row written before these fields shipped
167
+ * is served verbatim, so absent means unclassified — not a default. */
168
+ direction?: DriverDirection;
169
+ contribution?: DriverContribution;
149
170
  coefficient?: number;
150
171
  form: DriverForm;
172
+ /** Absent for a purely qualitative driver (no coefficient). */
151
173
  estimated_target_impact?: number;
152
174
  description?: string;
175
+ passthrough?: PassthroughSplit;
153
176
  }
154
177
  type ExplainWarning = {
155
178
  type: "simpsons_paradox";
@@ -225,12 +248,31 @@ interface OpportunityResult {
225
248
  target: string;
226
249
  period: [string, string];
227
250
  overall_value: number;
228
- /** "value_share" (additive) or "equal" (ratios). */
251
+ /**
252
+ * "rows" (rate-based additive sizing — the only basis that yields a sized
253
+ * upside figure), "value_share" (additive) or "equal" (ratios).
254
+ */
229
255
  weight_basis: string;
230
256
  dimensions: DimensionOpportunity[];
231
257
  skipped_dimensions: SkippedDimension[];
232
258
  downstream: PredictImpact[];
233
259
  }
260
+ /**
261
+ * Single-period structural decomposition. The server auto-derives the
262
+ * baseline as the equal-length window immediately before `period`, then
263
+ * returns an {@link ExplainResult}-shaped payload (so the same renderers
264
+ * work). Ignore the delta fields when rendering a pure distribution.
265
+ */
266
+ interface DistributionRequest {
267
+ target: string;
268
+ time_dimension: string;
269
+ /** `[start, end]` inclusive date strings. */
270
+ period: [string, string];
271
+ }
272
+ interface TimeDimensionsResponse {
273
+ /** view name → fully-qualified time-dimension ids (`view.dim`). */
274
+ by_view: Record<string, string[]>;
275
+ }
234
276
  /**
235
277
  * Shape of the inner request helper exposed by `OxyClient`. The metric-tree
236
278
  * client reuses it to inherit auth headers, timeout, baseUrl, and project
@@ -334,6 +376,13 @@ declare class MetricTreeClient {
334
376
  //#region src/anomalies.d.ts
335
377
  type AnomalyStatus = "new" | "acknowledged" | "dismissed";
336
378
  type AnomalySeverity = "low" | "medium" | "high";
379
+ /** One filter pinning an anomaly (or a failed monitor) to a segment. */
380
+ interface AnomalyFilter {
381
+ /** Fully-qualified dimension id, e.g. `"sales_daily.restaurant_id"`. */
382
+ member: string;
383
+ /** Matched values (OR within a filter). */
384
+ values: string[];
385
+ }
337
386
  /**
338
387
  * One row in the anomaly inbox. Detected by `oxy-metric-monitoring` per
339
388
  * `.monitor.yml` entry; upserted by repeat scans so unresolved anomalies
@@ -355,6 +404,18 @@ interface Anomaly {
355
404
  severity: AnomalySeverity | string;
356
405
  status: AnomalyStatus | string;
357
406
  label?: string | null;
407
+ /**
408
+ * Stable key derived from the monitor's filters (e.g.
409
+ * `"sales_daily.restaurant_id=loc-abc"`). Empty for chain-wide monitors.
410
+ */
411
+ dimension_key: string;
412
+ /**
413
+ * Raw filters identifying the segment; `null` for chain-wide monitors.
414
+ * Always present on the wire (the server serializes it unconditionally),
415
+ * hence required-nullable rather than optional — same shape as
416
+ * {@link ScanFailure.filters}.
417
+ */
418
+ filters: AnomalyFilter[] | null;
358
419
  /** Cached ExplainResult — populated by `POST /anomalies/:id/explain`. */
359
420
  explain_cache?: ExplainResult | null;
360
421
  explain_cached_at?: string | null;
@@ -373,10 +434,38 @@ interface ScanOptions {
373
434
  /** Override the reference "now" date (YYYY-MM-DD) — useful for demos. */
374
435
  as_of?: string;
375
436
  }
437
+ /** One `.monitor.yml` entry that errored during a scan. */
438
+ interface ScanFailure {
439
+ measure: string;
440
+ time_dimension: string;
441
+ granularity: string;
442
+ label: string | null;
443
+ /** Segment key for a `group_by`/filtered monitor; empty for chain-wide. */
444
+ dimension_key: string;
445
+ /** Raw filters identifying the segment; null for chain-wide monitors. */
446
+ filters: AnomalyFilter[] | null;
447
+ error: string;
448
+ }
376
449
  interface ScanResponse {
377
450
  monitors_scanned: number;
378
451
  monitors_failed: number;
379
452
  anomalies_persisted: number;
453
+ /**
454
+ * True when the scan is still running server-side (it exceeded the 55 s
455
+ * synchronous window, or a scan started within the last 60 s and this call
456
+ * was debounced). The counts are all `0` in that case — they are NOT a
457
+ * "nothing found" result. Refetch with `list()` after a short delay.
458
+ */
459
+ pending: boolean;
460
+ /**
461
+ * Per-monitor failures. Empty array (never absent) on a clean scan and on
462
+ * the `pending` path, where failures aren't known yet.
463
+ */
464
+ failures: ScanFailure[];
465
+ }
466
+ interface ExplainOptions {
467
+ /** Recompute even when the row already has a cached result. */
468
+ refresh?: boolean;
380
469
  }
381
470
  type RequestFn = <T>(endpoint: string, options?: RequestInit) => Promise<T>;
382
471
  /**
@@ -413,11 +502,20 @@ declare class AnomaliesClient {
413
502
  * workspace, runs the detector, and upserts matching rows into the
414
503
  * inbox. Returns counts of scanned / failed / persisted.
415
504
  *
505
+ * Long-running: the server waits up to 55 s, then returns
506
+ * `pending: true` with zeroed counts while the scan finishes in the
507
+ * background. Always check `pending` before treating `0` as "nothing
508
+ * found", and refetch with {@link list} shortly after.
509
+ *
416
510
  * @example
417
511
  * ```typescript
418
512
  * // Scan against a known-good reference date (matches the seed dataset)
419
513
  * const result = await client.anomalies.scan({ as_of: "2025-12-15" });
420
- * console.log(`${result.anomalies_persisted} anomalies detected`);
514
+ * if (result.pending) {
515
+ * console.log("scan still running — refetch shortly");
516
+ * } else {
517
+ * console.log(`${result.anomalies_persisted} anomalies detected`);
518
+ * }
421
519
  * ```
422
520
  */
423
521
  scan(options?: ScanOptions): Promise<ScanResponse>;
@@ -427,16 +525,48 @@ declare class AnomaliesClient {
427
525
  updateStatus(anomalyId: string, status: AnomalyStatus): Promise<Anomaly>;
428
526
  /**
429
527
  * Run the metric-tree `explain` for an anomaly and cache the result on
430
- * the row. Subsequent calls return the cached `ExplainResult` instantly.
528
+ * the row. Subsequent calls return the cached `ExplainResult` instantly;
529
+ * pass `{ refresh: true }` to bust the cache and recompute.
530
+ *
531
+ * The uncached path runs a 20-30 s recursive driver search — budget for it
532
+ * (or read `explain_cache` off the row from {@link list} when it's already
533
+ * populated).
431
534
  */
432
- explain(anomalyId: string): Promise<ExplainResult>;
535
+ explain(anomalyId: string, options?: ExplainOptions): Promise<ExplainResult>;
433
536
  }
434
537
  //#endregion
435
- //#region src/customer-app/debug.d.ts
538
+ //#region src/custom-app/base64.d.ts
539
+ /**
540
+ * Encode bytes as standard (padded) base64.
541
+ *
542
+ * ```ts
543
+ * const pdf = new Uint8Array(await renderReport());
544
+ * await ctx.email.send({
545
+ * to: ctx.user.email,
546
+ * subject: "Report",
547
+ * text: "attached",
548
+ * attachments: [{ filename: "report.pdf", content: bytesToBase64(pdf) }]
549
+ * });
550
+ * ```
551
+ *
552
+ * For **text** you generated, skip this entirely and pass the string with
553
+ * `encoding: "utf8"` — it needs no encoder and stays byte-exact for non-ASCII.
554
+ */
555
+ declare function bytesToBase64(input: Uint8Array | ArrayBuffer | ArrayBufferView): string;
556
+ /**
557
+ * Decode standard base64 to bytes — e.g. the body from
558
+ * `ctx.storage.get(key, { encoding: "base64" })`.
559
+ *
560
+ * Throws on malformed input rather than returning a short buffer: a truncated
561
+ * decode that reports success is a corrupt file nobody notices.
562
+ */
563
+ declare function base64ToBytes(base64: string): Uint8Array;
564
+ //#endregion
565
+ //#region src/custom-app/debug.d.ts
436
566
  /** Untyped at the boundary — keep it loose so server-side schema
437
567
  * additions don't break older bundles. Stable enough for inspection
438
568
  * but not a contract clients should depend on field-by-field. */
439
- interface CustomerAppDebugSnapshot {
569
+ interface CustomAppDebugSnapshot {
440
570
  org_slug: string;
441
571
  app_slug: string;
442
572
  app: {
@@ -460,13 +590,13 @@ interface CustomerAppDebugSnapshot {
460
590
  }
461
591
  /**
462
592
  * Fetch the server-side diagnostic snapshot for this bundle. Pair with
463
- * `loadCustomerAppManifest()` — pass its result here. Logs the
593
+ * `loadCustomAppManifest()` — pass its result here. Logs the
464
594
  * snapshot through the SDK logger so it appears in the bundle's
465
595
  * console at info level.
466
596
  */
467
- declare function getCustomerAppDebug(resolved: ResolvedCustomerAppManifest): Promise<CustomerAppDebugSnapshot>;
597
+ declare function getCustomAppDebug(resolved: ResolvedCustomAppManifest): Promise<CustomAppDebugSnapshot>;
468
598
  //#endregion
469
- //#region src/customer-app/function-context.d.ts
599
+ //#region src/custom-app/function-context.d.ts
470
600
  /**
471
601
  * The request passed as the first argument to a function's default export.
472
602
  *
@@ -486,12 +616,46 @@ interface OxyFunctionUser {
486
616
  id: string;
487
617
  email: string;
488
618
  orgId: string;
619
+ /**
620
+ * The caller's role **within this app**, derived server-side from app
621
+ * membership (with org-owner / Oxy-staff break-glass). Absent when they hold
622
+ * no membership.
623
+ *
624
+ * This is the value to gate a privileged surface on — it cannot be forged by
625
+ * the client, unlike a query param or a client-side flag:
626
+ *
627
+ * ```ts
628
+ * if (ctx.user.appRole !== "admin") {
629
+ * return Response.json({ error: "forbidden" }, { status: 403 });
630
+ * }
631
+ * ```
632
+ *
633
+ * Note it is deliberately NOT the org role: an app admin administers one app
634
+ * without holding org-Admin (which also carries billing and member management).
635
+ */
636
+ appRole?: "admin" | "member";
489
637
  }
490
638
  /** Result of a `ctx.fetch` call. */
491
639
  interface OxyFetchResult {
492
640
  status: number;
641
+ /** Response body, decoded per the requested {@link OxyFetchInit.encoding}. */
493
642
  body: string;
643
+ /** Echoes how `body` was encoded (`"utf8"` unless base64 was requested). */
644
+ encoding?: "utf8" | "base64";
494
645
  }
646
+ /**
647
+ * `init` for `ctx.fetch` — the standard `RequestInit` fields the host honours
648
+ * (`method`, `headers`, `body`) plus how to decode the response.
649
+ */
650
+ type OxyFetchInit = RequestInit & {
651
+ /**
652
+ * How to decode the response body. `"utf8"` (default) is **lossy for
653
+ * binary** — every non-UTF-8 byte becomes U+FFFD, so a fetched PDF/PNG comes
654
+ * back corrupt. Pass `"base64"` for any binary response, e.g. to hand it
655
+ * straight to an email attachment.
656
+ */
657
+ encoding?: "utf8" | "base64";
658
+ };
495
659
  /** `ctx.warehouse.*` — writes to one of the app's configured destination databases. */
496
660
  interface OxyWarehouseApi {
497
661
  insert(database: string, table: string, rows: OxyFunctionRow[]): Promise<unknown>;
@@ -539,6 +703,43 @@ interface EmailSendInput {
539
703
  * background (retried) sends become exactly-once once it does.
540
704
  */
541
705
  idempotencyKey?: string;
706
+ /**
707
+ * Files to attach. Max 20 per send, and **10 MiB decoded in total** — SES
708
+ * caps a whole message near 40 MB, so for anything larger store the file with
709
+ * {@link OxyStorageApi} and email a presigned link instead of inlining it.
710
+ *
711
+ * `content` is base64 by default; for generated text set
712
+ * `encoding: "utf8"` and attach the string as-is.
713
+ */
714
+ attachments?: EmailAttachment[];
715
+ }
716
+ /** One attachment on {@link EmailSendInput}. */
717
+ interface EmailAttachment {
718
+ /** Filename shown to the recipient. Required; path separators are stripped. */
719
+ filename: string;
720
+ /**
721
+ * File contents, interpreted per {@link EmailAttachment.encoding} — base64 by
722
+ * default, which is the only way binary crosses the isolate boundary.
723
+ */
724
+ content: string;
725
+ /**
726
+ * How `content` is encoded. Defaults to `"base64"`.
727
+ *
728
+ * Use `"utf8"` to attach text the function just generated (CSV, JSON, HTML)
729
+ * — it needs no encoder and is byte-exact for non-ASCII. `btoa` is the wrong
730
+ * tool there: it encodes U+0080..U+00FF as *Latin1*, so accented text comes
731
+ * out as mojibake rather than as an error. For binary, take base64 straight
732
+ * from the source — `ctx.storage.get(key, { encoding: "base64" })` or
733
+ * `ctx.fetch(url, { encoding: "base64" })` — or {@link bytesToBase64} for a
734
+ * `Uint8Array` you built yourself.
735
+ */
736
+ encoding?: "base64" | "utf8";
737
+ /** MIME type; defaults to `application/octet-stream`. */
738
+ contentType?: string;
739
+ /** Render inline (e.g. an image referenced as `cid:<contentId>`) instead of as a download. */
740
+ inline?: boolean;
741
+ /** Content-ID for an inline part, referenced from the HTML body as `cid:<contentId>`. */
742
+ contentId?: string;
542
743
  }
543
744
  /** Result of a successful `ctx.email.send`. */
544
745
  interface EmailSendResult {
@@ -549,6 +750,164 @@ interface EmailSendResult {
549
750
  interface OxyEmailApi {
550
751
  send(input: EmailSendInput): Promise<EmailSendResult>;
551
752
  }
753
+ /** Input to `ctx.storage.getUploadUrl`. */
754
+ interface StorageUploadUrlInput {
755
+ /**
756
+ * Destination path inside the app's silo, e.g. `"uploads/q1-report.pdf"`.
757
+ * Segments are sanitized server-side and cannot escape the silo. Omit to use
758
+ * `filename`, which is placed under `uploads/`.
759
+ */
760
+ pathname?: string;
761
+ /** Shorthand for `pathname: "uploads/<filename>"`. */
762
+ filename?: string;
763
+ /** MIME type; bound into the presigned PUT signature. Inferred when omitted. */
764
+ contentType?: string;
765
+ /**
766
+ * Exact byte length of the upload, bound into the signature — S3 rejects a
767
+ * body of any other size. Capped by the server's upload ceiling (100 MiB by
768
+ * default).
769
+ */
770
+ contentLength: number;
771
+ /** Presign lifetime in seconds (default 900; max 604800 — SigV4's own limit). */
772
+ expiresInSeconds?: number;
773
+ }
774
+ /** A minted presigned upload. */
775
+ interface StorageUploadUrl {
776
+ /** Presigned PUT — the browser uploads the file bytes directly to this URL. */
777
+ url: string;
778
+ /**
779
+ * The stored key. Record it (e.g. on a row in your warehouse) — it is how you
780
+ * fetch, list or link to the asset later. A random suffix is added so two
781
+ * people uploading `report.pdf` don't collide.
782
+ */
783
+ key: string;
784
+ /** ISO-8601 expiry of the presigned URL. */
785
+ expiresAt: string;
786
+ }
787
+ /** A minted presigned download. */
788
+ interface StorageDownloadUrl {
789
+ url: string;
790
+ expiresAt: string;
791
+ }
792
+ /** One asset in the app's silo. */
793
+ interface StorageObject {
794
+ key: string;
795
+ size: number;
796
+ contentType?: string | null;
797
+ /** ISO-8601. */
798
+ lastModified?: string | null;
799
+ }
800
+ /** One page of {@link OxyStorageApi.list}. */
801
+ interface StorageListPage {
802
+ objects: StorageObject[];
803
+ /** Pass back as `cursor` to fetch the next page; `null` when complete. */
804
+ cursor: string | null;
805
+ hasMore: boolean;
806
+ }
807
+ /** Options for {@link OxyStorageApi.put}. */
808
+ interface StoragePutOptions {
809
+ /** MIME type. Inferred from the pathname's extension when omitted. */
810
+ contentType?: string;
811
+ /**
812
+ * How `body` is encoded. `"base64"` is what makes **binary** generated assets
813
+ * (PDF, PNG, Parquet) possible — a UTF-8 string would corrupt them.
814
+ */
815
+ encoding?: "utf8" | "base64";
816
+ /** Append a short random component before the extension to avoid collisions. */
817
+ addRandomSuffix?: boolean;
818
+ /**
819
+ * Replace an existing asset at this path. Defaults to `false` — writing over
820
+ * an asset by accident is worse than an error, so this is opt-in.
821
+ */
822
+ allowOverwrite?: boolean;
823
+ /** `Cache-Control: max-age=<seconds>` stored on the object. */
824
+ cacheControlMaxAge?: number;
825
+ }
826
+ /** Result of a `put` (and of `copy`). */
827
+ interface StoragePutResult {
828
+ key: string;
829
+ size: number;
830
+ contentType: string;
831
+ }
832
+ /**
833
+ * `ctx.storage` — this app's **asset store**, covering both kinds of file an app
834
+ * produces, in one silo (`customer-app-storage/<app_id>/`):
835
+ *
836
+ * - **Uploaded** — a human picks a file; `getUploadUrl` mints a presigned PUT and
837
+ * the browser uploads **straight to S3**, so uploads aren't bounded by the
838
+ * request-body limit and the bytes never pass through your function.
839
+ * - **Generated** — your function produces the file (a rendered PDF, a CSV
840
+ * export, a chart PNG) and writes it with `put`, using
841
+ * `{ encoding: "base64" }` for binary.
842
+ *
843
+ * Gated by the fail-closed `storage.read` / `storage.write` capabilities in
844
+ * `oxy-app.json`. Every asset is private; reads are always presigned and
845
+ * time-boxed. Keys are confined to your app — another app's key is rejected.
846
+ *
847
+ * ```ts
848
+ * // Uploaded: mint a URL, browser PUTs to it, then record `key`.
849
+ * const { url, key } = await ctx.storage.getUploadUrl({
850
+ * filename: "q1-report.pdf", contentType: "application/pdf", contentLength: size,
851
+ * });
852
+ *
853
+ * // Generated: write a CSV your function just built.
854
+ * const { key } = await ctx.storage.put("generated/jan.csv", csv);
855
+ *
856
+ * // Either way: email a link that outlives the request.
857
+ * const { url: link } = await ctx.storage.getDownloadUrl(key, {
858
+ * expiresInSeconds: 604800, download: true,
859
+ * });
860
+ * ```
861
+ */
862
+ interface OxyStorageApi {
863
+ /** Mint a presigned PUT for a browser upload (requires `storage.write`). */
864
+ getUploadUrl(input: StorageUploadUrlInput): Promise<StorageUploadUrl>;
865
+ /**
866
+ * Mint a presigned GET (requires `storage.read`). `download: true` forces a
867
+ * save-as via `Content-Disposition`, which is what an emailed link wants.
868
+ */
869
+ getDownloadUrl(key: string, opts?: {
870
+ expiresInSeconds?: number;
871
+ download?: boolean;
872
+ }): Promise<StorageDownloadUrl>;
873
+ /**
874
+ * Write a generated asset (requires `storage.write`). Capped at 6 MiB — for
875
+ * anything larger, mint a presigned upload URL and stream to it.
876
+ */
877
+ put(pathname: string, body: string, opts?: StoragePutOptions): Promise<StoragePutResult>;
878
+ /** Read an asset back; `null` when absent (requires `storage.read`). */
879
+ get(key: string, opts?: {
880
+ encoding?: "utf8" | "base64";
881
+ }): Promise<{
882
+ body: string;
883
+ contentType: string | null;
884
+ size: number;
885
+ encoding: string;
886
+ } | null>;
887
+ /** Metadata without the body; `null` when absent (requires `storage.read`). */
888
+ head(key: string): Promise<StorageObject | null>;
889
+ /**
890
+ * One page of assets (requires `storage.read`). Paginated deliberately — pass
891
+ * the returned `cursor` back to walk a large silo without loading it all.
892
+ */
893
+ list(opts?: {
894
+ prefix?: string;
895
+ limit?: number;
896
+ cursor?: string;
897
+ }): Promise<StorageListPage>;
898
+ /**
899
+ * Delete one or many assets (requires `storage.write`). Idempotent — deleting
900
+ * an absent key is a no-op success. `deleted` is the number of keys **accepted**
901
+ * for deletion (an absent key counts too), not a count of keys that existed.
902
+ */
903
+ delete(keyOrKeys: string | string[]): Promise<{
904
+ deleted: number;
905
+ }>;
906
+ /** Server-side copy within the app's silo (requires `storage.write`). */
907
+ copy(fromKey: string, toPathname: string, opts?: {
908
+ allowOverwrite?: boolean;
909
+ }): Promise<StoragePutResult>;
910
+ }
552
911
  /**
553
912
  * The data-plane context passed as the second argument to a function's default
554
913
  * export. Mirrors the host-assembled `ctx` (`__buildCtx` in `runtime.rs`);
@@ -567,21 +926,26 @@ interface OxyFunctionContext {
567
926
  queryStream(sql: string, opts?: {
568
927
  batchSize?: number;
569
928
  }): AsyncGenerator<OxyFunctionRow[], void, unknown>;
570
- /** SSRF-allowlisted outbound HTTP with a response-size cap. */
571
- fetch(url: string, init?: RequestInit): Promise<OxyFetchResult>;
929
+ /**
930
+ * SSRF-allowlisted outbound HTTP with a response-size cap. Pass
931
+ * `{ encoding: "base64" }` for a binary response — the default UTF-8 decode
932
+ * corrupts it.
933
+ */
934
+ fetch(url: string, init?: OxyFetchInit): Promise<OxyFetchResult>;
572
935
  warehouse: OxyWarehouseApi;
573
936
  secrets: OxySecretsApi;
574
937
  semantic: OxySemanticApi;
575
938
  airway: OxyAirwayApi;
576
939
  email: OxyEmailApi;
940
+ storage: OxyStorageApi;
577
941
  }
578
942
  /** Signature of a function's default export: `export default async (req, ctx) => Response`. */
579
943
  type OxyFunctionHandler = (req: OxyFunctionRequest, ctx: OxyFunctionContext) => Promise<Response> | Response;
580
944
  //#endregion
581
- //#region src/customer-app/inject.d.ts
945
+ //#region src/custom-app/inject.d.ts
582
946
  /**
583
947
  * Shape of `window.__OXY_APP__` written by oxy at serve time.
584
- * Consumed by `loadCustomerAppManifest` as the authoritative identity
948
+ * Consumed by `loadCustomAppManifest` as the authoritative identity
585
949
  * source (overrides any hints in `oxy-app.json`).
586
950
  */
587
951
  interface OxyInjectedAppConfig {
@@ -607,7 +971,7 @@ declare global {
607
971
  */
608
972
  declare function readInjectedAppConfig(): OxyInjectedAppConfig | undefined;
609
973
  //#endregion
610
- //#region src/customer-app/logger.d.ts
974
+ //#region src/custom-app/logger.d.ts
611
975
  type OxyAppLogLevel = "debug" | "info" | "warn" | "error";
612
976
  interface OxyAppLogger {
613
977
  log(level: OxyAppLogLevel, msg: string, ctx?: Record<string, unknown>): void;
@@ -617,5 +981,333 @@ declare function setOxyAppLogger(logger: OxyAppLogger | null): void;
617
981
  /** Used by the SDK internals; not part of the public surface. */
618
982
  declare function getOxyAppLogger(): OxyAppLogger;
619
983
  //#endregion
620
- export { type AgentArtifact, type AgentRunEvent, type AgentRunState, type AgentSqlArtifact, AnomaliesClient, type Anomaly, type AnomalySeverity, type AnomalyStatus, type AppFetcher, type CustomerAppDebugSnapshot, type CustomerAppErrorReport, type DimensionOpportunity, type DriverAttribution, type DriverConfidence, type DriverDirection, type DriverForm, type DriverStrength, type EdgeKind, type EmailSendInput, type EmailSendResult, type ExplainConfigOverride, type ExplainNode, type ExplainRequest, type ExplainResult, type ExplainSibling, type ExplainWarning, type ListAnomaliesOptions, type ListAnomaliesResponse, type LoadManifestOptions, type MetricEdge, type MetricNode, type MetricTree, MetricTreeClient, type OpportunityRequest, type OpportunityResult, type OxyAirwayApi, OxyAnswer, type OxyAnswerProps, OxyApiError, type OxyAppFunctionManifest, type OxyAppLogLevel, type OxyAppLogger, type OxyAppManifest, OxyAppProvider, type OxyAppProviderProps, OxyChat, type OxyChatProps, type OxyEmailApi, type OxyFetchResult, type OxyFunctionContext, type OxyFunctionHandler, type OxyFunctionRequest, type OxyFunctionRow, type OxyFunctionUser, type OxyInjectedAppConfig, type OxySecretsApi, type OxySemanticApi, type OxyWarehouseApi, type PredictChange, type PredictImpact, type PredictResult, type ProcedureProgress, type ProcedureResult, type ProcedureRunState, type ResolvedCustomerAppManifest, type ScanOptions, type ScanResponse, type SegmentOpportunity, type SemanticArrayOp, type SemanticDateRangeOp, type SemanticFilter, type SemanticScalarOp, type SemanticTimeDimension, type SensitivityDriver, type SensitivityResult, type SkippedDimension, type SplitKind, type UseAgentRunInput, type UseAgentRunResult, type UseFunctionResult, type UseProcedureRunInput, type UseProcedureRunOpts, type UseProcedureRunResult, type UseQueryInput, type UseQueryOpts, type UseQueryResult, type UseSemanticQueryInput, type UseSemanticQueryOpts, type UseSemanticQueryResult, _resetCustomerAppManifestCacheForTest, apiErrorFromResponse, getCustomerAppDebug, getOxyAppLogger, interpretCustomerAppError, loadCustomerAppManifest, readInjectedAppConfig, setOxyAppLogger, useAgentRun, useFunction, useOxyApp, useProcedureRun, useQuery, useResolvedManifest, useSemanticQuery, useTrackEvent };
984
+ //#region src/custom-app/metric-tree-hooks.d.ts
985
+ /** Shared result envelope for every metric-tree hook. */
986
+ interface MetricTreeHookResult<Data> {
987
+ data: Data | null;
988
+ loading: boolean;
989
+ error: Error | null;
990
+ /** Force a re-run, bypassing nothing — the server honors `?refresh`. */
991
+ refetch: () => void;
992
+ }
993
+ interface EndpointOpts {
994
+ /** Set false to skip the request (e.g. waiting on a user selection). */
995
+ enabled?: boolean;
996
+ }
997
+ interface UseMetricTreeOpts extends EndpointOpts {
998
+ /** Optional measure id to root the returned subtree at. */
999
+ root?: string;
1000
+ }
1001
+ /**
1002
+ * The project's metric tree — measures (nodes) and their component /
1003
+ * driver relationships (edges) — or the subtree rooted at `opts.root`.
1004
+ * The structural backbone every other metric-tree analysis reads against.
1005
+ */
1006
+ declare function useMetricTree(opts?: UseMetricTreeOpts): MetricTreeHookResult<MetricTree>;
1007
+ /**
1008
+ * Ranked drivers of `measureId`, by influence — the "what moves this
1009
+ * measure" question. Pass `null` to stay idle until a measure is chosen.
1010
+ */
1011
+ declare function useSensitivity(measureId: string | null, opts?: EndpointOpts): MetricTreeHookResult<SensitivityResult>;
1012
+ /**
1013
+ * Propagate hypothetical `(measure, delta)` changes upward through the
1014
+ * tree and return the estimated impact on every downstream measure — a
1015
+ * pure metric-tree walk, no warehouse query. Pass `null` to stay idle.
1016
+ */
1017
+ declare function usePredict(changes: PredictChange[] | null, opts?: EndpointOpts): MetricTreeHookResult<PredictResult>;
1018
+ /**
1019
+ * Period-over-period root-cause decomposition: recursively splits the
1020
+ * target measure by components and dimensions until the move concentrates.
1021
+ * This is the heavy one — it can fire many warehouse queries and the
1022
+ * server caps it at 45s. Pass `null` to defer until periods are chosen.
1023
+ */
1024
+ declare function useExplain(request: ExplainRequest | null, opts?: EndpointOpts): MetricTreeHookResult<ExplainResult>;
1025
+ /**
1026
+ * Single-period distribution of a measure — an {@link ExplainResult}
1027
+ * against an auto-derived immediately-prior baseline. Same renderers as
1028
+ * `useExplain`; ignore the delta fields for a pure distribution view.
1029
+ */
1030
+ declare function useDistribution(request: DistributionRequest | null, opts?: EndpointOpts): MetricTreeHookResult<ExplainResult>;
1031
+ /**
1032
+ * Segment opportunity sizing for a measure over a period: finds
1033
+ * underperforming segments and sizes the addressable upside of closing
1034
+ * each rate gap against a benchmark peer. Pass `null` to stay idle until
1035
+ * a target + period are chosen.
1036
+ */
1037
+ declare function useOpportunity(request: OpportunityRequest | null, opts?: EndpointOpts): MetricTreeHookResult<OpportunityResult>;
1038
+ /**
1039
+ * The queryable time dimensions per view (`view.dim` ids) — what a
1040
+ * bundle offers as the period axis for `explain` / `opportunity` /
1041
+ * `distribution` instead of hardcoding a curated map.
1042
+ */
1043
+ declare function useTimeDimensions(opts?: EndpointOpts): MetricTreeHookResult<TimeDimensionsResponse>;
1044
+ //#endregion
1045
+ //#region src/custom-app/sse.d.ts
1046
+ /**
1047
+ * Read a `text/event-stream` response, invoking `onEvent` with each parsed
1048
+ * JSON frame. Frames that fail to parse are skipped (a malformed frame must
1049
+ * not tear down the whole stream). Resolves when the body closes.
1050
+ */
1051
+ declare function readJsonSseStream<E>(resp: Response, onEvent: (event: E) => void): Promise<void>;
1052
+ //#endregion
1053
+ //#region src/worldModel.d.ts
1054
+ /** How a measure aggregates across the entity hierarchy. */
1055
+ type AdditivityClass = "additive" | "non_additive" | "passthrough";
1056
+ interface WorldModelMeasure {
1057
+ name: string;
1058
+ measure_type: string;
1059
+ additivity: AdditivityClass;
1060
+ description?: string | null;
1061
+ expr?: string | null;
1062
+ label?: string | null;
1063
+ /** True when the measure decomposes into a metric-tree driver breakdown. */
1064
+ has_breakdown?: boolean;
1065
+ }
1066
+ /** A measure promoted onto this entity from a descendant view. */
1067
+ interface WorldModelInducedMeasure extends WorldModelMeasure {
1068
+ /** View the measure is actually declared on. */
1069
+ promoted_from: string;
1070
+ /** Promotion path from the declaring view up to this entity. */
1071
+ path: string[];
1072
+ }
1073
+ interface WorldModelDimension {
1074
+ name: string;
1075
+ dim_type: string;
1076
+ description?: string | null;
1077
+ label?: string | null;
1078
+ }
1079
+ interface WorldModelEntity {
1080
+ id: string;
1081
+ label: string;
1082
+ view: string;
1083
+ description?: string | null;
1084
+ depth: number;
1085
+ dimensions: WorldModelDimension[];
1086
+ own_measures: WorldModelMeasure[];
1087
+ induced_measures: WorldModelInducedMeasure[];
1088
+ display_field?: string | null;
1089
+ }
1090
+ /** A promotion edge: measures on `from` promote up to `to`. */
1091
+ interface WorldModelEdge {
1092
+ from: string;
1093
+ to: string;
1094
+ functional: boolean;
1095
+ }
1096
+ interface WorldModel {
1097
+ entities: WorldModelEntity[];
1098
+ edges: WorldModelEdge[];
1099
+ }
1100
+ interface WmInstance {
1101
+ key: string;
1102
+ display: string;
1103
+ }
1104
+ interface WmInstancesResponse {
1105
+ total: number;
1106
+ has_more: boolean;
1107
+ items: WmInstance[];
1108
+ }
1109
+ interface WmEntityCount {
1110
+ matched: number;
1111
+ total: number;
1112
+ /** Sample of reachable descendant rows at this grain (display strings). */
1113
+ sample?: string[];
1114
+ /** Navigation keys aligned with `sample`. */
1115
+ sample_keys?: string[];
1116
+ }
1117
+ interface WmFilterCountsResponse {
1118
+ counts: Record<string, WmEntityCount>;
1119
+ }
1120
+ interface WmBreakdownNode {
1121
+ /** Metric node id `view.measure`. */
1122
+ id: string;
1123
+ view: string;
1124
+ measure: string;
1125
+ label: string;
1126
+ measure_type: string;
1127
+ is_composite: boolean;
1128
+ is_root: boolean;
1129
+ expr?: string | null;
1130
+ /** Filled by `value` frames; null while pending. */
1131
+ value: string | null;
1132
+ unvalued_reason: string | null;
1133
+ }
1134
+ interface WmBreakdownEdge {
1135
+ from: string;
1136
+ to: string;
1137
+ operator: "add" | "sub" | "mul" | "div";
1138
+ sign: number;
1139
+ }
1140
+ /** One frame of the measure-breakdown stream. The `init` frame carries the
1141
+ * graph shape; `value` frames fill node values in as they resolve. */
1142
+ type WmMeasureBreakdownEvent = {
1143
+ kind: "init";
1144
+ root: string;
1145
+ nodes: Omit<WmBreakdownNode, "value" | "unvalued_reason">[];
1146
+ edges: WmBreakdownEdge[];
1147
+ } | {
1148
+ kind: "value";
1149
+ node_id: string;
1150
+ value: string | null;
1151
+ unvalued_reason: string | null;
1152
+ } | {
1153
+ kind: "done";
1154
+ };
1155
+ /** Accumulated breakdown — the shape `useMeasureBreakdown` folds the
1156
+ * stream into. */
1157
+ interface WmMeasureBreakdown {
1158
+ root: string;
1159
+ nodes: WmBreakdownNode[];
1160
+ edges: WmBreakdownEdge[];
1161
+ }
1162
+ //#endregion
1163
+ //#region src/custom-app/world-model-hooks.d.ts
1164
+ interface UseWorldModelGraphResult {
1165
+ data: WorldModel | null;
1166
+ loading: boolean;
1167
+ error: Error | null;
1168
+ refetch: () => void;
1169
+ }
1170
+ /**
1171
+ * The world-model graph — entities (nodes), their measures/dimensions, and
1172
+ * how measures promote across the entity hierarchy (edges). Applies the
1173
+ * project's `.world-model.yml` display config server-side.
1174
+ *
1175
+ * @remarks
1176
+ * This returns the raw semantic-layer entity graph. For the higher-level
1177
+ * node-paradigm interface (`world.metric(id)` speaking `expand` / `explain` /
1178
+ * `size`), use {@link useWorldModel} from `./world-node` instead.
1179
+ */
1180
+ declare function useWorldModelGraph(opts?: {
1181
+ enabled?: boolean;
1182
+ }): UseWorldModelGraphResult;
1183
+ interface UseWorldModelInstancesOpts {
1184
+ /** Substring/prefix search over the entity's display field. */
1185
+ search?: string;
1186
+ /** Max rows to return (default 50 server-side). */
1187
+ limit?: number;
1188
+ enabled?: boolean;
1189
+ }
1190
+ interface UseWorldModelInstancesResult {
1191
+ data: WmInstancesResponse | null;
1192
+ loading: boolean;
1193
+ error: Error | null;
1194
+ refetch: () => void;
1195
+ }
1196
+ /**
1197
+ * List the instances (rows) of `entityId` — a bounded, searchable picker
1198
+ * over the entity's primary keys + display label. Pass `null` for `entityId`
1199
+ * to stay idle until an entity is chosen.
1200
+ */
1201
+ declare function useWorldModelInstances(entityId: string | null, opts?: UseWorldModelInstancesOpts): UseWorldModelInstancesResult;
1202
+ interface UseMeasureBreakdownResult {
1203
+ /** Accumulated breakdown graph; null until the `init` frame. */
1204
+ breakdown: WmMeasureBreakdown | null;
1205
+ loading: boolean;
1206
+ done: boolean;
1207
+ error: Error | null;
1208
+ }
1209
+ /**
1210
+ * Stream the driver-tree breakdown of one instance's measure — the metric
1211
+ * decomposition (add/sub/mul/div component graph) with each node's value
1212
+ * filling in as it resolves. This is the per-instance RCA view. Pass `null`
1213
+ * for `measure` to stay idle.
1214
+ */
1215
+ declare function useMeasureBreakdown(entityId: string | null, keyValue: string | null, measure: string | null): UseMeasureBreakdownResult;
1216
+ //#endregion
1217
+ //#region src/custom-app/world-node.d.ts
1218
+ /** A `dimension → value` scope narrowed onto a node via {@link MetricHandle.drill}. */
1219
+ type MetricScope = Readonly<Record<string, string>>;
1220
+ /** Options for {@link MetricHandle.explain} — an {@link ExplainRequest} minus
1221
+ * the `target`, which the handle supplies from its own id. */
1222
+ type ExplainOpts = Omit<ExplainRequest, "target">;
1223
+ /** Options for {@link MetricHandle.size} — an {@link OpportunityRequest} minus
1224
+ * the `target`. */
1225
+ type SizeOpts = Omit<OpportunityRequest, "target">;
1226
+ /** One child revealed by {@link MetricHandle.expand}: the child measure's
1227
+ * node, the edge that connects it to the parent, and a handle to recurse. */
1228
+ interface ExpandedNode {
1229
+ /** The child measure (a component or a driver of the parent). */
1230
+ node: MetricNode;
1231
+ /** The parent → child edge — `kind`, `direction`, `strength`, `form`, … */
1232
+ edge: MetricEdge;
1233
+ /** A live handle on the child, carrying the parent's scope. */
1234
+ handle: MetricHandle;
1235
+ }
1236
+ /**
1237
+ * A live handle on one metric node. Carry it around and call a verb; every
1238
+ * verb returns either more nodes (`expand`), a scoped handle (`drill`), or an
1239
+ * analysis result (`explain` / `size` / `drivers`).
1240
+ */
1241
+ interface MetricHandle {
1242
+ /** Fully-qualified measure id (`view.measure`). */
1243
+ readonly id: string;
1244
+ /** The scope narrowed onto this handle by `drill` (empty for a root handle). */
1245
+ readonly scope: MetricScope;
1246
+ /** The measure's own tree node (label, expr, is_composite). */
1247
+ node(signal?: AbortSignal): Promise<MetricNode>;
1248
+ /** One hop of relationships — the metric's components and drivers as child nodes. */
1249
+ expand(signal?: AbortSignal): Promise<ExpandedNode[]>;
1250
+ /** The declared drivers of this measure, ranked by influence (sensitivity). */
1251
+ drivers(signal?: AbortSignal): Promise<SensitivityResult>;
1252
+ /** Root-cause a period-over-period move: why it dropped or climbed. */
1253
+ explain(opts: ExplainOpts, signal?: AbortSignal): Promise<ExplainResult>;
1254
+ /** Compare this node to its peers across each dimension and size the gap. */
1255
+ size(opts: SizeOpts, signal?: AbortSignal): Promise<OpportunityResult>;
1256
+ /** Narrow into a segment or entity instance — returns a scoped handle. */
1257
+ drill(scope: Record<string, string>): MetricHandle;
1258
+ }
1259
+ /**
1260
+ * The World Model interface, scoped to one project. The whole surface hangs
1261
+ * off this: grab a {@link MetricHandle} with `metric(id)` and the handle
1262
+ * speaks the verbs, or pull the whole graph with `tree(root?)`.
1263
+ */
1264
+ interface WorldModelApi {
1265
+ /** The active project id, or `null` before `<OxyAppProvider>` resolves one. */
1266
+ readonly projectId: string | null;
1267
+ /** The metric tree, rooted anywhere you like (default: the whole tree). */
1268
+ tree(root?: string, signal?: AbortSignal): Promise<MetricTree>;
1269
+ /** A live handle on one measure node. */
1270
+ metric(id: string): MetricHandle;
1271
+ }
1272
+ /**
1273
+ * Thrown by the value verbs (`explain` / `size`) when called on a handle that
1274
+ * has been `drill`ed. The metric-tree backend cannot yet scope these analyses
1275
+ * to a segment, so failing loud beats returning population numbers for a
1276
+ * question that asked about one segment.
1277
+ */
1278
+ declare class WorldModelScopeUnsupportedError extends Error {
1279
+ readonly code = "world_model_scope_unsupported";
1280
+ readonly scope: MetricScope;
1281
+ constructor(verb: string, scope: MetricScope);
1282
+ }
1283
+ /**
1284
+ * Build a {@link WorldModelApi} over a project id and fetcher. Framework-
1285
+ * agnostic — `useWorldModel()` wraps this for React, but it is directly
1286
+ * unit-testable with a mock fetcher.
1287
+ */
1288
+ declare function createWorldModel(projectId: string | null, fetcher: AppFetcher): WorldModelApi;
1289
+ /**
1290
+ * The World Model node interface, scoped to the active `<OxyAppProvider>`
1291
+ * project. Returns a stable {@link WorldModelApi} — grab a node with
1292
+ * `world.metric(id)` and let it speak the verbs.
1293
+ *
1294
+ * @example
1295
+ * ```tsx
1296
+ * const world = useWorldModel();
1297
+ * const revenue = world.metric("orders.net_revenue");
1298
+ * const children = await revenue.expand(); // components + drivers
1299
+ * const rca = await revenue.explain({
1300
+ * time_dimension: "orders.order_date",
1301
+ * current_period: ["2026-06-01", "2026-06-30"],
1302
+ * previous_period: ["2026-05-01", "2026-05-31"],
1303
+ * });
1304
+ * ```
1305
+ *
1306
+ * @remarks
1307
+ * This is the node-paradigm hook. For the raw semantic-layer entity/measure
1308
+ * graph, use {@link useWorldModelGraph} instead.
1309
+ */
1310
+ declare function useWorldModel(): WorldModelApi;
1311
+ //#endregion
1312
+ export { type AdditivityClass, type AgentArtifact, type AgentRunEvent, type AgentRunState, type AgentSqlArtifact, AnomaliesClient, type Anomaly, type AnomalyFilter, type AnomalySeverity, type AnomalyStatus, type AppFetcher, type CustomAppDebugSnapshot, type CustomAppErrorReport, type DimensionOpportunity, type DistributionRequest, type DriverAttribution, type DriverConfidence, type DriverDirection, type DriverForm, type DriverStrength, type EdgeKind, type EmailAttachment, type EmailSendInput, type EmailSendResult, type ExpandedNode, type ExplainConfigOverride, type ExplainNode, type ExplainOptions, type ExplainOpts, type ExplainRequest, type ExplainResult, type ExplainSibling, type ExplainWarning, type ListAnomaliesOptions, type ListAnomaliesResponse, type LoadManifestOptions, type MetricEdge, type MetricHandle, type MetricNode, type MetricScope, type MetricTree, MetricTreeClient, type MetricTreeHookResult, type OpportunityRequest, type OpportunityResult, type OxyAirwayApi, OxyAnswer, type OxyAnswerProps, OxyApiError, type OxyAppFunctionManifest, type OxyAppLogLevel, type OxyAppLogger, type OxyAppManifest, OxyAppProvider, type OxyAppProviderProps, OxyChat, type OxyChatProps, type OxyEmailApi, type OxyFetchResult, type OxyFunctionContext, type OxyFunctionHandler, type OxyFunctionRequest, type OxyFunctionRow, type OxyFunctionUser, type OxyInjectedAppConfig, type OxySecretsApi, type OxySemanticApi, type OxyStorageApi, type OxyWarehouseApi, type PredictChange, type PredictImpact, type PredictResult, type ProcedureProgress, type ProcedureResult, type ProcedureRunState, type ResolvedCustomAppManifest, type ScanFailure, type ScanOptions, type ScanResponse, type SegmentOpportunity, type SemanticArrayOp, type SemanticDateRangeOp, type SemanticFilter, type SemanticScalarOp, type SemanticTimeDimension, type SensitivityDriver, type SensitivityResult, type SizeOpts, type SkippedDimension, type SplitKind, type StorageDownloadUrl, type StorageListPage, type StorageObject, type StoragePutOptions, type StoragePutResult, type StorageUploadUrl, type StorageUploadUrlInput, type TimeDimensionsResponse, type UseAgentRunInput, type UseAgentRunResult, type UseFunctionResult, type UseMeasureBreakdownResult, type UseMetricTreeOpts, type UseProcedureRunInput, type UseProcedureRunOpts, type UseProcedureRunResult, type UseQueryInput, type UseQueryOpts, type UseQueryResult, type UseSemanticQueryInput, type UseSemanticQueryOpts, type UseSemanticQueryResult, type UseWorldModelGraphResult, type UseWorldModelInstancesOpts, type UseWorldModelInstancesResult, type WmBreakdownEdge, type WmBreakdownNode, type WmEntityCount, type WmFilterCountsResponse, type WmInstance, type WmInstancesResponse, type WmMeasureBreakdown, type WmMeasureBreakdownEvent, type WorldModel, type WorldModelApi, type WorldModelDimension, type WorldModelEdge, type WorldModelEntity, type WorldModelInducedMeasure, type WorldModelMeasure, WorldModelScopeUnsupportedError, _resetCustomAppManifestCacheForTest, apiErrorFromResponse, base64ToBytes, bytesToBase64, createWorldModel, getCustomAppDebug, getOxyAppLogger, interpretCustomAppError, loadCustomAppManifest, readInjectedAppConfig, readJsonSseStream, setOxyAppLogger, useAgentRun, useDistribution, useExplain, useFunction, useMeasureBreakdown, useMetricTree, useOpportunity, useOxyApp, usePredict, useProcedureRun, useQuery, useResolvedManifest, useSemanticQuery, useSensitivity, useTimeDimensions, useTrackEvent, useWorldModel, useWorldModelGraph, useWorldModelInstances };
621
1313
  //# sourceMappingURL=index.d.mts.map