pi-forge 1.2.0 → 1.2.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 +1 -1
- package/dist/client/assets/{CodeMirrorEditor-DXdXoCjw.js → CodeMirrorEditor-D_P6wobf.js} +2 -2
- package/dist/client/assets/{CodeMirrorEditor-DXdXoCjw.js.map → CodeMirrorEditor-D_P6wobf.js.map} +1 -1
- package/dist/client/assets/index-BDOppLth.css +1 -0
- package/dist/client/assets/{index-DRa0fybV.js → index-Bv9XfcDK.js} +71 -71
- package/dist/client/assets/index-Bv9XfcDK.js.map +1 -0
- package/dist/client/index.html +2 -2
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.map +1 -1
- package/dist/server/git-hunk-stager.js +137 -0
- package/dist/server/git-hunk-stager.js.map +1 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/export.js +66 -0
- package/dist/server/routes/export.js.map +1 -0
- package/dist/server/routes/git.js +61 -0
- package/dist/server/routes/git.js.map +1 -1
- package/dist/server/routes/search.js +108 -0
- package/dist/server/routes/search.js.map +1 -0
- package/dist/server/session-exporter.js +490 -0
- package/dist/server/session-exporter.js.map +1 -0
- package/dist/server/session-searcher.js +490 -0
- package/dist/server/session-searcher.js.map +1 -0
- package/package.json +1 -1
- package/dist/client/assets/index-DRa0fybV.js.map +0 -1
- package/dist/client/assets/index-b30wYoh-.css +0 -1
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { config } from "./config.js";
|
|
5
|
+
import { ripgrepAvailable } from "./file-searcher.js";
|
|
6
|
+
import { readProjects } from "./project-manager.js";
|
|
7
|
+
const SNIPPET_CONTEXT = 60;
|
|
8
|
+
export async function searchSessions(opts) {
|
|
9
|
+
const projects = await readProjects();
|
|
10
|
+
const projectById = new Map(projects.map((p) => [p.id, p]));
|
|
11
|
+
const lineHits = (await ripgrepAvailable())
|
|
12
|
+
? await collectWithRipgrep(opts)
|
|
13
|
+
: await collectInProcess(opts);
|
|
14
|
+
const grouped = new Map();
|
|
15
|
+
// Walk hits in `(file, lineNumber)` order so we can compute messageIndex
|
|
16
|
+
// (count of `type === "message"` lines preceding this one) without
|
|
17
|
+
// re-reading entire files. `collectWithRipgrep` and `collectInProcess`
|
|
18
|
+
// both honor that ordering.
|
|
19
|
+
for (const hit of lineHits) {
|
|
20
|
+
const projectId = projectIdFromPath(hit.filePath);
|
|
21
|
+
if (projectId === undefined)
|
|
22
|
+
continue; // Hit outside the per-project layout
|
|
23
|
+
if (!projectById.has(projectId))
|
|
24
|
+
continue; // Orphaned dir from a deleted project
|
|
25
|
+
// Lazy-initialize the per-file group on first hit; its `messageCounter`
|
|
26
|
+
// tracks the running message-line index within that file so
|
|
27
|
+
// subsequent hits in the same file don't have to rescan.
|
|
28
|
+
let group = grouped.get(hit.filePath);
|
|
29
|
+
if (group === undefined) {
|
|
30
|
+
const sessionId = await readSessionIdFromHeader(hit.filePath);
|
|
31
|
+
if (sessionId === undefined)
|
|
32
|
+
continue; // Corrupt / missing header
|
|
33
|
+
group = {
|
|
34
|
+
sessionId,
|
|
35
|
+
projectId,
|
|
36
|
+
filePath: hit.filePath,
|
|
37
|
+
matches: [],
|
|
38
|
+
messageCounter: 0,
|
|
39
|
+
};
|
|
40
|
+
grouped.set(hit.filePath, group);
|
|
41
|
+
}
|
|
42
|
+
if (group.matches.length >= opts.matchesPerSession)
|
|
43
|
+
continue;
|
|
44
|
+
const parsed = safeParseLine(hit.line);
|
|
45
|
+
if (parsed === undefined)
|
|
46
|
+
continue;
|
|
47
|
+
const extracted = extractSnippet(parsed, opts.query);
|
|
48
|
+
if (extracted === undefined)
|
|
49
|
+
continue;
|
|
50
|
+
// messageIndex tracking: count `type === "message"` lines from the
|
|
51
|
+
// start of the file up to AND INCLUDING this hit. We need to scan
|
|
52
|
+
// the file's intervening lines if we skipped any since the previous
|
|
53
|
+
// hit. The cheap path is "no skipped lines" (consecutive hits) —
|
|
54
|
+
// most queries only hit a handful of distinct lines per file.
|
|
55
|
+
const messageIndex = await advanceMessageIndex(group, hit.lineNumber);
|
|
56
|
+
if (messageIndex === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
group.matches.push({
|
|
59
|
+
messageIndex,
|
|
60
|
+
messageEnvelopeId: typeof parsed.id === "string" ? parsed.id : undefined,
|
|
61
|
+
kind: extracted.kind,
|
|
62
|
+
snippet: extracted.snippet,
|
|
63
|
+
matchOffset: extracted.matchOffset,
|
|
64
|
+
matchLength: extracted.matchLength,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const results = [];
|
|
68
|
+
let truncated = false;
|
|
69
|
+
// Sort by file mtime (newest first) so recent matches land at the top.
|
|
70
|
+
const fileStats = await Promise.all(Array.from(grouped.values()).map(async (g) => ({
|
|
71
|
+
group: g,
|
|
72
|
+
modifiedAt: await fileMtime(g.filePath),
|
|
73
|
+
sessionName: await readSessionNameFromFile(g.filePath),
|
|
74
|
+
})));
|
|
75
|
+
fileStats.sort((a, b) => (a.modifiedAt < b.modifiedAt ? 1 : -1));
|
|
76
|
+
for (const entry of fileStats) {
|
|
77
|
+
if (results.length >= opts.sessionLimit) {
|
|
78
|
+
truncated = true;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
const project = projectById.get(entry.group.projectId);
|
|
82
|
+
if (project === undefined)
|
|
83
|
+
continue;
|
|
84
|
+
results.push({
|
|
85
|
+
sessionId: entry.group.sessionId,
|
|
86
|
+
projectId: entry.group.projectId,
|
|
87
|
+
projectName: project.name,
|
|
88
|
+
sessionName: entry.sessionName,
|
|
89
|
+
modifiedAt: entry.modifiedAt,
|
|
90
|
+
matches: entry.group.matches,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
engine: (await ripgrepAvailable()) ? "ripgrep" : "node",
|
|
95
|
+
results,
|
|
96
|
+
truncated,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async function collectWithRipgrep(opts) {
|
|
100
|
+
// Hits are bounded by the global session limit × per-session matches —
|
|
101
|
+
// a generous ceiling that prevents runaway output without truncating
|
|
102
|
+
// legitimate workloads. The session-grouping pass downstream applies
|
|
103
|
+
// the actual per-session caps.
|
|
104
|
+
const maxLines = opts.sessionLimit * opts.matchesPerSession * 4;
|
|
105
|
+
const args = [
|
|
106
|
+
"--json",
|
|
107
|
+
"--no-heading",
|
|
108
|
+
"--max-filesize",
|
|
109
|
+
"100M", // session JSONLs can be sizeable
|
|
110
|
+
"--max-count",
|
|
111
|
+
String(maxLines),
|
|
112
|
+
"-i", // case-insensitive — matches the dropdown's "type to find" UX
|
|
113
|
+
"--fixed-strings",
|
|
114
|
+
"--glob",
|
|
115
|
+
"*.jsonl",
|
|
116
|
+
"--",
|
|
117
|
+
opts.query,
|
|
118
|
+
config.sessionDir,
|
|
119
|
+
];
|
|
120
|
+
return new Promise((resolveFn) => {
|
|
121
|
+
const hits = [];
|
|
122
|
+
const child = spawn("rg", args);
|
|
123
|
+
const timer = setTimeout(() => child.kill("SIGTERM"), opts.timeoutMs);
|
|
124
|
+
let buf = "";
|
|
125
|
+
let currentFile;
|
|
126
|
+
const finish = () => {
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
resolveFn(hits);
|
|
129
|
+
};
|
|
130
|
+
child.stdout.setEncoding("utf8");
|
|
131
|
+
child.stdout.on("data", (chunk) => {
|
|
132
|
+
buf += chunk;
|
|
133
|
+
let nl = buf.indexOf("\n");
|
|
134
|
+
while (nl !== -1) {
|
|
135
|
+
const line = buf.slice(0, nl);
|
|
136
|
+
buf = buf.slice(nl + 1);
|
|
137
|
+
if (line.length > 0)
|
|
138
|
+
handleEvent(line);
|
|
139
|
+
nl = buf.indexOf("\n");
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
child.on("error", () => finish());
|
|
143
|
+
child.on("close", () => finish());
|
|
144
|
+
const handleEvent = (jsonLine) => {
|
|
145
|
+
let event;
|
|
146
|
+
try {
|
|
147
|
+
event = JSON.parse(jsonLine);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (event.type === "begin") {
|
|
153
|
+
const data = event.data;
|
|
154
|
+
currentFile = data?.path?.text;
|
|
155
|
+
}
|
|
156
|
+
else if (event.type === "match" && currentFile !== undefined) {
|
|
157
|
+
if (hits.length >= maxLines) {
|
|
158
|
+
child.kill("SIGTERM");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const data = event.data;
|
|
162
|
+
if (data === undefined)
|
|
163
|
+
return;
|
|
164
|
+
const lineText = data.lines?.text ?? "";
|
|
165
|
+
const lineNumber = data.line_number ?? 0;
|
|
166
|
+
if (lineNumber === 0)
|
|
167
|
+
return;
|
|
168
|
+
hits.push({
|
|
169
|
+
filePath: currentFile,
|
|
170
|
+
lineNumber,
|
|
171
|
+
line: stripTrailingNewline(lineText),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/* ----------------------------- in-process path ----------------------------- */
|
|
178
|
+
async function collectInProcess(opts) {
|
|
179
|
+
const hits = [];
|
|
180
|
+
const deadline = Date.now() + opts.timeoutMs;
|
|
181
|
+
const needle = opts.query.toLowerCase();
|
|
182
|
+
const maxLines = opts.sessionLimit * opts.matchesPerSession * 4;
|
|
183
|
+
let projectDirs;
|
|
184
|
+
try {
|
|
185
|
+
projectDirs = await readdir(config.sessionDir);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return hits; // Session dir doesn't exist yet — empty result is fine.
|
|
189
|
+
}
|
|
190
|
+
for (const projectDir of projectDirs) {
|
|
191
|
+
if (Date.now() >= deadline || hits.length >= maxLines)
|
|
192
|
+
break;
|
|
193
|
+
const fullDir = join(config.sessionDir, projectDir);
|
|
194
|
+
let entries;
|
|
195
|
+
try {
|
|
196
|
+
entries = await readdir(fullDir, { withFileTypes: true });
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
for (const ent of entries) {
|
|
202
|
+
if (Date.now() >= deadline || hits.length >= maxLines)
|
|
203
|
+
break;
|
|
204
|
+
if (!ent.isFile() || !ent.name.endsWith(".jsonl"))
|
|
205
|
+
continue;
|
|
206
|
+
const filePath = join(fullDir, ent.name);
|
|
207
|
+
let content;
|
|
208
|
+
try {
|
|
209
|
+
content = await readFile(filePath, "utf8");
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const lines = content.split("\n");
|
|
215
|
+
for (let i = 0; i < lines.length; i++) {
|
|
216
|
+
if (Date.now() >= deadline || hits.length >= maxLines)
|
|
217
|
+
break;
|
|
218
|
+
const line = lines[i] ?? "";
|
|
219
|
+
if (line.length === 0)
|
|
220
|
+
continue;
|
|
221
|
+
if (line.toLowerCase().includes(needle)) {
|
|
222
|
+
hits.push({ filePath, lineNumber: i + 1, line });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return hits;
|
|
228
|
+
}
|
|
229
|
+
function safeParseLine(line) {
|
|
230
|
+
try {
|
|
231
|
+
return JSON.parse(line);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function extractSnippet(parsed, query) {
|
|
238
|
+
if (parsed.type !== "message")
|
|
239
|
+
return undefined;
|
|
240
|
+
const msg = parsed.message;
|
|
241
|
+
if (msg === undefined || msg === null || typeof msg !== "object")
|
|
242
|
+
return undefined;
|
|
243
|
+
const role = msg.role;
|
|
244
|
+
if (role !== "user" && role !== "assistant")
|
|
245
|
+
return undefined;
|
|
246
|
+
const content = msg.content;
|
|
247
|
+
// String content is the simple "user typed text" shape some SDK
|
|
248
|
+
// versions still emit. Treat as a single text block.
|
|
249
|
+
if (typeof content === "string") {
|
|
250
|
+
const hit = findMatch(content, query);
|
|
251
|
+
if (hit === undefined)
|
|
252
|
+
return undefined;
|
|
253
|
+
return {
|
|
254
|
+
kind: role === "user" ? "user" : "assistant",
|
|
255
|
+
snippet: clipSnippet(content, hit.offset, query.length),
|
|
256
|
+
matchOffset: clippedMatchOffset(content, hit.offset),
|
|
257
|
+
matchLength: query.length,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
if (!Array.isArray(content))
|
|
261
|
+
return undefined;
|
|
262
|
+
// Walk content blocks. Prefer text-block matches (most readable).
|
|
263
|
+
// If no text block matches but a toolCall does, surface the rendered
|
|
264
|
+
// tool form as the snippet.
|
|
265
|
+
for (const block of content) {
|
|
266
|
+
if (block === undefined || block === null || typeof block !== "object")
|
|
267
|
+
continue;
|
|
268
|
+
const b = block;
|
|
269
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
270
|
+
const hit = findMatch(b.text, query);
|
|
271
|
+
if (hit !== undefined) {
|
|
272
|
+
return {
|
|
273
|
+
kind: role === "user" ? "user" : "assistant",
|
|
274
|
+
snippet: clipSnippet(b.text, hit.offset, query.length),
|
|
275
|
+
matchOffset: clippedMatchOffset(b.text, hit.offset),
|
|
276
|
+
matchLength: query.length,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// Tool-call fallback: only assistants emit toolCall blocks.
|
|
282
|
+
if (role === "assistant") {
|
|
283
|
+
for (const block of content) {
|
|
284
|
+
if (block === undefined || block === null || typeof block !== "object")
|
|
285
|
+
continue;
|
|
286
|
+
const b = block;
|
|
287
|
+
if (b.type !== "toolCall")
|
|
288
|
+
continue;
|
|
289
|
+
const rendered = renderToolCall(b);
|
|
290
|
+
const hit = findMatch(rendered, query);
|
|
291
|
+
if (hit === undefined)
|
|
292
|
+
continue;
|
|
293
|
+
return {
|
|
294
|
+
kind: "tool_call",
|
|
295
|
+
snippet: clipSnippet(rendered, hit.offset, query.length),
|
|
296
|
+
matchOffset: clippedMatchOffset(rendered, hit.offset),
|
|
297
|
+
matchLength: query.length,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
function renderToolCall(block) {
|
|
304
|
+
const name = typeof block.name === "string" ? block.name : "tool";
|
|
305
|
+
const args = (block.arguments ?? block.input);
|
|
306
|
+
if (args === undefined || args === null || typeof args !== "object")
|
|
307
|
+
return name + "()";
|
|
308
|
+
const parts = [];
|
|
309
|
+
for (const [k, v] of Object.entries(args)) {
|
|
310
|
+
if (v === undefined || v === null)
|
|
311
|
+
continue;
|
|
312
|
+
let s;
|
|
313
|
+
if (typeof v === "string")
|
|
314
|
+
s = v;
|
|
315
|
+
else if (typeof v === "number" || typeof v === "boolean")
|
|
316
|
+
s = String(v);
|
|
317
|
+
else
|
|
318
|
+
s = JSON.stringify(v);
|
|
319
|
+
if (s.length > 200)
|
|
320
|
+
s = s.slice(0, 200) + "…";
|
|
321
|
+
parts.push(`${k}=${s}`);
|
|
322
|
+
}
|
|
323
|
+
return `${name}(${parts.join(", ")})`;
|
|
324
|
+
}
|
|
325
|
+
function findMatch(haystack, query) {
|
|
326
|
+
const i = haystack.toLowerCase().indexOf(query.toLowerCase());
|
|
327
|
+
if (i === -1)
|
|
328
|
+
return undefined;
|
|
329
|
+
return { offset: i };
|
|
330
|
+
}
|
|
331
|
+
function clipSnippet(source, matchOffset, matchLength) {
|
|
332
|
+
const start = Math.max(0, matchOffset - SNIPPET_CONTEXT);
|
|
333
|
+
const end = Math.min(source.length, matchOffset + matchLength + SNIPPET_CONTEXT);
|
|
334
|
+
let snippet = source.slice(start, end).replace(/\s+/g, " ").trim();
|
|
335
|
+
if (start > 0)
|
|
336
|
+
snippet = "…" + snippet;
|
|
337
|
+
if (end < source.length)
|
|
338
|
+
snippet = snippet + "…";
|
|
339
|
+
return snippet;
|
|
340
|
+
}
|
|
341
|
+
function clippedMatchOffset(source, matchOffset) {
|
|
342
|
+
// The clipped snippet always centers the match (with possible "…"
|
|
343
|
+
// prefix). Compute the new offset relative to the snippet so the
|
|
344
|
+
// client can highlight the exact substring.
|
|
345
|
+
const start = Math.max(0, matchOffset - SNIPPET_CONTEXT);
|
|
346
|
+
const prefixEllipsis = start > 0 ? 1 : 0;
|
|
347
|
+
const original = source.slice(start, matchOffset);
|
|
348
|
+
const collapsed = original.replace(/\s+/g, " ").replace(/^\s+/, "");
|
|
349
|
+
return prefixEllipsis + collapsed.length;
|
|
350
|
+
}
|
|
351
|
+
/* ----------------------------- file walking ----------------------------- */
|
|
352
|
+
const headerCache = new Map();
|
|
353
|
+
const nameCache = new Map();
|
|
354
|
+
const messageIndexCache = new Map();
|
|
355
|
+
async function readSessionIdFromHeader(filePath) {
|
|
356
|
+
if (headerCache.has(filePath))
|
|
357
|
+
return headerCache.get(filePath);
|
|
358
|
+
let content;
|
|
359
|
+
try {
|
|
360
|
+
content = await readFile(filePath, "utf8");
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
headerCache.set(filePath, undefined);
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
const firstNl = content.indexOf("\n");
|
|
367
|
+
const firstLine = firstNl === -1 ? content : content.slice(0, firstNl);
|
|
368
|
+
let header;
|
|
369
|
+
try {
|
|
370
|
+
header = JSON.parse(firstLine);
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
headerCache.set(filePath, undefined);
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
if (header.type !== "session" || typeof header.id !== "string") {
|
|
377
|
+
headerCache.set(filePath, undefined);
|
|
378
|
+
return undefined;
|
|
379
|
+
}
|
|
380
|
+
headerCache.set(filePath, header.id);
|
|
381
|
+
return header.id;
|
|
382
|
+
}
|
|
383
|
+
async function readSessionNameFromFile(filePath) {
|
|
384
|
+
if (nameCache.has(filePath))
|
|
385
|
+
return nameCache.get(filePath);
|
|
386
|
+
let content;
|
|
387
|
+
try {
|
|
388
|
+
content = await readFile(filePath, "utf8");
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
nameCache.set(filePath, undefined);
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
const lines = content.split("\n");
|
|
395
|
+
for (const line of lines) {
|
|
396
|
+
if (line.length === 0)
|
|
397
|
+
continue;
|
|
398
|
+
let parsed;
|
|
399
|
+
try {
|
|
400
|
+
parsed = JSON.parse(line);
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (parsed.type === "session_info" && typeof parsed.name === "string") {
|
|
406
|
+
nameCache.set(filePath, parsed.name);
|
|
407
|
+
return parsed.name;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
nameCache.set(filePath, undefined);
|
|
411
|
+
return undefined;
|
|
412
|
+
}
|
|
413
|
+
async function fileMtime(filePath) {
|
|
414
|
+
try {
|
|
415
|
+
const { stat } = await import("node:fs/promises");
|
|
416
|
+
const s = await stat(filePath);
|
|
417
|
+
return s.mtime.toISOString();
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
return new Date(0).toISOString();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
function projectIdFromPath(filePath) {
|
|
424
|
+
// ${SESSION_DIR}/<projectId>/<file>.jsonl — projectId is the
|
|
425
|
+
// immediate parent dir. Subagent child JSONLs live one level deeper
|
|
426
|
+
// and we ignore them here (their parent's main session is what we
|
|
427
|
+
// surface in search results).
|
|
428
|
+
const sessionDir = config.sessionDir;
|
|
429
|
+
if (!filePath.startsWith(sessionDir))
|
|
430
|
+
return undefined;
|
|
431
|
+
const rel = filePath.slice(sessionDir.length).replace(/^[/\\]+/, "");
|
|
432
|
+
const parts = rel.split(/[/\\]/);
|
|
433
|
+
if (parts.length < 2)
|
|
434
|
+
return undefined;
|
|
435
|
+
if (parts.length > 2)
|
|
436
|
+
return undefined; // Subagent child — skip
|
|
437
|
+
return parts[0];
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Scan from the file's last-known message-line cursor up to the line
|
|
441
|
+
* containing this hit, counting `type === "message"` lines. Returns the
|
|
442
|
+
* 0-based index of the message at `lineNumber` (or undefined if that
|
|
443
|
+
* line isn't a message line).
|
|
444
|
+
*/
|
|
445
|
+
async function advanceMessageIndex(group, lineNumber) {
|
|
446
|
+
const cached = messageIndexCache.get(group.filePath);
|
|
447
|
+
if (cached !== undefined) {
|
|
448
|
+
// Cached layout: array of all message-line numbers (1-based) in
|
|
449
|
+
// the file. Binary-search to find the index for this line.
|
|
450
|
+
const idx = cached.indexOf(lineNumber);
|
|
451
|
+
return idx === -1 ? undefined : idx;
|
|
452
|
+
}
|
|
453
|
+
let content;
|
|
454
|
+
try {
|
|
455
|
+
content = await readFile(group.filePath, "utf8");
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
const messageLines = [];
|
|
461
|
+
const lines = content.split("\n");
|
|
462
|
+
for (let i = 0; i < lines.length; i++) {
|
|
463
|
+
const line = lines[i] ?? "";
|
|
464
|
+
if (line.length === 0)
|
|
465
|
+
continue;
|
|
466
|
+
// Cheap pre-check before JSON.parse: every message line starts
|
|
467
|
+
// with `{"type":"message"`. Skipping the parse for non-message
|
|
468
|
+
// lines is a 10× speedup on long sessions.
|
|
469
|
+
if (!line.startsWith('{"type":"message"'))
|
|
470
|
+
continue;
|
|
471
|
+
messageLines.push(i + 1); // 1-based to match ripgrep
|
|
472
|
+
}
|
|
473
|
+
messageIndexCache.set(group.filePath, messageLines);
|
|
474
|
+
const idx = messageLines.indexOf(lineNumber);
|
|
475
|
+
return idx === -1 ? undefined : idx;
|
|
476
|
+
}
|
|
477
|
+
function stripTrailingNewline(s) {
|
|
478
|
+
if (s.endsWith("\r\n"))
|
|
479
|
+
return s.slice(0, -2);
|
|
480
|
+
if (s.endsWith("\n"))
|
|
481
|
+
return s.slice(0, -1);
|
|
482
|
+
return s;
|
|
483
|
+
}
|
|
484
|
+
/** Test-only: drop all per-file caches between assertions. */
|
|
485
|
+
export function _resetSessionSearcherCaches() {
|
|
486
|
+
headerCache.clear();
|
|
487
|
+
nameCache.clear();
|
|
488
|
+
messageIndexCache.clear();
|
|
489
|
+
}
|
|
490
|
+
//# sourceMappingURL=session-searcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-searcher.js","sourceRoot":"","sources":["../src/session-searcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AA2EpD,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAA0B;IAC7D,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAU,CAAC,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,CAAC,MAAM,gBAAgB,EAAE,CAAC;QACzC,CAAC,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC;QAChC,CAAC,CAAC,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEjC,MAAM,OAAO,GAAG,IAAI,GAAG,EASpB,CAAC;IAEJ,yEAAyE;IACzE,mEAAmE;IACnE,uEAAuE;IACvE,4BAA4B;IAC5B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS,CAAC,qCAAqC;QAC5E,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,SAAS,CAAC,sCAAsC;QAEjF,wEAAwE;QACxE,4DAA4D;QAC5D,yDAAyD;QACzD,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,SAAS,KAAK,SAAS;gBAAE,SAAS,CAAC,2BAA2B;YAClE,KAAK,GAAG;gBACN,SAAS;gBACT,SAAS;gBACT,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,OAAO,EAAE,EAAE;gBACX,cAAc,EAAE,CAAC;aAClB,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,iBAAiB;YAAE,SAAS;QAE7D,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS;QAEnC,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS;QAEtC,mEAAmE;QACnE,kEAAkE;QAClE,oEAAoE;QACpE,iEAAiE;QACjE,8DAA8D;QAC9D,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QACtE,IAAI,YAAY,KAAK,SAAS;YAAE,SAAS;QAEzC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YACjB,YAAY;YACZ,iBAAiB,EAAE,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;YACxE,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,WAAW,EAAE,SAAS,CAAC,WAAW;SACnC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAA+B,EAAE,CAAC;IAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,uEAAuE;IACvE,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7C,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;QACvC,WAAW,EAAE,MAAM,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC;KACvD,CAAC,CAAC,CACJ,CAAC;IACF,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjE,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,OAAO,CAAC,IAAI,CAAC;YACX,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS;YAChC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS;YAChC,WAAW,EAAE,OAAO,CAAC,IAAI;YACzB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,MAAM,EAAE,CAAC,MAAM,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;QACvD,OAAO;QACP,SAAS;KACV,CAAC;AACJ,CAAC;AAeD,KAAK,UAAU,kBAAkB,CAAC,IAA0B;IAC1D,uEAAuE;IACvE,qEAAqE;IACrE,qEAAqE;IACrE,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAEhE,MAAM,IAAI,GAAa;QACrB,QAAQ;QACR,cAAc;QACd,gBAAgB;QAChB,MAAM,EAAE,iCAAiC;QACzC,aAAa;QACb,MAAM,CAAC,QAAQ,CAAC;QAChB,IAAI,EAAE,8DAA8D;QACpE,iBAAiB;QACjB,QAAQ;QACR,SAAS;QACT,IAAI;QACJ,IAAI,CAAC,KAAK;QACV,MAAM,CAAC,UAAU;KAClB,CAAC;IAEF,OAAO,IAAI,OAAO,CAAY,CAAC,SAAS,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAc,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtE,IAAI,GAAG,GAAG,EAAE,CAAC;QACb,IAAI,WAA+B,CAAC;QAEpC,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,GAAG,IAAI,KAAK,CAAC;YACb,IAAI,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3B,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9B,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBACxB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;oBAAE,WAAW,CAAC,IAAI,CAAC,CAAC;gBACvC,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;QAElC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAQ,EAAE;YAC7C,IAAI,KAAmB,CAAC;YACxB,IAAI,CAAC;gBACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAiB,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAgD,CAAC;gBACpE,WAAW,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACjC,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC/D,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC;oBAC5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACtB,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAuE,CAAC;gBAC3F,IAAI,IAAI,KAAK,SAAS;oBAAE,OAAO;gBAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;gBACxC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;gBACzC,IAAI,UAAU,KAAK,CAAC;oBAAE,OAAO;gBAC7B,IAAI,CAAC,IAAI,CAAC;oBACR,QAAQ,EAAE,WAAW;oBACrB,UAAU;oBACV,IAAI,EAAE,oBAAoB,CAAC,QAAQ,CAAC;iBACrC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,gBAAgB,CAAC,IAA0B;IACxD,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAEhE,IAAI,WAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wDAAwD;IACvE,CAAC;IAED,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;YAAE,MAAM;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACpD,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;gBAAE,MAAM;YAC7D,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,SAAS;YAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;oBAAE,MAAM;gBAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAChC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxC,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAUD,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AASD,SAAS,cAAc,CAAC,MAAkB,EAAE,KAAa;IACvD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;IAC3B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACnF,MAAM,IAAI,GAAI,GAA0B,CAAC,IAAI,CAAC;IAC9C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,OAAO,GAAI,GAA6B,CAAC,OAAO,CAAC;IAEvD,gEAAgE;IAChE,qDAAqD;IACrD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACxC,OAAO;YACL,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;YAC5C,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACvD,WAAW,EAAE,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC;YACpD,WAAW,EAAE,KAAK,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9C,kEAAkE;IAClE,qEAAqE;IACrE,4BAA4B;IAC5B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QACjF,MAAM,CAAC,GAAG,KAA2C,CAAC;QACtD,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpD,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACrC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,OAAO;oBACL,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;oBAC5C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;oBACtD,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;oBACnD,WAAW,EAAE,KAAK,CAAC,MAAM;iBAC1B,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAS;YACjF,MAAM,CAAC,GAAG,KAAiF,CAAC;YAC5F,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACvC,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAS;YAChC,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;gBACxD,WAAW,EAAE,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;gBACrD,WAAW,EAAE,KAAK,CAAC,MAAM;aAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,KAA+D;IACrF,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAClE,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,CAAwC,CAAC;IACrF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,GAAG,IAAI,CAAC;IACxF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;YAAE,SAAS;QAC5C,IAAI,CAAS,CAAC;QACd,IAAI,OAAO,CAAC,KAAK,QAAQ;YAAE,CAAC,GAAG,CAAC,CAAC;aAC5B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS;YAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;;YACnE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG;YAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACxC,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB,EAAE,KAAa;IAChD,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,WAAW,CAAC,MAAc,EAAE,WAAmB,EAAE,WAAmB;IAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,eAAe,CAAC,CAAC;IACjF,IAAI,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnE,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,GAAG,GAAG,OAAO,CAAC;IACvC,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM;QAAE,OAAO,GAAG,OAAO,GAAG,GAAG,CAAC;IACjD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc,EAAE,WAAmB;IAC7D,kEAAkE;IAClE,iEAAiE;IACjE,4CAA4C;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpE,OAAO,cAAc,GAAG,SAAS,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED,8EAA8E;AAE9E,MAAM,WAAW,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;AACxD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAoB,CAAC;AAEtD,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IACrD,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,IAAI,MAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAqC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC/D,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,EAAE,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,QAAgB;IACrD,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5D,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,IAAI,MAA0C,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAuC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtE,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACrC,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB;IACzC,6DAA6D;IAC7D,oEAAoE;IACpE,kEAAkE;IAClE,8BAA8B;IAC9B,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,CAAC,wBAAwB;IAChE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,mBAAmB,CAChC,KAAmD,EACnD,UAAkB;IAElB,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,gEAAgE;QAChE,2DAA2D;QAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IACtC,CAAC;IACD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,+DAA+D;QAC/D,+DAA+D;QAC/D,2CAA2C;QAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC;YAAE,SAAS;QACpD,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,2BAA2B;IACvD,CAAC;IACD,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;AACtC,CAAC;AAED,SAAS,oBAAoB,CAAC,CAAS;IACrC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,2BAA2B;IACzC,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,iBAAiB,CAAC,KAAK,EAAE,CAAC;AAC5B,CAAC"}
|