@spool-lab/core 0.4.12 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +2 -2
  2. package/dist/db/db.d.ts +10 -2
  3. package/dist/db/db.d.ts.map +1 -1
  4. package/dist/db/db.js +119 -10
  5. package/dist/db/db.js.map +1 -1
  6. package/dist/db/queries.d.ts +5 -5
  7. package/dist/db/queries.d.ts.map +1 -1
  8. package/dist/db/queries.js +32 -14
  9. package/dist/db/queries.js.map +1 -1
  10. package/dist/index.d.ts +4 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +4 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/observability/exporter-file.d.ts +30 -0
  15. package/dist/observability/exporter-file.d.ts.map +1 -0
  16. package/dist/observability/exporter-file.js +125 -0
  17. package/dist/observability/exporter-file.js.map +1 -0
  18. package/dist/observability/exporter-pretty.d.ts +27 -0
  19. package/dist/observability/exporter-pretty.d.ts.map +1 -0
  20. package/dist/observability/exporter-pretty.js +84 -0
  21. package/dist/observability/exporter-pretty.js.map +1 -0
  22. package/dist/observability/index.d.ts +2 -0
  23. package/dist/observability/index.d.ts.map +1 -0
  24. package/dist/observability/index.js +2 -0
  25. package/dist/observability/index.js.map +1 -0
  26. package/dist/observability/layer.d.ts +29 -0
  27. package/dist/observability/layer.d.ts.map +1 -0
  28. package/dist/observability/layer.js +45 -0
  29. package/dist/observability/layer.js.map +1 -0
  30. package/dist/parsers/opencode.d.ts +23 -0
  31. package/dist/parsers/opencode.d.ts.map +1 -0
  32. package/dist/parsers/opencode.js +358 -0
  33. package/dist/parsers/opencode.js.map +1 -0
  34. package/dist/projects/sessions.d.ts +29 -1
  35. package/dist/projects/sessions.d.ts.map +1 -1
  36. package/dist/projects/sessions.js +115 -11
  37. package/dist/projects/sessions.js.map +1 -1
  38. package/dist/security/index.d.ts +14 -0
  39. package/dist/security/index.d.ts.map +1 -0
  40. package/dist/security/index.js +7 -0
  41. package/dist/security/index.js.map +1 -0
  42. package/dist/security/maintenance.d.ts +15 -0
  43. package/dist/security/maintenance.d.ts.map +1 -0
  44. package/dist/security/maintenance.js +68 -0
  45. package/dist/security/maintenance.js.map +1 -0
  46. package/dist/security/profile.d.ts +47 -0
  47. package/dist/security/profile.d.ts.map +1 -0
  48. package/dist/security/profile.js +131 -0
  49. package/dist/security/profile.js.map +1 -0
  50. package/dist/security/purge.d.ts +68 -0
  51. package/dist/security/purge.d.ts.map +1 -0
  52. package/dist/security/purge.js +193 -0
  53. package/dist/security/purge.js.map +1 -0
  54. package/dist/security/repo.d.ts +190 -0
  55. package/dist/security/repo.d.ts.map +1 -0
  56. package/dist/security/repo.js +594 -0
  57. package/dist/security/repo.js.map +1 -0
  58. package/dist/security/scan.d.ts +50 -0
  59. package/dist/security/scan.d.ts.map +1 -0
  60. package/dist/security/scan.js +122 -0
  61. package/dist/security/scan.js.map +1 -0
  62. package/dist/security/types.d.ts +146 -0
  63. package/dist/security/types.d.ts.map +1 -0
  64. package/dist/security/types.js +10 -0
  65. package/dist/security/types.js.map +1 -0
  66. package/dist/security/worker.d.ts +69 -0
  67. package/dist/security/worker.d.ts.map +1 -0
  68. package/dist/security/worker.js +228 -0
  69. package/dist/security/worker.js.map +1 -0
  70. package/dist/sync/source-paths.d.ts +1 -0
  71. package/dist/sync/source-paths.d.ts.map +1 -1
  72. package/dist/sync/source-paths.js +48 -6
  73. package/dist/sync/source-paths.js.map +1 -1
  74. package/dist/sync/syncer.d.ts +9 -1
  75. package/dist/sync/syncer.d.ts.map +1 -1
  76. package/dist/sync/syncer.js +128 -16
  77. package/dist/sync/syncer.js.map +1 -1
  78. package/dist/sync/watcher.d.ts.map +1 -1
  79. package/dist/sync/watcher.js +8 -2
  80. package/dist/sync/watcher.js.map +1 -1
  81. package/dist/types.d.ts +15 -1
  82. package/dist/types.d.ts.map +1 -1
  83. package/dist/util/resolve-bin.d.ts +34 -0
  84. package/dist/util/resolve-bin.d.ts.map +1 -1
  85. package/dist/util/resolve-bin.js +175 -20
  86. package/dist/util/resolve-bin.js.map +1 -1
  87. package/package.json +11 -2
@@ -0,0 +1,358 @@
1
+ import Database from 'better-sqlite3';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { stripSpoolSystemPrelude } from './spool-prelude.js';
4
+ export const OPENCODE_INDEX_VERSION = 'opencode-v3-session-model-json';
5
+ export const OPENCODE_DB_NAME = 'opencode.db';
6
+ const OPENCODE_SESSION_SEPARATOR = '#session=';
7
+ const OPENCODE_SUBAGENT_PARENT_PREFIX = 'opencode-subagent:';
8
+ const OPENCODE_SUBAGENT_HEADER_PREFIX = 'OpenCode subagent:';
9
+ // WAL/SHM/journal sidecars share the DB's basename + a suffix; watcher events on
10
+ // them must map back to the main file so commits append to -wal (whose writes the
11
+ // main file's mtime does not reflect until checkpoint) still trigger a re-index.
12
+ const OPENCODE_DB_SIDECAR_SUFFIXES = ['-wal', '-shm', '-journal'];
13
+ // Guards the recursive session-tree walks against pathological/corrupt parent
14
+ // chains. Real OpenCode trees are shallow (root → subagent → subagent); a cycle
15
+ // is unreachable from a NULL-parent root, but this bounds the walk regardless.
16
+ const OPENCODE_MAX_SESSION_DEPTH = 64;
17
+ const sessionMtimeCache = new Map();
18
+ export function makeOpenCodeSessionFilePath(dbPath, sessionId) {
19
+ return `${dbPath}${OPENCODE_SESSION_SEPARATOR}${encodeURIComponent(sessionId)}`;
20
+ }
21
+ export function parseOpenCodeSessionFilePath(filePath) {
22
+ const idx = filePath.lastIndexOf(OPENCODE_SESSION_SEPARATOR);
23
+ if (idx === -1)
24
+ return null;
25
+ const dbPath = filePath.slice(0, idx);
26
+ const encodedSessionId = filePath.slice(idx + OPENCODE_SESSION_SEPARATOR.length);
27
+ if (!dbPath || !encodedSessionId)
28
+ return null;
29
+ return { dbPath, sessionId: decodeURIComponent(encodedSessionId) };
30
+ }
31
+ export function isOpenCodeDatabaseFile(filePath) {
32
+ return basename(filePath) === OPENCODE_DB_NAME;
33
+ }
34
+ /**
35
+ * Map an OpenCode DB sidecar path (`opencode.db-wal` / `-shm` / `-journal`) back
36
+ * to the main `opencode.db`. Non-sidecar paths are returned unchanged. The watcher
37
+ * uses this so WAL-mode writes — which land in `-wal` and leave the main file's
38
+ * mtime stale until checkpoint — still schedule a re-index of the database.
39
+ */
40
+ export function normalizeOpenCodeWatchPath(filePath) {
41
+ const base = basename(filePath);
42
+ for (const suffix of OPENCODE_DB_SIDECAR_SUFFIXES) {
43
+ if (base === OPENCODE_DB_NAME + suffix) {
44
+ return join(dirname(filePath), OPENCODE_DB_NAME);
45
+ }
46
+ }
47
+ return filePath;
48
+ }
49
+ export function listOpenCodeSessionFilePaths(dbPath) {
50
+ const db = openOpenCodeDb(dbPath);
51
+ try {
52
+ const rows = db.prepare(`
53
+ WITH RECURSIVE active_sessions(id, root_id, time_updated, depth) AS (
54
+ SELECT id, id AS root_id, time_updated, 0 AS depth
55
+ FROM session
56
+ WHERE parent_id IS NULL AND time_archived IS NULL
57
+
58
+ UNION ALL
59
+
60
+ SELECT child.id, active_sessions.root_id, child.time_updated, active_sessions.depth + 1
61
+ FROM session child
62
+ JOIN active_sessions ON child.parent_id = active_sessions.id
63
+ WHERE child.time_archived IS NULL AND active_sessions.depth < ${OPENCODE_MAX_SESSION_DEPTH}
64
+ )
65
+ SELECT root_id AS id, MAX(time_updated) AS time_updated
66
+ FROM active_sessions
67
+ GROUP BY root_id
68
+ ORDER BY time_updated DESC, root_id DESC
69
+ `).all();
70
+ sessionMtimeCache.set(dbPath, new Map(rows.map(row => [row.id, row.time_updated])));
71
+ return rows.map(row => makeOpenCodeSessionFilePath(dbPath, row.id));
72
+ }
73
+ finally {
74
+ db.close();
75
+ }
76
+ }
77
+ export function getOpenCodeSessionIndexedMtime(filePath) {
78
+ const parsed = parseOpenCodeSessionFilePath(filePath);
79
+ if (!parsed) {
80
+ throw new Error(`OpenCode session path is missing ${OPENCODE_SESSION_SEPARATOR}: ${filePath}`);
81
+ }
82
+ const cached = sessionMtimeCache.get(parsed.dbPath)?.get(parsed.sessionId);
83
+ if (cached !== undefined)
84
+ return `${cached}::${OPENCODE_INDEX_VERSION}`;
85
+ const db = openOpenCodeDb(parsed.dbPath);
86
+ try {
87
+ const row = db.prepare(`
88
+ WITH RECURSIVE descendants(id, time_updated, depth) AS (
89
+ SELECT id, time_updated, 0 AS depth
90
+ FROM session
91
+ WHERE id = ? AND parent_id IS NULL AND time_archived IS NULL
92
+
93
+ UNION ALL
94
+
95
+ SELECT child.id, child.time_updated, descendants.depth + 1
96
+ FROM session child
97
+ JOIN descendants ON child.parent_id = descendants.id
98
+ WHERE child.time_archived IS NULL AND descendants.depth < ${OPENCODE_MAX_SESSION_DEPTH}
99
+ )
100
+ SELECT MAX(time_updated) AS time_updated
101
+ FROM descendants
102
+ `).get(parsed.sessionId);
103
+ if (!row?.time_updated)
104
+ throw new Error(`OpenCode parent session not found: ${parsed.sessionId}`);
105
+ return `${row.time_updated}::${OPENCODE_INDEX_VERSION}`;
106
+ }
107
+ finally {
108
+ db.close();
109
+ }
110
+ }
111
+ export function loadOpenCodeSession(filePath) {
112
+ const parsedPath = parseOpenCodeSessionFilePath(filePath);
113
+ if (!parsedPath)
114
+ return { kind: 'skipped' };
115
+ const db = openOpenCodeDb(parsedPath.dbPath);
116
+ try {
117
+ const session = db.prepare(`
118
+ SELECT id, parent_id, directory, title, time_created, time_updated, model, agent
119
+ FROM session
120
+ WHERE id = ? AND time_archived IS NULL
121
+ `).get(parsedPath.sessionId);
122
+ if (!session)
123
+ return { kind: 'filtered' };
124
+ // Subagent rows (parent_id set) are folded into their parent, never indexed
125
+ // standalone — surfacing them here would duplicate work already shown under
126
+ // the parent. listOpenCodeSessionFilePaths only ever yields root ids, so this
127
+ // guards the direct-load path (e.g. a stale indexed child path).
128
+ if (session.parent_id)
129
+ return { kind: 'filtered' };
130
+ let cwd = session.directory || '';
131
+ let model = normalizeModel(session.model);
132
+ const messages = loadMessagesForOpenCodeSession(db, session, {
133
+ sidechain: false,
134
+ onCwd: value => { if (!cwd)
135
+ cwd = value; },
136
+ onModel: value => { if (!model)
137
+ model = value; },
138
+ });
139
+ const childSessions = listOpenCodeChildSessions(db, session.id);
140
+ let endedAtMs = Math.max(session.time_updated, ...childSessions.map(child => child.time_updated));
141
+ for (const child of childSessions) {
142
+ const groupKey = `${OPENCODE_SUBAGENT_PARENT_PREFIX}${child.id}`;
143
+ const childMessages = loadMessagesForOpenCodeSession(db, child, {
144
+ sidechain: true,
145
+ uuidPrefix: `${child.id}:`,
146
+ parentUuid: groupKey,
147
+ });
148
+ if (childMessages.length === 0)
149
+ continue;
150
+ endedAtMs = Math.max(endedAtMs, child.time_updated);
151
+ messages.push(makeSubagentHeaderMessage(child, groupKey));
152
+ messages.push(...childMessages);
153
+ }
154
+ if (messages.length === 0)
155
+ return { kind: 'skipped' };
156
+ messages.sort(compareParsedMessages);
157
+ messages.forEach((message, index) => { message.seq = index; });
158
+ const firstUserMessage = messages.find(message => !message.isSidechain && message.role === 'user' && message.contentText.trim().length > 0);
159
+ const title = session.title?.trim()
160
+ || firstUserMessage?.contentText.replace(/<[^>]+>/g, '').trim().slice(0, 120)
161
+ || '(no title)';
162
+ return {
163
+ kind: 'parsed',
164
+ session: {
165
+ source: 'opencode',
166
+ sessionUuid: session.id,
167
+ filePath,
168
+ title,
169
+ cwd,
170
+ model,
171
+ startedAt: toIso(session.time_created),
172
+ endedAt: toIso(endedAtMs),
173
+ messages,
174
+ },
175
+ };
176
+ }
177
+ finally {
178
+ db.close();
179
+ }
180
+ }
181
+ export function parseOpenCodeSession(filePath) {
182
+ try {
183
+ const result = loadOpenCodeSession(filePath);
184
+ return result.kind === 'parsed' ? result.session : null;
185
+ }
186
+ catch {
187
+ return null;
188
+ }
189
+ }
190
+ function openOpenCodeDb(dbPath) {
191
+ const db = new Database(dbPath, { readonly: true, fileMustExist: true });
192
+ // OpenCode may hold a write lock while checkpointing the WAL; wait briefly
193
+ // instead of throwing SQLITE_BUSY and churning the sync error log.
194
+ db.pragma('busy_timeout = 5000');
195
+ return db;
196
+ }
197
+ function groupPartsByMessage(partRows) {
198
+ const byMessage = new Map();
199
+ for (const row of partRows) {
200
+ const list = byMessage.get(row.message_id) ?? [];
201
+ list.push(row);
202
+ byMessage.set(row.message_id, list);
203
+ }
204
+ return byMessage;
205
+ }
206
+ function listOpenCodeChildSessions(db, sessionId) {
207
+ return db.prepare(`
208
+ WITH RECURSIVE child_sessions(
209
+ id, parent_id, directory, title, time_created, time_updated, model, agent, depth
210
+ ) AS (
211
+ SELECT id, parent_id, directory, title, time_created, time_updated, model, agent, 1 AS depth
212
+ FROM session
213
+ WHERE parent_id = ? AND time_archived IS NULL
214
+
215
+ UNION ALL
216
+
217
+ SELECT child.id, child.parent_id, child.directory, child.title, child.time_created,
218
+ child.time_updated, child.model, child.agent, child_sessions.depth + 1
219
+ FROM session child
220
+ JOIN child_sessions ON child.parent_id = child_sessions.id
221
+ WHERE child.time_archived IS NULL AND child_sessions.depth < ${OPENCODE_MAX_SESSION_DEPTH}
222
+ )
223
+ SELECT id, parent_id, directory, title, time_created, time_updated, model, agent
224
+ FROM child_sessions
225
+ ORDER BY time_created ASC, depth ASC, id ASC
226
+ `).all(sessionId);
227
+ }
228
+ function loadMessagesForOpenCodeSession(db, session, opts) {
229
+ const messageRows = db.prepare(`
230
+ SELECT id, time_created, data
231
+ FROM message
232
+ WHERE session_id = ?
233
+ ORDER BY time_created ASC, id ASC
234
+ `).all(session.id);
235
+ if (messageRows.length === 0)
236
+ return [];
237
+ const partRows = db.prepare(`
238
+ SELECT id, message_id, time_created, data
239
+ FROM part
240
+ WHERE session_id = ?
241
+ ORDER BY message_id ASC, time_created ASC, id ASC
242
+ `).all(session.id);
243
+ const partsByMessage = groupPartsByMessage(partRows);
244
+ const messages = [];
245
+ for (const messageRow of messageRows) {
246
+ const messageData = parseJson(messageRow.data);
247
+ if (!messageData)
248
+ continue;
249
+ const role = messageData.role;
250
+ if (role !== 'user' && role !== 'assistant')
251
+ continue;
252
+ const cwd = messageData.path?.cwd ?? messageData.path?.root;
253
+ if (cwd)
254
+ opts.onCwd?.(cwd);
255
+ const model = modelFromMessage(messageData);
256
+ if (model)
257
+ opts.onModel?.(model);
258
+ const parts = (partsByMessage.get(messageRow.id) ?? [])
259
+ .map(part => parseJson(part.data))
260
+ .filter((part) => Boolean(part));
261
+ const contentText = extractText(parts);
262
+ const toolNames = extractToolNames(parts);
263
+ if (!contentText && toolNames.length === 0)
264
+ continue;
265
+ messages.push({
266
+ uuid: `${opts.uuidPrefix ?? ''}${messageRow.id}`,
267
+ parentUuid: opts.parentUuid ?? messageData.parentID ?? null,
268
+ role,
269
+ contentText,
270
+ timestamp: toIso(messageRow.time_created),
271
+ isSidechain: opts.sidechain,
272
+ toolNames,
273
+ seq: messages.length,
274
+ });
275
+ }
276
+ return messages;
277
+ }
278
+ function makeSubagentHeaderMessage(session, groupKey) {
279
+ const title = session.title?.trim() || session.id;
280
+ const agent = session.agent?.trim();
281
+ const label = agent ? `@${agent} · ${title}` : title;
282
+ return {
283
+ uuid: `${session.id}:header`,
284
+ parentUuid: groupKey,
285
+ role: 'system',
286
+ contentText: `${OPENCODE_SUBAGENT_HEADER_PREFIX} ${label}`,
287
+ timestamp: toIso(session.time_created),
288
+ isSidechain: true,
289
+ toolNames: agent ? [agent] : [],
290
+ seq: 0,
291
+ };
292
+ }
293
+ function compareParsedMessages(a, b) {
294
+ const byTimestamp = a.timestamp.localeCompare(b.timestamp);
295
+ if (byTimestamp !== 0)
296
+ return byTimestamp;
297
+ if (a.isSidechain !== b.isSidechain)
298
+ return a.isSidechain ? 1 : -1;
299
+ return a.uuid.localeCompare(b.uuid);
300
+ }
301
+ function extractText(parts) {
302
+ return stripSpoolSystemPrelude(parts
303
+ .filter(part => part.type === 'text' && typeof part.text === 'string')
304
+ .map(part => part.text ?? '')
305
+ .join('\n'))
306
+ .trim();
307
+ }
308
+ function extractToolNames(parts) {
309
+ return Array.from(new Set(parts
310
+ .filter(part => part.type === 'tool' && typeof part.tool === 'string' && part.tool.trim().length > 0)
311
+ .map(part => part.tool)));
312
+ }
313
+ function modelFromMessage(message) {
314
+ const providerId = message.model?.providerID ?? message.providerID;
315
+ const modelId = message.model?.modelID ?? message.modelID;
316
+ if (providerId && modelId)
317
+ return `${providerId}/${modelId}`;
318
+ return modelId ?? '';
319
+ }
320
+ // OpenCode stores `session.model` as a serialized JSON object
321
+ // (`{"id","providerID","variant"?}`), not a plain string — so trim alone would
322
+ // leak raw JSON into the model field. Parse it into the same `provider/model`
323
+ // shape modelFromMessage produces; fall back to the trimmed string for any
324
+ // non-JSON or unparseable value.
325
+ function normalizeModel(model) {
326
+ if (!model)
327
+ return '';
328
+ const trimmed = model.trim();
329
+ if (!trimmed.startsWith('{'))
330
+ return trimmed;
331
+ const parsed = parseJson(trimmed);
332
+ if (!parsed)
333
+ return trimmed;
334
+ const providerId = parsed.providerID;
335
+ const modelId = parsed.modelID ?? parsed.id;
336
+ if (providerId && modelId)
337
+ return `${providerId}/${modelId}`;
338
+ return modelId ?? '';
339
+ }
340
+ function parseJson(raw) {
341
+ try {
342
+ return JSON.parse(raw);
343
+ }
344
+ catch {
345
+ return null;
346
+ }
347
+ }
348
+ function toIso(ms) {
349
+ const date = new Date(ms);
350
+ return Number.isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString();
351
+ }
352
+ export function openCodeDbPathFromSessionPath(filePath) {
353
+ return parseOpenCodeSessionFilePath(filePath)?.dbPath ?? filePath;
354
+ }
355
+ export function openCodeDbDisplayPath(filePath) {
356
+ return dirname(openCodeDbPathFromSessionPath(filePath));
357
+ }
358
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/parsers/opencode.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,40 @@
1
1
  import type Database from 'better-sqlite3';
2
2
  import type { Session, SessionSource } from '../types.js';
3
3
  export type ProjectSessionSortOrder = 'recent' | 'oldest' | 'most_messages' | 'title';
4
+ export type SessionsCursor = {
5
+ startedAt: string;
6
+ sessionUuid: string;
7
+ messageCount: number;
8
+ title: string;
9
+ };
10
+ export type SessionsPage = {
11
+ sessions: Session[];
12
+ nextCursor: SessionsCursor | null;
13
+ };
4
14
  export interface ListSessionsByIdentityOptions {
5
15
  sources?: SessionSource[];
6
16
  sortOrder?: ProjectSessionSortOrder;
7
17
  limit?: number;
8
18
  excludePinned?: boolean;
19
+ cursor?: SessionsCursor;
9
20
  }
10
- export declare function listSessionsByIdentity(db: Database.Database, identityKey: string, options?: ListSessionsByIdentityOptions): Session[];
21
+ export declare function listSessionsByIdentity(db: Database.Database, identityKey: string, options?: ListSessionsByIdentityOptions): SessionsPage;
22
+ export declare function listRecentSessionsPage(db: Database.Database, options?: {
23
+ limit?: number;
24
+ cursor?: SessionsCursor;
25
+ }): SessionsPage;
26
+ export type DirectoryCount = {
27
+ cwd: string;
28
+ sessionCount: number;
29
+ lastSessionAt: string;
30
+ };
31
+ /**
32
+ * Per-cwd counts across the full project. Drives the chip strip's badges
33
+ * so they show the true distribution rather than just the loaded page.
34
+ * Honors the same `sources` filter as `listSessionsByIdentity`.
35
+ */
36
+ export declare function listProjectDirectoryCounts(db: Database.Database, identityKey: string, options?: {
37
+ sources?: SessionSource[];
38
+ }): DirectoryCount[];
11
39
  export declare function listPinnedSessionsByIdentity(db: Database.Database, identityKey: string): Session[];
12
40
  //# sourceMappingURL=sessions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGzD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAA;AAErF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,uBAAuB,CAAA;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,EAAE,CA2BX;AAED,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,EAAE,CAQX"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGzD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAA;AAErF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,EAAE,cAAc,GAAG,IAAI,CAAA;CAClC,CAAA;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,uBAAuB,CAAA;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAID,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,6BAAkC,GAC1C,YAAY,CA6Bd;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,cAAc,CAAA;CAAO,GACxD,YAAY,CAUd;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;CAAO,GAC1C,cAAc,EAAE,CAuBlB;AAED,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,EAAE,CAQX"}
@@ -1,6 +1,7 @@
1
1
  import { SESSION_SELECT, rowToSession } from '../db/queries.js';
2
+ const DEFAULT_PAGE_SIZE = 50;
2
3
  export function listSessionsByIdentity(db, identityKey, options = {}) {
3
- const { sources, sortOrder = 'recent', limit = 500, excludePinned = false } = options;
4
+ const { sources, sortOrder = 'recent', limit = DEFAULT_PAGE_SIZE, excludePinned = false, cursor, } = options;
4
5
  const conditions = ['p.identity_key = ?', 's.message_count > 0'];
5
6
  const params = [identityKey];
6
7
  if (sources && sources.length > 0) {
@@ -11,16 +12,52 @@ export function listSessionsByIdentity(db, identityKey, options = {}) {
11
12
  if (excludePinned) {
12
13
  conditions.push('NOT EXISTS (SELECT 1 FROM pins WHERE pins.session_uuid = s.session_uuid)');
13
14
  }
14
- const orderBy = orderByClause(sortOrder);
15
+ if (cursor) {
16
+ const c = cursorWhere(sortOrder, cursor);
17
+ conditions.push(c.sql);
18
+ params.push(...c.params);
19
+ }
20
+ return executePage(db, conditions, params, sortOrder, limit);
21
+ }
22
+ export function listRecentSessionsPage(db, options = {}) {
23
+ const { limit = DEFAULT_PAGE_SIZE, cursor } = options;
24
+ const conditions = ['s.message_count > 0'];
25
+ const params = [];
26
+ if (cursor) {
27
+ const c = cursorWhere('recent', cursor);
28
+ conditions.push(c.sql);
29
+ params.push(...c.params);
30
+ }
31
+ return executePage(db, conditions, params, 'recent', limit);
32
+ }
33
+ /**
34
+ * Per-cwd counts across the full project. Drives the chip strip's badges
35
+ * so they show the true distribution rather than just the loaded page.
36
+ * Honors the same `sources` filter as `listSessionsByIdentity`.
37
+ */
38
+ export function listProjectDirectoryCounts(db, identityKey, options = {}) {
39
+ const { sources } = options;
40
+ const conditions = ['p.identity_key = ?', 's.message_count > 0'];
41
+ const params = [identityKey];
42
+ if (sources && sources.length > 0) {
43
+ const placeholders = sources.map(() => '?').join(',');
44
+ conditions.push(`src.name IN (${placeholders})`);
45
+ params.push(...sources);
46
+ }
15
47
  const sql = `
16
- ${SESSION_SELECT}
48
+ SELECT
49
+ COALESCE(NULLIF(s.cwd, ''), '(unknown)') AS cwd,
50
+ COUNT(*) AS cnt,
51
+ MAX(s.started_at) AS last_at
52
+ FROM sessions s
53
+ JOIN sources src ON src.id = s.source_id
54
+ JOIN projects p ON p.id = s.project_id
17
55
  WHERE ${conditions.join(' AND ')}
18
- ORDER BY ${orderBy}
19
- LIMIT ?
56
+ GROUP BY cwd
57
+ ORDER BY MAX(s.started_at) DESC
20
58
  `;
21
- params.push(limit);
22
59
  const rows = db.prepare(sql).all(...params);
23
- return rows.map(rowToSession);
60
+ return rows.map(r => ({ cwd: r.cwd, sessionCount: r.cnt, lastSessionAt: r.last_at }));
24
61
  }
25
62
  export function listPinnedSessionsByIdentity(db, identityKey) {
26
63
  const rows = db.prepare(`
@@ -31,17 +68,84 @@ export function listPinnedSessionsByIdentity(db, identityKey) {
31
68
  `).all(identityKey);
32
69
  return rows.map(rowToSession);
33
70
  }
71
+ function executePage(db, conditions, params, sortOrder, limit) {
72
+ const sql = `
73
+ ${SESSION_SELECT}
74
+ WHERE ${conditions.join(' AND ')}
75
+ ORDER BY ${orderByClause(sortOrder)}
76
+ LIMIT ?
77
+ `;
78
+ // Fetch limit+1 so we can detect "more rows exist" without a count query.
79
+ const rows = db.prepare(sql).all(...params, limit + 1);
80
+ const hasMore = rows.length > limit;
81
+ const pageRows = hasMore ? rows.slice(0, limit) : rows;
82
+ const sessions = pageRows.map(rowToSession);
83
+ const last = sessions.at(-1);
84
+ const nextCursor = hasMore && last
85
+ ? {
86
+ startedAt: last.startedAt,
87
+ sessionUuid: last.sessionUuid,
88
+ messageCount: last.messageCount,
89
+ title: last.title ?? '',
90
+ }
91
+ : null;
92
+ return { sessions, nextCursor };
93
+ }
34
94
  function orderByClause(sortOrder) {
95
+ // session_uuid is the unique tiebreaker so the page boundary is deterministic
96
+ // and keyset pagination skips exactly the rows already shown.
97
+ switch (sortOrder) {
98
+ case 'oldest':
99
+ return 's.started_at ASC, s.session_uuid ASC';
100
+ case 'most_messages':
101
+ return 's.message_count DESC, s.started_at DESC, s.session_uuid ASC';
102
+ case 'title':
103
+ return "COALESCE(NULLIF(s.title, ''), '') ASC, s.started_at DESC, s.session_uuid ASC";
104
+ case 'recent':
105
+ default:
106
+ return 's.started_at DESC, s.session_uuid ASC';
107
+ }
108
+ }
109
+ function cursorWhere(sortOrder, c) {
110
+ const titleExpr = "COALESCE(NULLIF(s.title, ''), '')";
35
111
  switch (sortOrder) {
36
112
  case 'oldest':
37
- return 's.started_at ASC';
113
+ return {
114
+ sql: '(s.started_at > ? OR (s.started_at = ? AND s.session_uuid > ?))',
115
+ params: [c.startedAt, c.startedAt, c.sessionUuid],
116
+ };
38
117
  case 'most_messages':
39
- return 's.message_count DESC, s.started_at DESC';
118
+ return {
119
+ sql: `(
120
+ s.message_count < ?
121
+ OR (s.message_count = ? AND s.started_at < ?)
122
+ OR (s.message_count = ? AND s.started_at = ? AND s.session_uuid > ?)
123
+ )`,
124
+ params: [
125
+ c.messageCount,
126
+ c.messageCount, c.startedAt,
127
+ c.messageCount, c.startedAt, c.sessionUuid,
128
+ ],
129
+ };
40
130
  case 'title':
41
- return 'COALESCE(NULLIF(s.title, \'\'), \'\') ASC, s.started_at DESC';
131
+ return {
132
+ sql: `(
133
+ ${titleExpr} > ?
134
+ OR (${titleExpr} = ? AND s.started_at < ?)
135
+ OR (${titleExpr} = ? AND s.started_at = ? AND s.session_uuid > ?)
136
+ )`,
137
+ params: [
138
+ c.title,
139
+ c.title, c.startedAt,
140
+ c.title, c.startedAt, c.sessionUuid,
141
+ ],
142
+ };
42
143
  case 'recent':
43
144
  default:
44
- return 's.started_at DESC';
145
+ return {
146
+ sql: '(s.started_at < ? OR (s.started_at = ? AND s.session_uuid > ?))',
147
+ params: [c.startedAt, c.startedAt, c.sessionUuid],
148
+ };
45
149
  }
46
150
  }
47
151
  //# sourceMappingURL=sessions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAW/D,MAAM,UAAU,sBAAsB,CACpC,EAAqB,EACrB,WAAmB,EACnB,UAAyC,EAAE;IAE3C,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,QAAQ,EAAE,KAAK,GAAG,GAAG,EAAE,aAAa,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IAErF,MAAM,UAAU,GAAa,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAc,CAAC,WAAW,CAAC,CAAA;IAEvC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACrD,UAAU,CAAC,IAAI,CAAC,gBAAgB,YAAY,GAAG,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG;MACR,cAAc;YACR,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;eACrB,OAAO;;GAEnB,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAElB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAmC,CAAA;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,EAAqB,EACrB,WAAmB;IAEnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;MACpB,cAAc;;;;GAIjB,CAAC,CAAC,GAAG,CAAC,WAAW,CAAmC,CAAA;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,aAAa,CAAC,SAAkC;IACvD,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAA;QAC3B,KAAK,eAAe;YAClB,OAAO,yCAAyC,CAAA;QAClD,KAAK,OAAO;YACV,OAAO,8DAA8D,CAAA;QACvE,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,mBAAmB,CAAA;IAC9B,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type { FindingState, FindingRow, SessionWithFindingCounts, RiskByCategoryRow, OccurrenceBySession, DismissScope, FindingsChange, ScanStatus, } from './types.js';
2
+ export { REDACT_DETECTOR_VERSION, currentProfileString, parseProfile, profilesMatch, providersInProfile, } from './profile.js';
3
+ export type { ProfileOpts, ParsedProfile } from './profile.js';
4
+ export { insertFindings, deleteActiveFindings, deleteRefreshableFindings, updateSessionCounts, setSessionScanProfile, invalidateAllScanProfiles, invalidateSessionScanProfile, listSessionsNeedingScan, listFindings, listFindingsPage, listSessionsWithFindings, listSessionsWithFindingsPage, countSessionsWithFindings, occurrencesByValueHash, riskByCategory, lastScanCompletedAt, getFindingValue, getFindingValues, getAllowlists, isAllowlisted, addAllowlistSession, addAllowlistGlobal, removeAllowlistSession, removeAllowlistGlobal, listAllowlistEntries, countAllowlistEntries, dismissFinding, dismissFindings, undismissFinding, } from './repo.js';
5
+ export type { FindingFilter, SessionFindingFilter, FindingInput, AllowlistEntryRow, AllowlistSnapshot, Page, } from './repo.js';
6
+ export { scanSession, ScanError } from './scan.js';
7
+ export type { ScanResult, ScanSessionDeps } from './scan.js';
8
+ export { purgeFinding, purgeFindings, purgeEverywhere, orderForBulkPurge, PurgeError } from './purge.js';
9
+ export type { PurgeResult, PurgeDeps } from './purge.js';
10
+ export { makeScanWorker, waitForIdle } from './worker.js';
11
+ export type { ScanWorker, WorkerConfig } from './worker.js';
12
+ export { listBackups, deleteBackups, backupDirFor } from './maintenance.js';
13
+ export type { BackupFileInfo, DeleteBackupsResult, } from './maintenance.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,UAAU,EACV,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,kBAAkB,GACnB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,IAAI,GACL,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAClD,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE5D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACxG,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAExD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE3D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC3E,YAAY,EACV,cAAc,EACd,mBAAmB,GACpB,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,7 @@
1
+ export { REDACT_DETECTOR_VERSION, currentProfileString, parseProfile, profilesMatch, providersInProfile, } from './profile.js';
2
+ export { insertFindings, deleteActiveFindings, deleteRefreshableFindings, updateSessionCounts, setSessionScanProfile, invalidateAllScanProfiles, invalidateSessionScanProfile, listSessionsNeedingScan, listFindings, listFindingsPage, listSessionsWithFindings, listSessionsWithFindingsPage, countSessionsWithFindings, occurrencesByValueHash, riskByCategory, lastScanCompletedAt, getFindingValue, getFindingValues, getAllowlists, isAllowlisted, addAllowlistSession, addAllowlistGlobal, removeAllowlistSession, removeAllowlistGlobal, listAllowlistEntries, countAllowlistEntries, dismissFinding, dismissFindings, undismissFinding, } from './repo.js';
3
+ export { scanSession, ScanError } from './scan.js';
4
+ export { purgeFinding, purgeFindings, purgeEverywhere, orderForBulkPurge, PurgeError } from './purge.js';
5
+ export { makeScanWorker, waitForIdle } from './worker.js';
6
+ export { listBackups, deleteBackups, backupDirFor } from './maintenance.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,kBAAkB,GACnB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,EAChB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAUlB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGlD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGxG,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type Database from 'better-sqlite3';
2
+ export interface BackupFileInfo {
3
+ name: string;
4
+ sizeBytes: number;
5
+ mtimeMs: number;
6
+ kind: 'auto' | 'manual';
7
+ }
8
+ export interface DeleteBackupsResult {
9
+ deleted: number;
10
+ bytesFreed: number;
11
+ }
12
+ export declare function backupDirFor(db: Database.Database): string | null;
13
+ export declare function listBackups(db: Database.Database): BackupFileInfo[];
14
+ export declare function deleteBackups(db: Database.Database, names: readonly string[]): DeleteBackupsResult;
15
+ //# sourceMappingURL=maintenance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/security/maintenance.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAS1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,GAAG,IAAI,CAKjE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,cAAc,EAAE,CAsBnE;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,mBAAmB,CAwBrB"}