@songsid/agend 2.2.0-alpha.5 → 2.2.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-api.d.ts +22 -0
- package/dist/auth-api.js +65 -1
- package/dist/auth-api.js.map +1 -1
- package/dist/channel/adapters/discord.js +9 -0
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/command-table.d.ts +8 -1
- package/dist/command-table.js +13 -4
- package/dist/command-table.js.map +1 -1
- package/dist/fleet-manager.d.ts +38 -0
- package/dist/fleet-manager.js +128 -5
- package/dist/fleet-manager.js.map +1 -1
- package/dist/locale.js +10 -0
- package/dist/locale.js.map +1 -1
- package/dist/public-web-gateway.js +2 -2
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/topic-commands.js +3 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/ui/chat-render.js +6 -0
- package/dist/ui/chat-strings.js +4 -0
- package/dist/ui/chat-thread.js +7 -3
- package/dist/ui/panel-chat.js +7 -0
- package/dist/ui/preview-panel.js +2 -1
- package/dist/ui/preview.js +49 -0
- package/dist/ui/shared/agend-auth.js +15 -7
- package/dist/ui/shared/app.css +8 -1
- package/dist/ui/shared/signin.js +38 -1
- package/dist/ui/signin.html +3 -0
- package/dist/web-chat-history.d.ts +97 -6
- package/dist/web-chat-history.js +189 -12
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-chat-store.d.ts +45 -0
- package/dist/web-chat-store.js +192 -0
- package/dist/web-chat-store.js.map +1 -0
- package/dist/web-login.d.ts +2 -0
- package/dist/web-login.js +4 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-returning-device.d.ts +84 -0
- package/dist/web-returning-device.js +204 -0
- package/dist/web-returning-device.js.map +1 -0
- package/dist/web-upload.d.ts +21 -0
- package/dist/web-upload.js +50 -1
- package/dist/web-upload.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/shared/signin.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
// Two jobs: (1) when the page is what a gated URL answered with because the browser sent no cookie
|
|
4
4
|
// (a SameSite=Strict cookie is not sent on a navigation that came from a chat app), probe the session
|
|
5
5
|
// from *here* — a same-site request does carry the cookie — and carry on to the page that was asked
|
|
6
|
-
// for; (2) otherwise take the one-time code and exchange it.
|
|
6
|
+
// for; (2) otherwise take the one-time code and exchange it. A browser that signed in before with a code from
|
|
7
|
+
// /dashboard (a returning device, #1570) is also offered "Send me a new code": the server sends it privately to the
|
|
8
|
+
// person who received that earlier code — the page never learns who that is.
|
|
7
9
|
(() => {
|
|
8
10
|
"use strict";
|
|
9
11
|
const $ = (id) => document.getElementById(id);
|
|
@@ -15,6 +17,9 @@
|
|
|
15
17
|
refused: "That code did not work — it may be wrong, expired or already used. Ask for a new one with /dashboard.",
|
|
16
18
|
paused: "Too many wrong codes — sign-in is paused for a few minutes.",
|
|
17
19
|
network: "Could not reach AgEnD. Check the connection and try again.",
|
|
20
|
+
resend: "Send me a new code", resent: "A new code was sent to you privately in chat. Enter it above.",
|
|
21
|
+
resend_wait: "A code was asked for a moment ago — wait a little and try again.",
|
|
22
|
+
resend_refused: "A new code could not be sent. Ask for one with /dashboard.",
|
|
18
23
|
},
|
|
19
24
|
"zh-TW": {
|
|
20
25
|
checking: "正在確認登入狀態…", title: "登入 AgEnD", lead: "請輸入聊天頻道給你的一次性登入碼。",
|
|
@@ -23,6 +28,9 @@
|
|
|
23
28
|
refused: "登入碼無效:可能輸入錯誤、已過期或已使用。請用 /dashboard 再要一個。",
|
|
24
29
|
paused: "錯誤次數過多,登入暫停幾分鐘。",
|
|
25
30
|
network: "連不上 AgEnD,請檢查連線後再試。",
|
|
31
|
+
resend: "傳一組新的登入碼給我", resent: "新的登入碼已私訊給你,請在上方輸入。",
|
|
32
|
+
resend_wait: "剛剛才要過登入碼,請稍候再試。",
|
|
33
|
+
resend_refused: "無法傳送新的登入碼。請用 /dashboard 再要一個。",
|
|
26
34
|
},
|
|
27
35
|
};
|
|
28
36
|
const lang = /^zh/i.test(navigator.language || "") ? "zh-TW" : "en";
|
|
@@ -97,8 +105,36 @@
|
|
|
97
105
|
if (note) { sessionStorage.removeItem("agend_signout_note"); $("msg").textContent = note; }
|
|
98
106
|
} catch { /* private mode */ }
|
|
99
107
|
$("code").focus();
|
|
108
|
+
offerResend();
|
|
100
109
|
}
|
|
101
110
|
|
|
111
|
+
// Only a returning device gets the button; the answer is a boolean and asking has no side effect.
|
|
112
|
+
async function offerResend() {
|
|
113
|
+
try {
|
|
114
|
+
const r = await fetch("/auth/device", { credentials: "same-origin", cache: "no-store" });
|
|
115
|
+
if (r.ok && (await r.json()).returning === true) $("resend").hidden = false;
|
|
116
|
+
} catch { /* no button */ }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
$("resend").addEventListener("click", async () => {
|
|
120
|
+
const button = $("resend");
|
|
121
|
+
const msg = $("msg");
|
|
122
|
+
msg.textContent = "";
|
|
123
|
+
msg.classList?.remove("ok");
|
|
124
|
+
button.disabled = true;
|
|
125
|
+
try {
|
|
126
|
+
const r = await fetch("/auth/request-code", {
|
|
127
|
+
method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: "{}",
|
|
128
|
+
});
|
|
129
|
+
if (r.status === 202) { msg.classList?.add("ok"); msg.textContent = t("resent"); $("code").focus(); }
|
|
130
|
+
else if (r.status === 429) msg.textContent = t("resend_wait");
|
|
131
|
+
else { msg.textContent = t("resend_refused"); if (r.status === 401) button.hidden = true; }
|
|
132
|
+
} catch {
|
|
133
|
+
msg.textContent = t("network");
|
|
134
|
+
}
|
|
135
|
+
button.disabled = false;
|
|
136
|
+
});
|
|
137
|
+
|
|
102
138
|
async function probe() {
|
|
103
139
|
// A second bounce inside ten seconds means the cookie is valid but not being sent on the
|
|
104
140
|
// navigation; going round again would loop, so stop and let the person type a code.
|
|
@@ -116,6 +152,7 @@
|
|
|
116
152
|
const button = $("go");
|
|
117
153
|
const msg = $("msg");
|
|
118
154
|
msg.textContent = "";
|
|
155
|
+
msg.classList?.remove("ok");
|
|
119
156
|
button.disabled = true;
|
|
120
157
|
button.textContent = t("working");
|
|
121
158
|
try {
|
package/dist/ui/signin.html
CHANGED
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
border: 0; border-radius: var(--r-full); cursor: pointer; }
|
|
29
29
|
button:hover:not(:disabled) { opacity: .88; }
|
|
30
30
|
button:disabled { opacity: .6; cursor: default; }
|
|
31
|
+
button.secondary { margin-top: 10px; color: var(--text); background: transparent; border: 1px solid var(--border-strong); }
|
|
31
32
|
#msg { min-height: 1.5em; margin-top: 14px; font-size: var(--fs-sm); color: var(--danger); }
|
|
33
|
+
#msg.ok { color: var(--text-2); }
|
|
32
34
|
.hint { margin-top: 18px; font-size: var(--fs-xs); color: var(--text-3); }
|
|
33
35
|
.hint code { white-space: nowrap; font-family: var(--font-mono); }
|
|
34
36
|
[hidden] { display: none !important; }
|
|
@@ -45,6 +47,7 @@
|
|
|
45
47
|
<input id="code" name="code" inputmode="text" autocomplete="one-time-code" autocapitalize="characters"
|
|
46
48
|
autocorrect="off" spellcheck="false" maxlength="12" placeholder="XXXX-XXXX" required>
|
|
47
49
|
<button id="go" type="submit" data-i18n="submit">Sign in</button>
|
|
50
|
+
<button id="resend" type="button" class="secondary" hidden data-i18n="resend">Send me a new code</button>
|
|
48
51
|
<div id="msg" role="alert" aria-live="polite"></div>
|
|
49
52
|
<div class="hint" data-i18n="hint">Send /dashboard to your AgEnD bot, or run “<code>agend web --code</code>” on the host. A code works once and expires in 5 minutes.</div>
|
|
50
53
|
</form>
|
|
@@ -6,6 +6,17 @@ export interface WebChatAttachment {
|
|
|
6
6
|
size: number;
|
|
7
7
|
mime: string;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* #1565: a file shown with a message from before the fleet restarted that could not be served again (missing, moved,
|
|
11
|
+
* or failing one of the ledger's checks): no id — the page shows the name as unavailable, and nothing can be fetched.
|
|
12
|
+
*/
|
|
13
|
+
export interface WebChatGoneAttachment {
|
|
14
|
+
gone: true;
|
|
15
|
+
kind: "photo" | "document";
|
|
16
|
+
name: string;
|
|
17
|
+
size: number;
|
|
18
|
+
mime: string;
|
|
19
|
+
}
|
|
9
20
|
/**
|
|
10
21
|
* How far a message the web user sent has got (web track C3) — the ticks under it. The same lifecycle a
|
|
11
22
|
* Telegram message shows as reactions: waiting behind another message, handed to the agent, taken up by it,
|
|
@@ -24,8 +35,8 @@ export interface WebChatButtons {
|
|
|
24
35
|
by?: string;
|
|
25
36
|
}
|
|
26
37
|
export interface WebChatMessage {
|
|
27
|
-
/** Files shown with the message (absent when none). */
|
|
28
|
-
attachments?: WebChatAttachment
|
|
38
|
+
/** Files shown with the message (absent when none); a restored one that cannot be served again is `gone` (#1565). */
|
|
39
|
+
attachments?: Array<WebChatAttachment | WebChatGoneAttachment>;
|
|
29
40
|
/** #1266: an agent reply's buttons (agent messages only). */
|
|
30
41
|
buttons?: WebChatButtons;
|
|
31
42
|
/** The fleet process generation the id belongs to. */
|
|
@@ -55,6 +66,53 @@ export interface WebChatHistoryOptions {
|
|
|
55
66
|
replayMax?: number;
|
|
56
67
|
/** The generation id (tests); random otherwise. */
|
|
57
68
|
boot?: string;
|
|
69
|
+
/** #1565: where the history is kept between fleet processes (web-chat-store.ts); none: memory only. */
|
|
70
|
+
store?: WebChatPersistence | null;
|
|
71
|
+
/** #1565: the file ledger, so a kept message's files are served again after a restart; none: they are not. */
|
|
72
|
+
files?: WebChatFiles | null;
|
|
73
|
+
}
|
|
74
|
+
/** #1565: a message as it is kept on disk — what was said, never the interactive state; files with their paths. */
|
|
75
|
+
export interface StoredWebChatMessage {
|
|
76
|
+
boot: string;
|
|
77
|
+
id: number;
|
|
78
|
+
instance: string;
|
|
79
|
+
role: WebChatRole;
|
|
80
|
+
sender: string;
|
|
81
|
+
text: string;
|
|
82
|
+
ts: string;
|
|
83
|
+
attachments?: Array<{
|
|
84
|
+
id?: string;
|
|
85
|
+
path?: string;
|
|
86
|
+
kind: "photo" | "document";
|
|
87
|
+
name: string;
|
|
88
|
+
size: number;
|
|
89
|
+
mime: string;
|
|
90
|
+
}>;
|
|
91
|
+
}
|
|
92
|
+
/** #1565: what the history needs of the file ledger (web-upload.ts). */
|
|
93
|
+
export interface WebChatFiles {
|
|
94
|
+
/** The path to keep with a file id (null: not served, or an upload no message took — never kept). */
|
|
95
|
+
storablePath(id: string): string | null;
|
|
96
|
+
/** Serve a kept file again under its id if it passes every check; null: it does not (shown as unavailable). */
|
|
97
|
+
restore(entry: {
|
|
98
|
+
id: string;
|
|
99
|
+
path: string;
|
|
100
|
+
name: string;
|
|
101
|
+
mime: string;
|
|
102
|
+
kind: string;
|
|
103
|
+
}, instance: string): {
|
|
104
|
+
id: string;
|
|
105
|
+
kind: "photo" | "document";
|
|
106
|
+
size: number;
|
|
107
|
+
mime: string;
|
|
108
|
+
} | null;
|
|
109
|
+
/** These ids are no longer shown: nothing is served under them. */
|
|
110
|
+
drop(ids: string[]): void;
|
|
111
|
+
}
|
|
112
|
+
/** #1565: what the history needs of its disk store. */
|
|
113
|
+
export interface WebChatPersistence {
|
|
114
|
+
schedule(instance: string, snapshot: () => StoredWebChatMessage[]): void;
|
|
115
|
+
remove(instance: string): Promise<void>;
|
|
58
116
|
}
|
|
59
117
|
export declare const WEB_CHAT_TEXT_MAX = 16000;
|
|
60
118
|
/**
|
|
@@ -72,7 +130,36 @@ export declare class WebChatHistory {
|
|
|
72
130
|
private readonly perInstance;
|
|
73
131
|
private readonly perInstanceChars;
|
|
74
132
|
private readonly replayMax;
|
|
133
|
+
private store;
|
|
134
|
+
private files;
|
|
135
|
+
/** #1565: the boots of restored messages, by the time of their first message — older processes, in order. */
|
|
136
|
+
private readonly restoredBoots;
|
|
75
137
|
constructor(opts?: WebChatHistoryOptions);
|
|
138
|
+
/** #1565: keep this history on disk from now on (the fleet sets it at start, once its home is known). */
|
|
139
|
+
setStore(store: WebChatPersistence | null): void;
|
|
140
|
+
/** #1565: the file ledger (set at fleet start, before restore()). */
|
|
141
|
+
setFiles(files: WebChatFiles | null): void;
|
|
142
|
+
private persist;
|
|
143
|
+
/** #1565: a message as kept on disk: no buttons, no delivery, no message id; a file with the path it is served from. */
|
|
144
|
+
private stored;
|
|
145
|
+
/** #1565: the file ids these messages show that no message still kept for the instance shows: no longer served. */
|
|
146
|
+
private dropFiles;
|
|
147
|
+
/**
|
|
148
|
+
* The order of the boots this history holds: older processes first (by their first restored message), this process
|
|
149
|
+
* last. rank(boot) is its place, or -1 for a boot this history does not hold.
|
|
150
|
+
*/
|
|
151
|
+
private bootRanks;
|
|
152
|
+
/**
|
|
153
|
+
* #1565: the messages this instance had in an earlier fleet process, as stored (web-chat-store.ts) — validated
|
|
154
|
+
* here, never trusted: a row that is not ours in shape is dropped; text is cut; the role is kept as stored and is
|
|
155
|
+
* never made `agent` (anything else is a person's message); nothing interactive comes back (no buttons, no ticks).
|
|
156
|
+
* Bounds as for record(). Then each kept message's files are served again under their ids, by the file ledger's
|
|
157
|
+
* checks; a file that fails one — or is missing — is `gone` (its name shown as unavailable). Returns how many
|
|
158
|
+
* messages it restored. Only for an instance with nothing recorded yet in this process.
|
|
159
|
+
*/
|
|
160
|
+
restore(instance: string, rows: unknown[] | null): number;
|
|
161
|
+
/** #1565: a restored row's files served again (only the rows kept: an older one's file is never registered). */
|
|
162
|
+
private restoreFiles;
|
|
76
163
|
/** The id the next message will get minus one: the newest id handed out so far (0 when none). */
|
|
77
164
|
get lastId(): number;
|
|
78
165
|
/** Record one message; returns it with its id. Text beyond WEB_CHAT_TEXT_MAX is cut. */
|
|
@@ -103,6 +190,8 @@ export declare class WebChatHistory {
|
|
|
103
190
|
* Ids are this boot's: a cursor from another boot goes through replayFor(), never straight here.
|
|
104
191
|
*/
|
|
105
192
|
after(lastId: number): WebChatMessage[];
|
|
193
|
+
/** The retained messages that pass `keep`, across instances, in boot order then id order, at most replayMax (newest). */
|
|
194
|
+
private collect;
|
|
106
195
|
/**
|
|
107
196
|
* A delivery report for one of this instance's messages. Returns the message when its state changed (so the
|
|
108
197
|
* caller tells the pages), null when there is no such message or the report would move it back.
|
|
@@ -125,14 +214,16 @@ export declare class WebChatHistory {
|
|
|
125
214
|
delivery: WebDeliveryState;
|
|
126
215
|
}>;
|
|
127
216
|
cancelPending(instance: string): WebChatMessage[];
|
|
128
|
-
/** Forget an instance (deleted). */
|
|
217
|
+
/** Forget an instance (deleted) — and its file (#1565): a later instance of the same name starts empty. */
|
|
129
218
|
forget(instance: string): void;
|
|
130
219
|
/** The SSE cursor for one message: `<boot>-<id>`. */
|
|
131
220
|
cursorOf(m: WebChatMessage): string;
|
|
132
221
|
/**
|
|
133
|
-
* What a reconnecting stream with this `Last-Event-ID` should be sent. A cursor of this boot replays what
|
|
134
|
-
*
|
|
135
|
-
*
|
|
222
|
+
* What a reconnecting stream with this `Last-Event-ID` should be sent. A cursor of this boot replays what came
|
|
223
|
+
* after it. #1565: a cursor of a restored boot (a page that stayed open across the restart) gets what came after
|
|
224
|
+
* it in that boot and everything of the later boots — never a message it already has. A cursor of a boot this
|
|
225
|
+
* process does not hold gets everything retained (the page keeps one entry per boot+id, so nothing doubles). No
|
|
226
|
+
* cursor, or one that is not ours in shape, gets nothing.
|
|
136
227
|
*/
|
|
137
228
|
replayFor(cursor: {
|
|
138
229
|
boot: string;
|
package/dist/web-chat-history.js
CHANGED
|
@@ -7,11 +7,16 @@
|
|
|
7
7
|
* of one instance, and an EventSource that reconnects with `Last-Event-ID` is sent what it missed.
|
|
8
8
|
*
|
|
9
9
|
* Bounded by count AND by bytes per instance, so a chatty agent cannot grow the fleet process without limit.
|
|
10
|
-
*
|
|
10
|
+
* #1565: it also survives a fleet restart — the same bounded history is kept on the local disk (web-chat-store.ts)
|
|
11
|
+
* and restored at fleet start, every message with the boot and id it had. What is kept is what was said: the text,
|
|
12
|
+
* who said it, and its files (served again under their ids when they still pass the ledger's checks) — never the
|
|
13
|
+
* interactive state (buttons, delivery ticks), which belonged to the process that ended.
|
|
11
14
|
*
|
|
12
15
|
* Ids count from 1 in every fleet process, so an id alone is not an identity across a restart: each history
|
|
13
|
-
* has a random `boot` generation, every message carries it, and the SSE cursor is `<boot>-<id>`.
|
|
14
|
-
*
|
|
16
|
+
* has a random `boot` generation, every message carries it, and the SSE cursor is `<boot>-<id>`. Restored messages
|
|
17
|
+
* keep their boot and id, so a page that stayed open across the restart already holds them (it keeps one entry per
|
|
18
|
+
* boot+id); the server knows the order of the boots it holds, and a cursor of a restored boot is sent only what came
|
|
19
|
+
* after it.
|
|
15
20
|
*/
|
|
16
21
|
import { randomBytes } from "node:crypto";
|
|
17
22
|
/**
|
|
@@ -63,11 +68,121 @@ export class WebChatHistory {
|
|
|
63
68
|
perInstance;
|
|
64
69
|
perInstanceChars;
|
|
65
70
|
replayMax;
|
|
71
|
+
store;
|
|
72
|
+
files;
|
|
73
|
+
/** #1565: the boots of restored messages, by the time of their first message — older processes, in order. */
|
|
74
|
+
restoredBoots = new Map();
|
|
66
75
|
constructor(opts = {}) {
|
|
67
76
|
this.perInstance = opts.perInstance ?? 500;
|
|
68
77
|
this.perInstanceChars = opts.perInstanceChars ?? 1_000_000;
|
|
69
78
|
this.replayMax = opts.replayMax ?? 500;
|
|
70
79
|
this.boot = opts.boot ?? randomBytes(6).toString("hex");
|
|
80
|
+
this.store = opts.store ?? null;
|
|
81
|
+
this.files = opts.files ?? null;
|
|
82
|
+
}
|
|
83
|
+
/** #1565: keep this history on disk from now on (the fleet sets it at start, once its home is known). */
|
|
84
|
+
setStore(store) { this.store = store; }
|
|
85
|
+
/** #1565: the file ledger (set at fleet start, before restore()). */
|
|
86
|
+
setFiles(files) { this.files = files; }
|
|
87
|
+
persist(instance) {
|
|
88
|
+
if (!this.store)
|
|
89
|
+
return;
|
|
90
|
+
this.store.schedule(instance, () => (this.byInstance.get(instance)?.messages ?? []).map((m) => this.stored(m)));
|
|
91
|
+
}
|
|
92
|
+
/** #1565: a message as kept on disk: no buttons, no delivery, no message id; a file with the path it is served from. */
|
|
93
|
+
stored(m) {
|
|
94
|
+
const row = { boot: m.boot, id: m.id, instance: m.instance, role: m.role, sender: m.sender, text: m.text, ts: m.ts };
|
|
95
|
+
if (m.attachments?.length) {
|
|
96
|
+
row.attachments = m.attachments.map((a) => {
|
|
97
|
+
const base = { kind: a.kind, name: a.name, size: a.size, mime: a.mime };
|
|
98
|
+
const path = "id" in a && this.files ? this.files.storablePath(a.id) : null;
|
|
99
|
+
return path && "id" in a ? { id: a.id, path, ...base } : base;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return row;
|
|
103
|
+
}
|
|
104
|
+
/** #1565: the file ids these messages show that no message still kept for the instance shows: no longer served. */
|
|
105
|
+
dropFiles(instance, gone) {
|
|
106
|
+
if (!this.files)
|
|
107
|
+
return;
|
|
108
|
+
const ids = new Set();
|
|
109
|
+
for (const m of gone)
|
|
110
|
+
for (const a of m.attachments ?? [])
|
|
111
|
+
if ("id" in a)
|
|
112
|
+
ids.add(a.id);
|
|
113
|
+
if (!ids.size)
|
|
114
|
+
return;
|
|
115
|
+
for (const m of this.byInstance.get(instance)?.messages ?? [])
|
|
116
|
+
for (const a of m.attachments ?? [])
|
|
117
|
+
if ("id" in a)
|
|
118
|
+
ids.delete(a.id);
|
|
119
|
+
if (ids.size)
|
|
120
|
+
this.files.drop([...ids]);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The order of the boots this history holds: older processes first (by their first restored message), this process
|
|
124
|
+
* last. rank(boot) is its place, or -1 for a boot this history does not hold.
|
|
125
|
+
*/
|
|
126
|
+
bootRanks() {
|
|
127
|
+
const order = [...this.restoredBoots.entries()].sort((a, b) => (a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[0] < b[0] ? -1 : 1)).map(([b]) => b);
|
|
128
|
+
const at = new Map(order.map((b, i) => [b, i]));
|
|
129
|
+
return (boot) => (boot === this.boot ? Number.MAX_SAFE_INTEGER : at.get(boot) ?? -1);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* #1565: the messages this instance had in an earlier fleet process, as stored (web-chat-store.ts) — validated
|
|
133
|
+
* here, never trusted: a row that is not ours in shape is dropped; text is cut; the role is kept as stored and is
|
|
134
|
+
* never made `agent` (anything else is a person's message); nothing interactive comes back (no buttons, no ticks).
|
|
135
|
+
* Bounds as for record(). Then each kept message's files are served again under their ids, by the file ledger's
|
|
136
|
+
* checks; a file that fails one — or is missing — is `gone` (its name shown as unavailable). Returns how many
|
|
137
|
+
* messages it restored. Only for an instance with nothing recorded yet in this process.
|
|
138
|
+
*/
|
|
139
|
+
restore(instance, rows) {
|
|
140
|
+
if (!Array.isArray(rows) || this.byInstance.has(instance))
|
|
141
|
+
return 0;
|
|
142
|
+
const seen = new Set();
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const raw of rows) {
|
|
145
|
+
const r = restoredRow(raw, instance, this.boot);
|
|
146
|
+
if (!r)
|
|
147
|
+
continue;
|
|
148
|
+
const key = `${r.message.boot}:${r.message.id}`;
|
|
149
|
+
if (seen.has(key))
|
|
150
|
+
continue;
|
|
151
|
+
seen.add(key);
|
|
152
|
+
out.push(r);
|
|
153
|
+
}
|
|
154
|
+
// The newest within the bounds, in their order.
|
|
155
|
+
let chars = 0, from = out.length;
|
|
156
|
+
while (from > 0 && out.length - from < this.perInstance && chars + out[from - 1].message.text.length <= this.perInstanceChars)
|
|
157
|
+
chars += out[--from].message.text.length;
|
|
158
|
+
const kept = out.slice(from).map((r) => this.restoreFiles(r, instance));
|
|
159
|
+
if (!kept.length)
|
|
160
|
+
return 0;
|
|
161
|
+
this.byInstance.set(instance, { messages: kept, chars });
|
|
162
|
+
for (const m of kept) {
|
|
163
|
+
const first = this.restoredBoots.get(m.boot);
|
|
164
|
+
if (first === undefined || m.ts < first)
|
|
165
|
+
this.restoredBoots.set(m.boot, m.ts);
|
|
166
|
+
}
|
|
167
|
+
return kept.length;
|
|
168
|
+
}
|
|
169
|
+
/** #1565: a restored row's files served again (only the rows kept: an older one's file is never registered). */
|
|
170
|
+
restoreFiles(r, instance) {
|
|
171
|
+
if (!r.files.length)
|
|
172
|
+
return r.message;
|
|
173
|
+
const seen = new Set();
|
|
174
|
+
r.message.attachments = r.files.map((f) => {
|
|
175
|
+
const gone = { gone: true, kind: f.kind, name: f.name, size: f.size, mime: f.mime };
|
|
176
|
+
// One id, one file: a second row naming an id again is shown as unavailable rather than served twice.
|
|
177
|
+
if (!f.id || !f.path || !this.files || seen.has(f.id))
|
|
178
|
+
return gone;
|
|
179
|
+
const served = this.files.restore({ id: f.id, path: f.path, name: f.name, mime: f.mime, kind: f.kind }, instance);
|
|
180
|
+
if (!served || served.id !== f.id)
|
|
181
|
+
return gone;
|
|
182
|
+
seen.add(f.id);
|
|
183
|
+
return { id: served.id, kind: served.kind, name: f.name, size: served.size, mime: served.mime };
|
|
184
|
+
});
|
|
185
|
+
return r.message;
|
|
71
186
|
}
|
|
72
187
|
/** The id the next message will get minus one: the newest id handed out so far (0 when none). */
|
|
73
188
|
get lastId() { return this.nextId - 1; }
|
|
@@ -95,9 +210,16 @@ export class WebChatHistory {
|
|
|
95
210
|
}
|
|
96
211
|
slot.messages.push(entry);
|
|
97
212
|
slot.chars += entry.text.length;
|
|
213
|
+
const evicted = [];
|
|
98
214
|
while (slot.messages.length > 1 && (slot.messages.length > this.perInstance || slot.chars > this.perInstanceChars)) {
|
|
99
|
-
|
|
215
|
+
const old = slot.messages.shift();
|
|
216
|
+
slot.chars -= old.text.length;
|
|
217
|
+
evicted.push(old);
|
|
100
218
|
}
|
|
219
|
+
// #1565: a file leaves with its message — nothing is served under its id any more.
|
|
220
|
+
if (evicted.length)
|
|
221
|
+
this.dropFiles(entry.instance, evicted);
|
|
222
|
+
this.persist(entry.instance);
|
|
101
223
|
return entry;
|
|
102
224
|
}
|
|
103
225
|
/**
|
|
@@ -113,6 +235,7 @@ export class WebChatHistory {
|
|
|
113
235
|
const m = slot.messages[i];
|
|
114
236
|
if (m.buttons?.id === next.id) {
|
|
115
237
|
m.buttons = next;
|
|
238
|
+
this.persist(instance);
|
|
116
239
|
return m;
|
|
117
240
|
}
|
|
118
241
|
}
|
|
@@ -143,13 +266,19 @@ export class WebChatHistory {
|
|
|
143
266
|
after(lastId) {
|
|
144
267
|
if (!Number.isFinite(lastId) || lastId < 0)
|
|
145
268
|
return [];
|
|
269
|
+
// #1565: only this boot's ids compare with `lastId`; 0 (no cursor yet) is everything retained, restored too.
|
|
270
|
+
return this.collect((m) => (m.boot === this.boot ? m.id > lastId : lastId === 0));
|
|
271
|
+
}
|
|
272
|
+
/** The retained messages that pass `keep`, across instances, in boot order then id order, at most replayMax (newest). */
|
|
273
|
+
collect(keep) {
|
|
146
274
|
const out = [];
|
|
147
275
|
for (const slot of this.byInstance.values()) {
|
|
148
276
|
for (const m of slot.messages)
|
|
149
|
-
if (m
|
|
277
|
+
if (keep(m))
|
|
150
278
|
out.push(m);
|
|
151
279
|
}
|
|
152
|
-
|
|
280
|
+
const r = this.bootRanks();
|
|
281
|
+
out.sort((a, b) => (r(a.boot) - r(b.boot)) || (a.id - b.id));
|
|
153
282
|
return out.length > this.replayMax ? out.slice(-this.replayMax) : out;
|
|
154
283
|
}
|
|
155
284
|
/**
|
|
@@ -168,6 +297,7 @@ export class WebChatHistory {
|
|
|
168
297
|
if (next === m.delivery)
|
|
169
298
|
return null;
|
|
170
299
|
m.delivery = next;
|
|
300
|
+
this.persist(instance);
|
|
171
301
|
return m;
|
|
172
302
|
}
|
|
173
303
|
/**
|
|
@@ -202,23 +332,70 @@ export class WebChatHistory {
|
|
|
202
332
|
m.delivery = "cancelled";
|
|
203
333
|
changed.push(m);
|
|
204
334
|
}
|
|
335
|
+
if (changed.length)
|
|
336
|
+
this.persist(instance);
|
|
205
337
|
return changed.reverse();
|
|
206
338
|
}
|
|
207
|
-
/** Forget an instance (deleted). */
|
|
208
|
-
forget(instance) {
|
|
339
|
+
/** Forget an instance (deleted) — and its file (#1565): a later instance of the same name starts empty. */
|
|
340
|
+
forget(instance) {
|
|
341
|
+
const messages = this.byInstance.get(instance)?.messages ?? [];
|
|
342
|
+
this.byInstance.delete(instance);
|
|
343
|
+
this.dropFiles(instance, messages);
|
|
344
|
+
if (this.store)
|
|
345
|
+
void this.store.remove(instance);
|
|
346
|
+
}
|
|
209
347
|
/** The SSE cursor for one message: `<boot>-<id>`. */
|
|
210
348
|
cursorOf(m) { return `${m.boot}-${m.id}`; }
|
|
211
349
|
/**
|
|
212
|
-
* What a reconnecting stream with this `Last-Event-ID` should be sent. A cursor of this boot replays what
|
|
213
|
-
*
|
|
214
|
-
*
|
|
350
|
+
* What a reconnecting stream with this `Last-Event-ID` should be sent. A cursor of this boot replays what came
|
|
351
|
+
* after it. #1565: a cursor of a restored boot (a page that stayed open across the restart) gets what came after
|
|
352
|
+
* it in that boot and everything of the later boots — never a message it already has. A cursor of a boot this
|
|
353
|
+
* process does not hold gets everything retained (the page keeps one entry per boot+id, so nothing doubles). No
|
|
354
|
+
* cursor, or one that is not ours in shape, gets nothing.
|
|
215
355
|
*/
|
|
216
356
|
replayFor(cursor) {
|
|
217
357
|
if (!cursor)
|
|
218
358
|
return [];
|
|
219
|
-
|
|
359
|
+
if (cursor.boot === this.boot)
|
|
360
|
+
return this.after(cursor.id);
|
|
361
|
+
const rank = this.bootRanks();
|
|
362
|
+
const at = rank(cursor.boot);
|
|
363
|
+
if (at < 0)
|
|
364
|
+
return this.collect(() => true);
|
|
365
|
+
return this.collect((m) => { const r = rank(m.boot); return r > at || (r === at && m.id > cursor.id); });
|
|
220
366
|
}
|
|
221
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* #1565: one stored row as a restored message (and its files, to serve again), or null when it is not ours in shape.
|
|
370
|
+
* Only what was said comes back: no buttons, no delivery tick, no message id — whatever a row carries of those.
|
|
371
|
+
*/
|
|
372
|
+
function restoredRow(raw, instance, thisBoot) {
|
|
373
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
374
|
+
return null;
|
|
375
|
+
const r = raw;
|
|
376
|
+
if (typeof r.boot !== "string" || !/^[0-9a-f]{1,32}$/.test(r.boot) || r.boot === thisBoot)
|
|
377
|
+
return null;
|
|
378
|
+
if (typeof r.id !== "number" || !Number.isSafeInteger(r.id) || r.id < 1)
|
|
379
|
+
return null;
|
|
380
|
+
if (r.instance !== instance || typeof r.sender !== "string" || typeof r.text !== "string" || typeof r.ts !== "string")
|
|
381
|
+
return null;
|
|
382
|
+
// The role as stored — a person's message unless it is one of the three; never upgraded to `agent`.
|
|
383
|
+
const role = typeof r.role === "string" && ROLES.has(r.role) ? r.role : "user";
|
|
384
|
+
const message = { boot: r.boot, id: r.id, instance, role, sender: r.sender.slice(0, 256), text: r.text.slice(0, WEB_CHAT_TEXT_MAX), ts: r.ts.slice(0, 64) };
|
|
385
|
+
const files = !Array.isArray(r.attachments) ? [] : r.attachments.slice(0, 20).flatMap((a) => {
|
|
386
|
+
if (!a || typeof a !== "object" || Array.isArray(a))
|
|
387
|
+
return [];
|
|
388
|
+
const f = a;
|
|
389
|
+
if (typeof f.name !== "string")
|
|
390
|
+
return [];
|
|
391
|
+
return [{
|
|
392
|
+
...(typeof f.id === "string" ? { id: f.id } : {}), ...(typeof f.path === "string" ? { path: f.path } : {}),
|
|
393
|
+
kind: f.kind === "photo" ? "photo" : "document", name: f.name.slice(0, 255),
|
|
394
|
+
size: typeof f.size === "number" && Number.isSafeInteger(f.size) && f.size >= 0 ? f.size : 0, mime: typeof f.mime === "string" ? f.mime.slice(0, 128) : "",
|
|
395
|
+
}];
|
|
396
|
+
});
|
|
397
|
+
return { message, files };
|
|
398
|
+
}
|
|
222
399
|
/** `Last-Event-ID` as `<boot>-<id>`, or null when absent or not that shape. */
|
|
223
400
|
export function parseLastEventId(header) {
|
|
224
401
|
const raw = (Array.isArray(header) ? header[0] : header)?.trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-chat-history.js","sourceRoot":"","sources":["../src/web-chat-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY1C;;;;GAIG;AACH,MAAM,aAAa,GAAqC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAE5H,2GAA2G;AAC3G,MAAM,UAAU,iBAAiB,CAAC,IAAkC,EAAE,IAAsB;IAC1F,mFAAmF;IACnF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACjE,CAAC;AAGD,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAUxE,SAAS,cAAc,CAAC,GAAY;IAClC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5E,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3G,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/E,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK;QAC/E,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrF,CAAC;AACJ,CAAC;AAqCD,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,OAAO,cAAc;IACjB,MAAM,GAAG,CAAC,CAAC;IACnB,gEAAgE;IACvD,IAAI,CAAS;IACL,UAAU,GAAG,IAAI,GAAG,EAAyD,CAAC;IAC9E,WAAW,CAAS;IACpB,gBAAgB,CAAS;IACzB,SAAS,CAAS;IAEnC,YAAY,OAA8B,EAAE;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;QAC3C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,SAAS,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAED,iGAAiG;IACjG,IAAI,MAAM,KAAa,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAEhD,wFAAwF;IACxF,MAAM,CAAC,GAA4J;QACjK,MAAM,KAAK,GAAmB;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE;YACjB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9B,qEAAqE;YACrE,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAmB,CAAC,CAAC,CAAC,MAAM;YAC5F,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;YACxD,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpL,GAAG,CAAC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzG,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,IAAI,OAAO;YAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACrC,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;QAC5F,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACnH,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QACnD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,QAAgB,EAAE,GAAY;QAC1C,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;gBAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,OAAO,CAAC,CAAC;YAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oHAAoH;IACpH,YAAY;QACV,MAAM,GAAG,GAAyD,EAAE,CAAC;QACrE,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,QAAgB,EAAE,KAAK,GAAG,IAAI,CAAC,WAAW;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QACtD,MAAM,GAAG,GAAqB,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM;oBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAChC,OAAO,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACxE,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,KAAuB;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC/D,IAAI,CAA6B,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE;YAAE,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,SAAS,KAAK,SAAS;gBAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC/G,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClD,IAAI,IAAI,KAAK,CAAC,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACrC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;QAClB,OAAO,CAAC,CAAC;IACX,CAAC;IAED;;;;OAIG;IACH;;;;;OAKG;IACH,UAAU;QACR,MAAM,GAAG,GAA+E,EAAE,CAAC;QAC3F,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjK,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,aAAa,CAAC,QAAgB;QAC5B,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC/D,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;YACvB,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS;gBAAE,SAAS;YACxC,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;gBAAE,MAAM;YAC/D,CAAC,CAAC,QAAQ,GAAG,WAAW,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,oCAAoC;IACpC,MAAM,CAAC,QAAgB,IAAU,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEpE,qDAAqD;IACrD,QAAQ,CAAC,CAAiB,IAAY,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAEnE;;;;OAIG;IACH,SAAS,CAAC,MAA2C;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,MAAqC;IACpE,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IACjE,MAAM,CAAC,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC"}
|
|
1
|
+
{"version":3,"file":"web-chat-history.js","sourceRoot":"","sources":["../src/web-chat-history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAiB1C;;;;GAIG;AACH,MAAM,aAAa,GAAqC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAE5H,2GAA2G;AAC3G,MAAM,UAAU,iBAAiB,CAAC,IAAkC,EAAE,IAAsB;IAC1F,mFAAmF;IACnF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACjE,CAAC;AAGD,MAAM,KAAK,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAUxE,SAAS,cAAc,CAAC,GAAY;IAClC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5E,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3G,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/E,OAAO;QACL,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK;QAC/E,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrF,CAAC;AACJ,CAAC;AAqED,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,OAAO,cAAc;IACjB,MAAM,GAAG,CAAC,CAAC;IACnB,gEAAgE;IACvD,IAAI,CAAS;IACL,UAAU,GAAG,IAAI,GAAG,EAAyD,CAAC;IAC9E,WAAW,CAAS;IACpB,gBAAgB,CAAS;IACzB,SAAS,CAAS;IAC3B,KAAK,CAA4B;IACjC,KAAK,CAAsB;IACnC,6GAA6G;IAC5F,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE3D,YAAY,OAA8B,EAAE;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,GAAG,CAAC;QAC3C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,SAAS,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;IAClC,CAAC;IAED,yGAAyG;IACzG,QAAQ,CAAC,KAAgC,IAAU,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;IAExE,qEAAqE;IACrE,QAAQ,CAAC,KAA0B,IAAU,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;IAE1D,OAAO,CAAC,QAAgB;QAC9B,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClH,CAAC;IAED,wHAAwH;IAChH,MAAM,CAAC,CAAiB;QAC9B,MAAM,GAAG,GAAyB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;QAC3I,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;YAC1B,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACxC,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5E,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAChE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,mHAAmH;IAC3G,SAAS,CAAC,QAAgB,EAAE,IAA+B;QACjE,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE;gBAAE,IAAI,IAAI,IAAI,CAAC;oBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACxF,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,OAAO;QACtB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE;gBAAE,IAAI,IAAI,IAAI,CAAC;oBAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpI,IAAI,GAAG,CAAC,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACK,SAAS;QACf,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5I,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,QAAgB,EAAE,IAAsB;QAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,GAAG,GAA8D,EAAE,CAAC;QAC1E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;QACD,gDAAgD;QAChD,IAAI,KAAK,GAAG,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC;QACjC,OAAO,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB;YAAE,KAAK,IAAI,GAAG,CAAC,EAAE,IAAI,CAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1K,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,EAAE,GAAG,KAAK;gBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,gHAAgH;IACxG,YAAY,CAAC,CAAqD,EAAE,QAAgB;QAC1F,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,OAAO,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACxC,MAAM,IAAI,GAA0B,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3G,sGAAsG;YACtG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;YAClH,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACf,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QAClG,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,CAAC,OAAO,CAAC;IACnB,CAAC;IAED,iGAAiG;IACjG,IAAI,MAAM,KAAa,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAEhD,wFAAwF;IACxF,MAAM,CAAC,GAA4J;QACjK,MAAM,KAAK,GAAmB;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE;YACjB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9B,qEAAqE;YACrE,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAmB,CAAC,CAAC,CAAC,MAAM;YAC5F,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;YACxD,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpL,GAAG,CAAC,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzG,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/E,IAAI,OAAO;YAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACrC,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;YAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC;QAC5F,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACnH,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAG,CAAC;YACnC,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,mFAAmF;QACnF,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACH,aAAa,CAAC,QAAgB,EAAE,GAAY;QAC1C,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;gBAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAAC,OAAO,CAAC,CAAC;YAAC,CAAC;QACxF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oHAAoH;IACpH,YAAY;QACV,MAAM,GAAG,GAAyD,EAAE,CAAC;QACrE,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,QAAgB,EAAE,KAAK,GAAG,IAAI,CAAC,WAAW;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QACtD,6GAA6G;QAC7G,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,yHAAyH;IACjH,OAAO,CAAC,IAAoC;QAClD,MAAM,GAAG,GAAqB,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,IAAI,CAAC,CAAC,CAAC;oBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,OAAO,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACxE,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,KAAuB;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC/D,IAAI,CAA6B,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE;YAAE,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,SAAS,KAAK,SAAS;gBAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC/G,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,MAAM,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClD,IAAI,IAAI,KAAK,CAAC,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACrC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,CAAC,CAAC;IACX,CAAC;IAED;;;;OAIG;IACH;;;;;OAKG;IACH,UAAU;QACR,MAAM,GAAG,GAA+E,EAAE,CAAC;QAC3F,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjK,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,aAAa,CAAC,QAAgB;QAC5B,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC/D,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;YACvB,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS;gBAAE,SAAS;YACxC,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ;gBAAE,MAAM;YAC/D,CAAC,CAAC,QAAQ,GAAG,WAAW,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,2GAA2G;IAC3G,MAAM,CAAC,QAAgB;QACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC/D,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,qDAAqD;IACrD,QAAQ,CAAC,CAAiB,IAAY,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAEnE;;;;;;OAMG;IACH,SAAS,CAAC,MAA2C;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QACvB,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,EAAE,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3G,CAAC;CACF;AAKD;;;GAGG;AACH,SAAS,WAAW,CAAC,GAAY,EAAE,QAAgB,EAAE,QAAgB;IACnE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvG,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrF,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnI,oGAAoG;IACpG,MAAM,IAAI,GAAgB,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAmB,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3G,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC5K,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAkB,EAAE;QAC1G,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAC/D,MAAM,CAAC,GAAG,CAA4B,CAAC;QACvC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAC1C,OAAO,CAAC;gBACN,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1G,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBAC3E,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;aAC3J,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,MAAqC;IACpE,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IACjE,MAAM,CAAC,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StoredWebChatMessage } from "./web-chat-history.js";
|
|
2
|
+
export declare const WEB_CHAT_FILE = "web-chat.json";
|
|
3
|
+
/** A file larger than this is not read (the bounds keep a real one far smaller). */
|
|
4
|
+
export declare const WEB_CHAT_FILE_MAX_BYTES: number;
|
|
5
|
+
export interface WebChatStoreLogger {
|
|
6
|
+
warn(obj: unknown, msg?: string): void;
|
|
7
|
+
debug?(obj: unknown, msg?: string): void;
|
|
8
|
+
}
|
|
9
|
+
/** The rule instance paths are held to: no separator, no control character, no traversal. */
|
|
10
|
+
export declare function isSafeInstanceDirName(name: string): boolean;
|
|
11
|
+
export declare class WebChatDiskStore {
|
|
12
|
+
private readonly home;
|
|
13
|
+
private readonly logger;
|
|
14
|
+
private readonly debounceMs;
|
|
15
|
+
/**
|
|
16
|
+
* Who the instance is now: a fleet agent's working directory, a ClassicBot room's channel. Written with the file
|
|
17
|
+
* and required to match when it is read, so a later instance that only shares the name (deleted while the fleet was
|
|
18
|
+
* down, then created again elsewhere) never gets another one's history. Null: not configured — not written.
|
|
19
|
+
*/
|
|
20
|
+
private readonly ownerOf;
|
|
21
|
+
/** instance → its pending write (a timer) and whether one is in flight. */
|
|
22
|
+
private readonly pending;
|
|
23
|
+
/** Instances forgotten: a write already under way must not bring the file back. */
|
|
24
|
+
private readonly gone;
|
|
25
|
+
constructor(opts: {
|
|
26
|
+
home: string;
|
|
27
|
+
logger: WebChatStoreLogger;
|
|
28
|
+
debounceMs?: number;
|
|
29
|
+
ownerOf: (instance: string) => string | null;
|
|
30
|
+
});
|
|
31
|
+
pathOf(instance: string): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* The stored messages of one instance, as written (validated later by the history), or null: no file, or one that
|
|
34
|
+
* is skipped (too large, unreadable, not JSON, not ours, another instance's) — said once in the log.
|
|
35
|
+
*/
|
|
36
|
+
load(instance: string): unknown[] | null;
|
|
37
|
+
/** The instance's history changed: write it soon (debounced; one write in flight; the latest snapshot wins). */
|
|
38
|
+
schedule(instance: string, snapshot: () => StoredWebChatMessage[]): void;
|
|
39
|
+
private write;
|
|
40
|
+
private writeFile;
|
|
41
|
+
/** Every pending write done (tests; a clean shutdown). */
|
|
42
|
+
flush(): Promise<void>;
|
|
43
|
+
/** The instance is gone: no further write, and the file (and any temporary one of ours) is deleted. */
|
|
44
|
+
remove(instance: string): Promise<void>;
|
|
45
|
+
}
|