@athenaintel/react 0.10.41-rc.2 → 0.11.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.cjs CHANGED
@@ -42,8 +42,8 @@ var __privateWrapper = (obj, member, setter, getter) => ({
42
42
  var _focused, _cleanup, _setup, _a2, _provider, _providerCalled, _b, _online, _cleanup2, _setup2, _c, _gcTimeout, _d, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _e, _client2, _currentQuery, _currentQueryInitialState, _currentResult, _currentResultState, _currentResultOptions, _currentThenable, _selectError, _selectFn, _selectResult, _lastQueryWithDefinedData, _staleTimeoutId, _refetchIntervalId, _currentRefetchInterval, _trackedProps, _QueryObserver_instances, executeFetch_fn, updateStaleTimeout_fn, computeRefetchInterval_fn, updateRefetchInterval_fn, updateTimers_fn, clearStaleTimeout_fn, clearRefetchInterval_fn, updateQuery_fn, notify_fn, _f, _client3, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _g, _mutations, _scopes, _mutationId, _h, _queries, _i, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _j;
43
43
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
44
44
  const jsxRuntime = require("react/jsx-runtime");
45
- const react$1 = require("@assistant-ui/react");
46
45
  const React = require("react");
46
+ const react$1 = require("@assistant-ui/react");
47
47
  const AthenaAuthContext = require("./AthenaAuthContext-B3AwLA5Z.cjs");
48
48
  const localStorage$1 = require("@assistant-ui/react-statewire/local-storage");
49
49
  const tap = require("@assistant-ui/tap");
@@ -52,6 +52,7 @@ require("@assistant-ui/core");
52
52
  const react$2 = require("@assistant-ui/core/react");
53
53
  const reactLanggraph = require("@assistant-ui/react-langgraph");
54
54
  const reactStatewire = require("@assistant-ui/react-statewire");
55
+ const store = require("@assistant-ui/store");
55
56
  const ReactDOM = require("react-dom");
56
57
  function _interopNamespaceDefault(e) {
57
58
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -71,6 +72,909 @@ function _interopNamespaceDefault(e) {
71
72
  }
72
73
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
73
74
  const ReactDOM__namespace = /* @__PURE__ */ _interopNamespaceDefault(ReactDOM);
75
+ const version$1 = "0.11.0";
76
+ const packageJson = {
77
+ version: version$1
78
+ };
79
+ const ATHENA_REACT_SDK_VERSION = packageJson.version;
80
+ const DEFAULT_CAPTURE_GATE_CONFIG = {
81
+ globalMaxPerWindow: 50,
82
+ globalWindowMs: 1e4,
83
+ criticalReservePerWindow: 15,
84
+ defaultEventMaxPerWindow: 12,
85
+ defaultEventWindowMs: 6e4,
86
+ defaultDedupeWindowMs: 5e3,
87
+ flushIntervalMs: 3e4,
88
+ flushCoalesceThreshold: 20,
89
+ eventOverrides: {
90
+ memory_profile_sample: { maxPerWindow: 2, windowMs: 3e4, dedupeWindowMs: 15e3 },
91
+ long_task_detected: { maxPerWindow: 3, windowMs: 6e4, dedupeWindowMs: 1e4 },
92
+ collab_connection_status_changed: { maxPerWindow: 6, windowMs: 6e4 },
93
+ collab_first_remote_update: { maxPerWindow: 3, windowMs: 6e4 },
94
+ collab_first_local_update: { maxPerWindow: 3, windowMs: 6e4 },
95
+ collab_render_time_sync_fix: { maxPerWindow: 3, windowMs: 6e4 },
96
+ collab_visibility_recovery: { maxPerWindow: 4, windowMs: 6e4 },
97
+ langgraph_message_validation_error: {
98
+ maxPerWindow: 8,
99
+ windowMs: 6e4,
100
+ dedupeWindowMs: 15e3
101
+ },
102
+ langgraph_messages_validation_error: {
103
+ maxPerWindow: 5,
104
+ windowMs: 6e4,
105
+ dedupeWindowMs: 15e3
106
+ },
107
+ langgraph_interrupt_validation_error: {
108
+ maxPerWindow: 5,
109
+ windowMs: 6e4,
110
+ dedupeWindowMs: 15e3
111
+ },
112
+ langgraph_state_validation_error: {
113
+ maxPerWindow: 5,
114
+ windowMs: 6e4,
115
+ dedupeWindowMs: 15e3
116
+ },
117
+ graphql_error: { maxPerWindow: 12, windowMs: 6e4, dedupeWindowMs: 1e4 },
118
+ chat_error: { maxPerWindow: 8, windowMs: 6e4, dedupeWindowMs: 5e3 },
119
+ memory_critical_threshold: { maxPerWindow: 3, windowMs: 3e5 },
120
+ memory_warning_threshold: { maxPerWindow: 3, windowMs: 3e5 },
121
+ pptx_slide_changed: { maxPerWindow: 8, windowMs: 3e4 }
122
+ }
123
+ };
124
+ const CRITICAL_EVENT_PATTERNS = [
125
+ /(?:^|_)failed$/,
126
+ /(?:^|_)error(?:_|$)/,
127
+ /crash/,
128
+ /^oom_/,
129
+ /aw_snap/,
130
+ /chunk_load/,
131
+ /global_error/,
132
+ /\$exception$/,
133
+ /^404_error$/,
134
+ /^500_error$/,
135
+ /_boundary_/
136
+ ];
137
+ const BYPASS_OPTION_KEY = "__posthog_gate_bypass";
138
+ function isCriticalPosthogEvent(event) {
139
+ return CRITICAL_EVENT_PATTERNS.some((pattern) => pattern.test(event));
140
+ }
141
+ function shouldBypassCaptureGate(options) {
142
+ if (!options || typeof options !== "object") return false;
143
+ return options[BYPASS_OPTION_KEY] === true;
144
+ }
145
+ function withCaptureGateBypass(options) {
146
+ return {
147
+ ...options ?? {},
148
+ [BYPASS_OPTION_KEY]: true
149
+ };
150
+ }
151
+ function pruneWindow(window2, now, windowMs) {
152
+ const cutoff = now - windowMs;
153
+ while (window2.timestamps.length > 0 && window2.timestamps[0] < cutoff) {
154
+ window2.timestamps.shift();
155
+ }
156
+ }
157
+ function countInWindow(window2, now, windowMs) {
158
+ pruneWindow(window2, now, windowMs);
159
+ return window2.timestamps.length;
160
+ }
161
+ function recordInWindow(window2, now) {
162
+ window2.timestamps.push(now);
163
+ }
164
+ function stableStringify(value) {
165
+ if (value == null) return String(value);
166
+ if (typeof value !== "object") return String(value);
167
+ if (Array.isArray(value)) {
168
+ return `[${value.map((item) => stableStringify(item)).join(",")}]`;
169
+ }
170
+ const record2 = value;
171
+ const keys2 = Object.keys(record2).sort();
172
+ return `{${keys2.map((key) => `${key}:${stableStringify(record2[key])}`).join(",")}}`;
173
+ }
174
+ function fingerprintProperties(properties) {
175
+ if (!properties) return "";
176
+ const keys2 = [
177
+ "error",
178
+ "error_message",
179
+ "message",
180
+ "reason",
181
+ "status",
182
+ "code",
183
+ "asset_id",
184
+ "doc_id",
185
+ "thread_id",
186
+ "session_id",
187
+ "operation",
188
+ "path",
189
+ "url",
190
+ "chunk_identifier",
191
+ "validation_path"
192
+ ];
193
+ const subset = {};
194
+ for (const key of keys2) {
195
+ if (key in properties) {
196
+ subset[key] = properties[key];
197
+ }
198
+ }
199
+ return stableStringify(subset);
200
+ }
201
+ function buildCaptureFingerprint(event, properties) {
202
+ return `${event}|${fingerprintProperties(properties)}`;
203
+ }
204
+ function buildCoalescedCaptureProperties(payload) {
205
+ const windowMs = payload.lastAt - payload.firstAt;
206
+ return {
207
+ ...payload.properties,
208
+ coalesced: true,
209
+ coalesced_count: payload.coalescedCount,
210
+ coalesced_first_at: new Date(payload.firstAt).toISOString(),
211
+ coalesced_last_at: new Date(payload.lastAt).toISOString(),
212
+ coalesced_window_ms: windowMs,
213
+ coalesced_suppression_reason: payload.suppressionReason
214
+ };
215
+ }
216
+ class PosthogCaptureGate {
217
+ constructor(config2 = DEFAULT_CAPTURE_GATE_CONFIG) {
218
+ __publicField(this, "config");
219
+ __publicField(this, "globalWindow", { timestamps: [] });
220
+ __publicField(this, "eventWindows", /* @__PURE__ */ new Map());
221
+ __publicField(this, "activeDedupe", /* @__PURE__ */ new Map());
222
+ __publicField(this, "coalesceBuckets", /* @__PURE__ */ new Map());
223
+ __publicField(this, "emittedTotal", 0);
224
+ __publicField(this, "coalescedTotal", 0);
225
+ __publicField(this, "flushedCoalescedTotal", 0);
226
+ this.config = config2;
227
+ }
228
+ resetForTests() {
229
+ this.globalWindow.timestamps.length = 0;
230
+ this.eventWindows.clear();
231
+ this.activeDedupe.clear();
232
+ this.coalesceBuckets.clear();
233
+ this.emittedTotal = 0;
234
+ this.coalescedTotal = 0;
235
+ this.flushedCoalescedTotal = 0;
236
+ }
237
+ getSnapshot() {
238
+ const coalescedPendingByEvent = {};
239
+ let coalescedPending = 0;
240
+ for (const bucket of this.coalesceBuckets.values()) {
241
+ coalescedPending += bucket.count;
242
+ coalescedPendingByEvent[bucket.event] = (coalescedPendingByEvent[bucket.event] ?? 0) + bucket.count;
243
+ }
244
+ return {
245
+ coalescedPending,
246
+ coalescedPendingByEvent,
247
+ emittedTotal: this.emittedTotal,
248
+ coalescedTotal: this.coalescedTotal,
249
+ flushedCoalescedTotal: this.flushedCoalescedTotal
250
+ };
251
+ }
252
+ evaluateCapture(event, properties, options, now = Date.now()) {
253
+ if (shouldBypassCaptureGate(options)) {
254
+ return { action: "emit" };
255
+ }
256
+ const fingerprint = buildCaptureFingerprint(event, properties);
257
+ const bucketKey = fingerprint;
258
+ const override = this.config.eventOverrides[event];
259
+ const dedupeWindowMs = (override == null ? void 0 : override.dedupeWindowMs) ?? this.config.defaultDedupeWindowMs;
260
+ const lastDedupe = this.activeDedupe.get(event);
261
+ if (lastDedupe && lastDedupe.fingerprint === fingerprint && now - lastDedupe.at < dedupeWindowMs) {
262
+ return this.recordCoalesce(event, bucketKey, fingerprint, properties, "dedupe", now);
263
+ }
264
+ const critical = isCriticalPosthogEvent(event);
265
+ const globalCount = countInWindow(this.globalWindow, now, this.config.globalWindowMs);
266
+ const normalBudget = Math.max(
267
+ 0,
268
+ this.config.globalMaxPerWindow - this.config.criticalReservePerWindow
269
+ );
270
+ if (critical) {
271
+ if (globalCount >= this.config.globalMaxPerWindow) {
272
+ return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
273
+ }
274
+ } else if (globalCount >= normalBudget) {
275
+ return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
276
+ }
277
+ const eventWindow = this.eventWindows.get(event) ?? { timestamps: [] };
278
+ this.eventWindows.set(event, eventWindow);
279
+ const eventMax = (override == null ? void 0 : override.maxPerWindow) ?? this.config.defaultEventMaxPerWindow;
280
+ const eventWindowMs = (override == null ? void 0 : override.windowMs) ?? this.config.defaultEventWindowMs;
281
+ const eventCount = countInWindow(eventWindow, now, eventWindowMs);
282
+ if (eventCount >= eventMax) {
283
+ return this.recordCoalesce(event, bucketKey, fingerprint, properties, "event_budget", now);
284
+ }
285
+ recordInWindow(this.globalWindow, now);
286
+ recordInWindow(eventWindow, now);
287
+ this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
288
+ this.emittedTotal += 1;
289
+ return { action: "emit" };
290
+ }
291
+ /** Returns payloads ready to flush (does not mutate buckets until caller confirms). */
292
+ collectFlushCandidates(now = Date.now()) {
293
+ const payloads = [];
294
+ for (const bucket of this.coalesceBuckets.values()) {
295
+ const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
296
+ const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
297
+ if (!shouldFlushBySize && !shouldFlushByAge) {
298
+ continue;
299
+ }
300
+ payloads.push({
301
+ bucketKey: bucket.bucketKey,
302
+ event: bucket.event,
303
+ properties: bucket.sampleProperties,
304
+ coalescedCount: bucket.count,
305
+ firstAt: bucket.firstAt,
306
+ lastAt: bucket.lastAt,
307
+ suppressionReason: bucket.suppressionReason
308
+ });
309
+ }
310
+ return payloads;
311
+ }
312
+ /** Remove flushed bucket keys after successful emit. */
313
+ acknowledgeFlushed(payloads) {
314
+ for (const payload of payloads) {
315
+ this.coalesceBuckets.delete(payload.bucketKey);
316
+ this.flushedCoalescedTotal += payload.coalescedCount;
317
+ }
318
+ }
319
+ /** After coalescing, flush immediately if the bucket crossed the early threshold. */
320
+ takeBucketIfReady(bucketKey, now = Date.now()) {
321
+ const bucket = this.coalesceBuckets.get(bucketKey);
322
+ if (!bucket) return null;
323
+ const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
324
+ const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
325
+ if (!shouldFlushBySize && !shouldFlushByAge) {
326
+ return null;
327
+ }
328
+ this.coalesceBuckets.delete(bucketKey);
329
+ this.flushedCoalescedTotal += bucket.count;
330
+ return {
331
+ bucketKey: bucket.bucketKey,
332
+ event: bucket.event,
333
+ properties: bucket.sampleProperties,
334
+ coalescedCount: bucket.count,
335
+ firstAt: bucket.firstAt,
336
+ lastAt: bucket.lastAt,
337
+ suppressionReason: bucket.suppressionReason
338
+ };
339
+ }
340
+ /** Force-flush every pending bucket (e.g. page hide). */
341
+ collectAllPending() {
342
+ return [...this.coalesceBuckets.values()].map((bucket) => ({
343
+ bucketKey: bucket.bucketKey,
344
+ event: bucket.event,
345
+ properties: bucket.sampleProperties,
346
+ coalescedCount: bucket.count,
347
+ firstAt: bucket.firstAt,
348
+ lastAt: bucket.lastAt,
349
+ suppressionReason: bucket.suppressionReason
350
+ }));
351
+ }
352
+ recordCoalesce(event, bucketKey, fingerprint, properties, reason, now) {
353
+ const existing = this.coalesceBuckets.get(bucketKey);
354
+ if (existing) {
355
+ existing.count += 1;
356
+ existing.lastAt = now;
357
+ existing.sampleProperties = { ...existing.sampleProperties, ...properties ?? {} };
358
+ } else {
359
+ this.coalesceBuckets.set(bucketKey, {
360
+ event,
361
+ bucketKey,
362
+ fingerprint,
363
+ count: 1,
364
+ firstAt: now,
365
+ lastAt: now,
366
+ suppressionReason: reason,
367
+ sampleProperties: { ...properties ?? {} }
368
+ });
369
+ }
370
+ this.coalescedTotal += 1;
371
+ this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
372
+ return { action: "coalesce", reason, bucketKey };
373
+ }
374
+ }
375
+ const gate = new PosthogCaptureGate(DEFAULT_CAPTURE_GATE_CONFIG);
376
+ let wrappedClient = null;
377
+ let originalCaptureRef = null;
378
+ let flushTimer = null;
379
+ let lifecycleHooksInstalled = false;
380
+ function getPosthogCaptureGate() {
381
+ return gate;
382
+ }
383
+ function emitThroughOriginal(event, properties, options) {
384
+ if (!originalCaptureRef) return void 0;
385
+ return originalCaptureRef(event, properties, withCaptureGateBypass(options));
386
+ }
387
+ function flushCoalescedPayload(payload) {
388
+ emitThroughOriginal(payload.event, buildCoalescedCaptureProperties(payload));
389
+ }
390
+ function flushCoalescedCaptures(options) {
391
+ const payloads = (options == null ? void 0 : options.force) ? gate.collectAllPending() : gate.collectFlushCandidates();
392
+ if (payloads.length === 0) return;
393
+ for (const payload of payloads) {
394
+ flushCoalescedPayload(payload);
395
+ }
396
+ gate.acknowledgeFlushed(payloads);
397
+ }
398
+ function installLifecycleFlushHooks() {
399
+ if (lifecycleHooksInstalled || typeof window === "undefined") return;
400
+ lifecycleHooksInstalled = true;
401
+ const flushOnHide = () => {
402
+ flushCoalescedCaptures({ force: true });
403
+ };
404
+ window.addEventListener("pagehide", flushOnHide);
405
+ document.addEventListener("visibilitychange", () => {
406
+ if (document.visibilityState === "hidden") {
407
+ flushOnHide();
408
+ }
409
+ });
410
+ if (!flushTimer) {
411
+ flushTimer = setInterval(() => {
412
+ flushCoalescedCaptures();
413
+ }, DEFAULT_CAPTURE_GATE_CONFIG.flushIntervalMs);
414
+ }
415
+ }
416
+ function wrapPosthogClient(client) {
417
+ if (wrappedClient === client) {
418
+ return client;
419
+ }
420
+ originalCaptureRef = client.capture.bind(client);
421
+ const originalCaptureException = typeof client.captureException === "function" ? client.captureException.bind(client) : null;
422
+ installLifecycleFlushHooks();
423
+ client.capture = ((event, properties, options) => {
424
+ const outcome = gate.evaluateCapture(event, properties, options);
425
+ if (outcome.action === "coalesce") {
426
+ const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
427
+ if (readyPayload) {
428
+ flushCoalescedPayload(readyPayload);
429
+ }
430
+ return void 0;
431
+ }
432
+ return emitThroughOriginal(event, properties, options);
433
+ });
434
+ if (originalCaptureException) {
435
+ client.captureException = ((error2, additionalProperties) => {
436
+ const mergedProperties = {
437
+ ...additionalProperties ?? {},
438
+ $exception_message: error2 instanceof Error ? error2.message : String(error2),
439
+ $exception_type: error2 instanceof Error ? error2.name : typeof error2
440
+ };
441
+ const outcome = gate.evaluateCapture("$exception", mergedProperties);
442
+ if (outcome.action === "coalesce") {
443
+ const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
444
+ if (readyPayload) {
445
+ flushCoalescedPayload(readyPayload);
446
+ }
447
+ return void 0;
448
+ }
449
+ return originalCaptureException(error2, additionalProperties);
450
+ });
451
+ }
452
+ wrappedClient = client;
453
+ return client;
454
+ }
455
+ function capturePosthogEvent(client, event, properties, options) {
456
+ if (!client || typeof client.capture !== "function") return;
457
+ client.capture(event, properties, options);
458
+ }
459
+ function capturePosthogException(client, error2, properties, options) {
460
+ if (!client) return;
461
+ if (typeof client.captureException === "function") {
462
+ client.captureException(error2, properties);
463
+ return;
464
+ }
465
+ capturePosthogEvent(
466
+ client,
467
+ "$exception",
468
+ {
469
+ ...properties ?? {},
470
+ $exception_message: error2.message,
471
+ $exception_type: error2.name,
472
+ $exception_stack: error2.stack
473
+ },
474
+ options
475
+ );
476
+ }
477
+ let posthogInstance = null;
478
+ let initPromise = null;
479
+ const DEFAULT_HOST = "https://us.i.posthog.com";
480
+ async function initializePostHog(apiKey, host, debug) {
481
+ if (posthogInstance) return posthogInstance;
482
+ if (typeof window === "undefined") return null;
483
+ try {
484
+ const posthog = (await import("posthog-js")).default;
485
+ posthog.init(apiKey, {
486
+ api_host: host,
487
+ autocapture: true,
488
+ capture_pageview: false,
489
+ session_recording: {
490
+ recordCrossOriginIframes: true,
491
+ maskAllInputs: true
492
+ },
493
+ loaded: (ph) => {
494
+ wrapPosthogClient(ph);
495
+ if (debug) {
496
+ ph.debug(true);
497
+ }
498
+ }
499
+ });
500
+ wrapPosthogClient(posthog);
501
+ posthogInstance = posthog;
502
+ return posthog;
503
+ } catch {
504
+ initPromise = null;
505
+ return null;
506
+ }
507
+ }
508
+ function getPostHogInstance() {
509
+ return posthogInstance;
510
+ }
511
+ function PostHogProvider({
512
+ children,
513
+ config: config2
514
+ }) {
515
+ const apiKey = (config2 == null ? void 0 : config2.apiKey) ?? "";
516
+ const host = (config2 == null ? void 0 : config2.host) ?? DEFAULT_HOST;
517
+ const debug = (config2 == null ? void 0 : config2.debug) ?? false;
518
+ React.useEffect(() => {
519
+ if (!apiKey || typeof window === "undefined") return;
520
+ if (!initPromise) {
521
+ initPromise = initializePostHog(apiKey, host, debug);
522
+ }
523
+ }, [apiKey, host, debug]);
524
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
525
+ }
526
+ const ATHENA_SDK_ERROR_CODES = {
527
+ /** No token and no API key resolved before a request had to be sent. */
528
+ auth_missing: "auth_missing",
529
+ /** The server refused the credential (401 / statewire `unauthorized` fin). */
530
+ auth_rejected: "auth_rejected",
531
+ /** `/_athena/auth` or the iframe bridge did not answer within the timeout. */
532
+ auth_bridge_timeout: "auth_bridge_timeout",
533
+ /** `/_athena/auth` answered with a non-404 error. */
534
+ auth_bridge_failed: "auth_bridge_failed",
535
+ /** The statewire sync URL could not be derived from the configuration. */
536
+ config_invalid: "config_invalid",
537
+ /** A prop was set that the active transport ignores (e.g. `agent` on statewire). */
538
+ config_ignored: "config_ignored",
539
+ /** The thread list request failed. */
540
+ threads_list_failed: "threads_list_failed",
541
+ /** Loading a thread's history failed. */
542
+ thread_load_failed: "thread_load_failed",
543
+ /** The statewire host rejected a command (structured `{status, detail}`). */
544
+ statewire_rejected: "statewire_rejected",
545
+ /** The statewire connection is gone and will not reconnect on its own. */
546
+ statewire_gone: "statewire_gone",
547
+ /** The legacy `/api/chat` stream failed. */
548
+ stream_failed: "stream_failed",
549
+ /** The selected collab agent / channel was refused by the backend. */
550
+ collab_agent_rejected: "collab_agent_rejected",
551
+ /** Anything else. */
552
+ unknown: "unknown"
553
+ };
554
+ class AthenaSdkError extends Error {
555
+ constructor(options) {
556
+ super(options.message, options.cause === void 0 ? void 0 : { cause: options.cause });
557
+ __publicField(this, "code");
558
+ __publicField(this, "hint");
559
+ __publicField(this, "status");
560
+ __publicField(this, "detail");
561
+ __publicField(this, "context");
562
+ this.name = "AthenaSdkError";
563
+ this.code = options.code;
564
+ this.hint = options.hint;
565
+ this.status = options.status;
566
+ this.detail = options.detail;
567
+ this.context = options.context ?? {};
568
+ }
569
+ /** A log/console-friendly one-liner: `[code] message — hint`. */
570
+ describe() {
571
+ return `[${this.code}] ${this.message}${this.hint ? ` — ${this.hint}` : ""}`;
572
+ }
573
+ toJSON() {
574
+ return {
575
+ name: this.name,
576
+ code: this.code,
577
+ message: this.message,
578
+ hint: this.hint,
579
+ status: this.status,
580
+ detail: this.detail,
581
+ context: this.context
582
+ };
583
+ }
584
+ }
585
+ function isAthenaSdkError(value) {
586
+ return value instanceof AthenaSdkError;
587
+ }
588
+ function toAthenaSdkError(value, fallback) {
589
+ if (isAthenaSdkError(value)) return value;
590
+ const message = value instanceof Error && value.message ? value.message : fallback.message;
591
+ return new AthenaSdkError({ ...fallback, message, cause: value });
592
+ }
593
+ function readRejectionDetail(detail) {
594
+ if (typeof detail === "string") return { code: null, message: detail || null };
595
+ if (!detail || typeof detail !== "object") return { code: null, message: null };
596
+ const record2 = detail;
597
+ return {
598
+ code: typeof record2.code === "string" ? record2.code : null,
599
+ message: typeof record2.message === "string" ? record2.message : null
600
+ };
601
+ }
602
+ const ATHENA_DIAGNOSTIC_LEVELS = ["debug", "info", "warn", "error"];
603
+ const LEVEL_RANK = {
604
+ debug: 0,
605
+ info: 1,
606
+ warn: 2,
607
+ error: 3
608
+ };
609
+ const DEFAULT_CONFIG = {
610
+ console: false,
611
+ posthog: false,
612
+ bufferSize: 300
613
+ };
614
+ const CONSOLE_PREFIX = "[AthenaSDK]";
615
+ const LOCAL_STORAGE_DEBUG_KEY = "athena:debug";
616
+ const GLOBAL_KEY = "__ATHENA_SDK__";
617
+ const REDACT_KEYS = /token|secret|api[-_]?key|authorization|cookie|password/i;
618
+ function redact(data) {
619
+ if (!data) return void 0;
620
+ const out = {};
621
+ for (const [key, value] of Object.entries(data)) {
622
+ if (REDACT_KEYS.test(key)) {
623
+ out[key] = typeof value === "string" && value.length > 0 ? `<redacted:${value.length}>` : "<redacted>";
624
+ } else {
625
+ out[key] = value;
626
+ }
627
+ }
628
+ return out;
629
+ }
630
+ function nowMs() {
631
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
632
+ }
633
+ function readLocalDebugLevel() {
634
+ try {
635
+ if (typeof localStorage === "undefined") return null;
636
+ const raw = localStorage.getItem(LOCAL_STORAGE_DEBUG_KEY);
637
+ if (!raw) return null;
638
+ if (ATHENA_DIAGNOSTIC_LEVELS.includes(raw)) {
639
+ return raw;
640
+ }
641
+ return raw === "1" || raw === "true" ? "debug" : null;
642
+ } catch {
643
+ return null;
644
+ }
645
+ }
646
+ class AthenaDiagnosticsBus {
647
+ constructor() {
648
+ __publicField(this, "config", { ...DEFAULT_CONFIG });
649
+ __publicField(this, "events", []);
650
+ __publicField(this, "listeners", /* @__PURE__ */ new Set());
651
+ __publicField(this, "snapshotListeners", /* @__PURE__ */ new Set());
652
+ __publicField(this, "seq", 0);
653
+ __publicField(this, "gauges", {});
654
+ __publicField(this, "timings", {});
655
+ __publicField(this, "spans", /* @__PURE__ */ new Map());
656
+ __publicField(this, "cachedSnapshot", null);
657
+ }
658
+ configure(partial2) {
659
+ this.config = { ...this.config, ...partial2 };
660
+ if (this.events.length > this.config.bufferSize) {
661
+ this.events = this.events.slice(-this.config.bufferSize);
662
+ }
663
+ this.invalidate();
664
+ }
665
+ getConfig() {
666
+ return this.config;
667
+ }
668
+ /** Effective console level: the configured one, or `localStorage['athena:debug']`. */
669
+ consoleLevel() {
670
+ if (this.config.console !== false) return this.config.console;
671
+ return readLocalDebugLevel() ?? false;
672
+ }
673
+ emit(name, options = {}) {
674
+ const level = options.level ?? (options.error !== void 0 ? "error" : "info");
675
+ const error2 = options.error === void 0 ? void 0 : toAthenaSdkError(options.error, {
676
+ code: "unknown",
677
+ message: `Unexpected error during ${name}`
678
+ });
679
+ const event = {
680
+ seq: ++this.seq,
681
+ t: Math.round(nowMs() * 10) / 10,
682
+ at: (/* @__PURE__ */ new Date()).toISOString(),
683
+ name,
684
+ level,
685
+ ...options.durationMs !== void 0 && { durationMs: Math.round(options.durationMs) },
686
+ ...options.data && { data: redact(options.data) },
687
+ ...error2 && { error: error2 }
688
+ };
689
+ this.events.push(event);
690
+ if (this.events.length > this.config.bufferSize) {
691
+ this.events.splice(0, this.events.length - this.config.bufferSize);
692
+ }
693
+ if (event.durationMs !== void 0) {
694
+ this.timings[name] = event.durationMs;
695
+ }
696
+ this.invalidate();
697
+ this.echoToConsole(event);
698
+ this.forwardToPostHog(event);
699
+ for (const listener of this.listeners) {
700
+ try {
701
+ listener(event);
702
+ } catch (listenerError) {
703
+ console.error(`${CONSOLE_PREFIX} diagnostics listener threw`, listenerError);
704
+ }
705
+ }
706
+ if (this.config.onEvent) {
707
+ try {
708
+ this.config.onEvent(event);
709
+ } catch (callbackError) {
710
+ console.error(`${CONSOLE_PREFIX} onDiagnostic callback threw`, callbackError);
711
+ }
712
+ }
713
+ if (error2 && this.config.onError) {
714
+ try {
715
+ this.config.onError(error2, event);
716
+ } catch (callbackError) {
717
+ console.error(`${CONSOLE_PREFIX} onError callback threw`, callbackError);
718
+ }
719
+ }
720
+ for (const notify of this.snapshotListeners) notify();
721
+ return event;
722
+ }
723
+ /** Record an error-level event. Returns the normalized `AthenaSdkError`. */
724
+ error(name, error2, fallback, data) {
725
+ const normalized = toAthenaSdkError(error2, fallback);
726
+ this.emit(name, { level: "error", error: normalized, data });
727
+ return normalized;
728
+ }
729
+ /**
730
+ * Start a named span. Returns a function that ends it and emits `doneName`
731
+ * with `durationMs` (or `errorName` when passed an error). Also records a
732
+ * `performance.measure` so the span shows in the browser's Performance panel.
733
+ */
734
+ span(spanName, startName, data) {
735
+ const startedAt = nowMs();
736
+ this.spans.set(spanName, startedAt);
737
+ this.mark(`${spanName}:start`);
738
+ this.emit(startName, { level: "debug", data });
739
+ return (doneName, doneOptions = {}) => {
740
+ const durationMs = nowMs() - startedAt;
741
+ this.spans.delete(spanName);
742
+ this.mark(`${spanName}:end`);
743
+ this.measure(spanName);
744
+ this.emit(doneName, {
745
+ level: doneOptions.error !== void 0 ? "error" : "info",
746
+ durationMs,
747
+ data: doneOptions.data,
748
+ error: doneOptions.error
749
+ });
750
+ return durationMs;
751
+ };
752
+ }
753
+ /** Set a gauge (latest-value metric): connection status, transport, auth mode. */
754
+ gauge(name, value) {
755
+ if (this.gauges[name] === value) return;
756
+ this.gauges[name] = value;
757
+ this.invalidate();
758
+ for (const notify of this.snapshotListeners) notify();
759
+ }
760
+ subscribe(listener) {
761
+ this.listeners.add(listener);
762
+ return () => {
763
+ this.listeners.delete(listener);
764
+ };
765
+ }
766
+ /**
767
+ * Additive consumer registration: every registered consumer receives every
768
+ * event (and every error), unlike the single `onEvent`/`onError` config
769
+ * slots which are last-writer-wins. `AthenaProvider` registers through this
770
+ * so two mounted providers never clobber each other's callbacks.
771
+ */
772
+ addConsumer(consumer) {
773
+ return this.subscribe((event) => {
774
+ var _a3, _b2;
775
+ try {
776
+ (_a3 = consumer.onEvent) == null ? void 0 : _a3.call(consumer, event);
777
+ } catch (callbackError) {
778
+ console.error(`${CONSOLE_PREFIX} onDiagnostic consumer threw`, callbackError);
779
+ }
780
+ if (event.error) {
781
+ try {
782
+ (_b2 = consumer.onError) == null ? void 0 : _b2.call(consumer, event.error, event);
783
+ } catch (callbackError) {
784
+ console.error(`${CONSOLE_PREFIX} onError consumer threw`, callbackError);
785
+ }
786
+ }
787
+ });
788
+ }
789
+ /** Subscribe to snapshot changes (for `useSyncExternalStore`). */
790
+ subscribeSnapshot(listener) {
791
+ this.snapshotListeners.add(listener);
792
+ return () => {
793
+ this.snapshotListeners.delete(listener);
794
+ };
795
+ }
796
+ snapshot() {
797
+ if (!this.cachedSnapshot) {
798
+ const { onEvent: _onEvent, onError: _onError, ...config2 } = this.config;
799
+ this.cachedSnapshot = {
800
+ sdkVersion: ATHENA_REACT_SDK_VERSION,
801
+ config: config2,
802
+ events: [...this.events],
803
+ gauges: { ...this.gauges },
804
+ timings: { ...this.timings }
805
+ };
806
+ }
807
+ return this.cachedSnapshot;
808
+ }
809
+ /** Copy-paste-able JSON of the current snapshot (errors serialized). */
810
+ export() {
811
+ return JSON.stringify(
812
+ this.snapshot(),
813
+ (_key, value) => isAthenaSdkError(value) ? value.toJSON() : value,
814
+ 2
815
+ );
816
+ }
817
+ clear() {
818
+ this.events = [];
819
+ this.timings = {};
820
+ this.invalidate();
821
+ for (const notify of this.snapshotListeners) notify();
822
+ }
823
+ invalidate() {
824
+ this.cachedSnapshot = null;
825
+ }
826
+ mark(name) {
827
+ try {
828
+ if (typeof performance !== "undefined" && typeof performance.mark === "function") {
829
+ performance.mark(`athena-sdk:${name}`);
830
+ }
831
+ } catch {
832
+ }
833
+ }
834
+ measure(spanName) {
835
+ try {
836
+ if (typeof performance !== "undefined" && typeof performance.measure === "function") {
837
+ performance.measure(
838
+ `athena-sdk:${spanName}`,
839
+ `athena-sdk:${spanName}:start`,
840
+ `athena-sdk:${spanName}:end`
841
+ );
842
+ }
843
+ } catch {
844
+ }
845
+ }
846
+ echoToConsole(event) {
847
+ const level = this.consoleLevel();
848
+ if (level === false) {
849
+ if (event.level === "error" && event.error) {
850
+ console.error(`${CONSOLE_PREFIX} ${event.name}: ${event.error.describe()}`, event.data ?? "");
851
+ }
852
+ return;
853
+ }
854
+ if (LEVEL_RANK[event.level] < LEVEL_RANK[level]) return;
855
+ const suffix = event.durationMs !== void 0 ? ` (${event.durationMs}ms)` : "";
856
+ const line = `${CONSOLE_PREFIX} ${event.name}${suffix}`;
857
+ const payload = event.error ? { ...event.data, error: event.error.describe() } : event.data;
858
+ const method = event.level === "error" ? console.error : event.level === "warn" ? console.warn : event.level === "debug" ? console.debug : console.info;
859
+ method(line, payload ?? "");
860
+ }
861
+ forwardToPostHog(event) {
862
+ if (!this.config.posthog) return;
863
+ if (event.durationMs === void 0 && event.level !== "error") return;
864
+ try {
865
+ const client = getPostHogInstance();
866
+ capturePosthogEvent(client, `athena_sdk_${event.name.replace(/\./g, "_")}`, {
867
+ sdk_version: ATHENA_REACT_SDK_VERSION,
868
+ level: event.level,
869
+ ...event.durationMs !== void 0 && { duration_ms: event.durationMs },
870
+ ...event.error && {
871
+ error_code: event.error.code,
872
+ error_message: event.error.message,
873
+ error_status: event.error.status
874
+ },
875
+ ...event.data
876
+ });
877
+ } catch {
878
+ }
879
+ }
880
+ }
881
+ const athenaDiagnostics = new AthenaDiagnosticsBus();
882
+ function installAthenaDiagnosticsGlobal() {
883
+ if (typeof window === "undefined") return;
884
+ const globalWindow = window;
885
+ const existing = globalWindow[GLOBAL_KEY] ?? {};
886
+ globalWindow[GLOBAL_KEY] = {
887
+ ...existing,
888
+ version: ATHENA_REACT_SDK_VERSION,
889
+ diagnostics: {
890
+ snapshot: () => athenaDiagnostics.snapshot(),
891
+ export: () => athenaDiagnostics.export(),
892
+ clear: () => athenaDiagnostics.clear(),
893
+ enableConsole: (level = "debug") => {
894
+ try {
895
+ localStorage.setItem(LOCAL_STORAGE_DEBUG_KEY, level);
896
+ } catch {
897
+ }
898
+ athenaDiagnostics.configure({ console: level });
899
+ },
900
+ disableConsole: () => {
901
+ try {
902
+ localStorage.removeItem(LOCAL_STORAGE_DEBUG_KEY);
903
+ } catch {
904
+ }
905
+ athenaDiagnostics.configure({ console: false });
906
+ }
907
+ }
908
+ };
909
+ }
910
+ function debugPropToDiagnosticsConfig(debug) {
911
+ if (debug === void 0) return {};
912
+ if (debug === true) return { console: "debug" };
913
+ if (debug === false) return { console: false };
914
+ if (typeof debug === "string") return { console: debug };
915
+ return debug;
916
+ }
917
+ function useAthenaDiagnostics() {
918
+ const snapshot = React.useSyncExternalStore(
919
+ athenaDiagnostics.subscribeSnapshot.bind(athenaDiagnostics),
920
+ athenaDiagnostics.snapshot.bind(athenaDiagnostics),
921
+ athenaDiagnostics.snapshot.bind(athenaDiagnostics)
922
+ );
923
+ const clear = React.useCallback(() => athenaDiagnostics.clear(), []);
924
+ const exportJson = React.useCallback(() => athenaDiagnostics.export(), []);
925
+ return { ...snapshot, clear, export: exportJson };
926
+ }
927
+ const DEEP_AGENT_RUNTIME_MARKER = "athena_deep_agent";
928
+ const STATEWIRE_START_CHANNEL = "web";
929
+ const STATEWIRE_RUN_LABEL = "Athena SDK";
930
+ const DEFAULT_STATEWIRE_MODEL = "claude-sonnet-5";
931
+ const COLLAB_AGENT_REF_PREFIX = "collab_agent:";
932
+ function parseCollabAgentRef(agent2) {
933
+ if (typeof agent2 !== "string" || !agent2.startsWith(COLLAB_AGENT_REF_PREFIX)) return null;
934
+ const assetId = agent2.slice(COLLAB_AGENT_REF_PREFIX.length).trim();
935
+ return assetId || null;
936
+ }
937
+ function buildStatewireRunConfig(options = {}) {
938
+ var _a3, _b2, _c2, _d2, _e2;
939
+ const collabAgentId = parseCollabAgentRef(options.agent);
940
+ const collabChannelId = collabAgentId && ((_a3 = options.channel) == null ? void 0 : _a3.trim()) ? options.channel.trim() : void 0;
941
+ const model = options.model ?? (collabAgentId ? void 0 : DEFAULT_STATEWIRE_MODEL);
942
+ const panelModel = model ?? DEFAULT_STATEWIRE_MODEL;
943
+ const enabledTools = Array.from(
944
+ /* @__PURE__ */ new Set([...options.tools ?? [], ...options.frontendToolIds ?? []])
945
+ );
946
+ const systemPrompt = ((_b2 = options.systemPrompt) == null ? void 0 : _b2.trim()) ?? "";
947
+ return {
948
+ custom: {
949
+ runtime: DEEP_AGENT_RUNTIME_MARKER,
950
+ // With a collab channel selected, omit the SDK's own 'web' stamp: the
951
+ // request's explicit start_channel would win over the backend overlay's
952
+ // kind-mapped provenance (a custom SMS channel must stamp 'sms').
953
+ ...collabChannelId ? {} : { start_channel: STATEWIRE_START_CHANNEL },
954
+ ...model ? { model } : {},
955
+ // An empty list is behavior-identical to an absent key for the parser
956
+ // (both coerce to []), but the collab-agent overlay merges request keys
957
+ // OVER the agent definition — so an explicit empty list would erase the
958
+ // agent's configured tools. Omit it when empty.
959
+ ...enabledTools.length > 0 ? { enabled_tools: enabledTools } : {},
960
+ panel_config: {
961
+ model: panelModel,
962
+ enabled_tools: enabledTools,
963
+ system_prompt: systemPrompt,
964
+ run_label: STATEWIRE_RUN_LABEL
965
+ },
966
+ ...collabAgentId ? { collab_agent_id: collabAgentId } : {},
967
+ ...collabChannelId ? { collab_channel_id: collabChannelId } : {},
968
+ ...systemPrompt ? { system_prompt: systemPrompt } : {},
969
+ ...((_c2 = options.workbench) == null ? void 0 : _c2.length) ? { workbench: options.workbench } : {},
970
+ ...((_d2 = options.knowledgeBase) == null ? void 0 : _d2.length) ? { knowledge_base: options.knowledgeBase } : {},
971
+ ...options.customToolConfigs ? { custom_tool_configs: options.customToolConfigs } : {},
972
+ ...options.appId ? { app_id: options.appId } : {},
973
+ ...((_e2 = options.clientTools) == null ? void 0 : _e2.length) ? { client_tools: options.clientTools } : {},
974
+ ...options.extraRunConfig ?? {}
975
+ }
976
+ };
977
+ }
74
978
  const ATHENA_ENVIRONMENT_URLS = {
75
979
  production: {
76
980
  apiUrl: "https://iris.prd.athenaintel.com/api/chat",
@@ -274,7 +1178,7 @@ const normalizeOrigin = (value) => {
274
1178
  return null;
275
1179
  }
276
1180
  };
277
- const getTokenRefreshDelay = (expiresAt, nowMs) => {
1181
+ const getTokenRefreshDelay = (expiresAt, nowMs2) => {
278
1182
  if (typeof expiresAt !== "string") {
279
1183
  return DEFAULT_TOKEN_REFRESH_MS;
280
1184
  }
@@ -282,7 +1186,7 @@ const getTokenRefreshDelay = (expiresAt, nowMs) => {
282
1186
  if (!Number.isFinite(expiresAtMs)) {
283
1187
  return DEFAULT_TOKEN_REFRESH_MS;
284
1188
  }
285
- return Math.max(TOKEN_REFRESH_RETRY_BASE_MS, expiresAtMs - nowMs - TOKEN_REFRESH_BUFFER_MS);
1189
+ return Math.max(TOKEN_REFRESH_RETRY_BASE_MS, expiresAtMs - nowMs2 - TOKEN_REFRESH_BUFFER_MS);
286
1190
  };
287
1191
  const getAuthRetryDelay = (retryAttempt) => {
288
1192
  const safeAttempt = Number.isFinite(retryAttempt) ? Math.max(0, Math.floor(retryAttempt)) : 0;
@@ -316,6 +1220,15 @@ function useParentBridge({
316
1220
  const configReceived = React.useRef(false);
317
1221
  React.useEffect(() => {
318
1222
  if (!isInIframe) return;
1223
+ const endBridgeSpan = athenaDiagnostics.span("auth.bridge", "auth.bridge.start", {
1224
+ mode: "iframe"
1225
+ });
1226
+ let spanEnded = false;
1227
+ const endOnce = (name, options) => {
1228
+ if (spanEnded) return 0;
1229
+ spanEnded = true;
1230
+ return endBridgeSpan(name, options);
1231
+ };
319
1232
  const handler = (event) => {
320
1233
  if (!isTrustedOrigin({ origin: event.origin, trustedOrigins: runtimeTrustedOrigins })) {
321
1234
  return;
@@ -334,6 +1247,11 @@ function useParentBridge({
334
1247
  }));
335
1248
  }
336
1249
  if (event.data.type === "athena-auth" && typeof event.data.token === "string") {
1250
+ endOnce("auth.bridge.ready", { data: { mode: "iframe" } });
1251
+ athenaDiagnostics.emit("auth.token.acquired", {
1252
+ level: "debug",
1253
+ data: { source: "iframe-postmessage" }
1254
+ });
337
1255
  setState((prev) => ({
338
1256
  ...prev,
339
1257
  token: event.data.token,
@@ -347,6 +1265,13 @@ function useParentBridge({
347
1265
  readySignalSent.current = true;
348
1266
  }
349
1267
  const timer = setTimeout(() => {
1268
+ endOnce("auth.bridge.timeout", {
1269
+ data: {
1270
+ mode: "iframe",
1271
+ timeout_ms: BRIDGE_TIMEOUT_MS,
1272
+ config_received: configReceived.current
1273
+ }
1274
+ });
350
1275
  setState((prev) => prev.ready ? prev : { ...prev, ready: true });
351
1276
  }, BRIDGE_TIMEOUT_MS);
352
1277
  return () => {
@@ -399,9 +1324,20 @@ function useParentBridge({
399
1324
  }) => {
400
1325
  controller == null ? void 0 : controller.abort();
401
1326
  controller = new AbortController();
1327
+ const isInitial = markReadyOnFailure;
1328
+ const rawEndSpan = isInitial ? athenaDiagnostics.span("auth.bridge", "auth.bridge.start", { mode: "marathon" }) : null;
1329
+ let spanEnded = false;
1330
+ const endBridgeSpan = rawEndSpan ? (name, options) => {
1331
+ if (spanEnded) return 0;
1332
+ spanEnded = true;
1333
+ return rawEndSpan(name, options);
1334
+ } : null;
402
1335
  clearRequestTimer();
403
1336
  requestTimer = setTimeout(() => {
404
1337
  controller == null ? void 0 : controller.abort();
1338
+ endBridgeSpan == null ? void 0 : endBridgeSpan("auth.bridge.timeout", {
1339
+ data: { mode: "marathon", timeout_ms: BRIDGE_TIMEOUT_MS }
1340
+ });
405
1341
  if (markReadyOnFailure) {
406
1342
  markReady();
407
1343
  }
@@ -415,17 +1351,43 @@ function useParentBridge({
415
1351
  if (cancelled) return;
416
1352
  if (!resp.ok) {
417
1353
  if (resp.status === 404) {
1354
+ endBridgeSpan == null ? void 0 : endBridgeSpan("auth.bridge.absent", {
1355
+ data: { mode: "marathon", status: resp.status }
1356
+ });
418
1357
  markReady();
419
- } else if (markReadyOnFailure) {
420
- markReady();
421
- scheduleRetry();
422
1358
  } else {
1359
+ const failure = {
1360
+ level: "warn",
1361
+ data: { mode: "marathon", status: resp.status }
1362
+ };
1363
+ if (endBridgeSpan) {
1364
+ endBridgeSpan("auth.bridge.error", failure);
1365
+ } else {
1366
+ athenaDiagnostics.emit("auth.token.refresh_failed", failure);
1367
+ }
1368
+ if (markReadyOnFailure) {
1369
+ markReady();
1370
+ }
423
1371
  scheduleRetry();
424
1372
  }
425
1373
  return;
426
1374
  }
427
1375
  const data = await resp.json();
428
1376
  if (cancelled) return;
1377
+ if (endBridgeSpan) {
1378
+ endBridgeSpan("auth.bridge.ready", {
1379
+ data: { mode: "marathon", has_token: typeof data.token === "string" }
1380
+ });
1381
+ athenaDiagnostics.emit("auth.token.acquired", {
1382
+ level: "debug",
1383
+ data: { source: "marathon", expires_at: data.expires_at }
1384
+ });
1385
+ } else {
1386
+ athenaDiagnostics.emit("auth.token.refreshed", {
1387
+ level: "debug",
1388
+ data: { source: "marathon", expires_at: data.expires_at }
1389
+ });
1390
+ }
429
1391
  setState({
430
1392
  token: typeof data.token === "string" ? data.token : null,
431
1393
  apiUrl: typeof data.apiUrl === "string" ? data.apiUrl : null,
@@ -434,7 +1396,15 @@ function useParentBridge({
434
1396
  ready: true
435
1397
  });
436
1398
  scheduleRefresh(data.expires_at);
437
- } catch {
1399
+ } catch (error2) {
1400
+ if (!cancelled && !(error2 instanceof DOMException && error2.name === "AbortError")) {
1401
+ const failure = { level: "warn", data: { mode: "marathon" }, error: error2 };
1402
+ if (endBridgeSpan) {
1403
+ endBridgeSpan("auth.bridge.error", failure);
1404
+ } else {
1405
+ athenaDiagnostics.emit("auth.token.refresh_failed", failure);
1406
+ }
1407
+ }
438
1408
  if (markReadyOnFailure) {
439
1409
  markReady();
440
1410
  }
@@ -9880,24 +10850,42 @@ function getAthenaApiBaseUrl(backendUrl) {
9880
10850
  return stripped;
9881
10851
  }
9882
10852
  async function listThreads(backendUrl, auth, opts = {}) {
10853
+ var _a3;
9883
10854
  const base2 = getAthenaApiBaseUrl(backendUrl);
9884
- const res = await fetch(`${base2}/api/conversations/threads/list`, {
9885
- method: "POST",
9886
- headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
9887
- body: JSON.stringify({
9888
- limit: opts.limit ?? 50,
9889
- offset: opts.offset ?? 0,
9890
- // Default to the full recent-conversations set unless a caller
9891
- // explicitly asks to hide triggered/background sessions.
9892
- exclude_triggered: opts.exclude_triggered ?? false,
9893
- ...opts.app_id ? { app_id: opts.app_id } : {},
9894
- ...opts.start_channel ? { start_channel: opts.start_channel } : {}
9895
- })
10855
+ const endSpan = athenaDiagnostics.span("threads.list", "threads.list.start", {
10856
+ auth_mode: getAuthMode(auth),
10857
+ app_id: opts.app_id
9896
10858
  });
9897
- if (!res.ok) {
9898
- throw new Error(`[AthenaSDK] Failed to list threads: ${res.status}`);
10859
+ try {
10860
+ const res = await fetch(`${base2}/api/conversations/threads/list`, {
10861
+ method: "POST",
10862
+ headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
10863
+ body: JSON.stringify({
10864
+ limit: opts.limit ?? 50,
10865
+ offset: opts.offset ?? 0,
10866
+ // Default to the full recent-conversations set unless a caller
10867
+ // explicitly asks to hide triggered/background sessions.
10868
+ exclude_triggered: opts.exclude_triggered ?? false,
10869
+ ...opts.app_id ? { app_id: opts.app_id } : {},
10870
+ ...opts.start_channel ? { start_channel: opts.start_channel } : {}
10871
+ })
10872
+ });
10873
+ if (!res.ok) {
10874
+ throw new AthenaSdkError({
10875
+ code: res.status === 401 || res.status === 403 ? "auth_rejected" : "threads_list_failed",
10876
+ message: `Failed to list threads: ${res.status}`,
10877
+ status: res.status,
10878
+ hint: res.status === 401 || res.status === 403 ? "The credential was refused. Check the token/API key and that the user belongs to the workspace." : "Check backendUrl points at the Agora API base.",
10879
+ context: { auth_mode: getAuthMode(auth) }
10880
+ });
10881
+ }
10882
+ const data = await res.json();
10883
+ endSpan("threads.list.done", { data: { count: ((_a3 = data.threads) == null ? void 0 : _a3.length) ?? 0 } });
10884
+ return data;
10885
+ } catch (error2) {
10886
+ endSpan("threads.list.error", { error: error2 });
10887
+ throw error2;
9899
10888
  }
9900
- return res.json();
9901
10889
  }
9902
10890
  async function setThreadReadState(backendUrl, auth, opts) {
9903
10891
  const base2 = getAthenaApiBaseUrl(backendUrl);
@@ -9958,31 +10946,49 @@ function getResponseErrorBody(response) {
9958
10946
  return response.text().catch(() => "");
9959
10947
  }
9960
10948
  async function getThreadState(backendUrl, auth, threadId) {
10949
+ var _a3, _b2, _c2, _d2;
9961
10950
  const base2 = getAthenaApiBaseUrl(backendUrl);
9962
10951
  const authMode = getAuthMode(auth);
9963
10952
  const endpoint = `${base2}/api/conversations/threads/get`;
9964
- console.info("[AthenaSDK] Loading thread state from conversations API:", {
9965
- threadId,
9966
- endpoint,
9967
- authMode,
9968
- hasToken: Boolean(auth.token),
9969
- hasApiKey: Boolean(auth.apiKey)
9970
- });
9971
- const res = await fetch(endpoint, {
9972
- method: "POST",
9973
- headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
9974
- body: JSON.stringify({
9975
- thread_id: threadId,
9976
- skip_cache: true
9977
- })
10953
+ const endSpan = athenaDiagnostics.span("threads.history", "threads.history.start", {
10954
+ thread_id: threadId,
10955
+ auth_mode: authMode
9978
10956
  });
10957
+ let res;
10958
+ try {
10959
+ res = await fetch(endpoint, {
10960
+ method: "POST",
10961
+ headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
10962
+ body: JSON.stringify({
10963
+ thread_id: threadId,
10964
+ skip_cache: true
10965
+ })
10966
+ });
10967
+ } catch (error2) {
10968
+ endSpan("threads.history.error", { error: error2, data: { thread_id: threadId } });
10969
+ throw error2;
10970
+ }
9979
10971
  if (!res.ok) {
9980
10972
  const body = await getResponseErrorBody(res);
9981
- throw new Error(
9982
- `[AthenaSDK] Failed to get thread state: ${res.status} (${authMode})${body ? `: ${body.slice(0, 300)}` : ""}`
9983
- );
10973
+ const error2 = new AthenaSdkError({
10974
+ code: res.status === 401 || res.status === 403 ? "auth_rejected" : "thread_load_failed",
10975
+ message: `Failed to get thread state: ${res.status} (${authMode})${body ? `: ${body.slice(0, 300)}` : ""}`,
10976
+ status: res.status,
10977
+ hint: "A brand-new thread may not be persisted yet; anything else means the credential or backendUrl is wrong.",
10978
+ context: { thread_id: threadId, auth_mode: authMode }
10979
+ });
10980
+ endSpan("threads.history.error", { error: error2, data: { thread_id: threadId } });
10981
+ throw error2;
9984
10982
  }
9985
10983
  const data = await res.json();
10984
+ const channelMessages = (_b2 = (_a3 = data.thread) == null ? void 0 : _a3.channel_values) == null ? void 0 : _b2.messages;
10985
+ endSpan("threads.history.done", {
10986
+ data: {
10987
+ thread_id: threadId,
10988
+ found: data.thread_found !== false,
10989
+ message_count: Array.isArray(channelMessages) ? channelMessages.length : ((_d2 = (_c2 = data.thread) == null ? void 0 : _c2.messages) == null ? void 0 : _d2.length) ?? 0
10990
+ }
10991
+ });
9986
10992
  const thread = data.thread;
9987
10993
  if (data.thread_found === false || !thread) {
9988
10994
  return {
@@ -10264,17 +11270,35 @@ const useAthenaRuntime = (config2) => {
10264
11270
  };
10265
11271
  },
10266
11272
  onResponse: () => {
11273
+ athenaDiagnostics.emit("stream.connected", {
11274
+ level: "debug",
11275
+ data: { transport: "legacy", thread_id: threadIdRef.current }
11276
+ });
10267
11277
  if (IS_DEV) {
10268
11278
  console.log("[AthenaSDK] Stream connected");
10269
11279
  }
10270
11280
  },
10271
11281
  onFinish: () => {
11282
+ athenaDiagnostics.emit("run.done", {
11283
+ level: "debug",
11284
+ data: { transport: "legacy", thread_id: threadIdRef.current }
11285
+ });
10272
11286
  if (IS_DEV) {
10273
11287
  console.log("[AthenaSDK] Stream completed");
10274
11288
  }
10275
11289
  },
10276
11290
  onError: (error2, { commands: commands2, updateState }) => {
10277
11291
  var _a3;
11292
+ athenaDiagnostics.error(
11293
+ "stream.error",
11294
+ error2,
11295
+ {
11296
+ code: /\b401\b|unauthori[sz]ed/i.test(error2.message) ? "auth_rejected" : "stream_failed",
11297
+ message: error2.message || "The chat stream failed",
11298
+ hint: "Check the Iris apiUrl and the credential; the raw error is in `cause`."
11299
+ },
11300
+ { transport: "legacy", thread_id: threadIdRef.current }
11301
+ );
10278
11302
  const pendingCommands = commandsToMessages(commands2);
10279
11303
  const isInvalidStringLength = error2 instanceof RangeError && /Invalid string length/i.test(error2.message);
10280
11304
  const userErrorMessage = isInvalidStringLength ? "The response was too large to process. Try reducing the amount of content in a single request or starting a new chat." : error2.message;
@@ -10396,33 +11420,21 @@ const useAthenaRuntime = (config2) => {
10396
11420
  if (isExistingThread && !hasResumedRef.current) {
10397
11421
  hasResumedRef.current = true;
10398
11422
  (async () => {
10399
- var _a3, _b2;
11423
+ var _a3;
10400
11424
  const currentToken = getTokenRef.current ? await getTokenRef.current() ?? tokenRef.current : tokenRef.current;
10401
11425
  const auth = { apiKey: apiKeyRef.current, token: currentToken };
10402
- console.log("[AthenaSDK] Loading existing thread state:", {
10403
- threadId,
10404
- backendUrl
10405
- });
10406
11426
  try {
10407
11427
  const state = await getThreadState(backendUrl, auth, threadId);
10408
- const messageCount = ((_a3 = state == null ? void 0 : state.messages) == null ? void 0 : _a3.length) ?? 0;
10409
- console.log("[AthenaSDK] Got thread state:", {
10410
- threadId,
10411
- messageCount,
10412
- hasMessages: messageCount > 0
10413
- });
10414
11428
  runtime.thread.importExternalState({
10415
11429
  ...state
10416
11430
  });
10417
- console.log(
10418
- "[AthenaSDK] importExternalState completed, runtime messages:",
10419
- runtime.thread.getState().messages.length
10420
- );
10421
11431
  } catch (err) {
10422
- console.warn(
10423
- "[AthenaSDK] Failed to load thread state (may be a new streaming thread):",
10424
- err
10425
- );
11432
+ if (IS_DEV) {
11433
+ console.warn(
11434
+ "[AthenaSDK] Failed to load thread state (may be a new streaming thread):",
11435
+ err
11436
+ );
11437
+ }
10426
11438
  }
10427
11439
  try {
10428
11440
  const statusRes = await fetch(resolvedStatusApiUrl, {
@@ -10434,7 +11446,7 @@ const useAthenaRuntime = (config2) => {
10434
11446
  const status = await statusRes.json();
10435
11447
  if (status.isRunning) {
10436
11448
  try {
10437
- const lastMessageId = ((_b2 = runtime.thread.getState().messages.at(-1)) == null ? void 0 : _b2.id) ?? null;
11449
+ const lastMessageId = ((_a3 = runtime.thread.getState().messages.at(-1)) == null ? void 0 : _a3.id) ?? null;
10438
11450
  runtime.thread.resumeRun({ parentId: lastMessageId });
10439
11451
  } catch (resumeErr) {
10440
11452
  if (IS_DEV) {
@@ -10582,6 +11594,7 @@ function projectDeepAgentConnection(connection) {
10582
11594
  return {
10583
11595
  status: connection.status,
10584
11596
  cause: connection.cause,
11597
+ attempt: connection.attempt,
10585
11598
  ...message !== void 0 && { message }
10586
11599
  };
10587
11600
  }
@@ -10757,6 +11770,22 @@ function liftAopSourceIntoMetadata(message) {
10757
11770
  }
10758
11771
  };
10759
11772
  }
11773
+ function liftBranchIntoMetadata(message) {
11774
+ if (message.type !== "human" && message.type !== "ai") return message;
11775
+ const branch = message.branch;
11776
+ if (typeof branch !== "object" || branch === null || Array.isArray(branch)) return message;
11777
+ const kwargs = message.additional_kwargs;
11778
+ const existingMetadata = kwargs == null ? void 0 : kwargs.metadata;
11779
+ const metadata = typeof existingMetadata === "object" && existingMetadata !== null ? existingMetadata : {};
11780
+ if (typeof metadata.branch === "object" && metadata.branch !== null) return message;
11781
+ return {
11782
+ ...message,
11783
+ additional_kwargs: {
11784
+ ...kwargs,
11785
+ metadata: { ...metadata, branch }
11786
+ }
11787
+ };
11788
+ }
10760
11789
  const TOOL_MESSAGE_INTERNAL_KWARGS = /* @__PURE__ */ new Set([
10761
11790
  "reasoning",
10762
11791
  "tool_outputs",
@@ -10809,11 +11838,13 @@ function isConvertibleChatMessage(message) {
10809
11838
  }
10810
11839
  function sanitizeLangChainMessages(messages) {
10811
11840
  return messages.filter((message) => isConvertibleChatMessage(message) && !isMessageHiddenFromFrontend(message)).map(
10812
- (message) => liftToolMessageMetadataIntoArtifact(
10813
- liftAopSourceIntoMetadata(
10814
- liftCompactionBoundaryIntoMetadata(
10815
- liftConversationStatsIntoMetadata(
10816
- liftModelIntoMetadata(liftRunMarkerIntoMetadata(message))
11841
+ (message) => liftBranchIntoMetadata(
11842
+ liftToolMessageMetadataIntoArtifact(
11843
+ liftAopSourceIntoMetadata(
11844
+ liftCompactionBoundaryIntoMetadata(
11845
+ liftConversationStatsIntoMetadata(
11846
+ liftModelIntoMetadata(liftRunMarkerIntoMetadata(message))
11847
+ )
10817
11848
  )
10818
11849
  )
10819
11850
  )
@@ -10846,14 +11877,15 @@ function registerDeepAgentRunConfig(aui, getRunConfig) {
10846
11877
  })
10847
11878
  });
10848
11879
  }
10849
- function deepAgentThreadStatus(state) {
10850
- var _a3;
10851
- const runs = state == null ? void 0 : state.runs;
10852
- if (runs === void 0) return "loading";
10853
- return ((_a3 = runs[0]) == null ? void 0 : _a3.status) ?? "ready";
10854
- }
10855
11880
  function useDeepAgentThreadStatus() {
10856
- return reactStatewire.useStatewireState(deepAgentThreadStatus);
11881
+ return store.useAuiState((s) => {
11882
+ var _a3;
11883
+ const status = (_a3 = s.thread.extras) == null ? void 0 : _a3.status;
11884
+ if (status === void 0) {
11885
+ throw new Error("useDeepAgentThreadStatus requires a statewire thread");
11886
+ }
11887
+ return status;
11888
+ });
10857
11889
  }
10858
11890
  function shouldNotifyRunningChange(previous, next) {
10859
11891
  if (previous === null) return next.isRunning;
@@ -11074,7 +12106,7 @@ function useDeepAgentThread({
11074
12106
  }
11075
12107
  const connection = projectDeepAgentConnection(meta.connection);
11076
12108
  const previous = lastConnectionRef.current;
11077
- if ((previous == null ? void 0 : previous.threadId) !== attachId || previous.connection.status !== connection.status || previous.connection.cause !== connection.cause || previous.connection.message !== connection.message) {
12109
+ if ((previous == null ? void 0 : previous.threadId) !== attachId || previous.connection.status !== connection.status || previous.connection.cause !== connection.cause || previous.connection.message !== connection.message || previous.connection.attempt !== connection.attempt) {
11078
12110
  const update = { threadId: attachId, connection };
11079
12111
  lastConnectionRef.current = update;
11080
12112
  queueMicrotask(() => {
@@ -11146,46 +12178,30 @@ function toJSONSchema(schema2) {
11146
12178
  if (isStandardSchema(schema2)) throw new Error("Could not convert schema to JSON Schema. The schema implements Standard Schema but does not support JSON Schema conversion. If you are using Zod, please upgrade to Zod v4 (npm install zod@latest). Alternatively, pass a plain JSON Schema object instead.");
11147
12179
  return schema2;
11148
12180
  }
11149
- function defaultToolFilter(_name, tool) {
11150
- return !tool.disabled && tool.type !== "backend" && (tool.type !== "frontend" || tool.execute !== void 0);
11151
- }
11152
- function toolHasUploadableParameters(tool) {
11153
- var _a3;
11154
- return tool.parameters !== void 0 && !((_a3 = tool.unstable_backendDefault) == null ? void 0 : _a3.parameters);
11155
- }
11156
- function toToolsJSONSchema(tools, options = {}) {
11157
- if (!tools) return {};
11158
- const filter = options.filter ?? defaultToolFilter;
11159
- return Object.fromEntries(Object.entries(tools).filter(([name, tool]) => filter(name, tool)).filter((entry) => toolHasUploadableParameters(entry[1])).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, tool]) => [name, {
11160
- ...tool.description && { description: tool.description },
11161
- parameters: toJSONSchema(tool.parameters),
11162
- ...tool.providerOptions && { providerOptions: tool.providerOptions }
11163
- }]));
11164
- }
11165
12181
  function hasCallableExecute(entry) {
11166
12182
  return !!entry && typeof entry === "object" && typeof entry.execute === "function";
11167
12183
  }
11168
12184
  function collectStatewireClientTools(toolkit) {
11169
12185
  const executable = Object.entries(toolkit).filter(([, entry]) => hasCallableExecute(entry));
11170
12186
  if (executable.length === 0) return [];
11171
- let schemas;
11172
- try {
11173
- schemas = toToolsJSONSchema(toolkit, {
11174
- filter: (name) => executable.some(([toolName]) => toolName === name)
11175
- });
11176
- } catch (error2) {
11177
- console.warn("[AthenaSDK] failed to convert frontend tool schemas for statewire:", error2);
11178
- return [];
11179
- }
11180
12187
  return executable.flatMap(([name, entry]) => {
11181
- const schema2 = schemas[name];
11182
- if (!schema2) return [];
12188
+ if (entry.parameters === void 0) return [];
12189
+ let parameters;
12190
+ try {
12191
+ parameters = toJSONSchema(entry.parameters);
12192
+ } catch (error2) {
12193
+ console.warn(
12194
+ `[AthenaSDK] failed to convert frontend tool schema for statewire (${name}):`,
12195
+ error2
12196
+ );
12197
+ return [];
12198
+ }
11183
12199
  const execute = entry.execute;
11184
12200
  return [
11185
12201
  {
11186
12202
  name,
11187
- description: schema2.description,
11188
- parameters: schema2.parameters ?? { type: "object" },
12203
+ description: entry.description,
12204
+ parameters,
11189
12205
  handler: async (args, { toolCallId }) => {
11190
12206
  const controller = new AbortController();
11191
12207
  const output = await execute(args, {
@@ -11209,39 +12225,6 @@ function statewireClientToolWireEntries(tools) {
11209
12225
  requires_write: false
11210
12226
  }));
11211
12227
  }
11212
- const DEEP_AGENT_RUNTIME_MARKER = "athena_deep_agent";
11213
- const STATEWIRE_START_CHANNEL = "web";
11214
- const STATEWIRE_RUN_LABEL = "Athena SDK";
11215
- const DEFAULT_STATEWIRE_MODEL = "claude-sonnet-5";
11216
- function buildStatewireRunConfig(options = {}) {
11217
- var _a3, _b2, _c2, _d2;
11218
- const model = options.model ?? DEFAULT_STATEWIRE_MODEL;
11219
- const enabledTools = Array.from(
11220
- /* @__PURE__ */ new Set([...options.tools ?? [], ...options.frontendToolIds ?? []])
11221
- );
11222
- const systemPrompt = ((_a3 = options.systemPrompt) == null ? void 0 : _a3.trim()) ?? "";
11223
- return {
11224
- custom: {
11225
- runtime: DEEP_AGENT_RUNTIME_MARKER,
11226
- start_channel: STATEWIRE_START_CHANNEL,
11227
- model,
11228
- enabled_tools: enabledTools,
11229
- panel_config: {
11230
- model,
11231
- enabled_tools: enabledTools,
11232
- system_prompt: systemPrompt,
11233
- run_label: STATEWIRE_RUN_LABEL
11234
- },
11235
- ...systemPrompt ? { system_prompt: systemPrompt } : {},
11236
- ...((_b2 = options.workbench) == null ? void 0 : _b2.length) ? { workbench: options.workbench } : {},
11237
- ...((_c2 = options.knowledgeBase) == null ? void 0 : _c2.length) ? { knowledge_base: options.knowledgeBase } : {},
11238
- ...options.customToolConfigs ? { custom_tool_configs: options.customToolConfigs } : {},
11239
- ...options.appId ? { app_id: options.appId } : {},
11240
- ...((_d2 = options.clientTools) == null ? void 0 : _d2.length) ? { client_tools: options.clientTools } : {},
11241
- ...options.extraRunConfig ?? {}
11242
- }
11243
- };
11244
- }
11245
12228
  const EMPTY_TOOLKIT = {};
11246
12229
  const EMPTY_TOOL_IDS = [];
11247
12230
  function useStatewireClientTools(frontendToolkit) {
@@ -11259,6 +12242,8 @@ function useAthenaStatewireRuntime(config2) {
11259
12242
  token,
11260
12243
  getToken,
11261
12244
  model,
12245
+ agent: agent2,
12246
+ channel,
11262
12247
  tools = EMPTY_TOOL_IDS,
11263
12248
  frontendToolIds = EMPTY_TOOL_IDS,
11264
12249
  frontendToolkit = EMPTY_TOOLKIT,
@@ -11286,6 +12271,28 @@ function useAthenaStatewireRuntime(config2) {
11286
12271
  const clientToolsRef = React.useRef(clientTools);
11287
12272
  clientToolsRef.current = clientTools;
11288
12273
  const [canPersistSession] = React.useState(() => typeof localStorage !== "undefined");
12274
+ React.useEffect(() => {
12275
+ if (agent2 && !parseCollabAgentRef(agent2)) {
12276
+ athenaDiagnostics.emit("sdk.config.warning", {
12277
+ level: "warn",
12278
+ data: {
12279
+ prop: "agent",
12280
+ value: agent2,
12281
+ reason: "the statewire transport always runs the Athena deep agent; only 'collab_agent:<asset_id>' refs apply. Use transport='legacy' for named agents."
12282
+ }
12283
+ });
12284
+ }
12285
+ }, [agent2]);
12286
+ const attachSpanRef = React.useRef(null);
12287
+ const attachThreadRef = React.useRef(null);
12288
+ if (attachThreadRef.current !== threadId) {
12289
+ attachThreadRef.current = threadId;
12290
+ attachSpanRef.current = athenaDiagnostics.span(
12291
+ `statewire.attach:${threadId}`,
12292
+ "statewire.attach.start",
12293
+ { thread_id: threadId, is_new_chat: isNewChat }
12294
+ );
12295
+ }
11289
12296
  const thread = useDeepAgentThread({
11290
12297
  threadId,
11291
12298
  baseUrl: syncUrl,
@@ -11315,11 +12322,47 @@ function useAthenaStatewireRuntime(config2) {
11315
12322
  }
11316
12323
  },
11317
12324
  capabilities: { edit: true, reload: true, continue: true },
11318
- onConnectionChange,
12325
+ onStateChange: () => {
12326
+ const endSpan = attachSpanRef.current;
12327
+ if (endSpan) {
12328
+ attachSpanRef.current = null;
12329
+ endSpan("statewire.snapshot", { data: { thread_id: threadId } });
12330
+ }
12331
+ },
12332
+ onConnectionChange: (connection) => {
12333
+ athenaDiagnostics.gauge("statewire.connection", (connection == null ? void 0 : connection.status) ?? null);
12334
+ if ((connection == null ? void 0 : connection.status) === "gone") {
12335
+ athenaDiagnostics.emit("statewire.connection", {
12336
+ level: "warn",
12337
+ data: { status: connection.status, message: connection.message }
12338
+ });
12339
+ }
12340
+ onConnectionChange == null ? void 0 : onConnectionChange(connection);
12341
+ },
11319
12342
  onRawConnectionChange,
11320
- onLegacyReadOnly,
12343
+ onLegacyReadOnly: (legacyReadOnly) => {
12344
+ if (legacyReadOnly) {
12345
+ athenaDiagnostics.emit("statewire.read_only", {
12346
+ level: "warn",
12347
+ data: { thread_id: threadId }
12348
+ });
12349
+ }
12350
+ onLegacyReadOnly == null ? void 0 : onLegacyReadOnly(legacyReadOnly);
12351
+ },
11321
12352
  onRunningChange,
11322
12353
  onError: (error2) => {
12354
+ if (!isStatewireChannelTeardown(error2)) {
12355
+ athenaDiagnostics.error(
12356
+ "statewire.error",
12357
+ error2,
12358
+ {
12359
+ code: "statewire_rejected",
12360
+ message: "The statewire host rejected a command",
12361
+ hint: "Inspect error.detail — agora rejections carry a structured {code, message}."
12362
+ },
12363
+ { thread_id: threadId }
12364
+ );
12365
+ }
11323
12366
  if (onErrorRef.current) {
11324
12367
  onErrorRef.current(error2);
11325
12368
  return;
@@ -11335,6 +12378,8 @@ function useAthenaStatewireRuntime(config2) {
11335
12378
  const aui = react$1.useAui({ thread, tools: auiTools });
11336
12379
  const runConfigInputsRef = React.useRef({
11337
12380
  model,
12381
+ agent: agent2,
12382
+ channel,
11338
12383
  tools,
11339
12384
  frontendToolIds,
11340
12385
  workbench,
@@ -11346,6 +12391,8 @@ function useAthenaStatewireRuntime(config2) {
11346
12391
  });
11347
12392
  runConfigInputsRef.current = {
11348
12393
  model,
12394
+ agent: agent2,
12395
+ channel,
11349
12396
  tools,
11350
12397
  frontendToolIds,
11351
12398
  workbench,
@@ -11393,7 +12440,9 @@ function athenaStatewireErrorNotice(error2) {
11393
12440
  return {
11394
12441
  kind: "command",
11395
12442
  title: "Message was not sent",
11396
- message: error2 instanceof Error && error2.message.length > 0 ? error2.message : "The chat runtime rejected the command. Please try again."
12443
+ // The server's own detail names the actionable reason; the Error message is
12444
+ // generic client-side text like `command rejected (500)`.
12445
+ message: readDetailMessage(rejection == null ? void 0 : rejection.detail) ?? (error2 instanceof Error && error2.message.length > 0 ? error2.message : "The chat runtime rejected the command. Please try again.")
11397
12446
  };
11398
12447
  }
11399
12448
  const AthenaStatewireLifecycleContext = React.createContext(null);
@@ -11421,6 +12470,20 @@ function StatewireClientToolBridge({
11421
12470
  const toolsRef = React.useRef(tools);
11422
12471
  toolsRef.current = tools;
11423
12472
  const pendingRequest = inputRequests == null ? void 0 : inputRequests.find(isPendingClientToolRequest);
12473
+ const ownedClaimsRef = React.useRef(/* @__PURE__ */ new Set());
12474
+ const activeRef = React.useRef(true);
12475
+ const releaseClaim = React.useCallback((claim) => {
12476
+ ownedClaimsRef.current.delete(claim);
12477
+ clientToolRequests.release(claim);
12478
+ }, []);
12479
+ React.useEffect(() => {
12480
+ activeRef.current = true;
12481
+ return () => {
12482
+ activeRef.current = false;
12483
+ for (const claim of ownedClaimsRef.current) clientToolRequests.release(claim);
12484
+ ownedClaimsRef.current.clear();
12485
+ };
12486
+ }, []);
11424
12487
  const liveRequestIdsRef = React.useRef(/* @__PURE__ */ new Set());
11425
12488
  liveRequestIdsRef.current = new Set((inputRequests ?? []).map((request) => request.id));
11426
12489
  const executeRequest = React.useCallback(
@@ -11431,8 +12494,8 @@ function StatewireClientToolBridge({
11431
12494
  const registry2 = new Map(toolsRef.current.map((tool) => [tool.name, tool]));
11432
12495
  const results = {};
11433
12496
  for (const call of calls) {
11434
- if (!liveRequestIdsRef.current.has(request.id)) {
11435
- clientToolRequests.release(requestKey(threadId, request.id));
12497
+ if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12498
+ releaseClaim(requestKey(threadId, request.id));
11436
12499
  return;
11437
12500
  }
11438
12501
  const tool = registry2.get(call.tool_name);
@@ -11454,8 +12517,8 @@ function StatewireClientToolBridge({
11454
12517
  results[call.interrupt_id] = clientToolErrorEnvelope(error2);
11455
12518
  }
11456
12519
  }
11457
- if (!liveRequestIdsRef.current.has(request.id)) {
11458
- clientToolRequests.release(requestKey(threadId, request.id));
12520
+ if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12521
+ releaseClaim(requestKey(threadId, request.id));
11459
12522
  return;
11460
12523
  }
11461
12524
  try {
@@ -11465,16 +12528,19 @@ function StatewireClientToolBridge({
11465
12528
  requestId: request.id,
11466
12529
  response: { type: "resume", value: wireValue }
11467
12530
  });
12531
+ ownedClaimsRef.current.delete(requestKey(threadId, request.id));
11468
12532
  } catch (error2) {
11469
- clientToolRequests.release(requestKey(threadId, request.id));
12533
+ releaseClaim(requestKey(threadId, request.id));
11470
12534
  console.error("[AthenaSDK] failed to resume client tool results:", error2);
11471
12535
  }
11472
12536
  },
11473
- [sendCommand, threadId]
12537
+ [releaseClaim, sendCommand, threadId]
11474
12538
  );
11475
12539
  React.useEffect(() => {
11476
12540
  if (!pendingRequest) return;
11477
- if (!clientToolRequests.claim(requestKey(threadId, pendingRequest.id))) return;
12541
+ const claim = requestKey(threadId, pendingRequest.id);
12542
+ if (!clientToolRequests.claim(claim)) return;
12543
+ ownedClaimsRef.current.add(claim);
11478
12544
  void executeRequest(pendingRequest);
11479
12545
  }, [executeRequest, pendingRequest, threadId]);
11480
12546
  return null;
@@ -11489,6 +12555,9 @@ function resolveAthenaTransport({
11489
12555
  }) {
11490
12556
  return { transport: transport ?? DEFAULT_ATHENA_TRANSPORT, fallbackReason: null };
11491
12557
  }
12558
+ function allowsMidRunSend(transport) {
12559
+ return transport === ATHENA_TRANSPORTS.statewire;
12560
+ }
11492
12561
  var __defProp$i = Object.defineProperty;
11493
12562
  var __name$h = (target, value) => __defProp$i(target, "name", { value, configurable: true });
11494
12563
  function setRef$1(ref, value) {
@@ -15892,11 +16961,11 @@ const pickNumber = (...candidates) => {
15892
16961
  return void 0;
15893
16962
  };
15894
16963
  const autoOpen = (assetId, options = {}) => {
15895
- const store = useAssetPanelStore.getState();
15896
- if (!store.markAutoOpened(assetId)) return;
15897
- const existing = store.tabs.find((tab) => tab.id === assetId);
16964
+ const store2 = useAssetPanelStore.getState();
16965
+ if (!store2.markAutoOpened(assetId)) return;
16966
+ const existing = store2.tabs.find((tab) => tab.id === assetId);
15898
16967
  const keepCurrentSlide = options.preserveExistingSlide && existing;
15899
- store.openAsset(assetId, {
16968
+ store2.openAsset(assetId, {
15900
16969
  type: options.type ?? "unknown",
15901
16970
  ...keepCurrentSlide || options.slideNumber === void 0 ? {} : { slideNumber: options.slideNumber }
15902
16971
  });
@@ -18824,16 +19893,19 @@ function StatewireThreadListState({
18824
19893
  initialThreadId,
18825
19894
  children
18826
19895
  }) {
19896
+ var _a3;
18827
19897
  const [active, setActive] = React.useState(
18828
19898
  () => initialThreadId ? { id: initialThreadId, isNew: false } : { id: mintThreadId(), isNew: true }
18829
19899
  );
18830
19900
  const tokenRef = React.useRef(token);
18831
19901
  tokenRef.current = token;
19902
+ const authContext = React.useContext(AthenaAuthContext.AthenaAuthContext);
19903
+ const principal = ((_a3 = authContext == null ? void 0 : authContext.user) == null ? void 0 : _a3.userId) ?? "";
18832
19904
  const hasAuth = !!(apiKey || token);
18833
19905
  const { data, isLoading, refetch } = useQuery({
18834
- // Keyed on the user identity surface, not the raw token — token rotation
18835
- // for the same session must not refetch the whole list.
18836
- queryKey: [THREADS_QUERY_KEY, backendUrl, appId ?? "", apiKey ?? "", hasAuth],
19906
+ queryKey: [THREADS_QUERY_KEY, backendUrl, appId ?? "", principal, hasAuth],
19907
+ // Never serve another principal's list while the new one loads.
19908
+ placeholderData: void 0,
18837
19909
  queryFn: async () => {
18838
19910
  const { threads } = await listThreads(
18839
19911
  backendUrl,
@@ -18851,6 +19923,7 @@ function StatewireThreadListState({
18851
19923
  void refetch();
18852
19924
  }, [refetch]);
18853
19925
  const selectThread = React.useCallback((threadId) => {
19926
+ if (!threadId) return;
18854
19927
  setActive(
18855
19928
  (current) => current.id === threadId ? current : { id: threadId, isNew: false }
18856
19929
  );
@@ -18858,6 +19931,12 @@ function StatewireThreadListState({
18858
19931
  const newThread = React.useCallback(() => {
18859
19932
  setActive({ id: mintThreadId(), isNew: true });
18860
19933
  }, []);
19934
+ const isPersisted = !!(data == null ? void 0 : data.some((thread) => thread.id === active.id));
19935
+ React.useEffect(() => {
19936
+ if (isPersisted) {
19937
+ setActive((current) => current.isNew ? { ...current, isNew: false } : current);
19938
+ }
19939
+ }, [isPersisted]);
18861
19940
  const value = React.useMemo(
18862
19941
  () => ({
18863
19942
  threads: data ?? [],
@@ -19027,8 +20106,6 @@ function useAthenaThreadManager() {
19027
20106
  const statewireManager = React.useMemo(() => {
19028
20107
  if (!statewireList) return null;
19029
20108
  return {
19030
- // A never-started local chat stays out of the URL, mirroring the
19031
- // legacy manager's local-placeholder handling.
19032
20109
  activeThreadId: statewireList.isNewChat ? null : statewireList.activeThreadId,
19033
20110
  isListLoading: statewireList.isLoading,
19034
20111
  isThreadLoading: statewireIsThreadLoading,
@@ -19310,452 +20387,6 @@ const themes = {
19310
20387
  radius: "0.625rem"
19311
20388
  }
19312
20389
  };
19313
- const DEFAULT_CAPTURE_GATE_CONFIG = {
19314
- globalMaxPerWindow: 50,
19315
- globalWindowMs: 1e4,
19316
- criticalReservePerWindow: 15,
19317
- defaultEventMaxPerWindow: 12,
19318
- defaultEventWindowMs: 6e4,
19319
- defaultDedupeWindowMs: 5e3,
19320
- flushIntervalMs: 3e4,
19321
- flushCoalesceThreshold: 20,
19322
- eventOverrides: {
19323
- memory_profile_sample: { maxPerWindow: 2, windowMs: 3e4, dedupeWindowMs: 15e3 },
19324
- long_task_detected: { maxPerWindow: 3, windowMs: 6e4, dedupeWindowMs: 1e4 },
19325
- collab_connection_status_changed: { maxPerWindow: 6, windowMs: 6e4 },
19326
- collab_first_remote_update: { maxPerWindow: 3, windowMs: 6e4 },
19327
- collab_first_local_update: { maxPerWindow: 3, windowMs: 6e4 },
19328
- collab_render_time_sync_fix: { maxPerWindow: 3, windowMs: 6e4 },
19329
- collab_visibility_recovery: { maxPerWindow: 4, windowMs: 6e4 },
19330
- langgraph_message_validation_error: {
19331
- maxPerWindow: 8,
19332
- windowMs: 6e4,
19333
- dedupeWindowMs: 15e3
19334
- },
19335
- langgraph_messages_validation_error: {
19336
- maxPerWindow: 5,
19337
- windowMs: 6e4,
19338
- dedupeWindowMs: 15e3
19339
- },
19340
- langgraph_interrupt_validation_error: {
19341
- maxPerWindow: 5,
19342
- windowMs: 6e4,
19343
- dedupeWindowMs: 15e3
19344
- },
19345
- langgraph_state_validation_error: {
19346
- maxPerWindow: 5,
19347
- windowMs: 6e4,
19348
- dedupeWindowMs: 15e3
19349
- },
19350
- graphql_error: { maxPerWindow: 12, windowMs: 6e4, dedupeWindowMs: 1e4 },
19351
- chat_error: { maxPerWindow: 8, windowMs: 6e4, dedupeWindowMs: 5e3 },
19352
- memory_critical_threshold: { maxPerWindow: 3, windowMs: 3e5 },
19353
- memory_warning_threshold: { maxPerWindow: 3, windowMs: 3e5 },
19354
- pptx_slide_changed: { maxPerWindow: 8, windowMs: 3e4 }
19355
- }
19356
- };
19357
- const CRITICAL_EVENT_PATTERNS = [
19358
- /(?:^|_)failed$/,
19359
- /(?:^|_)error(?:_|$)/,
19360
- /crash/,
19361
- /^oom_/,
19362
- /aw_snap/,
19363
- /chunk_load/,
19364
- /global_error/,
19365
- /\$exception$/,
19366
- /^404_error$/,
19367
- /^500_error$/,
19368
- /_boundary_/
19369
- ];
19370
- const BYPASS_OPTION_KEY = "__posthog_gate_bypass";
19371
- function isCriticalPosthogEvent(event) {
19372
- return CRITICAL_EVENT_PATTERNS.some((pattern) => pattern.test(event));
19373
- }
19374
- function shouldBypassCaptureGate(options) {
19375
- if (!options || typeof options !== "object") return false;
19376
- return options[BYPASS_OPTION_KEY] === true;
19377
- }
19378
- function withCaptureGateBypass(options) {
19379
- return {
19380
- ...options ?? {},
19381
- [BYPASS_OPTION_KEY]: true
19382
- };
19383
- }
19384
- function pruneWindow(window2, now, windowMs) {
19385
- const cutoff = now - windowMs;
19386
- while (window2.timestamps.length > 0 && window2.timestamps[0] < cutoff) {
19387
- window2.timestamps.shift();
19388
- }
19389
- }
19390
- function countInWindow(window2, now, windowMs) {
19391
- pruneWindow(window2, now, windowMs);
19392
- return window2.timestamps.length;
19393
- }
19394
- function recordInWindow(window2, now) {
19395
- window2.timestamps.push(now);
19396
- }
19397
- function stableStringify(value) {
19398
- if (value == null) return String(value);
19399
- if (typeof value !== "object") return String(value);
19400
- if (Array.isArray(value)) {
19401
- return `[${value.map((item) => stableStringify(item)).join(",")}]`;
19402
- }
19403
- const record2 = value;
19404
- const keys2 = Object.keys(record2).sort();
19405
- return `{${keys2.map((key) => `${key}:${stableStringify(record2[key])}`).join(",")}}`;
19406
- }
19407
- function fingerprintProperties(properties) {
19408
- if (!properties) return "";
19409
- const keys2 = [
19410
- "error",
19411
- "error_message",
19412
- "message",
19413
- "reason",
19414
- "status",
19415
- "code",
19416
- "asset_id",
19417
- "doc_id",
19418
- "thread_id",
19419
- "session_id",
19420
- "operation",
19421
- "path",
19422
- "url",
19423
- "chunk_identifier",
19424
- "validation_path"
19425
- ];
19426
- const subset = {};
19427
- for (const key of keys2) {
19428
- if (key in properties) {
19429
- subset[key] = properties[key];
19430
- }
19431
- }
19432
- return stableStringify(subset);
19433
- }
19434
- function buildCaptureFingerprint(event, properties) {
19435
- return `${event}|${fingerprintProperties(properties)}`;
19436
- }
19437
- function buildCoalescedCaptureProperties(payload) {
19438
- const windowMs = payload.lastAt - payload.firstAt;
19439
- return {
19440
- ...payload.properties,
19441
- coalesced: true,
19442
- coalesced_count: payload.coalescedCount,
19443
- coalesced_first_at: new Date(payload.firstAt).toISOString(),
19444
- coalesced_last_at: new Date(payload.lastAt).toISOString(),
19445
- coalesced_window_ms: windowMs,
19446
- coalesced_suppression_reason: payload.suppressionReason
19447
- };
19448
- }
19449
- class PosthogCaptureGate {
19450
- constructor(config2 = DEFAULT_CAPTURE_GATE_CONFIG) {
19451
- __publicField(this, "config");
19452
- __publicField(this, "globalWindow", { timestamps: [] });
19453
- __publicField(this, "eventWindows", /* @__PURE__ */ new Map());
19454
- __publicField(this, "activeDedupe", /* @__PURE__ */ new Map());
19455
- __publicField(this, "coalesceBuckets", /* @__PURE__ */ new Map());
19456
- __publicField(this, "emittedTotal", 0);
19457
- __publicField(this, "coalescedTotal", 0);
19458
- __publicField(this, "flushedCoalescedTotal", 0);
19459
- this.config = config2;
19460
- }
19461
- resetForTests() {
19462
- this.globalWindow.timestamps.length = 0;
19463
- this.eventWindows.clear();
19464
- this.activeDedupe.clear();
19465
- this.coalesceBuckets.clear();
19466
- this.emittedTotal = 0;
19467
- this.coalescedTotal = 0;
19468
- this.flushedCoalescedTotal = 0;
19469
- }
19470
- getSnapshot() {
19471
- const coalescedPendingByEvent = {};
19472
- let coalescedPending = 0;
19473
- for (const bucket of this.coalesceBuckets.values()) {
19474
- coalescedPending += bucket.count;
19475
- coalescedPendingByEvent[bucket.event] = (coalescedPendingByEvent[bucket.event] ?? 0) + bucket.count;
19476
- }
19477
- return {
19478
- coalescedPending,
19479
- coalescedPendingByEvent,
19480
- emittedTotal: this.emittedTotal,
19481
- coalescedTotal: this.coalescedTotal,
19482
- flushedCoalescedTotal: this.flushedCoalescedTotal
19483
- };
19484
- }
19485
- evaluateCapture(event, properties, options, now = Date.now()) {
19486
- if (shouldBypassCaptureGate(options)) {
19487
- return { action: "emit" };
19488
- }
19489
- const fingerprint = buildCaptureFingerprint(event, properties);
19490
- const bucketKey = fingerprint;
19491
- const override = this.config.eventOverrides[event];
19492
- const dedupeWindowMs = (override == null ? void 0 : override.dedupeWindowMs) ?? this.config.defaultDedupeWindowMs;
19493
- const lastDedupe = this.activeDedupe.get(event);
19494
- if (lastDedupe && lastDedupe.fingerprint === fingerprint && now - lastDedupe.at < dedupeWindowMs) {
19495
- return this.recordCoalesce(event, bucketKey, fingerprint, properties, "dedupe", now);
19496
- }
19497
- const critical = isCriticalPosthogEvent(event);
19498
- const globalCount = countInWindow(this.globalWindow, now, this.config.globalWindowMs);
19499
- const normalBudget = Math.max(
19500
- 0,
19501
- this.config.globalMaxPerWindow - this.config.criticalReservePerWindow
19502
- );
19503
- if (critical) {
19504
- if (globalCount >= this.config.globalMaxPerWindow) {
19505
- return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
19506
- }
19507
- } else if (globalCount >= normalBudget) {
19508
- return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
19509
- }
19510
- const eventWindow = this.eventWindows.get(event) ?? { timestamps: [] };
19511
- this.eventWindows.set(event, eventWindow);
19512
- const eventMax = (override == null ? void 0 : override.maxPerWindow) ?? this.config.defaultEventMaxPerWindow;
19513
- const eventWindowMs = (override == null ? void 0 : override.windowMs) ?? this.config.defaultEventWindowMs;
19514
- const eventCount = countInWindow(eventWindow, now, eventWindowMs);
19515
- if (eventCount >= eventMax) {
19516
- return this.recordCoalesce(event, bucketKey, fingerprint, properties, "event_budget", now);
19517
- }
19518
- recordInWindow(this.globalWindow, now);
19519
- recordInWindow(eventWindow, now);
19520
- this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
19521
- this.emittedTotal += 1;
19522
- return { action: "emit" };
19523
- }
19524
- /** Returns payloads ready to flush (does not mutate buckets until caller confirms). */
19525
- collectFlushCandidates(now = Date.now()) {
19526
- const payloads = [];
19527
- for (const bucket of this.coalesceBuckets.values()) {
19528
- const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
19529
- const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
19530
- if (!shouldFlushBySize && !shouldFlushByAge) {
19531
- continue;
19532
- }
19533
- payloads.push({
19534
- bucketKey: bucket.bucketKey,
19535
- event: bucket.event,
19536
- properties: bucket.sampleProperties,
19537
- coalescedCount: bucket.count,
19538
- firstAt: bucket.firstAt,
19539
- lastAt: bucket.lastAt,
19540
- suppressionReason: bucket.suppressionReason
19541
- });
19542
- }
19543
- return payloads;
19544
- }
19545
- /** Remove flushed bucket keys after successful emit. */
19546
- acknowledgeFlushed(payloads) {
19547
- for (const payload of payloads) {
19548
- this.coalesceBuckets.delete(payload.bucketKey);
19549
- this.flushedCoalescedTotal += payload.coalescedCount;
19550
- }
19551
- }
19552
- /** After coalescing, flush immediately if the bucket crossed the early threshold. */
19553
- takeBucketIfReady(bucketKey, now = Date.now()) {
19554
- const bucket = this.coalesceBuckets.get(bucketKey);
19555
- if (!bucket) return null;
19556
- const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
19557
- const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
19558
- if (!shouldFlushBySize && !shouldFlushByAge) {
19559
- return null;
19560
- }
19561
- this.coalesceBuckets.delete(bucketKey);
19562
- this.flushedCoalescedTotal += bucket.count;
19563
- return {
19564
- bucketKey: bucket.bucketKey,
19565
- event: bucket.event,
19566
- properties: bucket.sampleProperties,
19567
- coalescedCount: bucket.count,
19568
- firstAt: bucket.firstAt,
19569
- lastAt: bucket.lastAt,
19570
- suppressionReason: bucket.suppressionReason
19571
- };
19572
- }
19573
- /** Force-flush every pending bucket (e.g. page hide). */
19574
- collectAllPending() {
19575
- return [...this.coalesceBuckets.values()].map((bucket) => ({
19576
- bucketKey: bucket.bucketKey,
19577
- event: bucket.event,
19578
- properties: bucket.sampleProperties,
19579
- coalescedCount: bucket.count,
19580
- firstAt: bucket.firstAt,
19581
- lastAt: bucket.lastAt,
19582
- suppressionReason: bucket.suppressionReason
19583
- }));
19584
- }
19585
- recordCoalesce(event, bucketKey, fingerprint, properties, reason, now) {
19586
- const existing = this.coalesceBuckets.get(bucketKey);
19587
- if (existing) {
19588
- existing.count += 1;
19589
- existing.lastAt = now;
19590
- existing.sampleProperties = { ...existing.sampleProperties, ...properties ?? {} };
19591
- } else {
19592
- this.coalesceBuckets.set(bucketKey, {
19593
- event,
19594
- bucketKey,
19595
- fingerprint,
19596
- count: 1,
19597
- firstAt: now,
19598
- lastAt: now,
19599
- suppressionReason: reason,
19600
- sampleProperties: { ...properties ?? {} }
19601
- });
19602
- }
19603
- this.coalescedTotal += 1;
19604
- this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
19605
- return { action: "coalesce", reason, bucketKey };
19606
- }
19607
- }
19608
- const gate = new PosthogCaptureGate(DEFAULT_CAPTURE_GATE_CONFIG);
19609
- let wrappedClient = null;
19610
- let originalCaptureRef = null;
19611
- let flushTimer = null;
19612
- let lifecycleHooksInstalled = false;
19613
- function getPosthogCaptureGate() {
19614
- return gate;
19615
- }
19616
- function emitThroughOriginal(event, properties, options) {
19617
- if (!originalCaptureRef) return void 0;
19618
- return originalCaptureRef(event, properties, withCaptureGateBypass(options));
19619
- }
19620
- function flushCoalescedPayload(payload) {
19621
- emitThroughOriginal(payload.event, buildCoalescedCaptureProperties(payload));
19622
- }
19623
- function flushCoalescedCaptures(options) {
19624
- const payloads = (options == null ? void 0 : options.force) ? gate.collectAllPending() : gate.collectFlushCandidates();
19625
- if (payloads.length === 0) return;
19626
- for (const payload of payloads) {
19627
- flushCoalescedPayload(payload);
19628
- }
19629
- gate.acknowledgeFlushed(payloads);
19630
- }
19631
- function installLifecycleFlushHooks() {
19632
- if (lifecycleHooksInstalled || typeof window === "undefined") return;
19633
- lifecycleHooksInstalled = true;
19634
- const flushOnHide = () => {
19635
- flushCoalescedCaptures({ force: true });
19636
- };
19637
- window.addEventListener("pagehide", flushOnHide);
19638
- document.addEventListener("visibilitychange", () => {
19639
- if (document.visibilityState === "hidden") {
19640
- flushOnHide();
19641
- }
19642
- });
19643
- if (!flushTimer) {
19644
- flushTimer = setInterval(() => {
19645
- flushCoalescedCaptures();
19646
- }, DEFAULT_CAPTURE_GATE_CONFIG.flushIntervalMs);
19647
- }
19648
- }
19649
- function wrapPosthogClient(client) {
19650
- if (wrappedClient === client) {
19651
- return client;
19652
- }
19653
- originalCaptureRef = client.capture.bind(client);
19654
- const originalCaptureException = typeof client.captureException === "function" ? client.captureException.bind(client) : null;
19655
- installLifecycleFlushHooks();
19656
- client.capture = ((event, properties, options) => {
19657
- const outcome = gate.evaluateCapture(event, properties, options);
19658
- if (outcome.action === "coalesce") {
19659
- const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
19660
- if (readyPayload) {
19661
- flushCoalescedPayload(readyPayload);
19662
- }
19663
- return void 0;
19664
- }
19665
- return emitThroughOriginal(event, properties, options);
19666
- });
19667
- if (originalCaptureException) {
19668
- client.captureException = ((error2, additionalProperties) => {
19669
- const mergedProperties = {
19670
- ...additionalProperties ?? {},
19671
- $exception_message: error2 instanceof Error ? error2.message : String(error2),
19672
- $exception_type: error2 instanceof Error ? error2.name : typeof error2
19673
- };
19674
- const outcome = gate.evaluateCapture("$exception", mergedProperties);
19675
- if (outcome.action === "coalesce") {
19676
- const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
19677
- if (readyPayload) {
19678
- flushCoalescedPayload(readyPayload);
19679
- }
19680
- return void 0;
19681
- }
19682
- return originalCaptureException(error2, additionalProperties);
19683
- });
19684
- }
19685
- wrappedClient = client;
19686
- return client;
19687
- }
19688
- function capturePosthogEvent(client, event, properties, options) {
19689
- if (!client || typeof client.capture !== "function") return;
19690
- client.capture(event, properties, options);
19691
- }
19692
- function capturePosthogException(client, error2, properties, options) {
19693
- if (!client) return;
19694
- if (typeof client.captureException === "function") {
19695
- client.captureException(error2, properties);
19696
- return;
19697
- }
19698
- capturePosthogEvent(
19699
- client,
19700
- "$exception",
19701
- {
19702
- ...properties ?? {},
19703
- $exception_message: error2.message,
19704
- $exception_type: error2.name,
19705
- $exception_stack: error2.stack
19706
- },
19707
- options
19708
- );
19709
- }
19710
- let posthogInstance = null;
19711
- let initPromise = null;
19712
- const DEFAULT_HOST = "https://us.i.posthog.com";
19713
- async function initializePostHog(apiKey, host, debug) {
19714
- if (posthogInstance) return posthogInstance;
19715
- if (typeof window === "undefined") return null;
19716
- try {
19717
- const posthog = (await import("posthog-js")).default;
19718
- posthog.init(apiKey, {
19719
- api_host: host,
19720
- autocapture: true,
19721
- capture_pageview: false,
19722
- session_recording: {
19723
- recordCrossOriginIframes: true,
19724
- maskAllInputs: true
19725
- },
19726
- loaded: (ph) => {
19727
- wrapPosthogClient(ph);
19728
- if (debug) {
19729
- ph.debug(true);
19730
- }
19731
- }
19732
- });
19733
- wrapPosthogClient(posthog);
19734
- posthogInstance = posthog;
19735
- return posthog;
19736
- } catch {
19737
- initPromise = null;
19738
- return null;
19739
- }
19740
- }
19741
- function getPostHogInstance() {
19742
- return posthogInstance;
19743
- }
19744
- function PostHogProvider({
19745
- children,
19746
- config: config2
19747
- }) {
19748
- const apiKey = (config2 == null ? void 0 : config2.apiKey) ?? "";
19749
- const host = (config2 == null ? void 0 : config2.host) ?? DEFAULT_HOST;
19750
- const debug = (config2 == null ? void 0 : config2.debug) ?? false;
19751
- React.useEffect(() => {
19752
- if (!apiKey || typeof window === "undefined") return;
19753
- if (!initPromise) {
19754
- initPromise = initializePostHog(apiKey, host, debug);
19755
- }
19756
- }, [apiKey, host, debug]);
19757
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
19758
- }
19759
20390
  const resolveTokenOverride = ({
19760
20391
  config: config2,
19761
20392
  token
@@ -19858,9 +20489,16 @@ const initialStatewireLifecycle = {
19858
20489
  reconnect: null
19859
20490
  };
19860
20491
  function statewireLifecycleReducer(state, action) {
20492
+ var _a3, _b2;
19861
20493
  switch (action.type) {
19862
- case "connection":
19863
- return { ...state, connection: action.connection };
20494
+ case "connection": {
20495
+ const healthy = ((_a3 = action.connection) == null ? void 0 : _a3.status) === "live" || ((_b2 = action.connection) == null ? void 0 : _b2.status) === "idle";
20496
+ return {
20497
+ ...state,
20498
+ connection: action.connection,
20499
+ error: healthy ? null : state.error
20500
+ };
20501
+ }
19864
20502
  case "error":
19865
20503
  return { ...state, error: action.error };
19866
20504
  case "legacy-read-only":
@@ -19878,6 +20516,8 @@ function AthenaStatewireStandalone({
19878
20516
  token,
19879
20517
  getToken,
19880
20518
  model,
20519
+ agent: agent2,
20520
+ channel,
19881
20521
  tools,
19882
20522
  frontendToolIds,
19883
20523
  frontendTools,
@@ -19909,6 +20549,8 @@ function AthenaStatewireStandalone({
19909
20549
  token,
19910
20550
  getToken,
19911
20551
  model,
20552
+ agent: agent2,
20553
+ channel,
19912
20554
  tools,
19913
20555
  frontendToolIds,
19914
20556
  frontendToolkit: frontendTools,
@@ -20184,6 +20826,7 @@ function AthenaProvider({
20184
20826
  apiKey,
20185
20827
  token: tokenProp,
20186
20828
  agent: agent2,
20829
+ channel,
20187
20830
  model,
20188
20831
  tools = [],
20189
20832
  frontendTools = {},
@@ -20206,8 +20849,32 @@ function AthenaProvider({
20206
20849
  theme,
20207
20850
  linkClicks,
20208
20851
  citationLinks,
20209
- posthog: posthogProp
20852
+ posthog: posthogProp,
20853
+ debug,
20854
+ onDiagnostic,
20855
+ onError
20210
20856
  }) {
20857
+ const onDiagnosticRef = React.useRef(onDiagnostic);
20858
+ onDiagnosticRef.current = onDiagnostic;
20859
+ const onErrorRef = React.useRef(onError);
20860
+ onErrorRef.current = onError;
20861
+ React.useEffect(() => {
20862
+ installAthenaDiagnosticsGlobal();
20863
+ return athenaDiagnostics.addConsumer({
20864
+ onEvent: (event) => {
20865
+ var _a3;
20866
+ return (_a3 = onDiagnosticRef.current) == null ? void 0 : _a3.call(onDiagnosticRef, event);
20867
+ },
20868
+ onError: (error2, event) => {
20869
+ var _a3;
20870
+ return (_a3 = onErrorRef.current) == null ? void 0 : _a3.call(onErrorRef, error2, event);
20871
+ }
20872
+ });
20873
+ }, []);
20874
+ const debugKey = JSON.stringify(debugPropToDiagnosticsConfig(debug));
20875
+ React.useEffect(() => {
20876
+ athenaDiagnostics.configure(debugPropToDiagnosticsConfig(debug));
20877
+ }, [debugKey]);
20211
20878
  const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
20212
20879
  const effectiveFrontendTools = React.useMemo(
20213
20880
  () => disableAutoOpen ? frontendTools : { ...DEFAULT_AUTO_OPEN_TOOLS, ...frontendTools },
@@ -20226,16 +20893,39 @@ function AthenaProvider({
20226
20893
  const configuredAppUrl = (config2 == null ? void 0 : config2.appUrl) ?? appUrl;
20227
20894
  const configuredTransport = (config2 == null ? void 0 : config2.transport) ?? transport;
20228
20895
  const configuredStatewireSyncUrl = (config2 == null ? void 0 : config2.statewireSyncUrl) ?? statewireSyncUrl;
20896
+ const configuredGetToken = (config2 == null ? void 0 : config2.getToken) ?? getToken;
20897
+ const configuredExtraRunConfig = (config2 == null ? void 0 : config2.extraRunConfig) ?? extraRunConfig;
20229
20898
  const configuredTrustedParentOrigins = config2 == null ? void 0 : config2.trustedParentOrigins;
20230
20899
  const posthogConfig = (config2 == null ? void 0 : config2.posthog) ?? posthogProp;
20231
20900
  const { transport: effectiveTransport, fallbackReason: transportFallbackReason } = resolveAthenaTransport({
20232
20901
  transport: configuredTransport
20233
20902
  });
20234
20903
  React.useEffect(() => {
20904
+ athenaDiagnostics.gauge("sdk.transport", effectiveTransport);
20905
+ athenaDiagnostics.emit("sdk.transport", {
20906
+ level: "debug",
20907
+ data: { transport: effectiveTransport, thread_list: enableThreadList }
20908
+ });
20235
20909
  if (transportFallbackReason) {
20910
+ athenaDiagnostics.emit("sdk.config.warning", {
20911
+ level: "warn",
20912
+ data: { prop: "transport", reason: transportFallbackReason }
20913
+ });
20236
20914
  console.warn(`[AthenaSDK] ${transportFallbackReason}`);
20237
20915
  }
20238
- }, [transportFallbackReason]);
20916
+ }, [effectiveTransport, enableThreadList, transportFallbackReason]);
20917
+ React.useEffect(() => {
20918
+ if (channel && effectiveTransport !== "statewire") {
20919
+ athenaDiagnostics.emit("sdk.config.warning", {
20920
+ level: "warn",
20921
+ data: {
20922
+ prop: "channel",
20923
+ value: channel,
20924
+ reason: "the 'channel' prop requires transport='statewire'; the legacy transport ignores it."
20925
+ }
20926
+ });
20927
+ }
20928
+ }, [channel, effectiveTransport]);
20239
20929
  const bridge = useParentBridge({
20240
20930
  trustedOrigins: configuredTrustedParentOrigins
20241
20931
  });
@@ -20260,8 +20950,10 @@ function AthenaProvider({
20260
20950
  appUrl: effectiveAppUrl,
20261
20951
  apiKey: configuredApiKey,
20262
20952
  token: effectiveToken,
20263
- getToken,
20953
+ getToken: configuredGetToken,
20264
20954
  model,
20955
+ agent: agent2,
20956
+ channel,
20265
20957
  tools,
20266
20958
  frontendToolIds: frontendToolNames,
20267
20959
  frontendTools: effectiveFrontendTools,
@@ -20270,7 +20962,7 @@ function AthenaProvider({
20270
20962
  systemPrompt,
20271
20963
  customToolConfigs,
20272
20964
  appId,
20273
- extraRunConfig,
20965
+ extraRunConfig: configuredExtraRunConfig,
20274
20966
  linkClicks,
20275
20967
  citationLinks
20276
20968
  };
@@ -54613,13 +55305,13 @@ function getEmptyMessage(scope, query) {
54613
55305
  function MentionIcon({ item }) {
54614
55306
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(MentionIconGlyph, { icon: item.fallbackIcon }) });
54615
55307
  }
54616
- const MentionSuggestionList = React.forwardRef(({ store, query, command: command2, closeMenu }, ref) => {
55308
+ const MentionSuggestionList = React.forwardRef(({ store: store2, query, command: command2, closeMenu }, ref) => {
54617
55309
  const [selectedIndex, setSelectedIndex] = React.useState(0);
54618
55310
  const [currentScope, setCurrentScope] = React.useState("root");
54619
55311
  const scrollContainerRef = React.useRef(null);
54620
- const hasGlobalSearch = store.state.registry.entries.has(GLOBAL_SEARCH_SCOPE$1);
55312
+ const hasGlobalSearch = store2.state.registry.entries.has(GLOBAL_SEARCH_SCOPE$1);
54621
55313
  const effectiveScope = currentScope === "root" && query.trim() && hasGlobalSearch ? GLOBAL_SEARCH_SCOPE$1 : currentScope;
54622
- const { items, isFetching } = useStore(store, (state) => ({
55314
+ const { items, isFetching } = useStore(store2, (state) => ({
54623
55315
  items: getFilteredItems(state.cache, effectiveScope, query),
54624
55316
  isFetching: false
54625
55317
  }));
@@ -54738,7 +55430,7 @@ const MentionSuggestionList = React.forwardRef(({ store, query, command: command
54738
55430
  ] });
54739
55431
  });
54740
55432
  MentionSuggestionList.displayName = "MentionSuggestionList";
54741
- const MentionSuggestionPopup = React.forwardRef(({ store, query, command: command2, clientRect: clientRect2, closeMenu, isHidden: isHidden3 = false }, ref) => {
55433
+ const MentionSuggestionPopup = React.forwardRef(({ store: store2, query, command: command2, clientRect: clientRect2, closeMenu, isHidden: isHidden3 = false }, ref) => {
54742
55434
  const listRef = React.useRef(null);
54743
55435
  const virtualRef = React.useRef({
54744
55436
  getBoundingClientRect: () => clientRect2 ? clientRect2() : new DOMRect()
@@ -54785,7 +55477,7 @@ const MentionSuggestionPopup = React.forwardRef(({ store, query, command: comman
54785
55477
  MentionSuggestionList,
54786
55478
  {
54787
55479
  ref: listRef,
54788
- store,
55480
+ store: store2,
54789
55481
  query,
54790
55482
  command: command2,
54791
55483
  closeMenu
@@ -55012,9 +55704,9 @@ function useMentionSuggestions(tools, options = {}) {
55012
55704
  populateMentionCache({ cache, tools, rootCategories });
55013
55705
  storeRef.current = new Store({ registry: registry2, cache });
55014
55706
  }
55015
- const store = storeRef.current;
55707
+ const store2 = storeRef.current;
55016
55708
  React.useEffect(() => {
55017
- store.setState((prev) => {
55709
+ store2.setState((prev) => {
55018
55710
  const newCache = createItemCache();
55019
55711
  if (rootCategories) {
55020
55712
  registerStaticSource(prev.registry, "toolkits");
@@ -55024,8 +55716,8 @@ function useMentionSuggestions(tools, options = {}) {
55024
55716
  populateMentionCache({ cache: newCache, tools, rootCategories });
55025
55717
  return { ...prev, cache: newCache };
55026
55718
  });
55027
- }, [tools, store, rootCategories, rootCategoriesKey]);
55028
- return store;
55719
+ }, [tools, store2, rootCategories, rootCategoriesKey]);
55720
+ return store2;
55029
55721
  }
55030
55722
  const AttachmentCtx = React.createContext(null);
55031
55723
  function AttachmentProvider({ children }) {
@@ -55323,7 +56015,7 @@ const TiptapComposer = ({ tools = [], rootCategories }) => {
55323
56015
  const isUploadingRef = React.useRef(isUploading);
55324
56016
  isUploadingRef.current = isUploading;
55325
56017
  const isRunningThread = react$1.useAuiState((s) => s.thread.isRunning);
55326
- const isThreadRunning = transport === "statewire" ? false : isRunningThread;
56018
+ const isThreadRunning = allowsMidRunSend(transport) ? false : isRunningThread;
55327
56019
  const isThreadRunningRef = React.useRef(isThreadRunning);
55328
56020
  isThreadRunningRef.current = isThreadRunning;
55329
56021
  const handleSubmit = React.useCallback(() => {
@@ -55345,10 +56037,8 @@ const TiptapComposer = ({ tools = [], rootCategories }) => {
55345
56037
  appUrl
55346
56038
  });
55347
56039
  if (fullMessage) {
55348
- aui.thread.append({
55349
- role: "user",
55350
- content: [{ type: "text", text: fullMessage }]
55351
- });
56040
+ aui.composer.setText(fullMessage);
56041
+ aui.composer.send();
55352
56042
  clearAttachments();
55353
56043
  clearQuote();
55354
56044
  }
@@ -55597,14 +56287,20 @@ const StatewireApprovalCardInner = () => {
55597
56287
  }
55598
56288
  const isRunning = react$1.useAuiState((s) => s.thread.isRunning);
55599
56289
  const sawResumeRunRef = React.useRef(false);
55600
- if (pending && isRunning) {
55601
- sawResumeRunRef.current = true;
55602
- } else if (pending && sawResumeRunRef.current && !isRunning) {
55603
- sawResumeRunRef.current = false;
55604
- setPending(false);
55605
- } else if (!pending) {
55606
- sawResumeRunRef.current = false;
55607
- }
56290
+ React.useEffect(() => {
56291
+ if (!pending) {
56292
+ sawResumeRunRef.current = false;
56293
+ return;
56294
+ }
56295
+ if (isRunning) {
56296
+ sawResumeRunRef.current = true;
56297
+ return;
56298
+ }
56299
+ if (sawResumeRunRef.current) {
56300
+ sawResumeRunRef.current = false;
56301
+ setPending(false);
56302
+ }
56303
+ }, [pending, isRunning]);
55608
56304
  React.useEffect(() => {
55609
56305
  if (!pending) return;
55610
56306
  const timer = setTimeout(() => {
@@ -55895,7 +56591,7 @@ const StatewireLegacyReadOnlyBanner = () => {
55895
56591
  /* @__PURE__ */ jsxRuntime.jsx(Archive, { className: "mt-0.5 size-4 shrink-0" }),
55896
56592
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
55897
56593
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-semibold text-xs", children: "Read-only conversation" }),
55898
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pt-0.5 text-xs leading-snug text-amber-800", children: "Its history remains available, but new messages cannot be added. Start a new chat to continue." })
56594
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pt-0.5 text-xs leading-snug text-amber-800", children: "This conversation’s history remains available, but new messages cannot be added. Start a new chat to continue." })
55899
56595
  ] })
55900
56596
  ] });
55901
56597
  };
@@ -57446,10 +58142,10 @@ function openStudioAsset({
57446
58142
  slideNumber,
57447
58143
  preserveExistingSlide
57448
58144
  }) {
57449
- const store = useAssetPanelStore.getState();
57450
- const existing = store.tabs.find((tab) => tab.id === assetId);
58145
+ const store2 = useAssetPanelStore.getState();
58146
+ const existing = store2.tabs.find((tab) => tab.id === assetId);
57451
58147
  const shouldKeepCurrentSlide = preserveExistingSlide && existing;
57452
- store.openAsset(assetId, {
58148
+ store2.openAsset(assetId, {
57453
58149
  type: assetType,
57454
58150
  ...!shouldKeepCurrentSlide && slideNumber !== void 0 ? { slideNumber } : {}
57455
58151
  });
@@ -61134,7 +61830,7 @@ const ThreadScrollToBottom = () => /* @__PURE__ */ jsxRuntime.jsx(react$1.Thread
61134
61830
  ) });
61135
61831
  const ComposerAction = () => {
61136
61832
  const { transport } = useAthenaConfig();
61137
- const queuesWhileRunning = transport === "statewire";
61833
+ const queuesWhileRunning = allowsMidRunSend(transport);
61138
61834
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between", children: [
61139
61835
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsx(FileUploadButton, {}) }),
61140
61836
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
@@ -61161,7 +61857,7 @@ const ComposerSendWithQuote = () => {
61161
61857
  const editorRef = useComposerEditorRef();
61162
61858
  const editorEmpty = useComposerEditorEmpty();
61163
61859
  const isRunningThread = react$1.useAuiState((s) => s.thread.isRunning);
61164
- const isThreadRunning = transport === "statewire" ? false : isRunningThread;
61860
+ const isThreadRunning = allowsMidRunSend(transport) ? false : isRunningThread;
61165
61861
  const hasExtras = !!quote || attachments.length > 0;
61166
61862
  const handleSend = React.useCallback(() => {
61167
61863
  var _a3;
@@ -61177,10 +61873,8 @@ const ComposerSendWithQuote = () => {
61177
61873
  appUrl
61178
61874
  });
61179
61875
  if (!fullMessage) return;
61180
- aui.thread.append({
61181
- role: "user",
61182
- content: [{ type: "text", text: fullMessage }]
61183
- });
61876
+ aui.composer.setText(fullMessage);
61877
+ aui.composer.send();
61184
61878
  clearQuote();
61185
61879
  clearAttachments();
61186
61880
  } else {
@@ -62416,6 +63110,8 @@ function useComposerAttachment() {
62416
63110
  }, [aui]);
62417
63111
  return { addFile, addContent, clear };
62418
63112
  }
63113
+ exports.ATHENA_REACT_SDK_VERSION = ATHENA_REACT_SDK_VERSION;
63114
+ exports.ATHENA_SDK_ERROR_CODES = ATHENA_SDK_ERROR_CODES;
62419
63115
  exports.ATHENA_TRANSPORTS = ATHENA_TRANSPORTS;
62420
63116
  exports.AppendDocumentToolUI = AppendDocumentToolUI;
62421
63117
  exports.AssetPanel = AssetPanel;
@@ -62426,10 +63122,12 @@ exports.AthenaChat = AthenaChat;
62426
63122
  exports.AthenaLayout = AthenaLayout;
62427
63123
  exports.AthenaProvider = AthenaProvider;
62428
63124
  exports.AthenaReasoningPart = AthenaReasoningPart;
63125
+ exports.AthenaSdkError = AthenaSdkError;
62429
63126
  exports.AthenaThreadIdContext = AthenaThreadIdContext;
62430
63127
  exports.AthenaUserMessage = AthenaUserMessage;
62431
63128
  exports.BrowseToolUI = BrowseToolUI;
62432
63129
  exports.Button = Button;
63130
+ exports.COLLAB_AGENT_REF_PREFIX = COLLAB_AGENT_REF_PREFIX;
62433
63131
  exports.Collapsible = Collapsible;
62434
63132
  exports.CollapsibleContent = CollapsibleContent;
62435
63133
  exports.CollapsibleTrigger = CollapsibleTrigger;
@@ -62486,8 +63184,10 @@ exports.TooltipProvider = TooltipProvider;
62486
63184
  exports.TooltipTrigger = TooltipTrigger;
62487
63185
  exports.UpdateSheetRangeToolUI = UpdateSheetRangeToolUI;
62488
63186
  exports.WebSearchToolUI = WebSearchToolUI;
63187
+ exports.allowsMidRunSend = allowsMidRunSend;
62489
63188
  exports.archiveThread = archiveThread;
62490
63189
  exports.asHitlApproval = asHitlApproval;
63190
+ exports.athenaDiagnostics = athenaDiagnostics;
62491
63191
  exports.athenaStatewireErrorNotice = athenaStatewireErrorNotice;
62492
63192
  exports.autoCloseInFlightSubgraphMessages = autoCloseInFlightSubgraphMessages;
62493
63193
  exports.buildCoalescedCaptureProperties = buildCoalescedCaptureProperties;
@@ -62511,13 +63211,17 @@ exports.getPostHogInstance = getPostHogInstance;
62511
63211
  exports.getPosthogCaptureGate = getPosthogCaptureGate;
62512
63212
  exports.getThreadState = getThreadState;
62513
63213
  exports.hasStatewireThreadExtras = hasStatewireThreadExtras;
63214
+ exports.installAthenaDiagnosticsGlobal = installAthenaDiagnosticsGlobal;
62514
63215
  exports.isAthenaCitationUrl = isAthenaCitationUrl;
63216
+ exports.isAthenaSdkError = isAthenaSdkError;
62515
63217
  exports.isCriticalPosthogEvent = isCriticalPosthogEvent;
62516
63218
  exports.isPendingInterrupt = isPendingInterrupt;
62517
63219
  exports.listThreads = listThreads;
62518
63220
  exports.normalizeResult = normalizeResult;
62519
63221
  exports.parseAthenaCitationLink = parseAthenaCitationLink;
63222
+ exports.parseCollabAgentRef = parseCollabAgentRef;
62520
63223
  exports.readInterruptMessage = readInterruptMessage;
63224
+ exports.readRejectionDetail = readRejectionDetail;
62521
63225
  exports.resetAssetAutoOpen = resetAssetAutoOpen;
62522
63226
  exports.resolveAthenaTransport = resolveAthenaTransport;
62523
63227
  exports.resolveStatewireSyncUrl = resolveStatewireSyncUrl;
@@ -62525,6 +63229,7 @@ exports.setThreadReadState = setThreadReadState;
62525
63229
  exports.statewireClientToolWireEntries = statewireClientToolWireEntries;
62526
63230
  exports.themeToStyleVars = themeToStyleVars;
62527
63231
  exports.themes = themes;
63232
+ exports.toAthenaSdkError = toAthenaSdkError;
62528
63233
  exports.truncate = truncate;
62529
63234
  exports.tryParseJson = tryParseJson$2;
62530
63235
  exports.useAppendToComposer = useAppendToComposer;
@@ -62532,6 +63237,7 @@ exports.useAssetEmbed = useAssetEmbed;
62532
63237
  exports.useAssetPanelStore = useAssetPanelStore;
62533
63238
  exports.useAthenaCitationLinkHandler = useAthenaCitationLinkHandler;
62534
63239
  exports.useAthenaConfig = useAthenaConfig;
63240
+ exports.useAthenaDiagnostics = useAthenaDiagnostics;
62535
63241
  exports.useAthenaLinkClickHandler = useAthenaLinkClickHandler;
62536
63242
  exports.useAthenaRuntime = useAthenaRuntime;
62537
63243
  exports.useAthenaStatewireLifecycle = useAthenaStatewireLifecycle;