@oxy-hq/sdk 2.3.0 → 2.5.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.
@@ -0,0 +1,656 @@
1
+
2
+ import * as React from "react";
3
+ //#region src/customer-app/manifest.d.ts
4
+ /**
5
+ * Declaration of a single Oxy Function shipped in the bundle's
6
+ * `functions/` dir. See `internal-docs/2026-06-12-customer-apps-functions-design.md`.
7
+ *
8
+ * All fields optional except that at least one invocation surface
9
+ * (`route`, `schedule`, or `airwayStep`) must be active. Absent =
10
+ * `route: true` (HTTP-invocable via `useFunction`).
11
+ */
12
+ interface OxyAppFunctionManifest {
13
+ /** Source entry, relative to the app dir. Default: `functions/<name>.ts`. */
14
+ entry?: string;
15
+ /** Cron expression. When set, the function fires on this schedule. */
16
+ schedule?: string;
17
+ /** IANA timezone for `schedule`. Default: `UTC`. */
18
+ timezone?: string;
19
+ /** Expose `POST .../fn/<name>` (called via `useFunction`). Default: true. */
20
+ route?: boolean;
21
+ /** Wire the function in as an Airway pipeline transform step. */
22
+ airwayStep?: {
23
+ pipeline: string;
24
+ resource: string;
25
+ };
26
+ /** Wall-clock timeout. Default 30, max 300. */
27
+ timeoutSeconds?: number;
28
+ /**
29
+ * Opt-in result caching for route invocations. Omit (the default) to never
30
+ * cache — the safe choice for a side-effectful function (writes, external
31
+ * POSTs, ELT). Set `ttlSeconds` ONLY for read-only / idempotent functions:
32
+ * results are then cached per (build, function, user, request body) for that
33
+ * window, and a repeat `useFunction().invoke(sameBody)` returns the cached
34
+ * result without re-running. A `?refresh` query bypasses it.
35
+ */
36
+ cache?: {
37
+ ttlSeconds?: number;
38
+ };
39
+ /**
40
+ * Databases this function's `ctx.warehouse.*` writes may target. Omit (or
41
+ * leave empty) and the function may NOT write to any database — writes are
42
+ * fail-closed and rejected before any connection is opened. Declare a
43
+ * destination here ONLY for a function that legitimately writes to it; a
44
+ * read-only function omits it. This scopes writes away from the project's
45
+ * source warehouse.
46
+ */
47
+ destinations?: string[];
48
+ /**
49
+ * Capability to write app-scoped secrets via `ctx.secrets.set` (fail-closed:
50
+ * omit → writes rejected). Only the app's own `apps/<app-id>/` namespace is
51
+ * writable. Declare for a function that persists state — e.g. a scheduled
52
+ * token-refresher that writes the rotated token back to Oxy Secrets.
53
+ */
54
+ secrets?: {
55
+ write?: boolean;
56
+ };
57
+ /**
58
+ * Capability to send email via `ctx.email.send` (fail-closed: omit → the
59
+ * host rejects `ctx.email.send` before any provider call). Declare for a
60
+ * function that emails the app's users — e.g. a `notify` route that sends a
61
+ * welcome message, or a scheduled digest. The sender mailbox is
62
+ * platform-controlled; a function may set `replyTo` but never `from`.
63
+ */
64
+ email?: {
65
+ send?: boolean;
66
+ };
67
+ /**
68
+ * Retry policy for **background** runs (a `schedule` fire or a manual job
69
+ * trigger). Omit → a job run is attempted once. Route (HTTP) invocations are
70
+ * request-scoped and never retried. `maxAttempts` counts the first try
71
+ * (`maxAttempts: 3` = up to 2 retries); backoff is exponential (doubling)
72
+ * between `minTimeoutMs` and `maxTimeoutMs`. Maps to the durable queue's
73
+ * retry policy — a transient failure re-runs the whole isolate.
74
+ */
75
+ retries?: {
76
+ maxAttempts?: number;
77
+ minTimeoutMs?: number;
78
+ maxTimeoutMs?: number;
79
+ };
80
+ /**
81
+ * Example input params for the function — a sample JSON body the admin "Run
82
+ * now" surface prefills so an operator knows what to pass (the function reads
83
+ * it as its `req` body, same as a route invocation). Advisory only; not
84
+ * enforced at runtime.
85
+ */
86
+ inputExample?: unknown;
87
+ }
88
+ /** Wire shape of `oxy-app.json` (v2 only). */
89
+ interface OxyAppManifest {
90
+ /** Must be 2. v1 manifests are no longer supported. */
91
+ schemaVersion: 2;
92
+ /**
93
+ * Optional display name. The admin "Link existing" dialog prefills
94
+ * its Name field from this. Omit to let oxy fall back to the
95
+ * folder basename.
96
+ */
97
+ name?: string;
98
+ /**
99
+ * URL slug. **Required.** The canonical source of truth — the
100
+ * dialog locks the slug field to this value, and
101
+ * `OXY_APP_BASE_PATH=/customer-apps/<org>/<slug>/` baked into the
102
+ * build must match.
103
+ */
104
+ slug: string;
105
+ /**
106
+ * Optional org slug. Prefills the dialog's org picker; operator
107
+ * can still override. Carries no security weight — the actual
108
+ * access check is on the linked row.
109
+ */
110
+ orgSlug?: string;
111
+ /**
112
+ * Optional project (workspace) uuid the bundle expects to read
113
+ * from. Used by `useQuery` to construct the
114
+ * `/api/projects/:id/query` URL.
115
+ */
116
+ projectId?: string;
117
+ /**
118
+ * Optional map of Oxy Functions (server-side handlers) shipped in the
119
+ * bundle's `functions/` dir, keyed by function name. Omit for a pure
120
+ * static bundle (today's default). See the functions design doc.
121
+ */
122
+ functions?: Record<string, OxyAppFunctionManifest>;
123
+ /**
124
+ * Optional Ask Oxygen binding (agent ref + composer chips). The
125
+ * platform's registered copy is authoritative (surfaced by
126
+ * shell-context); this local copy is the dev-time fallback so the
127
+ * shell's Ask dock works before the app is registered.
128
+ */
129
+ ask?: {
130
+ agent?: string;
131
+ suggestedQuestions?: string[];
132
+ };
133
+ }
134
+ /**
135
+ * Manifest + runtime-injected identity needed to call oxy. Callers
136
+ * should treat this as the only source of truth for "which org/app
137
+ * does this bundle belong to."
138
+ */
139
+ interface ResolvedCustomerAppManifest {
140
+ manifest: OxyAppManifest;
141
+ /**
142
+ * Always an empty array for v2 manifests. Kept for API compatibility;
143
+ * callers that previously iterated product names should switch to
144
+ * explicit `useQuery` calls.
145
+ * @deprecated Will be removed in a future version.
146
+ */
147
+ productNames: string[];
148
+ /** Org slug injected by oxy. */
149
+ orgSlug: string;
150
+ /** App slug injected by oxy. */
151
+ appSlug: string;
152
+ /**
153
+ * The oxy server's API base URL. Empty string when oxy serves the
154
+ * bundle itself (same-origin, the common case); a full URL only
155
+ * when the bundle is running under a dev server proxy.
156
+ */
157
+ apiBaseUrl: string;
158
+ /** App UUID; informational. */
159
+ appId?: string;
160
+ /**
161
+ * Project (workspace) UUID. Injection (`window.__OXY_APP__.projectId`)
162
+ * wins over the manifest's `projectId` field — the admin row is
163
+ * authoritative. Manifest `projectId` is a dev-time hint used only
164
+ * when running without a server. Used by `useQuery` to construct the
165
+ * `/api/projects/:id/query` URL.
166
+ */
167
+ projectId?: string;
168
+ }
169
+ interface LoadManifestOptions {
170
+ /**
171
+ * Override the URL the manifest is fetched from. Default:
172
+ * `<injected_base>/oxy-app.json` or `/oxy-app.json`.
173
+ * Useful for non-Next bundlers — set explicitly to wherever your
174
+ * bundler emits static assets.
175
+ */
176
+ manifestUrl?: string;
177
+ }
178
+ /**
179
+ * Load + validate the manifest. Cached after the first call so callers
180
+ * can invoke this from every component without coordinating.
181
+ */
182
+ declare function loadCustomerAppManifest(options?: LoadManifestOptions): Promise<ResolvedCustomerAppManifest>;
183
+ /** For tests: reset the cache between runs. */
184
+ declare function _resetCustomerAppManifestCacheForTest(): void;
185
+ //#endregion
186
+ //#region src/customer-app/errors.d.ts
187
+ /**
188
+ * Error thrown by all customer-app hooks when an API call returns a
189
+ * non-2xx response. Carries the structured `code` + `hint` the server
190
+ * emits so bundle UIs can render an actionable message instead of
191
+ * "404: { ...json... }".
192
+ */
193
+ declare class OxyApiError extends Error {
194
+ readonly status: number;
195
+ readonly code: string | null;
196
+ readonly hint: string | null;
197
+ constructor(opts: {
198
+ status: number;
199
+ message: string;
200
+ code?: string | null;
201
+ hint?: string | null;
202
+ });
203
+ }
204
+ /**
205
+ * Read a non-2xx response from oxy and return an `OxyApiError`.
206
+ * Parses the JSON envelope when present; falls back to raw text
207
+ * (truncated to 240 chars so a runaway HTML error page doesn't
208
+ * dominate the bundle UI).
209
+ */
210
+ declare function apiErrorFromResponse(resp: Response): Promise<OxyApiError>;
211
+ interface CustomerAppErrorReport {
212
+ title: string;
213
+ message: string;
214
+ hint: string;
215
+ docs?: string;
216
+ }
217
+ /** Interpret a thrown error as a structured report for UI display. */
218
+ declare function interpretCustomerAppError(err: unknown): CustomerAppErrorReport;
219
+ //#endregion
220
+ //#region src/customer-app/function-sse.d.ts
221
+ /** A captured `console.*` / `ctx.log` line from a function run. */
222
+ interface FunctionLog {
223
+ level: string;
224
+ message: string;
225
+ }
226
+ //#endregion
227
+ //#region src/customer-app/react.d.ts
228
+ /**
229
+ * Credentialed fetch wrapper stored in context so `useQuery` can share
230
+ * the same request mechanism without coupling it to the global `fetch`.
231
+ *
232
+ * Sends `credentials: "include"` so the session cookie rides along when
233
+ * the app is served by oxy (in-workspace / admin preview) — that cookie
234
+ * authorizes data calls. For local dev (cross-origin), the
235
+ * `@oxy-hq/vite-plugin` proxy attaches the developer's token. Bundles may
236
+ * override the fetcher for test/proxy environments.
237
+ */
238
+ type AppFetcher = typeof fetch;
239
+ interface OxyAppProviderProps {
240
+ /** Optional manifest load options. Same shape as `loadCustomerAppManifest`. */
241
+ manifestOptions?: LoadManifestOptions;
242
+ /**
243
+ * Rendered while the manifest is loading. Defaults to nothing; pass a
244
+ * spinner if you want one.
245
+ */
246
+ fallback?: React.ReactNode;
247
+ /**
248
+ * Rendered on manifest load failure. Receives the structured error
249
+ * report so the bundle can show its own branded error card. Defaults
250
+ * to a minimal text-only fallback (better than a blank page).
251
+ */
252
+ errorFallback?: (err: CustomerAppErrorReport) => React.ReactNode;
253
+ /**
254
+ * Override the fetch implementation used by all hooks (`useQuery`).
255
+ * Useful for test environments or proxy setups. Defaults to a wrapper
256
+ * that sets `credentials: "include"` on every request.
257
+ */
258
+ fetcher?: AppFetcher;
259
+ /**
260
+ * Origin of the oxy backend to call (e.g. `https://oxy.example.com` or
261
+ * `http://localhost:3000`). When set, the SDK resolves its relative `/api/…`
262
+ * requests — `shell-context`, Ask Oxygen, events — against this origin
263
+ * instead of the app's own, so a standalone / cross-origin dev app can drive
264
+ * the wired shell without a same-origin proxy. The backend must allow the
265
+ * app's origin (see oxy's dev-origin CORS list). Leave unset when the app is
266
+ * served same-origin by oxy.
267
+ */
268
+ backendUrl?: string;
269
+ children: React.ReactNode;
270
+ }
271
+ /**
272
+ * Top-level provider. Loads the manifest once on mount; children only
273
+ * render after the manifest is ready (or the error fallback fires).
274
+ */
275
+ declare function OxyAppProvider(props: OxyAppProviderProps): React.JSX.Element;
276
+ /**
277
+ * Read the resolved manifest from context. Throws if called outside
278
+ * `<OxyAppProvider>` — that's a programmer error worth surfacing
279
+ * loudly, not silently swallowing.
280
+ */
281
+ declare function useResolvedManifest(): ResolvedCustomerAppManifest;
282
+ /**
283
+ * Low-level hook that returns the raw context value (including the
284
+ * fetcher). Prefer `useResolvedManifest` for manifest access; use
285
+ * this only when you need the fetcher or identity without requiring
286
+ * the manifest to be ready (e.g. inside `useQuery`, or the shell
287
+ * chrome, which must never block the app on the manifest load).
288
+ */
289
+ declare function useOxyApp(): {
290
+ projectId: string | undefined;
291
+ appSlug: string | undefined;
292
+ orgSlug: string | undefined;
293
+ fetcher: AppFetcher;
294
+ };
295
+ interface UseQueryInput {
296
+ sql: string;
297
+ database?: string;
298
+ }
299
+ interface UseQueryOpts {
300
+ params?: Record<string, string | number | boolean | null | undefined>;
301
+ /** Set false to skip the request (e.g., waiting on user input). */
302
+ enabled?: boolean;
303
+ }
304
+ interface UseQueryResult<Row = Record<string, unknown>> {
305
+ rows: Row[];
306
+ columns: string[];
307
+ loading: boolean;
308
+ error: Error | null;
309
+ refetch: () => void;
310
+ }
311
+ /**
312
+ * Execute an ad-hoc SQL query against the project linked to this
313
+ * customer app. The query is specified inline by the caller; no
314
+ * manifest declaration is involved.
315
+ *
316
+ * Re-runs whenever `input` or enabled `params` change. Use the
317
+ * `enabled` option to defer the first fetch until required data is
318
+ * available (e.g. a user-supplied filter value).
319
+ */
320
+ declare function useQuery<Row = Record<string, unknown>>(input: UseQueryInput, opts?: UseQueryOpts): UseQueryResult<Row>;
321
+ interface UseFunctionResult<Data = unknown> {
322
+ /**
323
+ * Invoke the function with an optional JSON body. Resolves to the parsed
324
+ * result. Pass `{ idempotencyKey }` to make a side-effectful invocation
325
+ * exactly-once: a retry with the same key replays the stored result instead
326
+ * of re-executing. Send a fresh key per logical action (e.g. a UUID per
327
+ * journal entry).
328
+ */
329
+ invoke: (body?: unknown, opts?: {
330
+ idempotencyKey?: string;
331
+ }) => Promise<Data>;
332
+ /** Last successful result, or null before the first invoke. */
333
+ data: Data | null;
334
+ /** True while an invocation is in flight. */
335
+ isLoading: boolean;
336
+ /** Last invocation error, or null. On error this carries `.logs` too. */
337
+ error: Error | null;
338
+ /**
339
+ * `console.*` / `ctx.log` output from the last invoke (success or error), so
340
+ * a developer can see what the function printed without opening the oxy
341
+ * server logs. Empty for a cache hit or idempotent replay — no run happened,
342
+ * so there is nothing to log.
343
+ */
344
+ logs: FunctionLog[];
345
+ }
346
+ /**
347
+ * Imperative hook for invoking an Oxy Function by name.
348
+ *
349
+ * ```tsx
350
+ * const refresh = useFunction("refresh-sales");
351
+ * <button disabled={refresh.isLoading} onClick={() => refresh.invoke({ full: true })}>
352
+ * Refresh
353
+ * </button>
354
+ * ```
355
+ */
356
+ declare function useFunction<Data = unknown>(name: string): UseFunctionResult<Data>;
357
+ /** Scalar filter operators (compared against a single value). */
358
+ type SemanticScalarOp = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
359
+ /** Array filter operators (compared against a list). */
360
+ type SemanticArrayOp = "in" | "not_in";
361
+ /** Date-range filter operators. `from` / `to` accept ISO date strings. */
362
+ type SemanticDateRangeOp = "in_date_range" | "not_in_date_range";
363
+ /**
364
+ * One filter clause. The `field` references a dimension name within
365
+ * the topic; the `op` discriminator picks which other fields are
366
+ * meaningful. Wire shape matches `agentic_semantic::SemanticFilter`
367
+ * verbatim — the bundle's request body is forwarded to airlayer's
368
+ * compiler with no translation.
369
+ */
370
+ type SemanticFilter = {
371
+ field: string;
372
+ op: SemanticScalarOp;
373
+ value: string | number | boolean | null;
374
+ } | {
375
+ field: string;
376
+ op: SemanticArrayOp;
377
+ values: Array<string | number | boolean | null>;
378
+ } | {
379
+ field: string;
380
+ op: SemanticDateRangeOp;
381
+ from: string;
382
+ to: string;
383
+ };
384
+ /** Time dimensions with optional granularity (e.g. "day", "month"). */
385
+ interface SemanticTimeDimension {
386
+ dimension: string;
387
+ granularity?: "day" | "week" | "month" | "quarter" | "year";
388
+ }
389
+ interface UseSemanticQueryInput {
390
+ topic: string;
391
+ dimensions?: string[];
392
+ measures?: string[];
393
+ time_dimensions?: SemanticTimeDimension[];
394
+ filters?: SemanticFilter[];
395
+ limit?: number;
396
+ }
397
+ interface UseSemanticQueryOpts {
398
+ /** Set false to skip the request (e.g., waiting on user input). */
399
+ enabled?: boolean;
400
+ /**
401
+ * When true, the response includes the compiled SQL string at
402
+ * `sql`. Off by default — production callers shouldn't bake the
403
+ * warehouse SQL into their UI. Bundle authors flip this on while
404
+ * debugging.
405
+ */
406
+ debug?: boolean;
407
+ }
408
+ interface UseSemanticQueryResult<Row = Record<string, unknown>> {
409
+ rows: Row[];
410
+ columns: string[];
411
+ /** True when the result was capped at the server's row limit. */
412
+ truncated: boolean;
413
+ /** Compiled SQL — populated only when `opts.debug` is true. */
414
+ sql: string | null;
415
+ loading: boolean;
416
+ error: Error | null;
417
+ refetch: () => void;
418
+ }
419
+ /**
420
+ * Run a semantic-layer query against the project's `.view.yml` /
421
+ * `.topic.yml` definitions. The server compiles to SQL and executes
422
+ * through the same connector path as `useQuery`, so result shape
423
+ * matches.
424
+ *
425
+ * Re-runs whenever the input shape changes (deep-compared via JSON).
426
+ * Use `opts.enabled = false` to defer the first fetch until required
427
+ * inputs (e.g. a user-picked filter value) are available.
428
+ */
429
+ declare function useSemanticQuery<Row = Record<string, unknown>>(input: UseSemanticQueryInput, opts?: UseSemanticQueryOpts): UseSemanticQueryResult<Row>;
430
+ type ProcedureRunState = "idle" | "running" | "done" | "failed";
431
+ interface UseProcedureRunInput {
432
+ procedureId: string;
433
+ }
434
+ interface UseProcedureRunOpts {
435
+ /** Polling cadence in ms while running. Default: 2000 (procedures
436
+ * are typically minutes-long; tighter cadence wastes resources). */
437
+ pollIntervalMs?: number;
438
+ pollIntervalBackoffMs?: number;
439
+ /** Max client-side wait in ms. Default: 1 hour. */
440
+ maxWaitMs?: number;
441
+ }
442
+ interface ProcedureProgress {
443
+ step: string;
444
+ percent: number;
445
+ }
446
+ interface ProcedureResult {
447
+ summary: string;
448
+ outputs: Record<string, unknown>;
449
+ }
450
+ interface UseProcedureRunResult {
451
+ state: ProcedureRunState;
452
+ run: (params?: Record<string, unknown>) => void;
453
+ /** Cancel the in-flight run. Idempotent. */
454
+ cancel: () => void;
455
+ progress: ProcedureProgress | null;
456
+ result: ProcedureResult | null;
457
+ error: Error | null;
458
+ }
459
+ /**
460
+ * @beta Long-running procedure runner. The wire shape works end-to-end
461
+ * (start → poll → cancel; runs survive server restarts via the
462
+ * `customer_app_procedure_runs` table) but a few rough edges remain
463
+ * before this is GA-ready:
464
+ *
465
+ * - Hint surfaces for `procedure_not_found` are correct but the
466
+ * procedure-discovery rules (which directories the server scans,
467
+ * case-sensitivity, branch awareness) aren't documented yet.
468
+ * - Cancellation across multi-instance deployments leans on a
469
+ * periodic sweep — fine for now, but expect occasional latency
470
+ * between `cancel()` and the run actually stopping.
471
+ * - Progress reporting requires the procedure to emit named
472
+ * steps; bundles get `progress: null` until that lands.
473
+ *
474
+ * The API surface is stable; expect breaking changes only if the
475
+ * server-side `customer_app_procedure_runs` schema changes.
476
+ */
477
+ declare function useProcedureRun(input: UseProcedureRunInput, opts?: UseProcedureRunOpts): UseProcedureRunResult;
478
+ type AgentRunState = "idle" | "running" | "needs_clarification" | "done" | "failed";
479
+ interface AgentRunEvent {
480
+ type: string;
481
+ data: unknown;
482
+ }
483
+ /** SQL produced and (optionally) executed by the agent. Extracted
484
+ * from `query_generated` / `query_executed` / `verified_sql` /
485
+ * `semantic_query` / `omni_query` SSE events so callers don't have
486
+ * to scan the raw event stream themselves. */
487
+ interface AgentSqlArtifact {
488
+ type: "sql";
489
+ /** Stable id derived from the SSE event id so React keys stay
490
+ * stable across re-renders / reconnects. */
491
+ id: string;
492
+ /** Originating UI event type — preserves the verified/semantic/etc.
493
+ * flavor in case the renderer wants a badge. */
494
+ source: string;
495
+ sql: string;
496
+ /** Present when the SQL was executed and rows came back. */
497
+ results?: {
498
+ columns: string[];
499
+ rows: unknown[][];
500
+ rowCount: number;
501
+ };
502
+ /** Present when execution failed — surface it so the bundle UI can
503
+ * show the failure inline next to the SQL instead of swallowing
504
+ * it inside the agent's final answer. */
505
+ error?: string;
506
+ }
507
+ type AgentArtifact = AgentSqlArtifact;
508
+ interface UseAgentRunInput {
509
+ agentId: string;
510
+ }
511
+ interface UseAgentRunResult {
512
+ state: AgentRunState;
513
+ /** Submit a question and open the SSE stream. */
514
+ ask: (question: string, opts?: {
515
+ threadId?: string;
516
+ }) => void;
517
+ /** Cancel the in-flight stream + the server-side run. Idempotent. */
518
+ cancel: () => void;
519
+ /** Accumulated raw events for advanced consumers. */
520
+ events: AgentRunEvent[];
521
+ /** SQL artifacts extracted from the event stream — convenience
522
+ * view over `events` so renderers don't have to know which event
523
+ * types carry SQL. */
524
+ artifacts: AgentArtifact[];
525
+ /** Final answer once a `done` event arrives. Markdown. */
526
+ answer: string | null;
527
+ /** Clarification text once a suspension event arrives. */
528
+ clarification: string | null;
529
+ /** Thread id used by the active run (stable across follow-ups). */
530
+ threadId: string | null;
531
+ /**
532
+ * @beta Relative path to the full thread view in oxy (e.g.
533
+ * `/threads/<id>` for local mode, or
534
+ * `/<org_slug>/workspaces/<ws_id>/threads/<id>` in cloud). Set
535
+ * once the run starts so a bundle can render a "Continue in Oxy"
536
+ * link without constructing the URL itself.
537
+ *
538
+ * Caveats while in beta:
539
+ * - The bundle's origin and the oxy app shell's origin can
540
+ * differ in cloud deployments. If they do, this relative URL
541
+ * resolves against the bundle's origin and 404s. A future
542
+ * release will expose the oxy app origin via the manifest;
543
+ * for now, prefix at the call site if you know your
544
+ * deployment topology, or hide the link entirely.
545
+ * - The thread row may not be queryable until the run produces
546
+ * its first event — clicking the link immediately after
547
+ * `ask()` can land on a "thread not found" page.
548
+ */
549
+ threadUrl: string | null;
550
+ error: Error | null;
551
+ }
552
+ declare function useAgentRun(input: UseAgentRunInput): UseAgentRunResult;
553
+ /**
554
+ * Engineer-tagged usage event. Free-form `event_name` (≤ 64 chars,
555
+ * `[a-z][a-z0-9-]*` validated server-side) + optional JSON `payload`
556
+ * (object, ≤ 4 KiB serialized). Surfaces in the admin Activity tab
557
+ * grouped by name, with drill-down into recent occurrences.
558
+ *
559
+ * The handler returned by [`useTrackEvent`] is **fire-and-forget**:
560
+ * it enqueues the event into an in-memory batch flushed every second
561
+ * (and on `pagehide` so a navigation away doesn't drop the tail).
562
+ * No await semantics — call it inline from a click handler without
563
+ * awaiting it. Server-side validation errors are logged to the
564
+ * console; the call site doesn't need to handle them.
565
+ *
566
+ * Example:
567
+ * ```tsx
568
+ * const track = useTrackEvent();
569
+ * <button
570
+ * onClick={() => {
571
+ * track("export-clicked", { format: "csv", rowCount });
572
+ * doExport();
573
+ * }}
574
+ * >Export</button>
575
+ * ```
576
+ *
577
+ * Rate-limited at 60/min per (user, app) on the server. A burst that
578
+ * trips the limit drops the excess events with a console warning;
579
+ * within-limit events are unaffected.
580
+ */
581
+ declare function useTrackEvent(): (name: string, payload?: Record<string, unknown>) => void;
582
+ interface OxyAnswerProps {
583
+ /** Markdown answer text from `useAgentRun().answer`. */
584
+ answer: string | null;
585
+ /** SQL artifacts from `useAgentRun().artifacts`. */
586
+ artifacts?: AgentArtifact[];
587
+ /** Lifecycle state — drives the placeholder, spinner, error UI. */
588
+ state: AgentRunState;
589
+ /** Clarification text when `state === "needs_clarification"`. */
590
+ clarification?: string | null;
591
+ /** Failure reason when `state === "failed"`. */
592
+ error?: Error | null;
593
+ /**
594
+ * @beta Relative URL to the thread view in oxy — renders a
595
+ * "Continue in Oxy (beta)" link when set. Pass `null` to suppress
596
+ * the link entirely; the link is marked beta because the resolved
597
+ * URL may not reach a live thread in every deployment topology
598
+ * (see `UseAgentRunResult.threadUrl`).
599
+ */
600
+ threadUrl?: string | null;
601
+ /** Override the link label. Default: "Continue this thread in Oxy". */
602
+ threadLinkLabel?: string;
603
+ /** Maximum number of SQL result rows to render per artifact. Older
604
+ * rows truncated with a "+N more" note. Default: 10. */
605
+ maxArtifactRows?: number;
606
+ /** Class on the outer container — for callers using utility CSS. */
607
+ className?: string;
608
+ }
609
+ /**
610
+ * Renders an agent run's answer + artifacts + thread link as a
611
+ * single block. The default styling is intentionally neutral
612
+ * (system fonts, gray surfaces) so it blends into any bundle.
613
+ *
614
+ * Designed to be paired with `useAgentRun`:
615
+ *
616
+ * ```tsx
617
+ * const run = useAgentRun({ agentId: "analyst" });
618
+ * return (
619
+ * <>
620
+ * <button onClick={() => run.ask("how many users last week?")}>Ask</button>
621
+ * <OxyAnswer {...run} />
622
+ * </>
623
+ * );
624
+ * ```
625
+ */
626
+ declare function OxyAnswer(props: OxyAnswerProps): React.JSX.Element;
627
+ interface OxyChatProps {
628
+ /** Agent id (matches `<id>.agentic.yml` in the project). */
629
+ agentId: string;
630
+ /** Placeholder for the question input. */
631
+ placeholder?: string;
632
+ /** Button label. Default: "Ask". */
633
+ submitLabel?: string;
634
+ /** Rendered when the user hasn't asked anything yet. */
635
+ emptyState?: React.ReactNode;
636
+ /** Forwarded to the inner `<OxyAnswer>`. */
637
+ maxArtifactRows?: number;
638
+ /** Class on the outer container. */
639
+ className?: string;
640
+ }
641
+ /**
642
+ * Complete drop-in chat surface. One agent, one input, one answer
643
+ * view. The chat is single-turn by default — each new question
644
+ * cancels the previous run and clears the answer. Bundles that
645
+ * want a multi-turn conversation history compose their own UI
646
+ * using `useAgentRun` directly.
647
+ *
648
+ * Single-turn keeps the surface dead simple: bundles use this for
649
+ * the "ask anything about your data" widget that sits next to
650
+ * structured panels. Multi-turn is rare in those contexts and
651
+ * better expressed by the bundle.
652
+ */
653
+ declare function OxyChat(props: OxyChatProps): React.JSX.Element;
654
+ //#endregion
655
+ export { UseSemanticQueryOpts as A, CustomerAppErrorReport as B, UseProcedureRunInput as C, UseQueryOpts as D, UseQueryInput as E, useProcedureRun as F, OxyAppFunctionManifest as G, apiErrorFromResponse as H, useQuery as I, _resetCustomerAppManifestCacheForTest as J, OxyAppManifest as K, useResolvedManifest as L, useAgentRun as M, useFunction as N, UseQueryResult as O, useOxyApp as P, useSemanticQuery as R, UseFunctionResult as S, UseProcedureRunResult as T, interpretCustomerAppError as U, OxyApiError as V, LoadManifestOptions as W, loadCustomerAppManifest as Y, SemanticFilter as _, AppFetcher as a, UseAgentRunInput as b, OxyAppProvider as c, OxyChatProps as d, ProcedureProgress as f, SemanticDateRangeOp as g, SemanticArrayOp as h, AgentSqlArtifact as i, UseSemanticQueryResult as j, UseSemanticQueryInput as k, OxyAppProviderProps as l, ProcedureRunState as m, AgentRunEvent as n, OxyAnswer as o, ProcedureResult as p, ResolvedCustomerAppManifest as q, AgentRunState as r, OxyAnswerProps as s, AgentArtifact as t, OxyChat as u, SemanticScalarOp as v, UseProcedureRunOpts as w, UseAgentRunResult as x, SemanticTimeDimension as y, useTrackEvent as z };
656
+ //# sourceMappingURL=react-BnpR8VRJ.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-BnpR8VRJ.d.mts","names":[],"sources":["../src/customer-app/manifest.ts","../src/customer-app/errors.ts","../src/customer-app/function-sse.ts","../src/customer-app/react.tsx"],"mappings":"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"}