@ykurilov/agent-chat-react 0.80.0 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/{chunk-LF723Y52.js → chunk-PZZBB4Y6.js} +98 -58
- package/dist/chunk-PZZBB4Y6.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/panel.js +1 -1
- package/dist/types/chat-lifetime.d.ts +11 -0
- package/dist/types/widgets/use-widget-answer.d.ts +2 -0
- package/package.json +1 -1
- package/dist/chunk-LF723Y52.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @ykurilov/agent-chat-react
|
|
2
2
|
|
|
3
|
+
## 0.81.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 038b6e2: Исправления аудита клиентской зоны. `useAgentChat` без `key` при смене чата больше не переносит в новый чат дела прежнего: «Стоп», ответ на подтверждение или виджет, передачу поправок и сорвавшуюся голосовую замену; новый чат не остаётся «занятым», повторное открытие того же чата начинается с чистого состояния. Песочница не зовёт хуки приложения, которые пишут данные (`onStateChanged`, `onTurnFinished`, `onModelChosen`), ни в песочном чате, ни в копии чата человека; `newChatGreeting` и `modelMenu` решаются для настоящего админа. Вложения: удаление человеком и чистка брошенных больше не убирают файл, который отправляемое сообщение уже отметило; `confirmUserParts` отказывает `AttachmentRejectedError` (`attachment_not_found` — файла нет или отметка не записана, `attachment_unavailable` — сбой хранилища), а не отмечает молча.
|
|
8
|
+
|
|
9
|
+
### Как обновить приложение
|
|
10
|
+
|
|
11
|
+
Обновите пакеты SDK одной версией. Со встроенными хранилищами вложений (`createDiskAttachmentStorage`, `createMemoryAttachmentStorage`) ничего менять не нужно. Своё хранилище (`AttachmentStorage`, например S3) должно получить метод `removeUnattached(id): Promise<boolean>` — удалить файл, только если он не прикреплён, атомарно с `markAttached` того же файла; `removeUnattachedOlderThan` должен следовать тому же правилу. Без метода `createAttachments` бросает ошибку при запуске. Проверьте хранилище обновлённым `describeAttachmentStorageContract`. Если песочница полагалась на `onStateChanged`, `onTurnFinished` или `onModelChosen` в песочных чатах — в песочнице они больше не зовутся. [Подробности](https://github.com/ykurilov/agent-chat-sdk/blob/main/docs/audit-client.md).
|
|
12
|
+
|
|
13
|
+
## 0.80.1
|
|
14
|
+
|
|
15
|
+
No changes in this release.
|
|
16
|
+
|
|
3
17
|
## 0.80.0
|
|
4
18
|
|
|
5
19
|
No changes in this release.
|
|
@@ -1878,6 +1878,11 @@ function approvalOf(progress, controls) {
|
|
|
1878
1878
|
// src/widgets/use-widget-answer.ts
|
|
1879
1879
|
import { useCallback as useCallback2, useRef as useRef2, useState } from "react";
|
|
1880
1880
|
|
|
1881
|
+
// src/chat-lifetime.ts
|
|
1882
|
+
function ownedBy(owned, lifetime) {
|
|
1883
|
+
return owned !== null && owned.lifetime === lifetime && !lifetime.aborted ? owned.value : void 0;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1881
1886
|
// src/widgets/widget-answer-keys.ts
|
|
1882
1887
|
var CHOSEN_KEY = "\u0432\u044B\u0431\u0440\u0430\u043D\u043E";
|
|
1883
1888
|
var RATING_KEY = "\u043E\u0446\u0435\u043D\u043A\u0430";
|
|
@@ -1943,14 +1948,15 @@ function hasPendingApproval(messages) {
|
|
|
1943
1948
|
function useWidgetAnswer(deps) {
|
|
1944
1949
|
const depsRef = useRef2(deps);
|
|
1945
1950
|
depsRef.current = deps;
|
|
1946
|
-
const answering = useRef2(
|
|
1951
|
+
const answering = useRef2(null);
|
|
1947
1952
|
const [widgetPendingId, setWidgetPendingId] = useState(null);
|
|
1948
1953
|
const [widgetFailure, setWidgetFailure] = useState(null);
|
|
1949
1954
|
const answerWidget = useCallback2(async (toolCallId, answer, onAccepted) => {
|
|
1950
|
-
if (answering.current) return false;
|
|
1951
|
-
answering.current = true;
|
|
1952
1955
|
const current = depsRef.current;
|
|
1953
1956
|
const signal = current.chatSignal();
|
|
1957
|
+
if (ownedBy(answering.current, signal) !== void 0) return false;
|
|
1958
|
+
const pending = { lifetime: signal, value: toolCallId };
|
|
1959
|
+
answering.current = pending;
|
|
1954
1960
|
const fail = (kind, text) => {
|
|
1955
1961
|
if (!signal.aborted) setWidgetFailure({ id: toolCallId, kind, ...text !== void 0 && { text } });
|
|
1956
1962
|
return false;
|
|
@@ -1970,6 +1976,7 @@ function useWidgetAnswer(deps) {
|
|
|
1970
1976
|
return fail("connection");
|
|
1971
1977
|
}
|
|
1972
1978
|
const refusedByApp = response.ok ? null : await serverRefusalOf(response);
|
|
1979
|
+
if (signal.aborted) return false;
|
|
1973
1980
|
if (refusedByApp?.kind) {
|
|
1974
1981
|
current.announceAppRefusal(refusedByApp);
|
|
1975
1982
|
return fail("refused", refusedByApp.text);
|
|
@@ -1993,8 +2000,9 @@ function useWidgetAnswer(deps) {
|
|
|
1993
2000
|
}
|
|
1994
2001
|
if (!response.ok) return fail("connection");
|
|
1995
2002
|
const resumed = await resumedOf(response);
|
|
2003
|
+
if (signal.aborted) return true;
|
|
1996
2004
|
current.setMessages((messages) => withWidgetAnswer(messages, toolCallId, answer, resumed));
|
|
1997
|
-
|
|
2005
|
+
onAccepted?.();
|
|
1998
2006
|
if (!resumed) {
|
|
1999
2007
|
current.expectLiveEventsOf(toolCallId);
|
|
2000
2008
|
if (!signal.aborted) await current.rereadHistory(signal);
|
|
@@ -2010,12 +2018,16 @@ function useWidgetAnswer(deps) {
|
|
|
2010
2018
|
}
|
|
2011
2019
|
return true;
|
|
2012
2020
|
} finally {
|
|
2013
|
-
answering.current =
|
|
2021
|
+
if (answering.current === pending) answering.current = null;
|
|
2014
2022
|
if (!signal.aborted) setWidgetPendingId(null);
|
|
2015
2023
|
}
|
|
2016
2024
|
}, []);
|
|
2017
|
-
const answeringWidget = useCallback2(() => answering.current, []);
|
|
2018
|
-
|
|
2025
|
+
const answeringWidget = useCallback2(() => ownedBy(answering.current, depsRef.current.chatSignal()) !== void 0, []);
|
|
2026
|
+
const forgetChat = useCallback2(() => {
|
|
2027
|
+
setWidgetPendingId(null);
|
|
2028
|
+
setWidgetFailure(null);
|
|
2029
|
+
}, []);
|
|
2030
|
+
return { answerWidget, widgetPendingId, widgetFailure, answeringWidget, forgetChat };
|
|
2019
2031
|
}
|
|
2020
2032
|
async function resumedOf(response) {
|
|
2021
2033
|
try {
|
|
@@ -2447,7 +2459,7 @@ function useAgentChat({
|
|
|
2447
2459
|
const correctionsRef = useRef5(corrections);
|
|
2448
2460
|
correctionsRef.current = corrections;
|
|
2449
2461
|
const sendingCorrections = useRef5(/* @__PURE__ */ new Set());
|
|
2450
|
-
const steerQueue = useRef5(
|
|
2462
|
+
const steerQueue = useRef5(null);
|
|
2451
2463
|
const unconfirmedCorrection = useRef5(null);
|
|
2452
2464
|
const [handingOff, setHandingOff] = useState3(false);
|
|
2453
2465
|
const handOff = useRef5(null);
|
|
@@ -3039,7 +3051,7 @@ function useAgentChat({
|
|
|
3039
3051
|
}, [chatId]);
|
|
3040
3052
|
const [approvalPendingId, setApprovalPendingId] = useState3(null);
|
|
3041
3053
|
const [approvalFailure, setApprovalFailure] = useState3(null);
|
|
3042
|
-
const approving = useRef5(
|
|
3054
|
+
const approving = useRef5(null);
|
|
3043
3055
|
const historyReads = useRef5({ started: 0, shown: 0 });
|
|
3044
3056
|
const refreshFromServer = useCallback4(
|
|
3045
3057
|
async (signal, options = {}) => {
|
|
@@ -3103,9 +3115,13 @@ function useAgentChat({
|
|
|
3103
3115
|
useEffect3(() => setDetachedSince(null), [chatId]);
|
|
3104
3116
|
const respondToApproval = useCallback4(
|
|
3105
3117
|
async (approvalId, decision) => {
|
|
3106
|
-
if (approving.current) return;
|
|
3107
|
-
approving.current = true;
|
|
3108
3118
|
const signal = chatLifetime.current.signal;
|
|
3119
|
+
if (ownedBy(approving.current, signal) !== void 0) return;
|
|
3120
|
+
const pending = { lifetime: signal, value: approvalId };
|
|
3121
|
+
approving.current = pending;
|
|
3122
|
+
const fail = (kind, text) => {
|
|
3123
|
+
if (!signal.aborted) setApprovalFailure({ id: approvalId, kind, ...text !== void 0 && { text } });
|
|
3124
|
+
};
|
|
3109
3125
|
setApprovalFailure(null);
|
|
3110
3126
|
setApprovalPendingId(approvalId);
|
|
3111
3127
|
try {
|
|
@@ -3118,24 +3134,25 @@ function useAgentChat({
|
|
|
3118
3134
|
{ timeoutMs: settingsRef.current.requestTimeoutMs, wholeBody: true }
|
|
3119
3135
|
);
|
|
3120
3136
|
} catch {
|
|
3121
|
-
|
|
3137
|
+
fail("connection");
|
|
3122
3138
|
return;
|
|
3123
3139
|
}
|
|
3124
3140
|
const refusedByApp = response.ok ? null : await serverRefusalOf(response);
|
|
3141
|
+
if (signal.aborted) return;
|
|
3125
3142
|
if (refusedByApp?.kind) {
|
|
3126
3143
|
announceAppRefusal(refusedByApp);
|
|
3127
|
-
|
|
3144
|
+
fail("refused", refusedByApp.text);
|
|
3128
3145
|
return;
|
|
3129
3146
|
}
|
|
3130
3147
|
if (response.status === 429) {
|
|
3131
3148
|
const refusal2 = await spendingRefusalOf(response);
|
|
3132
3149
|
if (refusal2 && !signal.aborted) setSpending({ state: "exhausted", info: refusal2 });
|
|
3133
3150
|
const tooManyTurns = !refusal2 && await errorKindOf(response) === "too_many_turns";
|
|
3134
|
-
|
|
3151
|
+
fail(refusal2 ? "spending_limit" : tooManyTurns ? "too_many_turns" : "connection");
|
|
3135
3152
|
return;
|
|
3136
3153
|
}
|
|
3137
3154
|
if (response.status === 409 && await errorKindOf(response) === "busy") {
|
|
3138
|
-
|
|
3155
|
+
fail("busy");
|
|
3139
3156
|
return;
|
|
3140
3157
|
}
|
|
3141
3158
|
if (response.status === 409 || response.status === 404) {
|
|
@@ -3143,10 +3160,11 @@ function useAgentChat({
|
|
|
3143
3160
|
return;
|
|
3144
3161
|
}
|
|
3145
3162
|
if (!response.ok) {
|
|
3146
|
-
|
|
3163
|
+
fail("connection");
|
|
3147
3164
|
return;
|
|
3148
3165
|
}
|
|
3149
3166
|
const { resumed } = await response.json();
|
|
3167
|
+
if (signal.aborted) return;
|
|
3150
3168
|
setMessages((current) => withApprovalDecision(current, approvalId, decision, resumed));
|
|
3151
3169
|
if (!resumed) return;
|
|
3152
3170
|
setResuming(true);
|
|
@@ -3158,13 +3176,13 @@ function useAgentChat({
|
|
|
3158
3176
|
if (!signal.aborted) setResuming(false);
|
|
3159
3177
|
}
|
|
3160
3178
|
} finally {
|
|
3161
|
-
approving.current =
|
|
3179
|
+
if (approving.current === pending) approving.current = null;
|
|
3162
3180
|
if (!signal.aborted) setApprovalPendingId(null);
|
|
3163
3181
|
}
|
|
3164
3182
|
},
|
|
3165
3183
|
[announceAppRefusal, chatUrl2, request2, rereadHistory, resumeWithProbe, setMessages, startSeries]
|
|
3166
3184
|
);
|
|
3167
|
-
const { answerWidget, widgetPendingId, widgetFailure, answeringWidget } = useWidgetAnswer({
|
|
3185
|
+
const { answerWidget, widgetPendingId, widgetFailure, answeringWidget, forgetChat: forgetWidgetAnswer } = useWidgetAnswer({
|
|
3168
3186
|
chatUrl: chatUrl2,
|
|
3169
3187
|
request: request2,
|
|
3170
3188
|
requestTimeoutMs: () => settingsRef.current.requestTimeoutMs,
|
|
@@ -3184,8 +3202,18 @@ function useAgentChat({
|
|
|
3184
3202
|
showSpendingExhausted: (info) => setSpending({ state: "exhausted", info }),
|
|
3185
3203
|
errorKindOf
|
|
3186
3204
|
});
|
|
3205
|
+
useEffect3(
|
|
3206
|
+
() => () => {
|
|
3207
|
+
setResuming(false);
|
|
3208
|
+
setHandingOff(false);
|
|
3209
|
+
setApprovalPendingId(null);
|
|
3210
|
+
setApprovalFailure(null);
|
|
3211
|
+
forgetWidgetAnswer();
|
|
3212
|
+
},
|
|
3213
|
+
[chatId, forgetWidgetAnswer]
|
|
3214
|
+
);
|
|
3187
3215
|
const ownTurnStarting = useCallback4(
|
|
3188
|
-
() => busyRef.current || sending.current || approving.current || answeringWidget(),
|
|
3216
|
+
() => busyRef.current || sending.current || ownedBy(approving.current, chatLifetime.current.signal) !== void 0 || answeringWidget(),
|
|
3189
3217
|
[answeringWidget]
|
|
3190
3218
|
);
|
|
3191
3219
|
const connectionRef = useRef5(connection);
|
|
@@ -3271,18 +3299,19 @@ function useAgentChat({
|
|
|
3271
3299
|
[sendMessage, setMessages]
|
|
3272
3300
|
);
|
|
3273
3301
|
const handOffToCorrections = useCallback4(() => {
|
|
3274
|
-
if (handOff.current) return handOff.current;
|
|
3275
3302
|
const signal = chatLifetime.current.signal;
|
|
3303
|
+
const going = ownedBy(handOff.current, signal);
|
|
3304
|
+
if (going) return going;
|
|
3276
3305
|
setHandingOff(true);
|
|
3277
3306
|
const run = (async () => {
|
|
3278
|
-
await steerQueue.current;
|
|
3279
|
-
await stopping.current;
|
|
3307
|
+
await ownedBy(steerQueue.current, signal);
|
|
3308
|
+
await ownedBy(stopping.current, signal);
|
|
3280
3309
|
if (!signal.aborted) await refreshFromServer(signal);
|
|
3281
3310
|
})().finally(() => {
|
|
3282
|
-
handOff.current = null;
|
|
3311
|
+
if (handOff.current?.value === run) handOff.current = null;
|
|
3283
3312
|
if (!signal.aborted) setHandingOff(false);
|
|
3284
3313
|
});
|
|
3285
|
-
handOff.current = run;
|
|
3314
|
+
handOff.current = { lifetime: signal, value: run };
|
|
3286
3315
|
return run;
|
|
3287
3316
|
}, [refreshFromServer]);
|
|
3288
3317
|
handOffToCorrectionsRef.current = handOffToCorrections;
|
|
@@ -3302,7 +3331,7 @@ function useAgentChat({
|
|
|
3302
3331
|
setValue((current) => current.length === 0 ? text : current);
|
|
3303
3332
|
onRejected?.(kind);
|
|
3304
3333
|
};
|
|
3305
|
-
const sent = steerQueue.current.then(async () => {
|
|
3334
|
+
const sent = (ownedBy(steerQueue.current, signal) ?? Promise.resolve()).then(async () => {
|
|
3306
3335
|
let response;
|
|
3307
3336
|
try {
|
|
3308
3337
|
response = await fetchWithDeadline(
|
|
@@ -3322,15 +3351,17 @@ function useAgentChat({
|
|
|
3322
3351
|
if (signal.aborted || chatUrlRef.current !== asked) return;
|
|
3323
3352
|
if (!response.ok) {
|
|
3324
3353
|
const spendingLimit = response.status === 429 ? await spendingRefusalOf(response) : null;
|
|
3325
|
-
if (spendingLimit) setSpending({ state: "exhausted", info: spendingLimit });
|
|
3326
3354
|
const refusedWithText = await serverRefusalOf(response);
|
|
3355
|
+
const kind = spendingLimit ? "spending_limit" : refusedWithText?.kind ?? await errorKindOf(response);
|
|
3356
|
+
if (signal.aborted) return;
|
|
3357
|
+
if (spendingLimit) setSpending({ state: "exhausted", info: spendingLimit });
|
|
3327
3358
|
announceAppRefusal(refusedWithText);
|
|
3328
|
-
refused(
|
|
3359
|
+
refused(kind);
|
|
3329
3360
|
return;
|
|
3330
3361
|
}
|
|
3331
3362
|
if (!answeringRef.current) void handOffToCorrectionsRef.current();
|
|
3332
3363
|
});
|
|
3333
|
-
steerQueue.current = sent.catch(() => void 0);
|
|
3364
|
+
steerQueue.current = { lifetime: signal, value: sent.catch(() => void 0) };
|
|
3334
3365
|
},
|
|
3335
3366
|
[announceAppRefusal, chatUrl2, request2]
|
|
3336
3367
|
);
|
|
@@ -3430,24 +3461,31 @@ function useAgentChat({
|
|
|
3430
3461
|
if (loadedChatState !== null) publishedState2.current?.update(loadedChatState);
|
|
3431
3462
|
}, [loadedChatState]);
|
|
3432
3463
|
const stopping = useRef5(null);
|
|
3433
|
-
const
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3464
|
+
const stopIn = useCallback4(
|
|
3465
|
+
(lifetime) => {
|
|
3466
|
+
const going = ownedBy(stopping.current, lifetime);
|
|
3467
|
+
if (going) return going;
|
|
3468
|
+
if (lifetime.aborted) return Promise.resolve();
|
|
3469
|
+
if (seriesRef.current) cancelSeries();
|
|
3470
|
+
browserCallsLifetime.current?.abort();
|
|
3471
|
+
browserCallsLifetime.current = null;
|
|
3472
|
+
const stopped = (async () => {
|
|
3473
|
+
await fetchWithDeadline(request2, `${chatUrl2}/stop`, { method: "POST" }, {
|
|
3474
|
+
timeoutMs: settingsRef.current.requestTimeoutMs,
|
|
3475
|
+
wholeBody: true
|
|
3476
|
+
}).catch(() => void 0);
|
|
3477
|
+
if (lifetime.aborted) return;
|
|
3478
|
+
await stopChat();
|
|
3479
|
+
if (!lifetime.aborted) setMessages((messages2) => markLastAnswerStopped(messages2));
|
|
3480
|
+
})().finally(() => {
|
|
3481
|
+
if (stopping.current?.value === stopped) stopping.current = null;
|
|
3482
|
+
});
|
|
3483
|
+
stopping.current = { lifetime, value: stopped };
|
|
3484
|
+
return stopped;
|
|
3485
|
+
},
|
|
3486
|
+
[cancelSeries, chatUrl2, request2, setMessages, stopChat]
|
|
3487
|
+
);
|
|
3488
|
+
const stop = useCallback4(() => stopIn(chatLifetime.current.signal), [stopIn]);
|
|
3451
3489
|
const retry = useCallback4(() => {
|
|
3452
3490
|
if (connection === "offline") {
|
|
3453
3491
|
reconnectNow();
|
|
@@ -3532,11 +3570,12 @@ function useAgentChat({
|
|
|
3532
3570
|
},
|
|
3533
3571
|
[busy, canEdit, startEdit]
|
|
3534
3572
|
);
|
|
3535
|
-
const replacing = useRef5(
|
|
3573
|
+
const replacing = useRef5(null);
|
|
3536
3574
|
const replaceLastVoiceMessage = useCallback4(
|
|
3537
3575
|
(text, options) => {
|
|
3538
|
-
const
|
|
3539
|
-
|
|
3576
|
+
const signal = chatLifetime.current.signal;
|
|
3577
|
+
const run = (ownedBy(replacing.current, signal) ?? Promise.resolve()).then(async () => {
|
|
3578
|
+
if (signal.aborted) return false;
|
|
3540
3579
|
const messages2 = messagesRef.current;
|
|
3541
3580
|
const index = messages2.findLastIndex((message) => message.role === "user");
|
|
3542
3581
|
const target = messages2[index];
|
|
@@ -3544,24 +3583,25 @@ function useAgentChat({
|
|
|
3544
3583
|
if (!messages2.slice(index + 1).every(isEmptyAnswer)) return false;
|
|
3545
3584
|
const original = messages2;
|
|
3546
3585
|
setMessages([...messages2.slice(0, index), { ...target, parts: [{ type: "text", text }, { type: VOICE_MODE_PART_TYPE, data: true }] }]);
|
|
3547
|
-
await
|
|
3548
|
-
if (!await untilIdle(signal)) return restoreAfterFailure(original);
|
|
3549
|
-
for (let attempt = 0; attempt < REPLACE_ATTEMPTS; attempt++) {
|
|
3586
|
+
await stopIn(signal);
|
|
3587
|
+
if (!await untilIdle(signal)) return restoreAfterFailure(original, signal);
|
|
3588
|
+
for (let attempt = 0; attempt < REPLACE_ATTEMPTS && !signal.aborted; attempt++) {
|
|
3550
3589
|
const outcome = await startEdit(target.id, text, true, options?.sounds);
|
|
3551
3590
|
if (outcome.status === "started") return true;
|
|
3552
3591
|
if (!(outcome.status === "refused" && outcome.reason === "busy")) break;
|
|
3553
3592
|
await pause2(REPLACE_RETRY_MS, signal);
|
|
3554
3593
|
}
|
|
3555
|
-
return restoreAfterFailure(original);
|
|
3594
|
+
return restoreAfterFailure(original, signal);
|
|
3556
3595
|
});
|
|
3557
|
-
replacing.current = run.catch(() => false);
|
|
3596
|
+
replacing.current = { lifetime: signal, value: run.catch(() => false) };
|
|
3558
3597
|
return run;
|
|
3559
3598
|
},
|
|
3560
|
-
[exhausted, loaded, refreshFromServer, setMessages, startEdit,
|
|
3599
|
+
[exhausted, loaded, refreshFromServer, setMessages, startEdit, stopIn]
|
|
3561
3600
|
);
|
|
3562
|
-
function restoreAfterFailure(original) {
|
|
3601
|
+
function restoreAfterFailure(original, signal) {
|
|
3602
|
+
if (signal.aborted) return false;
|
|
3563
3603
|
setMessages(original);
|
|
3564
|
-
void refreshFromServer(
|
|
3604
|
+
void refreshFromServer(signal);
|
|
3565
3605
|
return false;
|
|
3566
3606
|
}
|
|
3567
3607
|
async function untilIdle(signal) {
|
|
@@ -7236,4 +7276,4 @@ export {
|
|
|
7236
7276
|
activeChatTitle,
|
|
7237
7277
|
useWorkspaceListSync
|
|
7238
7278
|
};
|
|
7239
|
-
//# sourceMappingURL=chunk-
|
|
7279
|
+
//# sourceMappingURL=chunk-PZZBB4Y6.js.map
|