@athenaintel/react 0.10.41 → 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 +1264 -600
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1290 -626
- package/dist/index.js.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +38 -2
- package/dist/runtime/statewire-run-config.d.ts +16 -1
- 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,
|
|
@@ -15914,11 +16961,11 @@ const pickNumber = (...candidates) => {
|
|
|
15914
16961
|
return void 0;
|
|
15915
16962
|
};
|
|
15916
16963
|
const autoOpen = (assetId, options = {}) => {
|
|
15917
|
-
const
|
|
15918
|
-
if (!
|
|
15919
|
-
const existing =
|
|
16964
|
+
const store2 = useAssetPanelStore.getState();
|
|
16965
|
+
if (!store2.markAutoOpened(assetId)) return;
|
|
16966
|
+
const existing = store2.tabs.find((tab) => tab.id === assetId);
|
|
15920
16967
|
const keepCurrentSlide = options.preserveExistingSlide && existing;
|
|
15921
|
-
|
|
16968
|
+
store2.openAsset(assetId, {
|
|
15922
16969
|
type: options.type ?? "unknown",
|
|
15923
16970
|
...keepCurrentSlide || options.slideNumber === void 0 ? {} : { slideNumber: options.slideNumber }
|
|
15924
16971
|
});
|
|
@@ -19340,452 +20387,6 @@ const themes = {
|
|
|
19340
20387
|
radius: "0.625rem"
|
|
19341
20388
|
}
|
|
19342
20389
|
};
|
|
19343
|
-
const DEFAULT_CAPTURE_GATE_CONFIG = {
|
|
19344
|
-
globalMaxPerWindow: 50,
|
|
19345
|
-
globalWindowMs: 1e4,
|
|
19346
|
-
criticalReservePerWindow: 15,
|
|
19347
|
-
defaultEventMaxPerWindow: 12,
|
|
19348
|
-
defaultEventWindowMs: 6e4,
|
|
19349
|
-
defaultDedupeWindowMs: 5e3,
|
|
19350
|
-
flushIntervalMs: 3e4,
|
|
19351
|
-
flushCoalesceThreshold: 20,
|
|
19352
|
-
eventOverrides: {
|
|
19353
|
-
memory_profile_sample: { maxPerWindow: 2, windowMs: 3e4, dedupeWindowMs: 15e3 },
|
|
19354
|
-
long_task_detected: { maxPerWindow: 3, windowMs: 6e4, dedupeWindowMs: 1e4 },
|
|
19355
|
-
collab_connection_status_changed: { maxPerWindow: 6, windowMs: 6e4 },
|
|
19356
|
-
collab_first_remote_update: { maxPerWindow: 3, windowMs: 6e4 },
|
|
19357
|
-
collab_first_local_update: { maxPerWindow: 3, windowMs: 6e4 },
|
|
19358
|
-
collab_render_time_sync_fix: { maxPerWindow: 3, windowMs: 6e4 },
|
|
19359
|
-
collab_visibility_recovery: { maxPerWindow: 4, windowMs: 6e4 },
|
|
19360
|
-
langgraph_message_validation_error: {
|
|
19361
|
-
maxPerWindow: 8,
|
|
19362
|
-
windowMs: 6e4,
|
|
19363
|
-
dedupeWindowMs: 15e3
|
|
19364
|
-
},
|
|
19365
|
-
langgraph_messages_validation_error: {
|
|
19366
|
-
maxPerWindow: 5,
|
|
19367
|
-
windowMs: 6e4,
|
|
19368
|
-
dedupeWindowMs: 15e3
|
|
19369
|
-
},
|
|
19370
|
-
langgraph_interrupt_validation_error: {
|
|
19371
|
-
maxPerWindow: 5,
|
|
19372
|
-
windowMs: 6e4,
|
|
19373
|
-
dedupeWindowMs: 15e3
|
|
19374
|
-
},
|
|
19375
|
-
langgraph_state_validation_error: {
|
|
19376
|
-
maxPerWindow: 5,
|
|
19377
|
-
windowMs: 6e4,
|
|
19378
|
-
dedupeWindowMs: 15e3
|
|
19379
|
-
},
|
|
19380
|
-
graphql_error: { maxPerWindow: 12, windowMs: 6e4, dedupeWindowMs: 1e4 },
|
|
19381
|
-
chat_error: { maxPerWindow: 8, windowMs: 6e4, dedupeWindowMs: 5e3 },
|
|
19382
|
-
memory_critical_threshold: { maxPerWindow: 3, windowMs: 3e5 },
|
|
19383
|
-
memory_warning_threshold: { maxPerWindow: 3, windowMs: 3e5 },
|
|
19384
|
-
pptx_slide_changed: { maxPerWindow: 8, windowMs: 3e4 }
|
|
19385
|
-
}
|
|
19386
|
-
};
|
|
19387
|
-
const CRITICAL_EVENT_PATTERNS = [
|
|
19388
|
-
/(?:^|_)failed$/,
|
|
19389
|
-
/(?:^|_)error(?:_|$)/,
|
|
19390
|
-
/crash/,
|
|
19391
|
-
/^oom_/,
|
|
19392
|
-
/aw_snap/,
|
|
19393
|
-
/chunk_load/,
|
|
19394
|
-
/global_error/,
|
|
19395
|
-
/\$exception$/,
|
|
19396
|
-
/^404_error$/,
|
|
19397
|
-
/^500_error$/,
|
|
19398
|
-
/_boundary_/
|
|
19399
|
-
];
|
|
19400
|
-
const BYPASS_OPTION_KEY = "__posthog_gate_bypass";
|
|
19401
|
-
function isCriticalPosthogEvent(event) {
|
|
19402
|
-
return CRITICAL_EVENT_PATTERNS.some((pattern) => pattern.test(event));
|
|
19403
|
-
}
|
|
19404
|
-
function shouldBypassCaptureGate(options) {
|
|
19405
|
-
if (!options || typeof options !== "object") return false;
|
|
19406
|
-
return options[BYPASS_OPTION_KEY] === true;
|
|
19407
|
-
}
|
|
19408
|
-
function withCaptureGateBypass(options) {
|
|
19409
|
-
return {
|
|
19410
|
-
...options ?? {},
|
|
19411
|
-
[BYPASS_OPTION_KEY]: true
|
|
19412
|
-
};
|
|
19413
|
-
}
|
|
19414
|
-
function pruneWindow(window2, now, windowMs) {
|
|
19415
|
-
const cutoff = now - windowMs;
|
|
19416
|
-
while (window2.timestamps.length > 0 && window2.timestamps[0] < cutoff) {
|
|
19417
|
-
window2.timestamps.shift();
|
|
19418
|
-
}
|
|
19419
|
-
}
|
|
19420
|
-
function countInWindow(window2, now, windowMs) {
|
|
19421
|
-
pruneWindow(window2, now, windowMs);
|
|
19422
|
-
return window2.timestamps.length;
|
|
19423
|
-
}
|
|
19424
|
-
function recordInWindow(window2, now) {
|
|
19425
|
-
window2.timestamps.push(now);
|
|
19426
|
-
}
|
|
19427
|
-
function stableStringify(value) {
|
|
19428
|
-
if (value == null) return String(value);
|
|
19429
|
-
if (typeof value !== "object") return String(value);
|
|
19430
|
-
if (Array.isArray(value)) {
|
|
19431
|
-
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
19432
|
-
}
|
|
19433
|
-
const record2 = value;
|
|
19434
|
-
const keys2 = Object.keys(record2).sort();
|
|
19435
|
-
return `{${keys2.map((key) => `${key}:${stableStringify(record2[key])}`).join(",")}}`;
|
|
19436
|
-
}
|
|
19437
|
-
function fingerprintProperties(properties) {
|
|
19438
|
-
if (!properties) return "";
|
|
19439
|
-
const keys2 = [
|
|
19440
|
-
"error",
|
|
19441
|
-
"error_message",
|
|
19442
|
-
"message",
|
|
19443
|
-
"reason",
|
|
19444
|
-
"status",
|
|
19445
|
-
"code",
|
|
19446
|
-
"asset_id",
|
|
19447
|
-
"doc_id",
|
|
19448
|
-
"thread_id",
|
|
19449
|
-
"session_id",
|
|
19450
|
-
"operation",
|
|
19451
|
-
"path",
|
|
19452
|
-
"url",
|
|
19453
|
-
"chunk_identifier",
|
|
19454
|
-
"validation_path"
|
|
19455
|
-
];
|
|
19456
|
-
const subset = {};
|
|
19457
|
-
for (const key of keys2) {
|
|
19458
|
-
if (key in properties) {
|
|
19459
|
-
subset[key] = properties[key];
|
|
19460
|
-
}
|
|
19461
|
-
}
|
|
19462
|
-
return stableStringify(subset);
|
|
19463
|
-
}
|
|
19464
|
-
function buildCaptureFingerprint(event, properties) {
|
|
19465
|
-
return `${event}|${fingerprintProperties(properties)}`;
|
|
19466
|
-
}
|
|
19467
|
-
function buildCoalescedCaptureProperties(payload) {
|
|
19468
|
-
const windowMs = payload.lastAt - payload.firstAt;
|
|
19469
|
-
return {
|
|
19470
|
-
...payload.properties,
|
|
19471
|
-
coalesced: true,
|
|
19472
|
-
coalesced_count: payload.coalescedCount,
|
|
19473
|
-
coalesced_first_at: new Date(payload.firstAt).toISOString(),
|
|
19474
|
-
coalesced_last_at: new Date(payload.lastAt).toISOString(),
|
|
19475
|
-
coalesced_window_ms: windowMs,
|
|
19476
|
-
coalesced_suppression_reason: payload.suppressionReason
|
|
19477
|
-
};
|
|
19478
|
-
}
|
|
19479
|
-
class PosthogCaptureGate {
|
|
19480
|
-
constructor(config2 = DEFAULT_CAPTURE_GATE_CONFIG) {
|
|
19481
|
-
__publicField(this, "config");
|
|
19482
|
-
__publicField(this, "globalWindow", { timestamps: [] });
|
|
19483
|
-
__publicField(this, "eventWindows", /* @__PURE__ */ new Map());
|
|
19484
|
-
__publicField(this, "activeDedupe", /* @__PURE__ */ new Map());
|
|
19485
|
-
__publicField(this, "coalesceBuckets", /* @__PURE__ */ new Map());
|
|
19486
|
-
__publicField(this, "emittedTotal", 0);
|
|
19487
|
-
__publicField(this, "coalescedTotal", 0);
|
|
19488
|
-
__publicField(this, "flushedCoalescedTotal", 0);
|
|
19489
|
-
this.config = config2;
|
|
19490
|
-
}
|
|
19491
|
-
resetForTests() {
|
|
19492
|
-
this.globalWindow.timestamps.length = 0;
|
|
19493
|
-
this.eventWindows.clear();
|
|
19494
|
-
this.activeDedupe.clear();
|
|
19495
|
-
this.coalesceBuckets.clear();
|
|
19496
|
-
this.emittedTotal = 0;
|
|
19497
|
-
this.coalescedTotal = 0;
|
|
19498
|
-
this.flushedCoalescedTotal = 0;
|
|
19499
|
-
}
|
|
19500
|
-
getSnapshot() {
|
|
19501
|
-
const coalescedPendingByEvent = {};
|
|
19502
|
-
let coalescedPending = 0;
|
|
19503
|
-
for (const bucket of this.coalesceBuckets.values()) {
|
|
19504
|
-
coalescedPending += bucket.count;
|
|
19505
|
-
coalescedPendingByEvent[bucket.event] = (coalescedPendingByEvent[bucket.event] ?? 0) + bucket.count;
|
|
19506
|
-
}
|
|
19507
|
-
return {
|
|
19508
|
-
coalescedPending,
|
|
19509
|
-
coalescedPendingByEvent,
|
|
19510
|
-
emittedTotal: this.emittedTotal,
|
|
19511
|
-
coalescedTotal: this.coalescedTotal,
|
|
19512
|
-
flushedCoalescedTotal: this.flushedCoalescedTotal
|
|
19513
|
-
};
|
|
19514
|
-
}
|
|
19515
|
-
evaluateCapture(event, properties, options, now = Date.now()) {
|
|
19516
|
-
if (shouldBypassCaptureGate(options)) {
|
|
19517
|
-
return { action: "emit" };
|
|
19518
|
-
}
|
|
19519
|
-
const fingerprint = buildCaptureFingerprint(event, properties);
|
|
19520
|
-
const bucketKey = fingerprint;
|
|
19521
|
-
const override = this.config.eventOverrides[event];
|
|
19522
|
-
const dedupeWindowMs = (override == null ? void 0 : override.dedupeWindowMs) ?? this.config.defaultDedupeWindowMs;
|
|
19523
|
-
const lastDedupe = this.activeDedupe.get(event);
|
|
19524
|
-
if (lastDedupe && lastDedupe.fingerprint === fingerprint && now - lastDedupe.at < dedupeWindowMs) {
|
|
19525
|
-
return this.recordCoalesce(event, bucketKey, fingerprint, properties, "dedupe", now);
|
|
19526
|
-
}
|
|
19527
|
-
const critical = isCriticalPosthogEvent(event);
|
|
19528
|
-
const globalCount = countInWindow(this.globalWindow, now, this.config.globalWindowMs);
|
|
19529
|
-
const normalBudget = Math.max(
|
|
19530
|
-
0,
|
|
19531
|
-
this.config.globalMaxPerWindow - this.config.criticalReservePerWindow
|
|
19532
|
-
);
|
|
19533
|
-
if (critical) {
|
|
19534
|
-
if (globalCount >= this.config.globalMaxPerWindow) {
|
|
19535
|
-
return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
|
|
19536
|
-
}
|
|
19537
|
-
} else if (globalCount >= normalBudget) {
|
|
19538
|
-
return this.recordCoalesce(event, bucketKey, fingerprint, properties, "global_budget", now);
|
|
19539
|
-
}
|
|
19540
|
-
const eventWindow = this.eventWindows.get(event) ?? { timestamps: [] };
|
|
19541
|
-
this.eventWindows.set(event, eventWindow);
|
|
19542
|
-
const eventMax = (override == null ? void 0 : override.maxPerWindow) ?? this.config.defaultEventMaxPerWindow;
|
|
19543
|
-
const eventWindowMs = (override == null ? void 0 : override.windowMs) ?? this.config.defaultEventWindowMs;
|
|
19544
|
-
const eventCount = countInWindow(eventWindow, now, eventWindowMs);
|
|
19545
|
-
if (eventCount >= eventMax) {
|
|
19546
|
-
return this.recordCoalesce(event, bucketKey, fingerprint, properties, "event_budget", now);
|
|
19547
|
-
}
|
|
19548
|
-
recordInWindow(this.globalWindow, now);
|
|
19549
|
-
recordInWindow(eventWindow, now);
|
|
19550
|
-
this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
|
|
19551
|
-
this.emittedTotal += 1;
|
|
19552
|
-
return { action: "emit" };
|
|
19553
|
-
}
|
|
19554
|
-
/** Returns payloads ready to flush (does not mutate buckets until caller confirms). */
|
|
19555
|
-
collectFlushCandidates(now = Date.now()) {
|
|
19556
|
-
const payloads = [];
|
|
19557
|
-
for (const bucket of this.coalesceBuckets.values()) {
|
|
19558
|
-
const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
|
|
19559
|
-
const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
|
|
19560
|
-
if (!shouldFlushBySize && !shouldFlushByAge) {
|
|
19561
|
-
continue;
|
|
19562
|
-
}
|
|
19563
|
-
payloads.push({
|
|
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
|
-
return payloads;
|
|
19574
|
-
}
|
|
19575
|
-
/** Remove flushed bucket keys after successful emit. */
|
|
19576
|
-
acknowledgeFlushed(payloads) {
|
|
19577
|
-
for (const payload of payloads) {
|
|
19578
|
-
this.coalesceBuckets.delete(payload.bucketKey);
|
|
19579
|
-
this.flushedCoalescedTotal += payload.coalescedCount;
|
|
19580
|
-
}
|
|
19581
|
-
}
|
|
19582
|
-
/** After coalescing, flush immediately if the bucket crossed the early threshold. */
|
|
19583
|
-
takeBucketIfReady(bucketKey, now = Date.now()) {
|
|
19584
|
-
const bucket = this.coalesceBuckets.get(bucketKey);
|
|
19585
|
-
if (!bucket) return null;
|
|
19586
|
-
const shouldFlushBySize = bucket.count >= this.config.flushCoalesceThreshold;
|
|
19587
|
-
const shouldFlushByAge = now - bucket.firstAt >= this.config.flushIntervalMs;
|
|
19588
|
-
if (!shouldFlushBySize && !shouldFlushByAge) {
|
|
19589
|
-
return null;
|
|
19590
|
-
}
|
|
19591
|
-
this.coalesceBuckets.delete(bucketKey);
|
|
19592
|
-
this.flushedCoalescedTotal += bucket.count;
|
|
19593
|
-
return {
|
|
19594
|
-
bucketKey: bucket.bucketKey,
|
|
19595
|
-
event: bucket.event,
|
|
19596
|
-
properties: bucket.sampleProperties,
|
|
19597
|
-
coalescedCount: bucket.count,
|
|
19598
|
-
firstAt: bucket.firstAt,
|
|
19599
|
-
lastAt: bucket.lastAt,
|
|
19600
|
-
suppressionReason: bucket.suppressionReason
|
|
19601
|
-
};
|
|
19602
|
-
}
|
|
19603
|
-
/** Force-flush every pending bucket (e.g. page hide). */
|
|
19604
|
-
collectAllPending() {
|
|
19605
|
-
return [...this.coalesceBuckets.values()].map((bucket) => ({
|
|
19606
|
-
bucketKey: bucket.bucketKey,
|
|
19607
|
-
event: bucket.event,
|
|
19608
|
-
properties: bucket.sampleProperties,
|
|
19609
|
-
coalescedCount: bucket.count,
|
|
19610
|
-
firstAt: bucket.firstAt,
|
|
19611
|
-
lastAt: bucket.lastAt,
|
|
19612
|
-
suppressionReason: bucket.suppressionReason
|
|
19613
|
-
}));
|
|
19614
|
-
}
|
|
19615
|
-
recordCoalesce(event, bucketKey, fingerprint, properties, reason, now) {
|
|
19616
|
-
const existing = this.coalesceBuckets.get(bucketKey);
|
|
19617
|
-
if (existing) {
|
|
19618
|
-
existing.count += 1;
|
|
19619
|
-
existing.lastAt = now;
|
|
19620
|
-
existing.sampleProperties = { ...existing.sampleProperties, ...properties ?? {} };
|
|
19621
|
-
} else {
|
|
19622
|
-
this.coalesceBuckets.set(bucketKey, {
|
|
19623
|
-
event,
|
|
19624
|
-
bucketKey,
|
|
19625
|
-
fingerprint,
|
|
19626
|
-
count: 1,
|
|
19627
|
-
firstAt: now,
|
|
19628
|
-
lastAt: now,
|
|
19629
|
-
suppressionReason: reason,
|
|
19630
|
-
sampleProperties: { ...properties ?? {} }
|
|
19631
|
-
});
|
|
19632
|
-
}
|
|
19633
|
-
this.coalescedTotal += 1;
|
|
19634
|
-
this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
|
|
19635
|
-
return { action: "coalesce", reason, bucketKey };
|
|
19636
|
-
}
|
|
19637
|
-
}
|
|
19638
|
-
const gate = new PosthogCaptureGate(DEFAULT_CAPTURE_GATE_CONFIG);
|
|
19639
|
-
let wrappedClient = null;
|
|
19640
|
-
let originalCaptureRef = null;
|
|
19641
|
-
let flushTimer = null;
|
|
19642
|
-
let lifecycleHooksInstalled = false;
|
|
19643
|
-
function getPosthogCaptureGate() {
|
|
19644
|
-
return gate;
|
|
19645
|
-
}
|
|
19646
|
-
function emitThroughOriginal(event, properties, options) {
|
|
19647
|
-
if (!originalCaptureRef) return void 0;
|
|
19648
|
-
return originalCaptureRef(event, properties, withCaptureGateBypass(options));
|
|
19649
|
-
}
|
|
19650
|
-
function flushCoalescedPayload(payload) {
|
|
19651
|
-
emitThroughOriginal(payload.event, buildCoalescedCaptureProperties(payload));
|
|
19652
|
-
}
|
|
19653
|
-
function flushCoalescedCaptures(options) {
|
|
19654
|
-
const payloads = (options == null ? void 0 : options.force) ? gate.collectAllPending() : gate.collectFlushCandidates();
|
|
19655
|
-
if (payloads.length === 0) return;
|
|
19656
|
-
for (const payload of payloads) {
|
|
19657
|
-
flushCoalescedPayload(payload);
|
|
19658
|
-
}
|
|
19659
|
-
gate.acknowledgeFlushed(payloads);
|
|
19660
|
-
}
|
|
19661
|
-
function installLifecycleFlushHooks() {
|
|
19662
|
-
if (lifecycleHooksInstalled || typeof window === "undefined") return;
|
|
19663
|
-
lifecycleHooksInstalled = true;
|
|
19664
|
-
const flushOnHide = () => {
|
|
19665
|
-
flushCoalescedCaptures({ force: true });
|
|
19666
|
-
};
|
|
19667
|
-
window.addEventListener("pagehide", flushOnHide);
|
|
19668
|
-
document.addEventListener("visibilitychange", () => {
|
|
19669
|
-
if (document.visibilityState === "hidden") {
|
|
19670
|
-
flushOnHide();
|
|
19671
|
-
}
|
|
19672
|
-
});
|
|
19673
|
-
if (!flushTimer) {
|
|
19674
|
-
flushTimer = setInterval(() => {
|
|
19675
|
-
flushCoalescedCaptures();
|
|
19676
|
-
}, DEFAULT_CAPTURE_GATE_CONFIG.flushIntervalMs);
|
|
19677
|
-
}
|
|
19678
|
-
}
|
|
19679
|
-
function wrapPosthogClient(client) {
|
|
19680
|
-
if (wrappedClient === client) {
|
|
19681
|
-
return client;
|
|
19682
|
-
}
|
|
19683
|
-
originalCaptureRef = client.capture.bind(client);
|
|
19684
|
-
const originalCaptureException = typeof client.captureException === "function" ? client.captureException.bind(client) : null;
|
|
19685
|
-
installLifecycleFlushHooks();
|
|
19686
|
-
client.capture = ((event, properties, options) => {
|
|
19687
|
-
const outcome = gate.evaluateCapture(event, properties, options);
|
|
19688
|
-
if (outcome.action === "coalesce") {
|
|
19689
|
-
const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
|
|
19690
|
-
if (readyPayload) {
|
|
19691
|
-
flushCoalescedPayload(readyPayload);
|
|
19692
|
-
}
|
|
19693
|
-
return void 0;
|
|
19694
|
-
}
|
|
19695
|
-
return emitThroughOriginal(event, properties, options);
|
|
19696
|
-
});
|
|
19697
|
-
if (originalCaptureException) {
|
|
19698
|
-
client.captureException = ((error2, additionalProperties) => {
|
|
19699
|
-
const mergedProperties = {
|
|
19700
|
-
...additionalProperties ?? {},
|
|
19701
|
-
$exception_message: error2 instanceof Error ? error2.message : String(error2),
|
|
19702
|
-
$exception_type: error2 instanceof Error ? error2.name : typeof error2
|
|
19703
|
-
};
|
|
19704
|
-
const outcome = gate.evaluateCapture("$exception", mergedProperties);
|
|
19705
|
-
if (outcome.action === "coalesce") {
|
|
19706
|
-
const readyPayload = gate.takeBucketIfReady(outcome.bucketKey);
|
|
19707
|
-
if (readyPayload) {
|
|
19708
|
-
flushCoalescedPayload(readyPayload);
|
|
19709
|
-
}
|
|
19710
|
-
return void 0;
|
|
19711
|
-
}
|
|
19712
|
-
return originalCaptureException(error2, additionalProperties);
|
|
19713
|
-
});
|
|
19714
|
-
}
|
|
19715
|
-
wrappedClient = client;
|
|
19716
|
-
return client;
|
|
19717
|
-
}
|
|
19718
|
-
function capturePosthogEvent(client, event, properties, options) {
|
|
19719
|
-
if (!client || typeof client.capture !== "function") return;
|
|
19720
|
-
client.capture(event, properties, options);
|
|
19721
|
-
}
|
|
19722
|
-
function capturePosthogException(client, error2, properties, options) {
|
|
19723
|
-
if (!client) return;
|
|
19724
|
-
if (typeof client.captureException === "function") {
|
|
19725
|
-
client.captureException(error2, properties);
|
|
19726
|
-
return;
|
|
19727
|
-
}
|
|
19728
|
-
capturePosthogEvent(
|
|
19729
|
-
client,
|
|
19730
|
-
"$exception",
|
|
19731
|
-
{
|
|
19732
|
-
...properties ?? {},
|
|
19733
|
-
$exception_message: error2.message,
|
|
19734
|
-
$exception_type: error2.name,
|
|
19735
|
-
$exception_stack: error2.stack
|
|
19736
|
-
},
|
|
19737
|
-
options
|
|
19738
|
-
);
|
|
19739
|
-
}
|
|
19740
|
-
let posthogInstance = null;
|
|
19741
|
-
let initPromise = null;
|
|
19742
|
-
const DEFAULT_HOST = "https://us.i.posthog.com";
|
|
19743
|
-
async function initializePostHog(apiKey, host, debug) {
|
|
19744
|
-
if (posthogInstance) return posthogInstance;
|
|
19745
|
-
if (typeof window === "undefined") return null;
|
|
19746
|
-
try {
|
|
19747
|
-
const posthog = (await import("posthog-js")).default;
|
|
19748
|
-
posthog.init(apiKey, {
|
|
19749
|
-
api_host: host,
|
|
19750
|
-
autocapture: true,
|
|
19751
|
-
capture_pageview: false,
|
|
19752
|
-
session_recording: {
|
|
19753
|
-
recordCrossOriginIframes: true,
|
|
19754
|
-
maskAllInputs: true
|
|
19755
|
-
},
|
|
19756
|
-
loaded: (ph) => {
|
|
19757
|
-
wrapPosthogClient(ph);
|
|
19758
|
-
if (debug) {
|
|
19759
|
-
ph.debug(true);
|
|
19760
|
-
}
|
|
19761
|
-
}
|
|
19762
|
-
});
|
|
19763
|
-
wrapPosthogClient(posthog);
|
|
19764
|
-
posthogInstance = posthog;
|
|
19765
|
-
return posthog;
|
|
19766
|
-
} catch {
|
|
19767
|
-
initPromise = null;
|
|
19768
|
-
return null;
|
|
19769
|
-
}
|
|
19770
|
-
}
|
|
19771
|
-
function getPostHogInstance() {
|
|
19772
|
-
return posthogInstance;
|
|
19773
|
-
}
|
|
19774
|
-
function PostHogProvider({
|
|
19775
|
-
children,
|
|
19776
|
-
config: config2
|
|
19777
|
-
}) {
|
|
19778
|
-
const apiKey = (config2 == null ? void 0 : config2.apiKey) ?? "";
|
|
19779
|
-
const host = (config2 == null ? void 0 : config2.host) ?? DEFAULT_HOST;
|
|
19780
|
-
const debug = (config2 == null ? void 0 : config2.debug) ?? false;
|
|
19781
|
-
React.useEffect(() => {
|
|
19782
|
-
if (!apiKey || typeof window === "undefined") return;
|
|
19783
|
-
if (!initPromise) {
|
|
19784
|
-
initPromise = initializePostHog(apiKey, host, debug);
|
|
19785
|
-
}
|
|
19786
|
-
}, [apiKey, host, debug]);
|
|
19787
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
19788
|
-
}
|
|
19789
20390
|
const resolveTokenOverride = ({
|
|
19790
20391
|
config: config2,
|
|
19791
20392
|
token
|
|
@@ -19915,6 +20516,8 @@ function AthenaStatewireStandalone({
|
|
|
19915
20516
|
token,
|
|
19916
20517
|
getToken,
|
|
19917
20518
|
model,
|
|
20519
|
+
agent: agent2,
|
|
20520
|
+
channel,
|
|
19918
20521
|
tools,
|
|
19919
20522
|
frontendToolIds,
|
|
19920
20523
|
frontendTools,
|
|
@@ -19946,6 +20549,8 @@ function AthenaStatewireStandalone({
|
|
|
19946
20549
|
token,
|
|
19947
20550
|
getToken,
|
|
19948
20551
|
model,
|
|
20552
|
+
agent: agent2,
|
|
20553
|
+
channel,
|
|
19949
20554
|
tools,
|
|
19950
20555
|
frontendToolIds,
|
|
19951
20556
|
frontendToolkit: frontendTools,
|
|
@@ -20221,6 +20826,7 @@ function AthenaProvider({
|
|
|
20221
20826
|
apiKey,
|
|
20222
20827
|
token: tokenProp,
|
|
20223
20828
|
agent: agent2,
|
|
20829
|
+
channel,
|
|
20224
20830
|
model,
|
|
20225
20831
|
tools = [],
|
|
20226
20832
|
frontendTools = {},
|
|
@@ -20243,8 +20849,32 @@ function AthenaProvider({
|
|
|
20243
20849
|
theme,
|
|
20244
20850
|
linkClicks,
|
|
20245
20851
|
citationLinks,
|
|
20246
|
-
posthog: posthogProp
|
|
20852
|
+
posthog: posthogProp,
|
|
20853
|
+
debug,
|
|
20854
|
+
onDiagnostic,
|
|
20855
|
+
onError
|
|
20247
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]);
|
|
20248
20878
|
const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
|
|
20249
20879
|
const effectiveFrontendTools = React.useMemo(
|
|
20250
20880
|
() => disableAutoOpen ? frontendTools : { ...DEFAULT_AUTO_OPEN_TOOLS, ...frontendTools },
|
|
@@ -20271,10 +20901,31 @@ function AthenaProvider({
|
|
|
20271
20901
|
transport: configuredTransport
|
|
20272
20902
|
});
|
|
20273
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
|
+
});
|
|
20274
20909
|
if (transportFallbackReason) {
|
|
20910
|
+
athenaDiagnostics.emit("sdk.config.warning", {
|
|
20911
|
+
level: "warn",
|
|
20912
|
+
data: { prop: "transport", reason: transportFallbackReason }
|
|
20913
|
+
});
|
|
20275
20914
|
console.warn(`[AthenaSDK] ${transportFallbackReason}`);
|
|
20276
20915
|
}
|
|
20277
|
-
}, [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]);
|
|
20278
20929
|
const bridge = useParentBridge({
|
|
20279
20930
|
trustedOrigins: configuredTrustedParentOrigins
|
|
20280
20931
|
});
|
|
@@ -20301,6 +20952,8 @@ function AthenaProvider({
|
|
|
20301
20952
|
token: effectiveToken,
|
|
20302
20953
|
getToken: configuredGetToken,
|
|
20303
20954
|
model,
|
|
20955
|
+
agent: agent2,
|
|
20956
|
+
channel,
|
|
20304
20957
|
tools,
|
|
20305
20958
|
frontendToolIds: frontendToolNames,
|
|
20306
20959
|
frontendTools: effectiveFrontendTools,
|
|
@@ -54652,13 +55305,13 @@ function getEmptyMessage(scope, query) {
|
|
|
54652
55305
|
function MentionIcon({ item }) {
|
|
54653
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 }) });
|
|
54654
55307
|
}
|
|
54655
|
-
const MentionSuggestionList = React.forwardRef(({ store, query, command: command2, closeMenu }, ref) => {
|
|
55308
|
+
const MentionSuggestionList = React.forwardRef(({ store: store2, query, command: command2, closeMenu }, ref) => {
|
|
54656
55309
|
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
|
54657
55310
|
const [currentScope, setCurrentScope] = React.useState("root");
|
|
54658
55311
|
const scrollContainerRef = React.useRef(null);
|
|
54659
|
-
const hasGlobalSearch =
|
|
55312
|
+
const hasGlobalSearch = store2.state.registry.entries.has(GLOBAL_SEARCH_SCOPE$1);
|
|
54660
55313
|
const effectiveScope = currentScope === "root" && query.trim() && hasGlobalSearch ? GLOBAL_SEARCH_SCOPE$1 : currentScope;
|
|
54661
|
-
const { items, isFetching } = useStore(
|
|
55314
|
+
const { items, isFetching } = useStore(store2, (state) => ({
|
|
54662
55315
|
items: getFilteredItems(state.cache, effectiveScope, query),
|
|
54663
55316
|
isFetching: false
|
|
54664
55317
|
}));
|
|
@@ -54777,7 +55430,7 @@ const MentionSuggestionList = React.forwardRef(({ store, query, command: command
|
|
|
54777
55430
|
] });
|
|
54778
55431
|
});
|
|
54779
55432
|
MentionSuggestionList.displayName = "MentionSuggestionList";
|
|
54780
|
-
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) => {
|
|
54781
55434
|
const listRef = React.useRef(null);
|
|
54782
55435
|
const virtualRef = React.useRef({
|
|
54783
55436
|
getBoundingClientRect: () => clientRect2 ? clientRect2() : new DOMRect()
|
|
@@ -54824,7 +55477,7 @@ const MentionSuggestionPopup = React.forwardRef(({ store, query, command: comman
|
|
|
54824
55477
|
MentionSuggestionList,
|
|
54825
55478
|
{
|
|
54826
55479
|
ref: listRef,
|
|
54827
|
-
store,
|
|
55480
|
+
store: store2,
|
|
54828
55481
|
query,
|
|
54829
55482
|
command: command2,
|
|
54830
55483
|
closeMenu
|
|
@@ -55051,9 +55704,9 @@ function useMentionSuggestions(tools, options = {}) {
|
|
|
55051
55704
|
populateMentionCache({ cache, tools, rootCategories });
|
|
55052
55705
|
storeRef.current = new Store({ registry: registry2, cache });
|
|
55053
55706
|
}
|
|
55054
|
-
const
|
|
55707
|
+
const store2 = storeRef.current;
|
|
55055
55708
|
React.useEffect(() => {
|
|
55056
|
-
|
|
55709
|
+
store2.setState((prev) => {
|
|
55057
55710
|
const newCache = createItemCache();
|
|
55058
55711
|
if (rootCategories) {
|
|
55059
55712
|
registerStaticSource(prev.registry, "toolkits");
|
|
@@ -55063,8 +55716,8 @@ function useMentionSuggestions(tools, options = {}) {
|
|
|
55063
55716
|
populateMentionCache({ cache: newCache, tools, rootCategories });
|
|
55064
55717
|
return { ...prev, cache: newCache };
|
|
55065
55718
|
});
|
|
55066
|
-
}, [tools,
|
|
55067
|
-
return
|
|
55719
|
+
}, [tools, store2, rootCategories, rootCategoriesKey]);
|
|
55720
|
+
return store2;
|
|
55068
55721
|
}
|
|
55069
55722
|
const AttachmentCtx = React.createContext(null);
|
|
55070
55723
|
function AttachmentProvider({ children }) {
|
|
@@ -57489,10 +58142,10 @@ function openStudioAsset({
|
|
|
57489
58142
|
slideNumber,
|
|
57490
58143
|
preserveExistingSlide
|
|
57491
58144
|
}) {
|
|
57492
|
-
const
|
|
57493
|
-
const existing =
|
|
58145
|
+
const store2 = useAssetPanelStore.getState();
|
|
58146
|
+
const existing = store2.tabs.find((tab) => tab.id === assetId);
|
|
57494
58147
|
const shouldKeepCurrentSlide = preserveExistingSlide && existing;
|
|
57495
|
-
|
|
58148
|
+
store2.openAsset(assetId, {
|
|
57496
58149
|
type: assetType,
|
|
57497
58150
|
...!shouldKeepCurrentSlide && slideNumber !== void 0 ? { slideNumber } : {}
|
|
57498
58151
|
});
|
|
@@ -62457,6 +63110,8 @@ function useComposerAttachment() {
|
|
|
62457
63110
|
}, [aui]);
|
|
62458
63111
|
return { addFile, addContent, clear };
|
|
62459
63112
|
}
|
|
63113
|
+
exports.ATHENA_REACT_SDK_VERSION = ATHENA_REACT_SDK_VERSION;
|
|
63114
|
+
exports.ATHENA_SDK_ERROR_CODES = ATHENA_SDK_ERROR_CODES;
|
|
62460
63115
|
exports.ATHENA_TRANSPORTS = ATHENA_TRANSPORTS;
|
|
62461
63116
|
exports.AppendDocumentToolUI = AppendDocumentToolUI;
|
|
62462
63117
|
exports.AssetPanel = AssetPanel;
|
|
@@ -62467,10 +63122,12 @@ exports.AthenaChat = AthenaChat;
|
|
|
62467
63122
|
exports.AthenaLayout = AthenaLayout;
|
|
62468
63123
|
exports.AthenaProvider = AthenaProvider;
|
|
62469
63124
|
exports.AthenaReasoningPart = AthenaReasoningPart;
|
|
63125
|
+
exports.AthenaSdkError = AthenaSdkError;
|
|
62470
63126
|
exports.AthenaThreadIdContext = AthenaThreadIdContext;
|
|
62471
63127
|
exports.AthenaUserMessage = AthenaUserMessage;
|
|
62472
63128
|
exports.BrowseToolUI = BrowseToolUI;
|
|
62473
63129
|
exports.Button = Button;
|
|
63130
|
+
exports.COLLAB_AGENT_REF_PREFIX = COLLAB_AGENT_REF_PREFIX;
|
|
62474
63131
|
exports.Collapsible = Collapsible;
|
|
62475
63132
|
exports.CollapsibleContent = CollapsibleContent;
|
|
62476
63133
|
exports.CollapsibleTrigger = CollapsibleTrigger;
|
|
@@ -62530,6 +63187,7 @@ exports.WebSearchToolUI = WebSearchToolUI;
|
|
|
62530
63187
|
exports.allowsMidRunSend = allowsMidRunSend;
|
|
62531
63188
|
exports.archiveThread = archiveThread;
|
|
62532
63189
|
exports.asHitlApproval = asHitlApproval;
|
|
63190
|
+
exports.athenaDiagnostics = athenaDiagnostics;
|
|
62533
63191
|
exports.athenaStatewireErrorNotice = athenaStatewireErrorNotice;
|
|
62534
63192
|
exports.autoCloseInFlightSubgraphMessages = autoCloseInFlightSubgraphMessages;
|
|
62535
63193
|
exports.buildCoalescedCaptureProperties = buildCoalescedCaptureProperties;
|
|
@@ -62553,13 +63211,17 @@ exports.getPostHogInstance = getPostHogInstance;
|
|
|
62553
63211
|
exports.getPosthogCaptureGate = getPosthogCaptureGate;
|
|
62554
63212
|
exports.getThreadState = getThreadState;
|
|
62555
63213
|
exports.hasStatewireThreadExtras = hasStatewireThreadExtras;
|
|
63214
|
+
exports.installAthenaDiagnosticsGlobal = installAthenaDiagnosticsGlobal;
|
|
62556
63215
|
exports.isAthenaCitationUrl = isAthenaCitationUrl;
|
|
63216
|
+
exports.isAthenaSdkError = isAthenaSdkError;
|
|
62557
63217
|
exports.isCriticalPosthogEvent = isCriticalPosthogEvent;
|
|
62558
63218
|
exports.isPendingInterrupt = isPendingInterrupt;
|
|
62559
63219
|
exports.listThreads = listThreads;
|
|
62560
63220
|
exports.normalizeResult = normalizeResult;
|
|
62561
63221
|
exports.parseAthenaCitationLink = parseAthenaCitationLink;
|
|
63222
|
+
exports.parseCollabAgentRef = parseCollabAgentRef;
|
|
62562
63223
|
exports.readInterruptMessage = readInterruptMessage;
|
|
63224
|
+
exports.readRejectionDetail = readRejectionDetail;
|
|
62563
63225
|
exports.resetAssetAutoOpen = resetAssetAutoOpen;
|
|
62564
63226
|
exports.resolveAthenaTransport = resolveAthenaTransport;
|
|
62565
63227
|
exports.resolveStatewireSyncUrl = resolveStatewireSyncUrl;
|
|
@@ -62567,6 +63229,7 @@ exports.setThreadReadState = setThreadReadState;
|
|
|
62567
63229
|
exports.statewireClientToolWireEntries = statewireClientToolWireEntries;
|
|
62568
63230
|
exports.themeToStyleVars = themeToStyleVars;
|
|
62569
63231
|
exports.themes = themes;
|
|
63232
|
+
exports.toAthenaSdkError = toAthenaSdkError;
|
|
62570
63233
|
exports.truncate = truncate;
|
|
62571
63234
|
exports.tryParseJson = tryParseJson$2;
|
|
62572
63235
|
exports.useAppendToComposer = useAppendToComposer;
|
|
@@ -62574,6 +63237,7 @@ exports.useAssetEmbed = useAssetEmbed;
|
|
|
62574
63237
|
exports.useAssetPanelStore = useAssetPanelStore;
|
|
62575
63238
|
exports.useAthenaCitationLinkHandler = useAthenaCitationLinkHandler;
|
|
62576
63239
|
exports.useAthenaConfig = useAthenaConfig;
|
|
63240
|
+
exports.useAthenaDiagnostics = useAthenaDiagnostics;
|
|
62577
63241
|
exports.useAthenaLinkClickHandler = useAthenaLinkClickHandler;
|
|
62578
63242
|
exports.useAthenaRuntime = useAthenaRuntime;
|
|
62579
63243
|
exports.useAthenaStatewireLifecycle = useAthenaStatewireLifecycle;
|