@athenaintel/react 0.10.41 → 0.11.1
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/README.md +123 -3
- 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 +2008 -1156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +2036 -1184
- 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/tools/tool-uis.d.ts +18 -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,231 +72,1134 @@ function _interopNamespaceDefault(e) {
|
|
|
71
72
|
}
|
|
72
73
|
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
73
74
|
const ReactDOM__namespace = /* @__PURE__ */ _interopNamespaceDefault(ReactDOM);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
backendUrl: "https://api.athenaintel.com/api/assistant-ui",
|
|
78
|
-
appUrl: "https://app.athenaintel.com"
|
|
79
|
-
},
|
|
80
|
-
staging: {
|
|
81
|
-
apiUrl: "https://iris.stg.athenaintel.com/api/chat",
|
|
82
|
-
backendUrl: "https://staging-api.athenaintel.com/api/assistant-ui",
|
|
83
|
-
appUrl: "https://staging-app.athenaintel.com"
|
|
84
|
-
}
|
|
75
|
+
const version$1 = "0.11.1";
|
|
76
|
+
const packageJson = {
|
|
77
|
+
version: version$1
|
|
85
78
|
};
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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 }
|
|
101
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));
|
|
102
140
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}) {
|
|
107
|
-
if (statewireSyncUrl) return statewireSyncUrl;
|
|
108
|
-
const derived = deriveStatewireSyncUrl({ apiUrl });
|
|
109
|
-
if (derived) return derived;
|
|
110
|
-
throw new Error(
|
|
111
|
-
`[AthenaSDK] transport 'statewire' could not derive a sync URL from apiUrl (${JSON.stringify(
|
|
112
|
-
apiUrl ?? null
|
|
113
|
-
)}). Pass an explicit statewireSyncUrl (the …/v2/threads mount). Credentials are never sent to a default host.`
|
|
114
|
-
);
|
|
141
|
+
function shouldBypassCaptureGate(options) {
|
|
142
|
+
if (!options || typeof options !== "object") return false;
|
|
143
|
+
return options[BYPASS_OPTION_KEY] === true;
|
|
115
144
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const getHostname$1 = (value) => {
|
|
127
|
-
if (!value) return null;
|
|
128
|
-
try {
|
|
129
|
-
return new URL(value).hostname;
|
|
130
|
-
} catch {
|
|
131
|
-
return null;
|
|
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();
|
|
132
155
|
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
return `${parsedUrl.protocol}//${match2.groups.prefix}--${MARATHON_APP_PORT}.${match2.groups.domain}`;
|
|
148
|
-
} catch {
|
|
149
|
-
return null;
|
|
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(",")}]`;
|
|
150
169
|
}
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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];
|
|
161
197
|
}
|
|
162
|
-
return `${parsedUrl.protocol}//${match2.groups.prefix}--8787.${match2.groups.domain}/api/chat`;
|
|
163
|
-
} catch {
|
|
164
|
-
return null;
|
|
165
198
|
}
|
|
166
|
-
|
|
167
|
-
function getAthenaEnvironmentUrls({
|
|
168
|
-
environment = DEFAULT_ATHENA_ENVIRONMENT
|
|
169
|
-
} = {}) {
|
|
170
|
-
return ATHENA_ENVIRONMENT_URLS[environment];
|
|
199
|
+
return stableStringify(subset);
|
|
171
200
|
}
|
|
172
|
-
function
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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;
|
|
182
243
|
}
|
|
183
|
-
|
|
184
|
-
|
|
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" };
|
|
185
255
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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);
|
|
192
263
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
sourcePort: "8000"
|
|
206
|
-
});
|
|
207
|
-
if (workspaceAppUrl) return workspaceAppUrl;
|
|
208
|
-
const backendHostname = getHostname$1(backendUrl);
|
|
209
|
-
if (backendHostname === "api.athenaintel.com") {
|
|
210
|
-
return ATHENA_ENVIRONMENT_URLS.production.appUrl;
|
|
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);
|
|
211
276
|
}
|
|
212
|
-
|
|
213
|
-
|
|
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);
|
|
214
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" };
|
|
215
290
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
+
});
|
|
225
309
|
}
|
|
226
|
-
|
|
227
|
-
|
|
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;
|
|
228
317
|
}
|
|
229
318
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (assetIds) {
|
|
239
|
-
const normalizedAssetIds = (Array.isArray(assetIds) ? assetIds : [assetIds]).map((assetId) => assetId.trim()).filter((assetId) => assetId.length > 0);
|
|
240
|
-
if (normalizedAssetIds.length > 0) {
|
|
241
|
-
url.searchParams.set("asset_ids", normalizedAssetIds.join(","));
|
|
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;
|
|
242
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
|
+
};
|
|
243
339
|
}
|
|
244
|
-
|
|
245
|
-
|
|
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
|
+
}));
|
|
246
351
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
+
});
|
|
257
369
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return false;
|
|
370
|
+
this.coalescedTotal += 1;
|
|
371
|
+
this.activeDedupe.set(event, { fingerprint, bucketKey, at: now });
|
|
372
|
+
return { action: "coalesce", reason, bucketKey };
|
|
262
373
|
}
|
|
263
374
|
}
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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);
|
|
275
395
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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);
|
|
280
414
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
415
|
+
}
|
|
416
|
+
function wrapPosthogClient(client) {
|
|
417
|
+
if (wrappedClient === client) {
|
|
418
|
+
return client;
|
|
284
419
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
+
}
|
|
978
|
+
const ATHENA_ENVIRONMENT_URLS = {
|
|
979
|
+
production: {
|
|
980
|
+
apiUrl: "https://iris.prd.athenaintel.com/api/chat",
|
|
981
|
+
backendUrl: "https://api.athenaintel.com/api/assistant-ui",
|
|
982
|
+
appUrl: "https://app.athenaintel.com"
|
|
983
|
+
},
|
|
984
|
+
staging: {
|
|
985
|
+
apiUrl: "https://iris.stg.athenaintel.com/api/chat",
|
|
986
|
+
backendUrl: "https://staging-api.athenaintel.com/api/assistant-ui",
|
|
987
|
+
appUrl: "https://staging-app.athenaintel.com"
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
const DEFAULT_ATHENA_ENVIRONMENT = "production";
|
|
991
|
+
const DEFAULT_API_URL = ATHENA_ENVIRONMENT_URLS.production.apiUrl;
|
|
992
|
+
const DEFAULT_BACKEND_URL = ATHENA_ENVIRONMENT_URLS.production.backendUrl;
|
|
993
|
+
const DEFAULT_APP_URL = ATHENA_ENVIRONMENT_URLS.production.appUrl;
|
|
994
|
+
const DEFAULT_STATEWIRE_SYNC_URL = "https://iris.prd.athenaintel.com/v2/threads";
|
|
995
|
+
const STATEWIRE_SYNC_PATHNAME = "/v2/threads";
|
|
996
|
+
function deriveStatewireSyncUrl({
|
|
997
|
+
apiUrl
|
|
998
|
+
}) {
|
|
999
|
+
if (!apiUrl) return null;
|
|
1000
|
+
try {
|
|
1001
|
+
const parsedUrl = new URL(apiUrl);
|
|
1002
|
+
return `${parsedUrl.origin}${STATEWIRE_SYNC_PATHNAME}`;
|
|
1003
|
+
} catch {
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
function resolveStatewireSyncUrl({
|
|
1008
|
+
statewireSyncUrl,
|
|
1009
|
+
apiUrl
|
|
1010
|
+
}) {
|
|
1011
|
+
if (statewireSyncUrl) return statewireSyncUrl;
|
|
1012
|
+
const derived = deriveStatewireSyncUrl({ apiUrl });
|
|
1013
|
+
if (derived) return derived;
|
|
1014
|
+
throw new Error(
|
|
1015
|
+
`[AthenaSDK] transport 'statewire' could not derive a sync URL from apiUrl (${JSON.stringify(
|
|
1016
|
+
apiUrl ?? null
|
|
1017
|
+
)}). Pass an explicit statewireSyncUrl (the …/v2/threads mount). Credentials are never sent to a default host.`
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
const MARATHON_APP_PORT = "8082";
|
|
1021
|
+
const SPACES_PATHNAME = "dashboard/spaces/";
|
|
1022
|
+
const normalizeBaseUrl = (url) => url.replace(/\/+$/, "");
|
|
1023
|
+
const createUrlWithFallback = (url, fallbackUrl) => {
|
|
1024
|
+
try {
|
|
1025
|
+
return new URL(`${normalizeBaseUrl(url)}/`);
|
|
1026
|
+
} catch {
|
|
1027
|
+
return new URL(`${normalizeBaseUrl(fallbackUrl)}/`);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
const getHostname$1 = (value) => {
|
|
1031
|
+
if (!value) return null;
|
|
1032
|
+
try {
|
|
1033
|
+
return new URL(value).hostname;
|
|
1034
|
+
} catch {
|
|
1035
|
+
return null;
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
const deriveWorkspaceAppUrl = ({
|
|
1039
|
+
sourceUrl,
|
|
1040
|
+
sourcePort
|
|
1041
|
+
}) => {
|
|
1042
|
+
var _a3;
|
|
1043
|
+
try {
|
|
1044
|
+
const parsedUrl = new URL(sourceUrl);
|
|
1045
|
+
const match2 = parsedUrl.hostname.match(
|
|
1046
|
+
new RegExp(`^(?<prefix>.+)--${sourcePort}\\.(?<domain>app\\.athenaintel\\.com|staging-app\\.athenaintel\\.com)$`)
|
|
1047
|
+
);
|
|
1048
|
+
if (!((_a3 = match2 == null ? void 0 : match2.groups) == null ? void 0 : _a3.prefix) || !match2.groups.domain) {
|
|
1049
|
+
return null;
|
|
1050
|
+
}
|
|
1051
|
+
return `${parsedUrl.protocol}//${match2.groups.prefix}--${MARATHON_APP_PORT}.${match2.groups.domain}`;
|
|
1052
|
+
} catch {
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
const deriveWorkspaceApiUrl = (backendUrl) => {
|
|
1057
|
+
var _a3;
|
|
1058
|
+
try {
|
|
1059
|
+
const parsedUrl = new URL(backendUrl);
|
|
1060
|
+
const match2 = parsedUrl.hostname.match(
|
|
1061
|
+
/^(?<prefix>.+)--8000\.(?<domain>app\.athenaintel\.com|staging-app\.athenaintel\.com)$/
|
|
1062
|
+
);
|
|
1063
|
+
if (!((_a3 = match2 == null ? void 0 : match2.groups) == null ? void 0 : _a3.prefix) || !match2.groups.domain) {
|
|
1064
|
+
return null;
|
|
1065
|
+
}
|
|
1066
|
+
return `${parsedUrl.protocol}//${match2.groups.prefix}--8787.${match2.groups.domain}/api/chat`;
|
|
1067
|
+
} catch {
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
function getAthenaEnvironmentUrls({
|
|
1072
|
+
environment = DEFAULT_ATHENA_ENVIRONMENT
|
|
1073
|
+
} = {}) {
|
|
1074
|
+
return ATHENA_ENVIRONMENT_URLS[environment];
|
|
1075
|
+
}
|
|
1076
|
+
function deriveAthenaApiUrl({
|
|
1077
|
+
backendUrl
|
|
1078
|
+
}) {
|
|
1079
|
+
if (!backendUrl) return null;
|
|
1080
|
+
const workspaceApiUrl = deriveWorkspaceApiUrl(backendUrl);
|
|
1081
|
+
if (workspaceApiUrl) return workspaceApiUrl;
|
|
1082
|
+
try {
|
|
1083
|
+
const parsedUrl = new URL(backendUrl);
|
|
1084
|
+
if (parsedUrl.hostname === "api.athenaintel.com") {
|
|
1085
|
+
return ATHENA_ENVIRONMENT_URLS.production.apiUrl;
|
|
1086
|
+
}
|
|
1087
|
+
if (parsedUrl.hostname === "staging-api.athenaintel.com") {
|
|
1088
|
+
return ATHENA_ENVIRONMENT_URLS.staging.apiUrl;
|
|
1089
|
+
}
|
|
1090
|
+
if (parsedUrl.hostname === "localhost" || parsedUrl.hostname === "127.0.0.1") {
|
|
1091
|
+
parsedUrl.port = "8787";
|
|
1092
|
+
parsedUrl.pathname = "/api/chat";
|
|
1093
|
+
parsedUrl.search = "";
|
|
1094
|
+
parsedUrl.hash = "";
|
|
1095
|
+
return parsedUrl.toString();
|
|
1096
|
+
}
|
|
1097
|
+
} catch {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1102
|
+
function deriveAthenaAppUrl({
|
|
1103
|
+
apiUrl,
|
|
1104
|
+
backendUrl
|
|
1105
|
+
}) {
|
|
1106
|
+
if (backendUrl) {
|
|
1107
|
+
const workspaceAppUrl = deriveWorkspaceAppUrl({
|
|
1108
|
+
sourceUrl: backendUrl,
|
|
1109
|
+
sourcePort: "8000"
|
|
1110
|
+
});
|
|
1111
|
+
if (workspaceAppUrl) return workspaceAppUrl;
|
|
1112
|
+
const backendHostname = getHostname$1(backendUrl);
|
|
1113
|
+
if (backendHostname === "api.athenaintel.com") {
|
|
1114
|
+
return ATHENA_ENVIRONMENT_URLS.production.appUrl;
|
|
1115
|
+
}
|
|
1116
|
+
if (backendHostname === "staging-api.athenaintel.com") {
|
|
1117
|
+
return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
if (apiUrl) {
|
|
1121
|
+
const workspaceAppUrl = deriveWorkspaceAppUrl({
|
|
1122
|
+
sourceUrl: apiUrl,
|
|
1123
|
+
sourcePort: "8787"
|
|
1124
|
+
});
|
|
1125
|
+
if (workspaceAppUrl) return workspaceAppUrl;
|
|
1126
|
+
const apiHostname = getHostname$1(apiUrl);
|
|
1127
|
+
if (apiHostname === "sync.athenaintel.com" || apiHostname === "iris.prd.athenaintel.com") {
|
|
1128
|
+
return ATHENA_ENVIRONMENT_URLS.production.appUrl;
|
|
1129
|
+
}
|
|
1130
|
+
if (apiHostname === "staging-sync.athenaintel.com" || apiHostname === "iris.stg.athenaintel.com") {
|
|
1131
|
+
return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
function createAthenaSpacesUrl({
|
|
1137
|
+
appUrl = DEFAULT_APP_URL,
|
|
1138
|
+
assetIds,
|
|
1139
|
+
sessionId
|
|
1140
|
+
}) {
|
|
1141
|
+
const url = new URL(SPACES_PATHNAME, createUrlWithFallback(appUrl, DEFAULT_APP_URL));
|
|
1142
|
+
if (assetIds) {
|
|
1143
|
+
const normalizedAssetIds = (Array.isArray(assetIds) ? assetIds : [assetIds]).map((assetId) => assetId.trim()).filter((assetId) => assetId.length > 0);
|
|
1144
|
+
if (normalizedAssetIds.length > 0) {
|
|
1145
|
+
url.searchParams.set("asset_ids", normalizedAssetIds.join(","));
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
if (sessionId) {
|
|
1149
|
+
url.searchParams.set("session_id", sessionId);
|
|
1150
|
+
}
|
|
1151
|
+
return url.toString();
|
|
1152
|
+
}
|
|
1153
|
+
function isTrustedOrigin({
|
|
1154
|
+
origin,
|
|
1155
|
+
trustedOrigins
|
|
1156
|
+
}) {
|
|
1157
|
+
try {
|
|
1158
|
+
const normalizedOrigin = new URL(origin).origin;
|
|
1159
|
+
if (trustedOrigins.includes(normalizedOrigin)) {
|
|
1160
|
+
return true;
|
|
1161
|
+
}
|
|
1162
|
+
const { hostname } = new URL(normalizedOrigin);
|
|
1163
|
+
return hostname === "athenaintel.com" || hostname.endsWith(".athenaintel.com") || hostname === "localhost";
|
|
1164
|
+
} catch {
|
|
1165
|
+
return false;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
const BRIDGE_TIMEOUT_MS = 2e3;
|
|
1169
|
+
const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
1170
|
+
const TOKEN_REFRESH_RETRY_BASE_MS = 60 * 1e3;
|
|
1171
|
+
const TOKEN_REFRESH_RETRY_MAX_MS = 5 * 60 * 1e3;
|
|
1172
|
+
const DEFAULT_TOKEN_REFRESH_MS = 55 * 60 * 1e3;
|
|
1173
|
+
const EMPTY_TRUSTED_ORIGINS = [];
|
|
1174
|
+
const normalizeOrigin = (value) => {
|
|
1175
|
+
try {
|
|
1176
|
+
return new URL(value).origin;
|
|
1177
|
+
} catch {
|
|
1178
|
+
return null;
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
const getTokenRefreshDelay = (expiresAt, nowMs2) => {
|
|
1182
|
+
if (typeof expiresAt !== "string") {
|
|
1183
|
+
return DEFAULT_TOKEN_REFRESH_MS;
|
|
1184
|
+
}
|
|
1185
|
+
const expiresAtMs = Date.parse(expiresAt);
|
|
1186
|
+
if (!Number.isFinite(expiresAtMs)) {
|
|
1187
|
+
return DEFAULT_TOKEN_REFRESH_MS;
|
|
1188
|
+
}
|
|
1189
|
+
return Math.max(TOKEN_REFRESH_RETRY_BASE_MS, expiresAtMs - nowMs2 - TOKEN_REFRESH_BUFFER_MS);
|
|
1190
|
+
};
|
|
1191
|
+
const getAuthRetryDelay = (retryAttempt) => {
|
|
1192
|
+
const safeAttempt = Number.isFinite(retryAttempt) ? Math.max(0, Math.floor(retryAttempt)) : 0;
|
|
1193
|
+
return Math.min(TOKEN_REFRESH_RETRY_MAX_MS, TOKEN_REFRESH_RETRY_BASE_MS * 2 ** safeAttempt);
|
|
1194
|
+
};
|
|
1195
|
+
function useParentBridge({
|
|
1196
|
+
trustedOrigins = EMPTY_TRUSTED_ORIGINS
|
|
1197
|
+
} = {}) {
|
|
1198
|
+
const isInIframe = typeof window !== "undefined" && window.parent !== window;
|
|
1199
|
+
const runtimeTrustedOrigins = React.useMemo(() => {
|
|
1200
|
+
const origins = /* @__PURE__ */ new Set();
|
|
1201
|
+
if (typeof window !== "undefined") {
|
|
1202
|
+
origins.add(window.location.origin);
|
|
299
1203
|
}
|
|
300
1204
|
for (const trustedOrigin of trustedOrigins) {
|
|
301
1205
|
const normalizedOrigin = normalizeOrigin(trustedOrigin);
|
|
@@ -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;
|
|
@@ -11038,6 +12070,9 @@ function useDeepAgentThread({
|
|
|
11038
12070
|
return statewireTransport(
|
|
11039
12071
|
{
|
|
11040
12072
|
url: `${baseUrl.replace(/\/+$/, "")}/${encodeURIComponent(threadId)}`,
|
|
12073
|
+
// A never-started chat has no server session yet: the transport
|
|
12074
|
+
// makes no network calls until the first command send.
|
|
12075
|
+
...preloadRef.current.preload && { isNew: true },
|
|
11041
12076
|
headers: (ctx) => headersRef.current(ctx),
|
|
11042
12077
|
...sessionStore && { sessionStore }
|
|
11043
12078
|
},
|
|
@@ -11074,7 +12109,7 @@ function useDeepAgentThread({
|
|
|
11074
12109
|
}
|
|
11075
12110
|
const connection = projectDeepAgentConnection(meta.connection);
|
|
11076
12111
|
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) {
|
|
12112
|
+
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
12113
|
const update = { threadId: attachId, connection };
|
|
11079
12114
|
lastConnectionRef.current = update;
|
|
11080
12115
|
queueMicrotask(() => {
|
|
@@ -11146,46 +12181,30 @@ function toJSONSchema(schema2) {
|
|
|
11146
12181
|
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
12182
|
return schema2;
|
|
11148
12183
|
}
|
|
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
12184
|
function hasCallableExecute(entry) {
|
|
11166
12185
|
return !!entry && typeof entry === "object" && typeof entry.execute === "function";
|
|
11167
12186
|
}
|
|
11168
12187
|
function collectStatewireClientTools(toolkit) {
|
|
11169
12188
|
const executable = Object.entries(toolkit).filter(([, entry]) => hasCallableExecute(entry));
|
|
11170
12189
|
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
12190
|
return executable.flatMap(([name, entry]) => {
|
|
11181
|
-
|
|
11182
|
-
|
|
12191
|
+
if (entry.parameters === void 0) return [];
|
|
12192
|
+
let parameters;
|
|
12193
|
+
try {
|
|
12194
|
+
parameters = toJSONSchema(entry.parameters);
|
|
12195
|
+
} catch (error2) {
|
|
12196
|
+
console.warn(
|
|
12197
|
+
`[AthenaSDK] failed to convert frontend tool schema for statewire (${name}):`,
|
|
12198
|
+
error2
|
|
12199
|
+
);
|
|
12200
|
+
return [];
|
|
12201
|
+
}
|
|
11183
12202
|
const execute = entry.execute;
|
|
11184
12203
|
return [
|
|
11185
12204
|
{
|
|
11186
12205
|
name,
|
|
11187
|
-
description:
|
|
11188
|
-
parameters
|
|
12206
|
+
description: entry.description,
|
|
12207
|
+
parameters,
|
|
11189
12208
|
handler: async (args, { toolCallId }) => {
|
|
11190
12209
|
const controller = new AbortController();
|
|
11191
12210
|
const output = await execute(args, {
|
|
@@ -11209,39 +12228,6 @@ function statewireClientToolWireEntries(tools) {
|
|
|
11209
12228
|
requires_write: false
|
|
11210
12229
|
}));
|
|
11211
12230
|
}
|
|
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
12231
|
const EMPTY_TOOLKIT = {};
|
|
11246
12232
|
const EMPTY_TOOL_IDS = [];
|
|
11247
12233
|
function useStatewireClientTools(frontendToolkit) {
|
|
@@ -11259,6 +12245,8 @@ function useAthenaStatewireRuntime(config2) {
|
|
|
11259
12245
|
token,
|
|
11260
12246
|
getToken,
|
|
11261
12247
|
model,
|
|
12248
|
+
agent: agent2,
|
|
12249
|
+
channel,
|
|
11262
12250
|
tools = EMPTY_TOOL_IDS,
|
|
11263
12251
|
frontendToolIds = EMPTY_TOOL_IDS,
|
|
11264
12252
|
frontendToolkit = EMPTY_TOOLKIT,
|
|
@@ -11286,6 +12274,28 @@ function useAthenaStatewireRuntime(config2) {
|
|
|
11286
12274
|
const clientToolsRef = React.useRef(clientTools);
|
|
11287
12275
|
clientToolsRef.current = clientTools;
|
|
11288
12276
|
const [canPersistSession] = React.useState(() => typeof localStorage !== "undefined");
|
|
12277
|
+
React.useEffect(() => {
|
|
12278
|
+
if (agent2 && !parseCollabAgentRef(agent2)) {
|
|
12279
|
+
athenaDiagnostics.emit("sdk.config.warning", {
|
|
12280
|
+
level: "warn",
|
|
12281
|
+
data: {
|
|
12282
|
+
prop: "agent",
|
|
12283
|
+
value: agent2,
|
|
12284
|
+
reason: "the statewire transport always runs the Athena deep agent; only 'collab_agent:<asset_id>' refs apply. Use transport='legacy' for named agents."
|
|
12285
|
+
}
|
|
12286
|
+
});
|
|
12287
|
+
}
|
|
12288
|
+
}, [agent2]);
|
|
12289
|
+
const attachSpanRef = React.useRef(null);
|
|
12290
|
+
const attachThreadRef = React.useRef(null);
|
|
12291
|
+
if (attachThreadRef.current !== threadId) {
|
|
12292
|
+
attachThreadRef.current = threadId;
|
|
12293
|
+
attachSpanRef.current = athenaDiagnostics.span(
|
|
12294
|
+
`statewire.attach:${threadId}`,
|
|
12295
|
+
"statewire.attach.start",
|
|
12296
|
+
{ thread_id: threadId, is_new_chat: isNewChat }
|
|
12297
|
+
);
|
|
12298
|
+
}
|
|
11289
12299
|
const thread = useDeepAgentThread({
|
|
11290
12300
|
threadId,
|
|
11291
12301
|
baseUrl: syncUrl,
|
|
@@ -11315,11 +12325,47 @@ function useAthenaStatewireRuntime(config2) {
|
|
|
11315
12325
|
}
|
|
11316
12326
|
},
|
|
11317
12327
|
capabilities: { edit: true, reload: true, continue: true },
|
|
11318
|
-
|
|
12328
|
+
onStateChange: () => {
|
|
12329
|
+
const endSpan = attachSpanRef.current;
|
|
12330
|
+
if (endSpan) {
|
|
12331
|
+
attachSpanRef.current = null;
|
|
12332
|
+
endSpan("statewire.snapshot", { data: { thread_id: threadId } });
|
|
12333
|
+
}
|
|
12334
|
+
},
|
|
12335
|
+
onConnectionChange: (connection) => {
|
|
12336
|
+
athenaDiagnostics.gauge("statewire.connection", (connection == null ? void 0 : connection.status) ?? null);
|
|
12337
|
+
if ((connection == null ? void 0 : connection.status) === "gone") {
|
|
12338
|
+
athenaDiagnostics.emit("statewire.connection", {
|
|
12339
|
+
level: "warn",
|
|
12340
|
+
data: { status: connection.status, message: connection.message }
|
|
12341
|
+
});
|
|
12342
|
+
}
|
|
12343
|
+
onConnectionChange == null ? void 0 : onConnectionChange(connection);
|
|
12344
|
+
},
|
|
11319
12345
|
onRawConnectionChange,
|
|
11320
|
-
onLegacyReadOnly
|
|
12346
|
+
onLegacyReadOnly: (legacyReadOnly) => {
|
|
12347
|
+
if (legacyReadOnly) {
|
|
12348
|
+
athenaDiagnostics.emit("statewire.read_only", {
|
|
12349
|
+
level: "warn",
|
|
12350
|
+
data: { thread_id: threadId }
|
|
12351
|
+
});
|
|
12352
|
+
}
|
|
12353
|
+
onLegacyReadOnly == null ? void 0 : onLegacyReadOnly(legacyReadOnly);
|
|
12354
|
+
},
|
|
11321
12355
|
onRunningChange,
|
|
11322
12356
|
onError: (error2) => {
|
|
12357
|
+
if (!isStatewireChannelTeardown(error2)) {
|
|
12358
|
+
athenaDiagnostics.error(
|
|
12359
|
+
"statewire.error",
|
|
12360
|
+
error2,
|
|
12361
|
+
{
|
|
12362
|
+
code: "statewire_rejected",
|
|
12363
|
+
message: "The statewire host rejected a command",
|
|
12364
|
+
hint: "Inspect error.detail — agora rejections carry a structured {code, message}."
|
|
12365
|
+
},
|
|
12366
|
+
{ thread_id: threadId }
|
|
12367
|
+
);
|
|
12368
|
+
}
|
|
11323
12369
|
if (onErrorRef.current) {
|
|
11324
12370
|
onErrorRef.current(error2);
|
|
11325
12371
|
return;
|
|
@@ -11335,6 +12381,8 @@ function useAthenaStatewireRuntime(config2) {
|
|
|
11335
12381
|
const aui = react$1.useAui({ thread, tools: auiTools });
|
|
11336
12382
|
const runConfigInputsRef = React.useRef({
|
|
11337
12383
|
model,
|
|
12384
|
+
agent: agent2,
|
|
12385
|
+
channel,
|
|
11338
12386
|
tools,
|
|
11339
12387
|
frontendToolIds,
|
|
11340
12388
|
workbench,
|
|
@@ -11346,6 +12394,8 @@ function useAthenaStatewireRuntime(config2) {
|
|
|
11346
12394
|
});
|
|
11347
12395
|
runConfigInputsRef.current = {
|
|
11348
12396
|
model,
|
|
12397
|
+
agent: agent2,
|
|
12398
|
+
channel,
|
|
11349
12399
|
tools,
|
|
11350
12400
|
frontendToolIds,
|
|
11351
12401
|
workbench,
|
|
@@ -15914,11 +16964,11 @@ const pickNumber = (...candidates) => {
|
|
|
15914
16964
|
return void 0;
|
|
15915
16965
|
};
|
|
15916
16966
|
const autoOpen = (assetId, options = {}) => {
|
|
15917
|
-
const
|
|
15918
|
-
if (!
|
|
15919
|
-
const existing =
|
|
16967
|
+
const store2 = useAssetPanelStore.getState();
|
|
16968
|
+
if (!store2.markAutoOpened(assetId)) return;
|
|
16969
|
+
const existing = store2.tabs.find((tab) => tab.id === assetId);
|
|
15920
16970
|
const keepCurrentSlide = options.preserveExistingSlide && existing;
|
|
15921
|
-
|
|
16971
|
+
store2.openAsset(assetId, {
|
|
15922
16972
|
type: options.type ?? "unknown",
|
|
15923
16973
|
...keepCurrentSlide || options.slideNumber === void 0 ? {} : { slideNumber: options.slideNumber }
|
|
15924
16974
|
});
|
|
@@ -19013,779 +20063,333 @@ function useActiveThreadStateHydration({
|
|
|
19013
20063
|
threadId,
|
|
19014
20064
|
apiKey,
|
|
19015
20065
|
token
|
|
19016
|
-
});
|
|
19017
|
-
if (hydratedKeysRef.current.has(hydrationKey)) {
|
|
19018
|
-
return;
|
|
19019
|
-
}
|
|
19020
|
-
let cancelled = false;
|
|
19021
|
-
(async () => {
|
|
19022
|
-
var _a3, _b2;
|
|
19023
|
-
try {
|
|
19024
|
-
const state = await getThreadState(backendUrl, { apiKey, token }, threadId);
|
|
19025
|
-
if (cancelled || activeThreadIdRef.current !== threadId) {
|
|
19026
|
-
return;
|
|
19027
|
-
}
|
|
19028
|
-
if (aui.thread.getState().messages.length > 0) {
|
|
19029
|
-
return;
|
|
19030
|
-
}
|
|
19031
|
-
(_b2 = (_a3 = aui.thread).importExternalState) == null ? void 0 : _b2.call(_a3, state);
|
|
19032
|
-
hydratedKeysRef.current.add(hydrationKey);
|
|
19033
|
-
} catch (error2) {
|
|
19034
|
-
console.warn("[AthenaSDK] Failed to hydrate active thread state:", error2);
|
|
19035
|
-
}
|
|
19036
|
-
})();
|
|
19037
|
-
return () => {
|
|
19038
|
-
cancelled = true;
|
|
19039
|
-
};
|
|
19040
|
-
}, [apiKey, aui, backendUrl, hasThread, isRunning, messageCount, threadId, token]);
|
|
19041
|
-
}
|
|
19042
|
-
const LOCAL_ID_PREFIX = "__LOCALID_";
|
|
19043
|
-
const isLocalPlaceholder = (id) => !!id && id.startsWith(LOCAL_ID_PREFIX);
|
|
19044
|
-
const selectActiveThreadRemoteId = (state) => {
|
|
19045
|
-
const { mainThreadId, threadItems } = state;
|
|
19046
|
-
if (!mainThreadId) {
|
|
19047
|
-
return null;
|
|
19048
|
-
}
|
|
19049
|
-
const item = threadItems.find((t) => t.id === mainThreadId);
|
|
19050
|
-
const remoteId = item ? item.remoteId ?? null : mainThreadId;
|
|
19051
|
-
return isLocalPlaceholder(remoteId) ? null : remoteId;
|
|
19052
|
-
};
|
|
19053
|
-
function useAthenaThreadManager() {
|
|
19054
|
-
const statewireList = useAthenaStatewireThreadList();
|
|
19055
|
-
const statewireIsThreadLoading = react$1.useAuiState((s) => {
|
|
19056
|
-
var _a3;
|
|
19057
|
-
return ((_a3 = s.optional.thread) == null ? void 0 : _a3.isLoading) ?? false;
|
|
19058
|
-
});
|
|
19059
|
-
const statewireManager = React.useMemo(() => {
|
|
19060
|
-
if (!statewireList) return null;
|
|
19061
|
-
return {
|
|
19062
|
-
activeThreadId: statewireList.isNewChat ? null : statewireList.activeThreadId,
|
|
19063
|
-
isListLoading: statewireList.isLoading,
|
|
19064
|
-
isThreadLoading: statewireIsThreadLoading,
|
|
19065
|
-
switchToThread: async (threadId) => statewireList.selectThread(threadId),
|
|
19066
|
-
switchToNewThread: async () => statewireList.newThread()
|
|
19067
|
-
};
|
|
19068
|
-
}, [statewireList, statewireIsThreadLoading]);
|
|
19069
|
-
const aui = react$1.useAui();
|
|
19070
|
-
const hasThreads = aui.threads.source !== null;
|
|
19071
|
-
const activeThreadId = react$1.useAuiState((s) => {
|
|
19072
|
-
const threads = s.optional.threads;
|
|
19073
|
-
return threads ? selectActiveThreadRemoteId(threads) : null;
|
|
19074
|
-
});
|
|
19075
|
-
const isThreadLoading = react$1.useAuiState((s) => {
|
|
19076
|
-
var _a3;
|
|
19077
|
-
return ((_a3 = s.optional.thread) == null ? void 0 : _a3.isLoading) ?? false;
|
|
19078
|
-
});
|
|
19079
|
-
const isListLoading = react$1.useAuiState((s) => {
|
|
19080
|
-
var _a3;
|
|
19081
|
-
return (_a3 = s.optional.threads) == null ? void 0 : _a3.isLoading;
|
|
19082
|
-
});
|
|
19083
|
-
const auiRef = React.useRef(aui);
|
|
19084
|
-
auiRef.current = aui;
|
|
19085
|
-
const switchToThread = React.useCallback(
|
|
19086
|
-
async (id) => auiRef.current.threads.switchToThread(id),
|
|
19087
|
-
[]
|
|
19088
|
-
);
|
|
19089
|
-
const switchToNewThread = React.useCallback(
|
|
19090
|
-
async () => auiRef.current.threads.switchToNewThread(),
|
|
19091
|
-
[]
|
|
19092
|
-
);
|
|
19093
|
-
const legacyManager = React.useMemo(() => {
|
|
19094
|
-
if (!hasThreads || isListLoading == null) {
|
|
19095
|
-
return null;
|
|
19096
|
-
}
|
|
19097
|
-
return {
|
|
19098
|
-
activeThreadId,
|
|
19099
|
-
isListLoading,
|
|
19100
|
-
isThreadLoading,
|
|
19101
|
-
switchToThread,
|
|
19102
|
-
switchToNewThread
|
|
19103
|
-
};
|
|
19104
|
-
}, [hasThreads, activeThreadId, isListLoading, isThreadLoading, switchToThread, switchToNewThread]);
|
|
19105
|
-
return statewireManager ?? legacyManager;
|
|
19106
|
-
}
|
|
19107
|
-
const POLL_DELAY_MS = 5e3;
|
|
19108
|
-
const POLL_INTERVAL_MS = 1e3;
|
|
19109
|
-
const POLL_MAX_DURATION_MS = 6e4;
|
|
19110
|
-
function useThreadTitlePolling(refresh) {
|
|
19111
|
-
const threadKey = react$1.useAuiState(
|
|
19112
|
-
(s) => {
|
|
19113
|
-
var _a3, _b2;
|
|
19114
|
-
return ((_a3 = s.optional.threadListItem) == null ? void 0 : _a3.remoteId) ?? ((_b2 = s.optional.threadListItem) == null ? void 0 : _b2.id) ?? null;
|
|
19115
|
-
}
|
|
19116
|
-
);
|
|
19117
|
-
const hasMessages = react$1.useAuiState((s) => {
|
|
19118
|
-
var _a3;
|
|
19119
|
-
return (((_a3 = s.optional.thread) == null ? void 0 : _a3.messages.length) ?? 0) > 0;
|
|
19120
|
-
});
|
|
19121
|
-
const currentTitle = react$1.useAuiState((s) => {
|
|
19122
|
-
var _a3;
|
|
19123
|
-
return ((_a3 = s.optional.threadListItem) == null ? void 0 : _a3.title) ?? "";
|
|
19124
|
-
});
|
|
19125
|
-
const trimmedTitle = currentTitle.trim();
|
|
19126
|
-
const hasTitle = trimmedTitle.length > 0 && !isSerializedContentPartsTitle(trimmedTitle);
|
|
19127
|
-
const polledThreadsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
19128
|
-
const refreshRef = React.useRef(refresh);
|
|
19129
|
-
refreshRef.current = refresh;
|
|
19130
|
-
React.useEffect(() => {
|
|
19131
|
-
if (!threadKey || hasTitle || !hasMessages) {
|
|
19132
|
-
return;
|
|
19133
|
-
}
|
|
19134
|
-
if (polledThreadsRef.current.has(threadKey)) {
|
|
19135
|
-
return;
|
|
19136
|
-
}
|
|
19137
|
-
polledThreadsRef.current.add(threadKey);
|
|
19138
|
-
let stopped = false;
|
|
19139
|
-
let intervalId = null;
|
|
19140
|
-
let maxTimeoutId = null;
|
|
19141
|
-
const stop = () => {
|
|
19142
|
-
stopped = true;
|
|
19143
|
-
if (intervalId !== null) {
|
|
19144
|
-
clearInterval(intervalId);
|
|
19145
|
-
intervalId = null;
|
|
19146
|
-
}
|
|
19147
|
-
if (maxTimeoutId !== null) {
|
|
19148
|
-
clearTimeout(maxTimeoutId);
|
|
19149
|
-
maxTimeoutId = null;
|
|
19150
|
-
}
|
|
19151
|
-
};
|
|
19152
|
-
const startTimeoutId = setTimeout(() => {
|
|
19153
|
-
if (stopped) return;
|
|
19154
|
-
refreshRef.current();
|
|
19155
|
-
intervalId = setInterval(() => {
|
|
19156
|
-
refreshRef.current();
|
|
19157
|
-
}, POLL_INTERVAL_MS);
|
|
19158
|
-
maxTimeoutId = setTimeout(stop, POLL_MAX_DURATION_MS - POLL_DELAY_MS);
|
|
19159
|
-
}, POLL_DELAY_MS);
|
|
19160
|
-
return () => {
|
|
19161
|
-
clearTimeout(startTimeoutId);
|
|
19162
|
-
stop();
|
|
19163
|
-
};
|
|
19164
|
-
}, [threadKey, hasTitle, hasMessages]);
|
|
19165
|
-
}
|
|
19166
|
-
const THEME_TO_CSS = {
|
|
19167
|
-
primary: "--primary",
|
|
19168
|
-
primaryForeground: "--primary-foreground",
|
|
19169
|
-
background: "--background",
|
|
19170
|
-
foreground: "--foreground",
|
|
19171
|
-
muted: "--muted",
|
|
19172
|
-
mutedForeground: "--muted-foreground",
|
|
19173
|
-
accent: "--accent",
|
|
19174
|
-
accentForeground: "--accent-foreground",
|
|
19175
|
-
secondary: "--secondary",
|
|
19176
|
-
secondaryForeground: "--secondary-foreground",
|
|
19177
|
-
card: "--card",
|
|
19178
|
-
cardForeground: "--card-foreground",
|
|
19179
|
-
popover: "--popover",
|
|
19180
|
-
popoverForeground: "--popover-foreground",
|
|
19181
|
-
destructive: "--destructive",
|
|
19182
|
-
border: "--border",
|
|
19183
|
-
input: "--input",
|
|
19184
|
-
ring: "--ring",
|
|
19185
|
-
radius: "--radius",
|
|
19186
|
-
fontFamily: "--font-family",
|
|
19187
|
-
// Extended SDK-specific variables
|
|
19188
|
-
sidebarBackground: "--sidebar-background",
|
|
19189
|
-
sidebarBorder: "--sidebar-border",
|
|
19190
|
-
sidebarWidth: "--sidebar-width",
|
|
19191
|
-
userBubble: "--user-bubble",
|
|
19192
|
-
userBubbleForeground: "--user-bubble-foreground",
|
|
19193
|
-
userBubbleRadius: "--user-bubble-radius",
|
|
19194
|
-
assistantForeground: "--assistant-foreground",
|
|
19195
|
-
assistantBubble: "--assistant-bubble",
|
|
19196
|
-
composerBorder: "--composer-border",
|
|
19197
|
-
composerRadius: "--composer-radius",
|
|
19198
|
-
threadMaxWidth: "--thread-max-width"
|
|
19199
|
-
};
|
|
19200
|
-
function themeToStyleVars(theme) {
|
|
19201
|
-
const vars = {};
|
|
19202
|
-
for (const [key, value] of Object.entries(theme)) {
|
|
19203
|
-
if (value != null && THEME_TO_CSS[key]) {
|
|
19204
|
-
vars[THEME_TO_CSS[key]] = value;
|
|
19205
|
-
}
|
|
19206
|
-
}
|
|
19207
|
-
return vars;
|
|
19208
|
-
}
|
|
19209
|
-
const themes = {
|
|
19210
|
-
/** Default light theme. Neutral grays with blue accent. */
|
|
19211
|
-
light: {
|
|
19212
|
-
background: "oklch(0.99 0 0)",
|
|
19213
|
-
foreground: "oklch(0.13 0 0)",
|
|
19214
|
-
primary: "oklch(0.55 0.2 250)",
|
|
19215
|
-
primaryForeground: "oklch(1 0 0)",
|
|
19216
|
-
secondary: "oklch(0.96 0.005 250)",
|
|
19217
|
-
secondaryForeground: "oklch(0.13 0 0)",
|
|
19218
|
-
muted: "oklch(0.96 0.005 250)",
|
|
19219
|
-
mutedForeground: "oklch(0.5 0.02 250)",
|
|
19220
|
-
accent: "oklch(0.94 0.01 250)",
|
|
19221
|
-
accentForeground: "oklch(0.13 0 0)",
|
|
19222
|
-
card: "oklch(0.99 0 0)",
|
|
19223
|
-
cardForeground: "oklch(0.13 0 0)",
|
|
19224
|
-
popover: "oklch(0.99 0 0)",
|
|
19225
|
-
popoverForeground: "oklch(0.13 0 0)",
|
|
19226
|
-
destructive: "oklch(0.55 0.22 27)",
|
|
19227
|
-
border: "oklch(0.91 0.005 250)",
|
|
19228
|
-
input: "oklch(0.91 0.005 250)",
|
|
19229
|
-
ring: "oklch(0.55 0.2 250)",
|
|
19230
|
-
radius: "0.625rem"
|
|
19231
|
-
},
|
|
19232
|
-
/** Dark theme. Deep gray background with lighter text. */
|
|
19233
|
-
dark: {
|
|
19234
|
-
background: "oklch(0.15 0 0)",
|
|
19235
|
-
foreground: "oklch(0.95 0 0)",
|
|
19236
|
-
primary: "oklch(0.7 0.15 250)",
|
|
19237
|
-
primaryForeground: "oklch(0.13 0 0)",
|
|
19238
|
-
secondary: "oklch(0.22 0 0)",
|
|
19239
|
-
secondaryForeground: "oklch(0.95 0 0)",
|
|
19240
|
-
muted: "oklch(0.22 0 0)",
|
|
19241
|
-
mutedForeground: "oklch(0.65 0 0)",
|
|
19242
|
-
accent: "oklch(0.25 0 0)",
|
|
19243
|
-
accentForeground: "oklch(0.95 0 0)",
|
|
19244
|
-
card: "oklch(0.18 0 0)",
|
|
19245
|
-
cardForeground: "oklch(0.95 0 0)",
|
|
19246
|
-
popover: "oklch(0.18 0 0)",
|
|
19247
|
-
popoverForeground: "oklch(0.95 0 0)",
|
|
19248
|
-
destructive: "oklch(0.65 0.2 25)",
|
|
19249
|
-
border: "oklch(1 0 0 / 10%)",
|
|
19250
|
-
input: "oklch(1 0 0 / 15%)",
|
|
19251
|
-
ring: "oklch(0.7 0.15 250)",
|
|
19252
|
-
radius: "0.625rem"
|
|
19253
|
-
},
|
|
19254
|
-
/** Midnight theme. Deep navy with soft blue tones. */
|
|
19255
|
-
midnight: {
|
|
19256
|
-
background: "oklch(0.16 0.02 260)",
|
|
19257
|
-
foreground: "oklch(0.92 0.01 250)",
|
|
19258
|
-
primary: "oklch(0.68 0.16 250)",
|
|
19259
|
-
primaryForeground: "oklch(0.98 0 0)",
|
|
19260
|
-
secondary: "oklch(0.22 0.02 260)",
|
|
19261
|
-
secondaryForeground: "oklch(0.92 0.01 250)",
|
|
19262
|
-
muted: "oklch(0.22 0.02 260)",
|
|
19263
|
-
mutedForeground: "oklch(0.6 0.04 250)",
|
|
19264
|
-
accent: "oklch(0.26 0.03 260)",
|
|
19265
|
-
accentForeground: "oklch(0.92 0.01 250)",
|
|
19266
|
-
card: "oklch(0.19 0.02 260)",
|
|
19267
|
-
cardForeground: "oklch(0.92 0.01 250)",
|
|
19268
|
-
popover: "oklch(0.19 0.02 260)",
|
|
19269
|
-
popoverForeground: "oklch(0.92 0.01 250)",
|
|
19270
|
-
destructive: "oklch(0.65 0.2 25)",
|
|
19271
|
-
border: "oklch(0.3 0.03 260)",
|
|
19272
|
-
input: "oklch(0.3 0.03 260)",
|
|
19273
|
-
ring: "oklch(0.68 0.16 250)",
|
|
19274
|
-
radius: "0.625rem"
|
|
19275
|
-
},
|
|
19276
|
-
/** Warm earthy theme. Brown and sand tones. */
|
|
19277
|
-
warm: {
|
|
19278
|
-
background: "oklch(0.98 0.005 80)",
|
|
19279
|
-
foreground: "oklch(0.2 0.02 50)",
|
|
19280
|
-
primary: "oklch(0.55 0.12 50)",
|
|
19281
|
-
primaryForeground: "oklch(0.98 0 0)",
|
|
19282
|
-
secondary: "oklch(0.94 0.01 80)",
|
|
19283
|
-
secondaryForeground: "oklch(0.2 0.02 50)",
|
|
19284
|
-
muted: "oklch(0.95 0.01 80)",
|
|
19285
|
-
mutedForeground: "oklch(0.5 0.03 50)",
|
|
19286
|
-
accent: "oklch(0.92 0.015 80)",
|
|
19287
|
-
accentForeground: "oklch(0.2 0.02 50)",
|
|
19288
|
-
card: "oklch(0.98 0.005 80)",
|
|
19289
|
-
cardForeground: "oklch(0.2 0.02 50)",
|
|
19290
|
-
popover: "oklch(0.98 0.005 80)",
|
|
19291
|
-
popoverForeground: "oklch(0.2 0.02 50)",
|
|
19292
|
-
destructive: "oklch(0.55 0.2 25)",
|
|
19293
|
-
border: "oklch(0.9 0.01 80)",
|
|
19294
|
-
input: "oklch(0.9 0.01 80)",
|
|
19295
|
-
ring: "oklch(0.55 0.12 50)",
|
|
19296
|
-
radius: "0.75rem"
|
|
19297
|
-
},
|
|
19298
|
-
/** Purple creative theme. Vibrant purple accent. */
|
|
19299
|
-
purple: {
|
|
19300
|
-
background: "oklch(0.99 0.003 310)",
|
|
19301
|
-
foreground: "oklch(0.15 0.02 310)",
|
|
19302
|
-
primary: "oklch(0.55 0.22 310)",
|
|
19303
|
-
primaryForeground: "oklch(1 0 0)",
|
|
19304
|
-
secondary: "oklch(0.96 0.01 310)",
|
|
19305
|
-
secondaryForeground: "oklch(0.15 0.02 310)",
|
|
19306
|
-
muted: "oklch(0.96 0.01 310)",
|
|
19307
|
-
mutedForeground: "oklch(0.5 0.04 310)",
|
|
19308
|
-
accent: "oklch(0.94 0.015 310)",
|
|
19309
|
-
accentForeground: "oklch(0.15 0.02 310)",
|
|
19310
|
-
card: "oklch(0.99 0.003 310)",
|
|
19311
|
-
cardForeground: "oklch(0.15 0.02 310)",
|
|
19312
|
-
popover: "oklch(0.99 0.003 310)",
|
|
19313
|
-
popoverForeground: "oklch(0.15 0.02 310)",
|
|
19314
|
-
destructive: "oklch(0.55 0.22 27)",
|
|
19315
|
-
border: "oklch(0.92 0.005 310)",
|
|
19316
|
-
input: "oklch(0.92 0.005 310)",
|
|
19317
|
-
ring: "oklch(0.55 0.22 310)",
|
|
19318
|
-
radius: "0.75rem"
|
|
19319
|
-
},
|
|
19320
|
-
/** Green nature theme. Fresh green tones. */
|
|
19321
|
-
green: {
|
|
19322
|
-
background: "oklch(0.99 0.003 150)",
|
|
19323
|
-
foreground: "oklch(0.15 0.02 150)",
|
|
19324
|
-
primary: "oklch(0.55 0.18 155)",
|
|
19325
|
-
primaryForeground: "oklch(1 0 0)",
|
|
19326
|
-
secondary: "oklch(0.96 0.01 150)",
|
|
19327
|
-
secondaryForeground: "oklch(0.15 0.02 150)",
|
|
19328
|
-
muted: "oklch(0.96 0.01 150)",
|
|
19329
|
-
mutedForeground: "oklch(0.5 0.03 150)",
|
|
19330
|
-
accent: "oklch(0.94 0.015 150)",
|
|
19331
|
-
accentForeground: "oklch(0.15 0.02 150)",
|
|
19332
|
-
card: "oklch(0.99 0.003 150)",
|
|
19333
|
-
cardForeground: "oklch(0.15 0.02 150)",
|
|
19334
|
-
popover: "oklch(0.99 0.003 150)",
|
|
19335
|
-
popoverForeground: "oklch(0.15 0.02 150)",
|
|
19336
|
-
destructive: "oklch(0.55 0.22 27)",
|
|
19337
|
-
border: "oklch(0.92 0.008 150)",
|
|
19338
|
-
input: "oklch(0.92 0.008 150)",
|
|
19339
|
-
ring: "oklch(0.55 0.18 155)",
|
|
19340
|
-
radius: "0.625rem"
|
|
19341
|
-
}
|
|
19342
|
-
};
|
|
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;
|
|
20066
|
+
});
|
|
20067
|
+
if (hydratedKeysRef.current.has(hydrationKey)) {
|
|
20068
|
+
return;
|
|
19694
20069
|
}
|
|
19695
|
-
|
|
19696
|
-
|
|
19697
|
-
|
|
19698
|
-
|
|
19699
|
-
|
|
19700
|
-
|
|
19701
|
-
|
|
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);
|
|
20070
|
+
let cancelled = false;
|
|
20071
|
+
(async () => {
|
|
20072
|
+
var _a3, _b2;
|
|
20073
|
+
try {
|
|
20074
|
+
const state = await getThreadState(backendUrl, { apiKey, token }, threadId);
|
|
20075
|
+
if (cancelled || activeThreadIdRef.current !== threadId) {
|
|
20076
|
+
return;
|
|
19709
20077
|
}
|
|
19710
|
-
|
|
20078
|
+
if (aui.thread.getState().messages.length > 0) {
|
|
20079
|
+
return;
|
|
20080
|
+
}
|
|
20081
|
+
(_b2 = (_a3 = aui.thread).importExternalState) == null ? void 0 : _b2.call(_a3, state);
|
|
20082
|
+
hydratedKeysRef.current.add(hydrationKey);
|
|
20083
|
+
} catch (error2) {
|
|
20084
|
+
console.warn("[AthenaSDK] Failed to hydrate active thread state:", error2);
|
|
19711
20085
|
}
|
|
19712
|
-
|
|
19713
|
-
|
|
19714
|
-
|
|
19715
|
-
|
|
19716
|
-
|
|
19717
|
-
}
|
|
19718
|
-
function capturePosthogEvent(client, event, properties, options) {
|
|
19719
|
-
if (!client || typeof client.capture !== "function") return;
|
|
19720
|
-
client.capture(event, properties, options);
|
|
20086
|
+
})();
|
|
20087
|
+
return () => {
|
|
20088
|
+
cancelled = true;
|
|
20089
|
+
};
|
|
20090
|
+
}, [apiKey, aui, backendUrl, hasThread, isRunning, messageCount, threadId, token]);
|
|
19721
20091
|
}
|
|
19722
|
-
|
|
19723
|
-
|
|
19724
|
-
|
|
19725
|
-
|
|
19726
|
-
|
|
20092
|
+
const LOCAL_ID_PREFIX = "__LOCALID_";
|
|
20093
|
+
const isLocalPlaceholder = (id) => !!id && id.startsWith(LOCAL_ID_PREFIX);
|
|
20094
|
+
const selectActiveThreadRemoteId = (state) => {
|
|
20095
|
+
const { mainThreadId, threadItems } = state;
|
|
20096
|
+
if (!mainThreadId) {
|
|
20097
|
+
return null;
|
|
19727
20098
|
}
|
|
19728
|
-
|
|
19729
|
-
|
|
19730
|
-
|
|
19731
|
-
|
|
19732
|
-
|
|
19733
|
-
|
|
19734
|
-
|
|
19735
|
-
|
|
19736
|
-
|
|
19737
|
-
|
|
20099
|
+
const item = threadItems.find((t) => t.id === mainThreadId);
|
|
20100
|
+
const remoteId = item ? item.remoteId ?? null : mainThreadId;
|
|
20101
|
+
return isLocalPlaceholder(remoteId) ? null : remoteId;
|
|
20102
|
+
};
|
|
20103
|
+
function useAthenaThreadManager() {
|
|
20104
|
+
const statewireList = useAthenaStatewireThreadList();
|
|
20105
|
+
const statewireIsThreadLoading = react$1.useAuiState((s) => {
|
|
20106
|
+
var _a3;
|
|
20107
|
+
return ((_a3 = s.optional.thread) == null ? void 0 : _a3.isLoading) ?? false;
|
|
20108
|
+
});
|
|
20109
|
+
const statewireManager = React.useMemo(() => {
|
|
20110
|
+
if (!statewireList) return null;
|
|
20111
|
+
return {
|
|
20112
|
+
activeThreadId: statewireList.isNewChat ? null : statewireList.activeThreadId,
|
|
20113
|
+
isListLoading: statewireList.isLoading,
|
|
20114
|
+
isThreadLoading: statewireIsThreadLoading,
|
|
20115
|
+
switchToThread: async (threadId) => statewireList.selectThread(threadId),
|
|
20116
|
+
switchToNewThread: async () => statewireList.newThread()
|
|
20117
|
+
};
|
|
20118
|
+
}, [statewireList, statewireIsThreadLoading]);
|
|
20119
|
+
const aui = react$1.useAui();
|
|
20120
|
+
const hasThreads = aui.threads.source !== null;
|
|
20121
|
+
const activeThreadId = react$1.useAuiState((s) => {
|
|
20122
|
+
const threads = s.optional.threads;
|
|
20123
|
+
return threads ? selectActiveThreadRemoteId(threads) : null;
|
|
20124
|
+
});
|
|
20125
|
+
const isThreadLoading = react$1.useAuiState((s) => {
|
|
20126
|
+
var _a3;
|
|
20127
|
+
return ((_a3 = s.optional.thread) == null ? void 0 : _a3.isLoading) ?? false;
|
|
20128
|
+
});
|
|
20129
|
+
const isListLoading = react$1.useAuiState((s) => {
|
|
20130
|
+
var _a3;
|
|
20131
|
+
return (_a3 = s.optional.threads) == null ? void 0 : _a3.isLoading;
|
|
20132
|
+
});
|
|
20133
|
+
const auiRef = React.useRef(aui);
|
|
20134
|
+
auiRef.current = aui;
|
|
20135
|
+
const switchToThread = React.useCallback(
|
|
20136
|
+
async (id) => auiRef.current.threads.switchToThread(id),
|
|
20137
|
+
[]
|
|
20138
|
+
);
|
|
20139
|
+
const switchToNewThread = React.useCallback(
|
|
20140
|
+
async () => auiRef.current.threads.switchToNewThread(),
|
|
20141
|
+
[]
|
|
19738
20142
|
);
|
|
20143
|
+
const legacyManager = React.useMemo(() => {
|
|
20144
|
+
if (!hasThreads || isListLoading == null) {
|
|
20145
|
+
return null;
|
|
20146
|
+
}
|
|
20147
|
+
return {
|
|
20148
|
+
activeThreadId,
|
|
20149
|
+
isListLoading,
|
|
20150
|
+
isThreadLoading,
|
|
20151
|
+
switchToThread,
|
|
20152
|
+
switchToNewThread
|
|
20153
|
+
};
|
|
20154
|
+
}, [hasThreads, activeThreadId, isListLoading, isThreadLoading, switchToThread, switchToNewThread]);
|
|
20155
|
+
return statewireManager ?? legacyManager;
|
|
19739
20156
|
}
|
|
19740
|
-
|
|
19741
|
-
|
|
19742
|
-
const
|
|
19743
|
-
|
|
19744
|
-
|
|
19745
|
-
|
|
19746
|
-
|
|
19747
|
-
|
|
19748
|
-
|
|
19749
|
-
|
|
19750
|
-
|
|
19751
|
-
|
|
19752
|
-
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
|
|
19756
|
-
|
|
19757
|
-
|
|
19758
|
-
|
|
19759
|
-
|
|
19760
|
-
|
|
20157
|
+
const POLL_DELAY_MS = 5e3;
|
|
20158
|
+
const POLL_INTERVAL_MS = 1e3;
|
|
20159
|
+
const POLL_MAX_DURATION_MS = 6e4;
|
|
20160
|
+
function useThreadTitlePolling(refresh) {
|
|
20161
|
+
const threadKey = react$1.useAuiState(
|
|
20162
|
+
(s) => {
|
|
20163
|
+
var _a3, _b2;
|
|
20164
|
+
return ((_a3 = s.optional.threadListItem) == null ? void 0 : _a3.remoteId) ?? ((_b2 = s.optional.threadListItem) == null ? void 0 : _b2.id) ?? null;
|
|
20165
|
+
}
|
|
20166
|
+
);
|
|
20167
|
+
const hasMessages = react$1.useAuiState((s) => {
|
|
20168
|
+
var _a3;
|
|
20169
|
+
return (((_a3 = s.optional.thread) == null ? void 0 : _a3.messages.length) ?? 0) > 0;
|
|
20170
|
+
});
|
|
20171
|
+
const currentTitle = react$1.useAuiState((s) => {
|
|
20172
|
+
var _a3;
|
|
20173
|
+
return ((_a3 = s.optional.threadListItem) == null ? void 0 : _a3.title) ?? "";
|
|
20174
|
+
});
|
|
20175
|
+
const trimmedTitle = currentTitle.trim();
|
|
20176
|
+
const hasTitle = trimmedTitle.length > 0 && !isSerializedContentPartsTitle(trimmedTitle);
|
|
20177
|
+
const polledThreadsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
20178
|
+
const refreshRef = React.useRef(refresh);
|
|
20179
|
+
refreshRef.current = refresh;
|
|
20180
|
+
React.useEffect(() => {
|
|
20181
|
+
if (!threadKey || hasTitle || !hasMessages) {
|
|
20182
|
+
return;
|
|
20183
|
+
}
|
|
20184
|
+
if (polledThreadsRef.current.has(threadKey)) {
|
|
20185
|
+
return;
|
|
20186
|
+
}
|
|
20187
|
+
polledThreadsRef.current.add(threadKey);
|
|
20188
|
+
let stopped = false;
|
|
20189
|
+
let intervalId = null;
|
|
20190
|
+
let maxTimeoutId = null;
|
|
20191
|
+
const stop = () => {
|
|
20192
|
+
stopped = true;
|
|
20193
|
+
if (intervalId !== null) {
|
|
20194
|
+
clearInterval(intervalId);
|
|
20195
|
+
intervalId = null;
|
|
19761
20196
|
}
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
|
|
19766
|
-
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
20197
|
+
if (maxTimeoutId !== null) {
|
|
20198
|
+
clearTimeout(maxTimeoutId);
|
|
20199
|
+
maxTimeoutId = null;
|
|
20200
|
+
}
|
|
20201
|
+
};
|
|
20202
|
+
const startTimeoutId = setTimeout(() => {
|
|
20203
|
+
if (stopped) return;
|
|
20204
|
+
refreshRef.current();
|
|
20205
|
+
intervalId = setInterval(() => {
|
|
20206
|
+
refreshRef.current();
|
|
20207
|
+
}, POLL_INTERVAL_MS);
|
|
20208
|
+
maxTimeoutId = setTimeout(stop, POLL_MAX_DURATION_MS - POLL_DELAY_MS);
|
|
20209
|
+
}, POLL_DELAY_MS);
|
|
20210
|
+
return () => {
|
|
20211
|
+
clearTimeout(startTimeoutId);
|
|
20212
|
+
stop();
|
|
20213
|
+
};
|
|
20214
|
+
}, [threadKey, hasTitle, hasMessages]);
|
|
19773
20215
|
}
|
|
19774
|
-
|
|
19775
|
-
|
|
19776
|
-
|
|
19777
|
-
|
|
19778
|
-
|
|
19779
|
-
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
|
|
19784
|
-
|
|
20216
|
+
const THEME_TO_CSS = {
|
|
20217
|
+
primary: "--primary",
|
|
20218
|
+
primaryForeground: "--primary-foreground",
|
|
20219
|
+
background: "--background",
|
|
20220
|
+
foreground: "--foreground",
|
|
20221
|
+
muted: "--muted",
|
|
20222
|
+
mutedForeground: "--muted-foreground",
|
|
20223
|
+
accent: "--accent",
|
|
20224
|
+
accentForeground: "--accent-foreground",
|
|
20225
|
+
secondary: "--secondary",
|
|
20226
|
+
secondaryForeground: "--secondary-foreground",
|
|
20227
|
+
card: "--card",
|
|
20228
|
+
cardForeground: "--card-foreground",
|
|
20229
|
+
popover: "--popover",
|
|
20230
|
+
popoverForeground: "--popover-foreground",
|
|
20231
|
+
destructive: "--destructive",
|
|
20232
|
+
border: "--border",
|
|
20233
|
+
input: "--input",
|
|
20234
|
+
ring: "--ring",
|
|
20235
|
+
radius: "--radius",
|
|
20236
|
+
fontFamily: "--font-family",
|
|
20237
|
+
// Extended SDK-specific variables
|
|
20238
|
+
sidebarBackground: "--sidebar-background",
|
|
20239
|
+
sidebarBorder: "--sidebar-border",
|
|
20240
|
+
sidebarWidth: "--sidebar-width",
|
|
20241
|
+
userBubble: "--user-bubble",
|
|
20242
|
+
userBubbleForeground: "--user-bubble-foreground",
|
|
20243
|
+
userBubbleRadius: "--user-bubble-radius",
|
|
20244
|
+
assistantForeground: "--assistant-foreground",
|
|
20245
|
+
assistantBubble: "--assistant-bubble",
|
|
20246
|
+
composerBorder: "--composer-border",
|
|
20247
|
+
composerRadius: "--composer-radius",
|
|
20248
|
+
threadMaxWidth: "--thread-max-width"
|
|
20249
|
+
};
|
|
20250
|
+
function themeToStyleVars(theme) {
|
|
20251
|
+
const vars = {};
|
|
20252
|
+
for (const [key, value] of Object.entries(theme)) {
|
|
20253
|
+
if (value != null && THEME_TO_CSS[key]) {
|
|
20254
|
+
vars[THEME_TO_CSS[key]] = value;
|
|
19785
20255
|
}
|
|
19786
|
-
}
|
|
19787
|
-
return
|
|
20256
|
+
}
|
|
20257
|
+
return vars;
|
|
19788
20258
|
}
|
|
20259
|
+
const themes = {
|
|
20260
|
+
/** Default light theme. Neutral grays with blue accent. */
|
|
20261
|
+
light: {
|
|
20262
|
+
background: "oklch(0.99 0 0)",
|
|
20263
|
+
foreground: "oklch(0.13 0 0)",
|
|
20264
|
+
primary: "oklch(0.55 0.2 250)",
|
|
20265
|
+
primaryForeground: "oklch(1 0 0)",
|
|
20266
|
+
secondary: "oklch(0.96 0.005 250)",
|
|
20267
|
+
secondaryForeground: "oklch(0.13 0 0)",
|
|
20268
|
+
muted: "oklch(0.96 0.005 250)",
|
|
20269
|
+
mutedForeground: "oklch(0.5 0.02 250)",
|
|
20270
|
+
accent: "oklch(0.94 0.01 250)",
|
|
20271
|
+
accentForeground: "oklch(0.13 0 0)",
|
|
20272
|
+
card: "oklch(0.99 0 0)",
|
|
20273
|
+
cardForeground: "oklch(0.13 0 0)",
|
|
20274
|
+
popover: "oklch(0.99 0 0)",
|
|
20275
|
+
popoverForeground: "oklch(0.13 0 0)",
|
|
20276
|
+
destructive: "oklch(0.55 0.22 27)",
|
|
20277
|
+
border: "oklch(0.91 0.005 250)",
|
|
20278
|
+
input: "oklch(0.91 0.005 250)",
|
|
20279
|
+
ring: "oklch(0.55 0.2 250)",
|
|
20280
|
+
radius: "0.625rem"
|
|
20281
|
+
},
|
|
20282
|
+
/** Dark theme. Deep gray background with lighter text. */
|
|
20283
|
+
dark: {
|
|
20284
|
+
background: "oklch(0.15 0 0)",
|
|
20285
|
+
foreground: "oklch(0.95 0 0)",
|
|
20286
|
+
primary: "oklch(0.7 0.15 250)",
|
|
20287
|
+
primaryForeground: "oklch(0.13 0 0)",
|
|
20288
|
+
secondary: "oklch(0.22 0 0)",
|
|
20289
|
+
secondaryForeground: "oklch(0.95 0 0)",
|
|
20290
|
+
muted: "oklch(0.22 0 0)",
|
|
20291
|
+
mutedForeground: "oklch(0.65 0 0)",
|
|
20292
|
+
accent: "oklch(0.25 0 0)",
|
|
20293
|
+
accentForeground: "oklch(0.95 0 0)",
|
|
20294
|
+
card: "oklch(0.18 0 0)",
|
|
20295
|
+
cardForeground: "oklch(0.95 0 0)",
|
|
20296
|
+
popover: "oklch(0.18 0 0)",
|
|
20297
|
+
popoverForeground: "oklch(0.95 0 0)",
|
|
20298
|
+
destructive: "oklch(0.65 0.2 25)",
|
|
20299
|
+
border: "oklch(1 0 0 / 10%)",
|
|
20300
|
+
input: "oklch(1 0 0 / 15%)",
|
|
20301
|
+
ring: "oklch(0.7 0.15 250)",
|
|
20302
|
+
radius: "0.625rem"
|
|
20303
|
+
},
|
|
20304
|
+
/** Midnight theme. Deep navy with soft blue tones. */
|
|
20305
|
+
midnight: {
|
|
20306
|
+
background: "oklch(0.16 0.02 260)",
|
|
20307
|
+
foreground: "oklch(0.92 0.01 250)",
|
|
20308
|
+
primary: "oklch(0.68 0.16 250)",
|
|
20309
|
+
primaryForeground: "oklch(0.98 0 0)",
|
|
20310
|
+
secondary: "oklch(0.22 0.02 260)",
|
|
20311
|
+
secondaryForeground: "oklch(0.92 0.01 250)",
|
|
20312
|
+
muted: "oklch(0.22 0.02 260)",
|
|
20313
|
+
mutedForeground: "oklch(0.6 0.04 250)",
|
|
20314
|
+
accent: "oklch(0.26 0.03 260)",
|
|
20315
|
+
accentForeground: "oklch(0.92 0.01 250)",
|
|
20316
|
+
card: "oklch(0.19 0.02 260)",
|
|
20317
|
+
cardForeground: "oklch(0.92 0.01 250)",
|
|
20318
|
+
popover: "oklch(0.19 0.02 260)",
|
|
20319
|
+
popoverForeground: "oklch(0.92 0.01 250)",
|
|
20320
|
+
destructive: "oklch(0.65 0.2 25)",
|
|
20321
|
+
border: "oklch(0.3 0.03 260)",
|
|
20322
|
+
input: "oklch(0.3 0.03 260)",
|
|
20323
|
+
ring: "oklch(0.68 0.16 250)",
|
|
20324
|
+
radius: "0.625rem"
|
|
20325
|
+
},
|
|
20326
|
+
/** Warm earthy theme. Brown and sand tones. */
|
|
20327
|
+
warm: {
|
|
20328
|
+
background: "oklch(0.98 0.005 80)",
|
|
20329
|
+
foreground: "oklch(0.2 0.02 50)",
|
|
20330
|
+
primary: "oklch(0.55 0.12 50)",
|
|
20331
|
+
primaryForeground: "oklch(0.98 0 0)",
|
|
20332
|
+
secondary: "oklch(0.94 0.01 80)",
|
|
20333
|
+
secondaryForeground: "oklch(0.2 0.02 50)",
|
|
20334
|
+
muted: "oklch(0.95 0.01 80)",
|
|
20335
|
+
mutedForeground: "oklch(0.5 0.03 50)",
|
|
20336
|
+
accent: "oklch(0.92 0.015 80)",
|
|
20337
|
+
accentForeground: "oklch(0.2 0.02 50)",
|
|
20338
|
+
card: "oklch(0.98 0.005 80)",
|
|
20339
|
+
cardForeground: "oklch(0.2 0.02 50)",
|
|
20340
|
+
popover: "oklch(0.98 0.005 80)",
|
|
20341
|
+
popoverForeground: "oklch(0.2 0.02 50)",
|
|
20342
|
+
destructive: "oklch(0.55 0.2 25)",
|
|
20343
|
+
border: "oklch(0.9 0.01 80)",
|
|
20344
|
+
input: "oklch(0.9 0.01 80)",
|
|
20345
|
+
ring: "oklch(0.55 0.12 50)",
|
|
20346
|
+
radius: "0.75rem"
|
|
20347
|
+
},
|
|
20348
|
+
/** Purple creative theme. Vibrant purple accent. */
|
|
20349
|
+
purple: {
|
|
20350
|
+
background: "oklch(0.99 0.003 310)",
|
|
20351
|
+
foreground: "oklch(0.15 0.02 310)",
|
|
20352
|
+
primary: "oklch(0.55 0.22 310)",
|
|
20353
|
+
primaryForeground: "oklch(1 0 0)",
|
|
20354
|
+
secondary: "oklch(0.96 0.01 310)",
|
|
20355
|
+
secondaryForeground: "oklch(0.15 0.02 310)",
|
|
20356
|
+
muted: "oklch(0.96 0.01 310)",
|
|
20357
|
+
mutedForeground: "oklch(0.5 0.04 310)",
|
|
20358
|
+
accent: "oklch(0.94 0.015 310)",
|
|
20359
|
+
accentForeground: "oklch(0.15 0.02 310)",
|
|
20360
|
+
card: "oklch(0.99 0.003 310)",
|
|
20361
|
+
cardForeground: "oklch(0.15 0.02 310)",
|
|
20362
|
+
popover: "oklch(0.99 0.003 310)",
|
|
20363
|
+
popoverForeground: "oklch(0.15 0.02 310)",
|
|
20364
|
+
destructive: "oklch(0.55 0.22 27)",
|
|
20365
|
+
border: "oklch(0.92 0.005 310)",
|
|
20366
|
+
input: "oklch(0.92 0.005 310)",
|
|
20367
|
+
ring: "oklch(0.55 0.22 310)",
|
|
20368
|
+
radius: "0.75rem"
|
|
20369
|
+
},
|
|
20370
|
+
/** Green nature theme. Fresh green tones. */
|
|
20371
|
+
green: {
|
|
20372
|
+
background: "oklch(0.99 0.003 150)",
|
|
20373
|
+
foreground: "oklch(0.15 0.02 150)",
|
|
20374
|
+
primary: "oklch(0.55 0.18 155)",
|
|
20375
|
+
primaryForeground: "oklch(1 0 0)",
|
|
20376
|
+
secondary: "oklch(0.96 0.01 150)",
|
|
20377
|
+
secondaryForeground: "oklch(0.15 0.02 150)",
|
|
20378
|
+
muted: "oklch(0.96 0.01 150)",
|
|
20379
|
+
mutedForeground: "oklch(0.5 0.03 150)",
|
|
20380
|
+
accent: "oklch(0.94 0.015 150)",
|
|
20381
|
+
accentForeground: "oklch(0.15 0.02 150)",
|
|
20382
|
+
card: "oklch(0.99 0.003 150)",
|
|
20383
|
+
cardForeground: "oklch(0.15 0.02 150)",
|
|
20384
|
+
popover: "oklch(0.99 0.003 150)",
|
|
20385
|
+
popoverForeground: "oklch(0.15 0.02 150)",
|
|
20386
|
+
destructive: "oklch(0.55 0.22 27)",
|
|
20387
|
+
border: "oklch(0.92 0.008 150)",
|
|
20388
|
+
input: "oklch(0.92 0.008 150)",
|
|
20389
|
+
ring: "oklch(0.55 0.18 155)",
|
|
20390
|
+
radius: "0.625rem"
|
|
20391
|
+
}
|
|
20392
|
+
};
|
|
19789
20393
|
const resolveTokenOverride = ({
|
|
19790
20394
|
config: config2,
|
|
19791
20395
|
token
|
|
@@ -19915,6 +20519,8 @@ function AthenaStatewireStandalone({
|
|
|
19915
20519
|
token,
|
|
19916
20520
|
getToken,
|
|
19917
20521
|
model,
|
|
20522
|
+
agent: agent2,
|
|
20523
|
+
channel,
|
|
19918
20524
|
tools,
|
|
19919
20525
|
frontendToolIds,
|
|
19920
20526
|
frontendTools,
|
|
@@ -19946,6 +20552,8 @@ function AthenaStatewireStandalone({
|
|
|
19946
20552
|
token,
|
|
19947
20553
|
getToken,
|
|
19948
20554
|
model,
|
|
20555
|
+
agent: agent2,
|
|
20556
|
+
channel,
|
|
19949
20557
|
tools,
|
|
19950
20558
|
frontendToolIds,
|
|
19951
20559
|
frontendToolkit: frontendTools,
|
|
@@ -20221,6 +20829,7 @@ function AthenaProvider({
|
|
|
20221
20829
|
apiKey,
|
|
20222
20830
|
token: tokenProp,
|
|
20223
20831
|
agent: agent2,
|
|
20832
|
+
channel,
|
|
20224
20833
|
model,
|
|
20225
20834
|
tools = [],
|
|
20226
20835
|
frontendTools = {},
|
|
@@ -20243,8 +20852,32 @@ function AthenaProvider({
|
|
|
20243
20852
|
theme,
|
|
20244
20853
|
linkClicks,
|
|
20245
20854
|
citationLinks,
|
|
20246
|
-
posthog: posthogProp
|
|
20855
|
+
posthog: posthogProp,
|
|
20856
|
+
debug,
|
|
20857
|
+
onDiagnostic,
|
|
20858
|
+
onError
|
|
20247
20859
|
}) {
|
|
20860
|
+
const onDiagnosticRef = React.useRef(onDiagnostic);
|
|
20861
|
+
onDiagnosticRef.current = onDiagnostic;
|
|
20862
|
+
const onErrorRef = React.useRef(onError);
|
|
20863
|
+
onErrorRef.current = onError;
|
|
20864
|
+
React.useEffect(() => {
|
|
20865
|
+
installAthenaDiagnosticsGlobal();
|
|
20866
|
+
return athenaDiagnostics.addConsumer({
|
|
20867
|
+
onEvent: (event) => {
|
|
20868
|
+
var _a3;
|
|
20869
|
+
return (_a3 = onDiagnosticRef.current) == null ? void 0 : _a3.call(onDiagnosticRef, event);
|
|
20870
|
+
},
|
|
20871
|
+
onError: (error2, event) => {
|
|
20872
|
+
var _a3;
|
|
20873
|
+
return (_a3 = onErrorRef.current) == null ? void 0 : _a3.call(onErrorRef, error2, event);
|
|
20874
|
+
}
|
|
20875
|
+
});
|
|
20876
|
+
}, []);
|
|
20877
|
+
const debugKey = JSON.stringify(debugPropToDiagnosticsConfig(debug));
|
|
20878
|
+
React.useEffect(() => {
|
|
20879
|
+
athenaDiagnostics.configure(debugPropToDiagnosticsConfig(debug));
|
|
20880
|
+
}, [debugKey]);
|
|
20248
20881
|
const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
|
|
20249
20882
|
const effectiveFrontendTools = React.useMemo(
|
|
20250
20883
|
() => disableAutoOpen ? frontendTools : { ...DEFAULT_AUTO_OPEN_TOOLS, ...frontendTools },
|
|
@@ -20271,10 +20904,31 @@ function AthenaProvider({
|
|
|
20271
20904
|
transport: configuredTransport
|
|
20272
20905
|
});
|
|
20273
20906
|
React.useEffect(() => {
|
|
20907
|
+
athenaDiagnostics.gauge("sdk.transport", effectiveTransport);
|
|
20908
|
+
athenaDiagnostics.emit("sdk.transport", {
|
|
20909
|
+
level: "debug",
|
|
20910
|
+
data: { transport: effectiveTransport, thread_list: enableThreadList }
|
|
20911
|
+
});
|
|
20274
20912
|
if (transportFallbackReason) {
|
|
20913
|
+
athenaDiagnostics.emit("sdk.config.warning", {
|
|
20914
|
+
level: "warn",
|
|
20915
|
+
data: { prop: "transport", reason: transportFallbackReason }
|
|
20916
|
+
});
|
|
20275
20917
|
console.warn(`[AthenaSDK] ${transportFallbackReason}`);
|
|
20276
20918
|
}
|
|
20277
|
-
}, [transportFallbackReason]);
|
|
20919
|
+
}, [effectiveTransport, enableThreadList, transportFallbackReason]);
|
|
20920
|
+
React.useEffect(() => {
|
|
20921
|
+
if (channel && effectiveTransport !== "statewire") {
|
|
20922
|
+
athenaDiagnostics.emit("sdk.config.warning", {
|
|
20923
|
+
level: "warn",
|
|
20924
|
+
data: {
|
|
20925
|
+
prop: "channel",
|
|
20926
|
+
value: channel,
|
|
20927
|
+
reason: "the 'channel' prop requires transport='statewire'; the legacy transport ignores it."
|
|
20928
|
+
}
|
|
20929
|
+
});
|
|
20930
|
+
}
|
|
20931
|
+
}, [channel, effectiveTransport]);
|
|
20278
20932
|
const bridge = useParentBridge({
|
|
20279
20933
|
trustedOrigins: configuredTrustedParentOrigins
|
|
20280
20934
|
});
|
|
@@ -20301,6 +20955,8 @@ function AthenaProvider({
|
|
|
20301
20955
|
token: effectiveToken,
|
|
20302
20956
|
getToken: configuredGetToken,
|
|
20303
20957
|
model,
|
|
20958
|
+
agent: agent2,
|
|
20959
|
+
channel,
|
|
20304
20960
|
tools,
|
|
20305
20961
|
frontendToolIds: frontendToolNames,
|
|
20306
20962
|
frontendTools: effectiveFrontendTools,
|
|
@@ -54652,13 +55308,13 @@ function getEmptyMessage(scope, query) {
|
|
|
54652
55308
|
function MentionIcon({ item }) {
|
|
54653
55309
|
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
55310
|
}
|
|
54655
|
-
const MentionSuggestionList = React.forwardRef(({ store, query, command: command2, closeMenu }, ref) => {
|
|
55311
|
+
const MentionSuggestionList = React.forwardRef(({ store: store2, query, command: command2, closeMenu }, ref) => {
|
|
54656
55312
|
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
|
54657
55313
|
const [currentScope, setCurrentScope] = React.useState("root");
|
|
54658
55314
|
const scrollContainerRef = React.useRef(null);
|
|
54659
|
-
const hasGlobalSearch =
|
|
55315
|
+
const hasGlobalSearch = store2.state.registry.entries.has(GLOBAL_SEARCH_SCOPE$1);
|
|
54660
55316
|
const effectiveScope = currentScope === "root" && query.trim() && hasGlobalSearch ? GLOBAL_SEARCH_SCOPE$1 : currentScope;
|
|
54661
|
-
const { items, isFetching } = useStore(
|
|
55317
|
+
const { items, isFetching } = useStore(store2, (state) => ({
|
|
54662
55318
|
items: getFilteredItems(state.cache, effectiveScope, query),
|
|
54663
55319
|
isFetching: false
|
|
54664
55320
|
}));
|
|
@@ -54777,7 +55433,7 @@ const MentionSuggestionList = React.forwardRef(({ store, query, command: command
|
|
|
54777
55433
|
] });
|
|
54778
55434
|
});
|
|
54779
55435
|
MentionSuggestionList.displayName = "MentionSuggestionList";
|
|
54780
|
-
const MentionSuggestionPopup = React.forwardRef(({ store, query, command: command2, clientRect: clientRect2, closeMenu, isHidden: isHidden3 = false }, ref) => {
|
|
55436
|
+
const MentionSuggestionPopup = React.forwardRef(({ store: store2, query, command: command2, clientRect: clientRect2, closeMenu, isHidden: isHidden3 = false }, ref) => {
|
|
54781
55437
|
const listRef = React.useRef(null);
|
|
54782
55438
|
const virtualRef = React.useRef({
|
|
54783
55439
|
getBoundingClientRect: () => clientRect2 ? clientRect2() : new DOMRect()
|
|
@@ -54824,7 +55480,7 @@ const MentionSuggestionPopup = React.forwardRef(({ store, query, command: comman
|
|
|
54824
55480
|
MentionSuggestionList,
|
|
54825
55481
|
{
|
|
54826
55482
|
ref: listRef,
|
|
54827
|
-
store,
|
|
55483
|
+
store: store2,
|
|
54828
55484
|
query,
|
|
54829
55485
|
command: command2,
|
|
54830
55486
|
closeMenu
|
|
@@ -55051,9 +55707,9 @@ function useMentionSuggestions(tools, options = {}) {
|
|
|
55051
55707
|
populateMentionCache({ cache, tools, rootCategories });
|
|
55052
55708
|
storeRef.current = new Store({ registry: registry2, cache });
|
|
55053
55709
|
}
|
|
55054
|
-
const
|
|
55710
|
+
const store2 = storeRef.current;
|
|
55055
55711
|
React.useEffect(() => {
|
|
55056
|
-
|
|
55712
|
+
store2.setState((prev) => {
|
|
55057
55713
|
const newCache = createItemCache();
|
|
55058
55714
|
if (rootCategories) {
|
|
55059
55715
|
registerStaticSource(prev.registry, "toolkits");
|
|
@@ -55063,8 +55719,8 @@ function useMentionSuggestions(tools, options = {}) {
|
|
|
55063
55719
|
populateMentionCache({ cache: newCache, tools, rootCategories });
|
|
55064
55720
|
return { ...prev, cache: newCache };
|
|
55065
55721
|
});
|
|
55066
|
-
}, [tools,
|
|
55067
|
-
return
|
|
55722
|
+
}, [tools, store2, rootCategories, rootCategoriesKey]);
|
|
55723
|
+
return store2;
|
|
55068
55724
|
}
|
|
55069
55725
|
const AttachmentCtx = React.createContext(null);
|
|
55070
55726
|
function AttachmentProvider({ children }) {
|
|
@@ -55385,13 +56041,13 @@ const TiptapComposer = ({ tools = [], rootCategories }) => {
|
|
|
55385
56041
|
});
|
|
55386
56042
|
if (fullMessage) {
|
|
55387
56043
|
aui.composer.setText(fullMessage);
|
|
55388
|
-
aui.composer.send();
|
|
56044
|
+
aui.composer.send({ steer: false });
|
|
55389
56045
|
clearAttachments();
|
|
55390
56046
|
clearQuote();
|
|
55391
56047
|
}
|
|
55392
56048
|
} else {
|
|
55393
56049
|
aui.composer.setText(markdown);
|
|
55394
|
-
aui.composer.send();
|
|
56050
|
+
aui.composer.send({ steer: false });
|
|
55395
56051
|
}
|
|
55396
56052
|
editor2.commands.clearContent();
|
|
55397
56053
|
}, [aui, clearAttachments, clearQuote, appUrl]);
|
|
@@ -56028,6 +56684,10 @@ const TOOL_META = {
|
|
|
56028
56684
|
// Presentations
|
|
56029
56685
|
create_powerpoint_deck: { displayName: "Building presentation", icon: Monitor },
|
|
56030
56686
|
execute_presentation_code: { displayName: "Generating slides", icon: Monitor },
|
|
56687
|
+
execute_word_document_code: { displayName: "Editing Word document", icon: FileText },
|
|
56688
|
+
execute_spreadsheet_code: { displayName: "Editing spreadsheet", icon: ChartColumn },
|
|
56689
|
+
execute_spreadsheet_commands: { displayName: "Editing spreadsheet", icon: ChartColumn },
|
|
56690
|
+
unified_email_list_accounts: { displayName: "Checking email accounts", icon: Mail },
|
|
56031
56691
|
// Code & Data
|
|
56032
56692
|
run_python_code: { displayName: "Running analysis", icon: Code },
|
|
56033
56693
|
run_sql_query_tool: { displayName: "Running SQL query", icon: Database, describer: (a) => a.sql_query ?? a.query ?? a.sql ? `"${truncateLine(a.sql_query ?? a.query ?? a.sql)}"` : "" },
|
|
@@ -56075,14 +56735,14 @@ function extractResultMessage(result) {
|
|
|
56075
56735
|
return null;
|
|
56076
56736
|
}
|
|
56077
56737
|
function isResultSuccess(result) {
|
|
56078
|
-
|
|
56079
|
-
|
|
56080
|
-
if (
|
|
56081
|
-
|
|
56082
|
-
|
|
56083
|
-
return result.success === true;
|
|
56738
|
+
const obj = typeof result === "string" ? tryParseJson$1(result) : typeof result === "object" && result !== null ? result : null;
|
|
56739
|
+
if (obj) {
|
|
56740
|
+
if (obj.success === false || obj.ok === false) return false;
|
|
56741
|
+
if (typeof obj.error === "string" && obj.error.length > 0) return false;
|
|
56742
|
+
return true;
|
|
56084
56743
|
}
|
|
56085
|
-
return
|
|
56744
|
+
if (typeof result === "string") return !/^\s*error\b/i.test(result);
|
|
56745
|
+
return true;
|
|
56086
56746
|
}
|
|
56087
56747
|
function extractAssetId$1(result) {
|
|
56088
56748
|
if (!result) return null;
|
|
@@ -56247,7 +56907,7 @@ function ToolFallbackTrigger({
|
|
|
56247
56907
|
"span",
|
|
56248
56908
|
{
|
|
56249
56909
|
className: cn(
|
|
56250
|
-
"relative inline-block leading-tight",
|
|
56910
|
+
"relative inline-block text-[13px] font-medium leading-tight",
|
|
56251
56911
|
isCancelled && "text-muted-foreground line-through"
|
|
56252
56912
|
),
|
|
56253
56913
|
children: [
|
|
@@ -57232,17 +57892,103 @@ BrowseToolUI.displayName = "BrowseToolUI";
|
|
|
57232
57892
|
function parseEmailResults(data) {
|
|
57233
57893
|
const results = data.limited_results ?? data.results ?? data.emails ?? data.messages;
|
|
57234
57894
|
if (!Array.isArray(results)) return [];
|
|
57235
|
-
return results.slice(0,
|
|
57236
|
-
const item = r2;
|
|
57237
|
-
return
|
|
57238
|
-
|
|
57239
|
-
|
|
57240
|
-
|
|
57241
|
-
|
|
57242
|
-
|
|
57243
|
-
|
|
57895
|
+
return results.slice(0, 50).flatMap((r2) => {
|
|
57896
|
+
const item = asRecord(r2);
|
|
57897
|
+
if (!item) return [];
|
|
57898
|
+
return [
|
|
57899
|
+
{
|
|
57900
|
+
subject: asString(item.subject) ?? asString(item.title),
|
|
57901
|
+
from: asString(item.from) ?? asString(item.sender) ?? asString(item.from_email),
|
|
57902
|
+
date: asString(item.date) ?? asString(item.received_at) ?? asString(item.sent_at),
|
|
57903
|
+
snippet: asString(item.snippet) ?? asString(item.preview) ?? asString(item.body_preview),
|
|
57904
|
+
isDraft: item.is_draft === true
|
|
57905
|
+
}
|
|
57906
|
+
];
|
|
57244
57907
|
});
|
|
57245
57908
|
}
|
|
57909
|
+
function formatEmailDate(raw) {
|
|
57910
|
+
if (!raw) return void 0;
|
|
57911
|
+
const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(raw.trim());
|
|
57912
|
+
const date2 = dateOnly ? new Date(Number(dateOnly[1]), Number(dateOnly[2]) - 1, Number(dateOnly[3])) : new Date(raw);
|
|
57913
|
+
if (Number.isNaN(date2.getTime())) return raw;
|
|
57914
|
+
const now = /* @__PURE__ */ new Date();
|
|
57915
|
+
if (!dateOnly && date2.toDateString() === now.toDateString()) {
|
|
57916
|
+
return date2.toLocaleTimeString(void 0, {
|
|
57917
|
+
hour: "numeric",
|
|
57918
|
+
minute: "2-digit"
|
|
57919
|
+
});
|
|
57920
|
+
}
|
|
57921
|
+
const sameYear = date2.getFullYear() === now.getFullYear();
|
|
57922
|
+
return date2.toLocaleDateString(void 0, {
|
|
57923
|
+
month: "short",
|
|
57924
|
+
day: "numeric",
|
|
57925
|
+
...sameYear ? {} : { year: "numeric" }
|
|
57926
|
+
});
|
|
57927
|
+
}
|
|
57928
|
+
const EMAIL_QUERY_OPERATOR = /(?:^|\s)(received|after|before|from|to|subject|has|in|is):(?:"([^"]+)"|(\S+))/gi;
|
|
57929
|
+
function humanEmailDate(raw) {
|
|
57930
|
+
return formatEmailDate(raw.replace(/\//g, "-")) ?? raw;
|
|
57931
|
+
}
|
|
57932
|
+
function humanizeEmailQuery(query) {
|
|
57933
|
+
if (!query.trim()) return "";
|
|
57934
|
+
const phrases = [];
|
|
57935
|
+
let freeText = query;
|
|
57936
|
+
for (const match2 of query.matchAll(EMAIL_QUERY_OPERATOR)) {
|
|
57937
|
+
const [token, op, quoted, bare] = match2;
|
|
57938
|
+
const value = quoted ?? bare ?? "";
|
|
57939
|
+
freeText = freeText.replace(token, " ");
|
|
57940
|
+
switch (op.toLowerCase()) {
|
|
57941
|
+
case "received": {
|
|
57942
|
+
const [start, end] = value.split("..");
|
|
57943
|
+
phrases.push(
|
|
57944
|
+
end ? `${humanEmailDate(start)} – ${humanEmailDate(end)}` : humanEmailDate(start)
|
|
57945
|
+
);
|
|
57946
|
+
break;
|
|
57947
|
+
}
|
|
57948
|
+
case "after":
|
|
57949
|
+
phrases.push(`after ${humanEmailDate(value)}`);
|
|
57950
|
+
break;
|
|
57951
|
+
case "before":
|
|
57952
|
+
phrases.push(`before ${humanEmailDate(value)}`);
|
|
57953
|
+
break;
|
|
57954
|
+
case "from":
|
|
57955
|
+
phrases.push(`from ${value}`);
|
|
57956
|
+
break;
|
|
57957
|
+
case "to":
|
|
57958
|
+
phrases.push(`to ${value}`);
|
|
57959
|
+
break;
|
|
57960
|
+
case "subject":
|
|
57961
|
+
phrases.push(`subject “${value}”`);
|
|
57962
|
+
break;
|
|
57963
|
+
case "has":
|
|
57964
|
+
phrases.push(value === "attachment" ? "with attachments" : `has ${value}`);
|
|
57965
|
+
break;
|
|
57966
|
+
case "in":
|
|
57967
|
+
phrases.push(value === "drafts" ? "drafts only" : `in ${value}`);
|
|
57968
|
+
break;
|
|
57969
|
+
case "is":
|
|
57970
|
+
phrases.push(value);
|
|
57971
|
+
break;
|
|
57972
|
+
}
|
|
57973
|
+
}
|
|
57974
|
+
const remainder = freeText.trim().replace(/\s+/g, " ");
|
|
57975
|
+
if (remainder) phrases.push(`“${remainder}”`);
|
|
57976
|
+
return phrases.join(" · ");
|
|
57977
|
+
}
|
|
57978
|
+
const INLINE_EMAIL_ROWS = 3;
|
|
57979
|
+
function EmailResultRow({ email: email2 }) {
|
|
57980
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5 py-2 first:pt-0 last:pb-0", children: [
|
|
57981
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
57982
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-baseline gap-1.5 text-[12px] font-medium text-foreground", children: [
|
|
57983
|
+
email2.isDraft && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 rounded bg-amber-100 px-1 py-px text-[9px] font-semibold uppercase tracking-wide text-amber-700", children: "Draft" }),
|
|
57984
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: email2.subject || "No subject" })
|
|
57985
|
+
] }),
|
|
57986
|
+
email2.date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: formatEmailDate(email2.date) })
|
|
57987
|
+
] }),
|
|
57988
|
+
email2.from && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: email2.from }),
|
|
57989
|
+
email2.snippet && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-relaxed text-muted-foreground/80", children: truncate(email2.snippet, 150) })
|
|
57990
|
+
] });
|
|
57991
|
+
}
|
|
57246
57992
|
const EmailSearchToolUIImpl = ({
|
|
57247
57993
|
toolName,
|
|
57248
57994
|
args,
|
|
@@ -57253,35 +57999,96 @@ const EmailSearchToolUIImpl = ({
|
|
|
57253
57999
|
const query = (typedArgs == null ? void 0 : typedArgs.query) ?? (typedArgs == null ? void 0 : typedArgs.search_query) ?? "";
|
|
57254
58000
|
const data = React.useMemo(() => normalizeResult(result), [result]);
|
|
57255
58001
|
const emails = React.useMemo(() => data ? parseEmailResults(data) : [], [data]);
|
|
58002
|
+
const provider = typeof (data == null ? void 0 : data.provider) === "string" ? data.provider : void 0;
|
|
58003
|
+
const totalCount = typeof (data == null ? void 0 : data.count) === "number" ? data.count : emails.length;
|
|
57256
58004
|
const isRunning = (status == null ? void 0 : status.type) === "running";
|
|
57257
58005
|
const isComplete = (status == null ? void 0 : status.type) === "complete";
|
|
57258
58006
|
const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? status.error : null;
|
|
58007
|
+
const readableQuery = React.useMemo(() => humanizeEmailQuery(query), [query]);
|
|
58008
|
+
const inlineEmails = emails.slice(0, INLINE_EMAIL_ROWS);
|
|
58009
|
+
const overflowEmails = emails.slice(INLINE_EMAIL_ROWS);
|
|
58010
|
+
const countLabel = emails.length > 0 && totalCount > emails.length ? `${emails.length} of ${totalCount}` : `${totalCount}`;
|
|
57259
58011
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
57260
58012
|
ToolCard,
|
|
57261
58013
|
{
|
|
57262
58014
|
icon: Mail,
|
|
57263
58015
|
status: (status == null ? void 0 : status.type) ?? "complete",
|
|
57264
|
-
title: isRunning ? "Searching
|
|
57265
|
-
subtitle:
|
|
58016
|
+
title: isRunning ? "Searching email…" : "Email search",
|
|
58017
|
+
subtitle: readableQuery ? truncate(readableQuery, 90) : void 0,
|
|
57266
58018
|
toolName,
|
|
57267
58019
|
args: typedArgs,
|
|
57268
58020
|
result,
|
|
57269
|
-
badge: isComplete
|
|
58021
|
+
badge: isComplete ? totalCount > 0 ? `${countLabel} email${totalCount === 1 ? "" : "s"}${provider ? ` · ${provider}` : ""}` : "No matches" : void 0,
|
|
58022
|
+
error: errorMsg,
|
|
58023
|
+
children: isComplete && emails.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/40 px-4 py-2.5", children: [
|
|
58024
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col divide-y divide-border/30", children: inlineEmails.map((email2, i) => /* @__PURE__ */ jsxRuntime.jsx(EmailResultRow, { email: email2 }, i)) }),
|
|
58025
|
+
overflowEmails.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
58026
|
+
ExpandableSection,
|
|
58027
|
+
{
|
|
58028
|
+
label: `Show ${overflowEmails.length} more`,
|
|
58029
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col divide-y divide-border/30", children: overflowEmails.map((email2, i) => /* @__PURE__ */ jsxRuntime.jsx(EmailResultRow, { email: email2 }, i)) })
|
|
58030
|
+
}
|
|
58031
|
+
)
|
|
58032
|
+
] })
|
|
58033
|
+
}
|
|
58034
|
+
);
|
|
58035
|
+
};
|
|
58036
|
+
const EmailSearchToolUI = React.memo(
|
|
58037
|
+
EmailSearchToolUIImpl
|
|
58038
|
+
);
|
|
58039
|
+
EmailSearchToolUI.displayName = "EmailSearchToolUI";
|
|
58040
|
+
function parseEmailAccounts(data) {
|
|
58041
|
+
const accounts = data.accounts ?? data.results;
|
|
58042
|
+
if (!Array.isArray(accounts)) return [];
|
|
58043
|
+
return accounts.slice(0, 10).flatMap((raw) => {
|
|
58044
|
+
const item = asRecord(raw);
|
|
58045
|
+
if (!item) return [];
|
|
58046
|
+
const defaultFlag = typeof item.is_default === "boolean" ? item.is_default : item.default;
|
|
58047
|
+
return [
|
|
58048
|
+
{
|
|
58049
|
+
address: asString(item.email_address) ?? asString(item.email) ?? asString(item.address),
|
|
58050
|
+
provider: asString(item.provider) ?? asString(item.provider_name),
|
|
58051
|
+
name: asString(item.account_name) ?? asString(item.name),
|
|
58052
|
+
isDefault: defaultFlag === true
|
|
58053
|
+
}
|
|
58054
|
+
];
|
|
58055
|
+
});
|
|
58056
|
+
}
|
|
58057
|
+
const EmailAccountsToolUIImpl = ({
|
|
58058
|
+
toolName,
|
|
58059
|
+
args,
|
|
58060
|
+
result,
|
|
58061
|
+
status
|
|
58062
|
+
}) => {
|
|
58063
|
+
const data = React.useMemo(() => normalizeResult(result), [result]);
|
|
58064
|
+
const accounts = React.useMemo(
|
|
58065
|
+
() => data ? parseEmailAccounts(data) : [],
|
|
58066
|
+
[data]
|
|
58067
|
+
);
|
|
58068
|
+
const isRunning = (status == null ? void 0 : status.type) === "running";
|
|
58069
|
+
const isComplete = (status == null ? void 0 : status.type) === "complete";
|
|
58070
|
+
const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? status.error : null;
|
|
58071
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
58072
|
+
ToolCard,
|
|
58073
|
+
{
|
|
58074
|
+
icon: Mail,
|
|
58075
|
+
status: (status == null ? void 0 : status.type) ?? "complete",
|
|
58076
|
+
title: isRunning ? "Checking connected email accounts…" : "Email accounts",
|
|
58077
|
+
toolName,
|
|
58078
|
+
args,
|
|
58079
|
+
result,
|
|
58080
|
+
badge: isComplete && accounts.length > 0 ? `${accounts.length} connected` : void 0,
|
|
57270
58081
|
error: errorMsg,
|
|
57271
|
-
children: isComplete &&
|
|
58082
|
+
children: isComplete && accounts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col divide-y divide-border/30", children: accounts.map((account, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
57272
58083
|
"div",
|
|
57273
58084
|
{
|
|
57274
|
-
className:
|
|
58085
|
+
className: "flex items-center justify-between gap-2 py-1.5 first:pt-0 last:pb-0",
|
|
57275
58086
|
children: [
|
|
57276
|
-
/* @__PURE__ */ jsxRuntime.
|
|
57277
|
-
|
|
57278
|
-
|
|
57279
|
-
|
|
57280
|
-
|
|
57281
|
-
email2.date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: email2.date })
|
|
57282
|
-
] }),
|
|
57283
|
-
email2.from && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-muted-foreground", children: email2.from }),
|
|
57284
|
-
email2.snippet && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-relaxed text-muted-foreground/80", children: truncate(email2.snippet, 150) })
|
|
58087
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-[12px] text-foreground", children: account.address || account.name || "Unknown account" }),
|
|
58088
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
58089
|
+
account.isDefault && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-emerald-50 px-1.5 py-px text-[9px] font-semibold uppercase tracking-wide text-emerald-700", children: "Default" }),
|
|
58090
|
+
account.provider && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-md bg-muted/60 px-1.5 py-0.5 text-[10px] text-muted-foreground", children: account.provider })
|
|
58091
|
+
] })
|
|
57285
58092
|
]
|
|
57286
58093
|
},
|
|
57287
58094
|
i
|
|
@@ -57289,10 +58096,10 @@ const EmailSearchToolUIImpl = ({
|
|
|
57289
58096
|
}
|
|
57290
58097
|
);
|
|
57291
58098
|
};
|
|
57292
|
-
const
|
|
57293
|
-
|
|
58099
|
+
const EmailAccountsToolUI = React.memo(
|
|
58100
|
+
EmailAccountsToolUIImpl
|
|
57294
58101
|
);
|
|
57295
|
-
|
|
58102
|
+
EmailAccountsToolUI.displayName = "EmailAccountsToolUI";
|
|
57296
58103
|
function extractAssetId(result) {
|
|
57297
58104
|
const data = normalizeResult(result);
|
|
57298
58105
|
if (!data) return null;
|
|
@@ -57329,6 +58136,9 @@ function asRecord(value) {
|
|
|
57329
58136
|
}
|
|
57330
58137
|
return value;
|
|
57331
58138
|
}
|
|
58139
|
+
function asString(value) {
|
|
58140
|
+
return typeof value === "string" ? value : void 0;
|
|
58141
|
+
}
|
|
57332
58142
|
const PRESENTATION_CODE_SLIDE_NUMBER_KEYS = [
|
|
57333
58143
|
"slideNumber",
|
|
57334
58144
|
"slide_number",
|
|
@@ -57425,22 +58235,51 @@ function CreateAssetToolUIImpl({
|
|
|
57425
58235
|
args: typedArgs,
|
|
57426
58236
|
result,
|
|
57427
58237
|
error: errorMsg,
|
|
57428
|
-
children: assetId && isComplete && !isCancelled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58238
|
+
children: assetId && isComplete && !isCancelled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
57429
58239
|
"button",
|
|
57430
58240
|
{
|
|
57431
58241
|
type: "button",
|
|
57432
58242
|
onClick: handleOpen,
|
|
57433
|
-
className: "flex items-center gap-
|
|
58243
|
+
className: "group flex w-full items-center gap-3 rounded-lg border border-border/60 bg-muted/20 px-3 py-2.5 text-left transition-colors hover:border-border hover:bg-muted/40",
|
|
57434
58244
|
children: [
|
|
57435
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
57436
|
-
|
|
57437
|
-
|
|
58245
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58246
|
+
"div",
|
|
58247
|
+
{
|
|
58248
|
+
className: cn(
|
|
58249
|
+
"flex size-10 shrink-0 items-center justify-center rounded-lg",
|
|
58250
|
+
ASSET_TILE_STYLE[assetType] ?? ASSET_TILE_STYLE.unknown
|
|
58251
|
+
),
|
|
58252
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-5" })
|
|
58253
|
+
}
|
|
58254
|
+
),
|
|
58255
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
58256
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate text-[13px] font-medium text-foreground", children: createdName || name || "Untitled" }),
|
|
58257
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px] text-muted-foreground", children: [
|
|
58258
|
+
ASSET_TILE_LABEL[assetType] ?? "Asset",
|
|
58259
|
+
" · Click to open"
|
|
58260
|
+
] })
|
|
58261
|
+
] }),
|
|
58262
|
+
/* @__PURE__ */ jsxRuntime.jsx(ExternalLink, { className: "size-3.5 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100" })
|
|
57438
58263
|
]
|
|
57439
58264
|
}
|
|
57440
58265
|
) })
|
|
57441
58266
|
}
|
|
57442
58267
|
);
|
|
57443
58268
|
}
|
|
58269
|
+
const ASSET_TILE_STYLE = {
|
|
58270
|
+
document: "bg-blue-500/10 text-blue-600",
|
|
58271
|
+
spreadsheet: "bg-emerald-500/10 text-emerald-600",
|
|
58272
|
+
presentation: "bg-orange-500/10 text-orange-600",
|
|
58273
|
+
notebook: "bg-violet-500/10 text-violet-600",
|
|
58274
|
+
unknown: "bg-muted text-muted-foreground"
|
|
58275
|
+
};
|
|
58276
|
+
const ASSET_TILE_LABEL = {
|
|
58277
|
+
document: "Document",
|
|
58278
|
+
spreadsheet: "Spreadsheet",
|
|
58279
|
+
presentation: "Presentation",
|
|
58280
|
+
notebook: "Notebook",
|
|
58281
|
+
unknown: "Asset"
|
|
58282
|
+
};
|
|
57444
58283
|
const CreateDocumentToolUIImpl = (props) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
57445
58284
|
CreateAssetToolUIImpl,
|
|
57446
58285
|
{
|
|
@@ -57489,10 +58328,10 @@ function openStudioAsset({
|
|
|
57489
58328
|
slideNumber,
|
|
57490
58329
|
preserveExistingSlide
|
|
57491
58330
|
}) {
|
|
57492
|
-
const
|
|
57493
|
-
const existing =
|
|
58331
|
+
const store2 = useAssetPanelStore.getState();
|
|
58332
|
+
const existing = store2.tabs.find((tab) => tab.id === assetId);
|
|
57494
58333
|
const shouldKeepCurrentSlide = preserveExistingSlide && existing;
|
|
57495
|
-
|
|
58334
|
+
store2.openAsset(assetId, {
|
|
57496
58335
|
type: assetType,
|
|
57497
58336
|
...!shouldKeepCurrentSlide && slideNumber !== void 0 ? { slideNumber } : {}
|
|
57498
58337
|
});
|
|
@@ -59863,6 +60702,8 @@ const TOOL_UI_REGISTRY = {
|
|
|
59863
60702
|
open_browser: OpenBrowserToolUI,
|
|
59864
60703
|
search_email: EmailSearchToolUI,
|
|
59865
60704
|
unified_email_search: EmailSearchToolUI,
|
|
60705
|
+
unified_email_list_accounts: EmailAccountsToolUI,
|
|
60706
|
+
email_list_accounts: EmailAccountsToolUI,
|
|
59866
60707
|
create_email_draft: CreateEmailDraftToolUI,
|
|
59867
60708
|
unified_email_create_draft: CreateEmailDraftToolUI,
|
|
59868
60709
|
create_new_document: CreateDocumentToolUI,
|
|
@@ -60621,7 +61462,7 @@ function useSendMessage() {
|
|
|
60621
61462
|
shouldReplace || !currentText ? text2 : `${currentText}
|
|
60622
61463
|
${text2}`
|
|
60623
61464
|
);
|
|
60624
|
-
await aui.composer.send();
|
|
61465
|
+
await aui.composer.send({ steer: false });
|
|
60625
61466
|
},
|
|
60626
61467
|
[aui]
|
|
60627
61468
|
);
|
|
@@ -61221,13 +62062,13 @@ const ComposerSendWithQuote = () => {
|
|
|
61221
62062
|
});
|
|
61222
62063
|
if (!fullMessage) return;
|
|
61223
62064
|
aui.composer.setText(fullMessage);
|
|
61224
|
-
aui.composer.send();
|
|
62065
|
+
aui.composer.send({ steer: false });
|
|
61225
62066
|
clearQuote();
|
|
61226
62067
|
clearAttachments();
|
|
61227
62068
|
} else {
|
|
61228
62069
|
if (!userText) return;
|
|
61229
62070
|
aui.composer.setText(userText);
|
|
61230
|
-
aui.composer.send();
|
|
62071
|
+
aui.composer.send({ steer: false });
|
|
61231
62072
|
}
|
|
61232
62073
|
editor == null ? void 0 : editor.clear();
|
|
61233
62074
|
}, [aui, quote, attachments, hasExtras, isUploading, isThreadRunning, clearQuote, clearAttachments, editorRef, appUrl]);
|
|
@@ -62457,6 +63298,8 @@ function useComposerAttachment() {
|
|
|
62457
63298
|
}, [aui]);
|
|
62458
63299
|
return { addFile, addContent, clear };
|
|
62459
63300
|
}
|
|
63301
|
+
exports.ATHENA_REACT_SDK_VERSION = ATHENA_REACT_SDK_VERSION;
|
|
63302
|
+
exports.ATHENA_SDK_ERROR_CODES = ATHENA_SDK_ERROR_CODES;
|
|
62460
63303
|
exports.ATHENA_TRANSPORTS = ATHENA_TRANSPORTS;
|
|
62461
63304
|
exports.AppendDocumentToolUI = AppendDocumentToolUI;
|
|
62462
63305
|
exports.AssetPanel = AssetPanel;
|
|
@@ -62467,10 +63310,12 @@ exports.AthenaChat = AthenaChat;
|
|
|
62467
63310
|
exports.AthenaLayout = AthenaLayout;
|
|
62468
63311
|
exports.AthenaProvider = AthenaProvider;
|
|
62469
63312
|
exports.AthenaReasoningPart = AthenaReasoningPart;
|
|
63313
|
+
exports.AthenaSdkError = AthenaSdkError;
|
|
62470
63314
|
exports.AthenaThreadIdContext = AthenaThreadIdContext;
|
|
62471
63315
|
exports.AthenaUserMessage = AthenaUserMessage;
|
|
62472
63316
|
exports.BrowseToolUI = BrowseToolUI;
|
|
62473
63317
|
exports.Button = Button;
|
|
63318
|
+
exports.COLLAB_AGENT_REF_PREFIX = COLLAB_AGENT_REF_PREFIX;
|
|
62474
63319
|
exports.Collapsible = Collapsible;
|
|
62475
63320
|
exports.CollapsibleContent = CollapsibleContent;
|
|
62476
63321
|
exports.CollapsibleTrigger = CollapsibleTrigger;
|
|
@@ -62530,6 +63375,7 @@ exports.WebSearchToolUI = WebSearchToolUI;
|
|
|
62530
63375
|
exports.allowsMidRunSend = allowsMidRunSend;
|
|
62531
63376
|
exports.archiveThread = archiveThread;
|
|
62532
63377
|
exports.asHitlApproval = asHitlApproval;
|
|
63378
|
+
exports.athenaDiagnostics = athenaDiagnostics;
|
|
62533
63379
|
exports.athenaStatewireErrorNotice = athenaStatewireErrorNotice;
|
|
62534
63380
|
exports.autoCloseInFlightSubgraphMessages = autoCloseInFlightSubgraphMessages;
|
|
62535
63381
|
exports.buildCoalescedCaptureProperties = buildCoalescedCaptureProperties;
|
|
@@ -62553,13 +63399,17 @@ exports.getPostHogInstance = getPostHogInstance;
|
|
|
62553
63399
|
exports.getPosthogCaptureGate = getPosthogCaptureGate;
|
|
62554
63400
|
exports.getThreadState = getThreadState;
|
|
62555
63401
|
exports.hasStatewireThreadExtras = hasStatewireThreadExtras;
|
|
63402
|
+
exports.installAthenaDiagnosticsGlobal = installAthenaDiagnosticsGlobal;
|
|
62556
63403
|
exports.isAthenaCitationUrl = isAthenaCitationUrl;
|
|
63404
|
+
exports.isAthenaSdkError = isAthenaSdkError;
|
|
62557
63405
|
exports.isCriticalPosthogEvent = isCriticalPosthogEvent;
|
|
62558
63406
|
exports.isPendingInterrupt = isPendingInterrupt;
|
|
62559
63407
|
exports.listThreads = listThreads;
|
|
62560
63408
|
exports.normalizeResult = normalizeResult;
|
|
62561
63409
|
exports.parseAthenaCitationLink = parseAthenaCitationLink;
|
|
63410
|
+
exports.parseCollabAgentRef = parseCollabAgentRef;
|
|
62562
63411
|
exports.readInterruptMessage = readInterruptMessage;
|
|
63412
|
+
exports.readRejectionDetail = readRejectionDetail;
|
|
62563
63413
|
exports.resetAssetAutoOpen = resetAssetAutoOpen;
|
|
62564
63414
|
exports.resolveAthenaTransport = resolveAthenaTransport;
|
|
62565
63415
|
exports.resolveStatewireSyncUrl = resolveStatewireSyncUrl;
|
|
@@ -62567,6 +63417,7 @@ exports.setThreadReadState = setThreadReadState;
|
|
|
62567
63417
|
exports.statewireClientToolWireEntries = statewireClientToolWireEntries;
|
|
62568
63418
|
exports.themeToStyleVars = themeToStyleVars;
|
|
62569
63419
|
exports.themes = themes;
|
|
63420
|
+
exports.toAthenaSdkError = toAthenaSdkError;
|
|
62570
63421
|
exports.truncate = truncate;
|
|
62571
63422
|
exports.tryParseJson = tryParseJson$2;
|
|
62572
63423
|
exports.useAppendToComposer = useAppendToComposer;
|
|
@@ -62574,6 +63425,7 @@ exports.useAssetEmbed = useAssetEmbed;
|
|
|
62574
63425
|
exports.useAssetPanelStore = useAssetPanelStore;
|
|
62575
63426
|
exports.useAthenaCitationLinkHandler = useAthenaCitationLinkHandler;
|
|
62576
63427
|
exports.useAthenaConfig = useAthenaConfig;
|
|
63428
|
+
exports.useAthenaDiagnostics = useAthenaDiagnostics;
|
|
62577
63429
|
exports.useAthenaLinkClickHandler = useAthenaLinkClickHandler;
|
|
62578
63430
|
exports.useAthenaRuntime = useAthenaRuntime;
|
|
62579
63431
|
exports.useAthenaStatewireLifecycle = useAthenaStatewireLifecycle;
|