@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/chat/statewire-client-tools.d.ts +14 -7
- package/dist/diagnostics/athena-diagnostics.d.ts +138 -0
- package/dist/diagnostics/errors.d.ts +67 -0
- package/dist/diagnostics/useAthenaDiagnostics.d.ts +13 -0
- package/dist/index.cjs +1343 -637
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1369 -663
- package/dist/index.js.map +1 -1
- package/dist/provider/AthenaContext.d.ts +3 -3
- package/dist/provider/AthenaProvider.d.ts +42 -4
- package/dist/provider/config.d.ts +6 -0
- package/dist/runtime/statewire-run-config.d.ts +16 -1
- package/dist/runtime/transport.d.ts +8 -0
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +5 -0
- package/dist/version.d.ts +6 -0
- package/package.json +3 -3
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,
|
|
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 -
|
|
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
|
|
9885
|
-
|
|
9886
|
-
|
|
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
|
-
|
|
9898
|
-
|
|
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
|
-
|
|
9965
|
-
threadId,
|
|
9966
|
-
|
|
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
|
-
|
|
9982
|
-
|
|
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
|
|
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
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
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 = ((
|
|
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) =>
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
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
|
|
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
|
-
|
|
11182
|
-
|
|
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:
|
|
11188
|
-
parameters
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
15896
|
-
if (!
|
|
15897
|
-
const existing =
|
|
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
|
-
|
|
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
|
-
|
|
18835
|
-
//
|
|
18836
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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
|
|
55707
|
+
const store2 = storeRef.current;
|
|
55016
55708
|
React.useEffect(() => {
|
|
55017
|
-
|
|
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,
|
|
55028
|
-
return
|
|
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
|
|
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.
|
|
55349
|
-
|
|
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
|
-
|
|
55601
|
-
|
|
55602
|
-
|
|
55603
|
-
|
|
55604
|
-
|
|
55605
|
-
|
|
55606
|
-
|
|
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: "
|
|
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
|
|
57450
|
-
const existing =
|
|
58145
|
+
const store2 = useAssetPanelStore.getState();
|
|
58146
|
+
const existing = store2.tabs.find((tab) => tab.id === assetId);
|
|
57451
58147
|
const shouldKeepCurrentSlide = preserveExistingSlide && existing;
|
|
57452
|
-
|
|
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
|
|
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
|
|
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.
|
|
61181
|
-
|
|
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;
|