@husk-ai/sessions 0.1.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.
Files changed (69) hide show
  1. package/dist/chat.d.ts +11 -0
  2. package/dist/chat.d.ts.map +1 -0
  3. package/dist/chat.js +2 -0
  4. package/dist/chat.js.map +1 -0
  5. package/dist/distill.d.ts +130 -0
  6. package/dist/distill.d.ts.map +1 -0
  7. package/dist/distill.js +773 -0
  8. package/dist/distill.js.map +1 -0
  9. package/dist/distiller.d.ts +18 -0
  10. package/dist/distiller.d.ts.map +1 -0
  11. package/dist/distiller.js +23 -0
  12. package/dist/distiller.js.map +1 -0
  13. package/dist/formatter.d.ts +8 -0
  14. package/dist/formatter.d.ts.map +1 -0
  15. package/dist/formatter.js +11 -0
  16. package/dist/formatter.js.map +1 -0
  17. package/dist/importers/chatgpt.d.ts +12 -0
  18. package/dist/importers/chatgpt.d.ts.map +1 -0
  19. package/dist/importers/chatgpt.js +223 -0
  20. package/dist/importers/chatgpt.js.map +1 -0
  21. package/dist/importers/claude.d.ts +37 -0
  22. package/dist/importers/claude.d.ts.map +1 -0
  23. package/dist/importers/claude.js +512 -0
  24. package/dist/importers/claude.js.map +1 -0
  25. package/dist/importers/cursor.d.ts +12 -0
  26. package/dist/importers/cursor.d.ts.map +1 -0
  27. package/dist/importers/cursor.js +229 -0
  28. package/dist/importers/cursor.js.map +1 -0
  29. package/dist/importers/fsutil.d.ts +22 -0
  30. package/dist/importers/fsutil.d.ts.map +1 -0
  31. package/dist/importers/fsutil.js +79 -0
  32. package/dist/importers/fsutil.js.map +1 -0
  33. package/dist/importers/gemini.d.ts +13 -0
  34. package/dist/importers/gemini.d.ts.map +1 -0
  35. package/dist/importers/gemini.js +228 -0
  36. package/dist/importers/gemini.js.map +1 -0
  37. package/dist/importers/index.d.ts +70 -0
  38. package/dist/importers/index.d.ts.map +1 -0
  39. package/dist/importers/index.js +258 -0
  40. package/dist/importers/index.js.map +1 -0
  41. package/dist/importers/markdown.d.ts +14 -0
  42. package/dist/importers/markdown.d.ts.map +1 -0
  43. package/dist/importers/markdown.js +188 -0
  44. package/dist/importers/markdown.js.map +1 -0
  45. package/dist/importers/universal.d.ts +16 -0
  46. package/dist/importers/universal.d.ts.map +1 -0
  47. package/dist/importers/universal.js +106 -0
  48. package/dist/importers/universal.js.map +1 -0
  49. package/dist/index.d.ts +17 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +16 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/prompts.d.ts +151 -0
  54. package/dist/prompts.d.ts.map +1 -0
  55. package/dist/prompts.js +109 -0
  56. package/dist/prompts.js.map +1 -0
  57. package/dist/redactor.d.ts +38 -0
  58. package/dist/redactor.d.ts.map +1 -0
  59. package/dist/redactor.js +144 -0
  60. package/dist/redactor.js.map +1 -0
  61. package/dist/scaffold.d.ts +40 -0
  62. package/dist/scaffold.d.ts.map +1 -0
  63. package/dist/scaffold.js +0 -0
  64. package/dist/scaffold.js.map +1 -0
  65. package/dist/serialize.d.ts +15 -0
  66. package/dist/serialize.d.ts.map +1 -0
  67. package/dist/serialize.js +122 -0
  68. package/dist/serialize.js.map +1 -0
  69. package/package.json +28 -0
@@ -0,0 +1,229 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { HuskError, id } from '@husk-ai/core';
5
+ import { isDirectory, listFiles } from './fsutil.js';
6
+ /**
7
+ * Cursor chat history.
8
+ *
9
+ * Cursor keeps chats inside VS Code's `state.vscdb`, which is SQLite. Husk
10
+ * forbids native modules, so there is no SQLite driver here and there will not
11
+ * be one. What this importer does instead:
12
+ *
13
+ * - parses Cursor's own JSON/markdown chat exports properly, and
14
+ * - for a raw `state.vscdb`, scans the file for the embedded JSON blobs Cursor
15
+ * stores as text values and parses the ones that are complete.
16
+ *
17
+ * The second path is best-effort and says so. It recovers whole chats when the
18
+ * blob is not spread across SQLite overflow pages, and recovers nothing when it
19
+ * is -- it never invents a partial conversation.
20
+ */
21
+ function isRecord(v) {
22
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
23
+ }
24
+ function asString(v) {
25
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
26
+ }
27
+ /** Cursor encodes the speaker as `type: 1` (user) / `type: 2` (assistant). */
28
+ function bubbleRole(bubble) {
29
+ if (bubble.type === 1)
30
+ return 'user';
31
+ if (bubble.type === 2)
32
+ return 'assistant';
33
+ const t = asString(bubble.type) ?? asString(bubble.role) ?? asString(bubble.author);
34
+ switch ((t ?? '').toLowerCase()) {
35
+ case 'assistant':
36
+ case 'ai':
37
+ case 'bot':
38
+ return 'assistant';
39
+ case 'system':
40
+ return 'system';
41
+ case 'tool':
42
+ return 'tool';
43
+ default:
44
+ return 'user';
45
+ }
46
+ }
47
+ function bubbleText(bubble) {
48
+ const direct = asString(bubble.text) ?? asString(bubble.rawText) ?? asString(bubble.content) ?? asString(bubble.message);
49
+ if (direct)
50
+ return direct;
51
+ if (Array.isArray(bubble.parts)) {
52
+ return bubble.parts
53
+ .map((p) => (typeof p === 'string' ? p : isRecord(p) ? (asString(p.text) ?? '') : ''))
54
+ .filter(Boolean)
55
+ .join('\n');
56
+ }
57
+ return '';
58
+ }
59
+ function bubblesToMessages(bubbles) {
60
+ const out = [];
61
+ for (const b of bubbles) {
62
+ if (!isRecord(b))
63
+ continue;
64
+ const text = bubbleText(b).trim();
65
+ const toolName = asString(b.toolName) ?? (isRecord(b.toolFormerData) ? asString(b.toolFormerData.name) : undefined);
66
+ if (!text && !toolName)
67
+ continue;
68
+ const ts = typeof b.timestamp === 'number' ? new Date(b.timestamp).toISOString() : asString(b.timestamp);
69
+ out.push({
70
+ role: toolName ? 'tool' : bubbleRole(b),
71
+ content: text,
72
+ ...(ts ? { ts } : {}),
73
+ ...(toolName ? { toolName } : {}),
74
+ });
75
+ }
76
+ return out;
77
+ }
78
+ /** Walk any shape and pull out things that look like a Cursor conversation. */
79
+ function collectConversations(root, origin) {
80
+ const out = [];
81
+ const seen = new Set();
82
+ const visit = (node, depth) => {
83
+ if (depth > 12 || !node || typeof node !== 'object' || seen.has(node))
84
+ return;
85
+ seen.add(node);
86
+ if (Array.isArray(node)) {
87
+ for (const item of node)
88
+ visit(item, depth + 1);
89
+ return;
90
+ }
91
+ const rec = node;
92
+ for (const key of ['bubbles', 'conversation', 'messages', 'richText']) {
93
+ const value = rec[key];
94
+ if (!Array.isArray(value))
95
+ continue;
96
+ const messages = bubblesToMessages(value);
97
+ if (messages.length >= 2) {
98
+ out.push({
99
+ id: asString(rec.composerId) ?? asString(rec.tabId) ?? asString(rec.id) ?? id('cursor'),
100
+ source: 'cursor',
101
+ messages,
102
+ ...(asString(rec.name) ?? asString(rec.title)
103
+ ? { title: (asString(rec.name) ?? asString(rec.title)) }
104
+ : {}),
105
+ ...(origin ? { origin } : {}),
106
+ });
107
+ return;
108
+ }
109
+ }
110
+ for (const value of Object.values(rec))
111
+ visit(value, depth + 1);
112
+ };
113
+ visit(root, 0);
114
+ return out;
115
+ }
116
+ /** Pull balanced JSON objects out of a binary blob. Only complete ones survive. */
117
+ function salvageJsonObjects(text, max = 400) {
118
+ const out = [];
119
+ const anchors = /\{"(?:composerId|tabs|conversation|bubbles|richText)"/g;
120
+ let m;
121
+ while ((m = anchors.exec(text)) !== null && out.length < max) {
122
+ let depth = 0;
123
+ let inString = false;
124
+ let escaped = false;
125
+ let end = -1;
126
+ for (let i = m.index; i < text.length && i - m.index < 8_000_000; i++) {
127
+ const ch = text[i];
128
+ if (escaped) {
129
+ escaped = false;
130
+ continue;
131
+ }
132
+ if (ch === '\\') {
133
+ escaped = true;
134
+ continue;
135
+ }
136
+ if (ch === '"')
137
+ inString = !inString;
138
+ if (inString)
139
+ continue;
140
+ if (ch === '{')
141
+ depth++;
142
+ else if (ch === '}') {
143
+ depth--;
144
+ if (depth === 0) {
145
+ end = i + 1;
146
+ break;
147
+ }
148
+ }
149
+ }
150
+ if (end < 0)
151
+ continue;
152
+ try {
153
+ out.push(JSON.parse(text.slice(m.index, end)));
154
+ }
155
+ catch {
156
+ // Truncated by a SQLite overflow page boundary. Nothing recoverable here.
157
+ }
158
+ }
159
+ return out;
160
+ }
161
+ export class CursorImporter {
162
+ id = 'cursor';
163
+ displayName = 'Cursor chat';
164
+ async detect(input) {
165
+ try {
166
+ const path = input.path?.replace(/\\/g, '/').toLowerCase();
167
+ let score = 0;
168
+ if (path?.endsWith('.vscdb'))
169
+ score = path.includes('cursor') ? 0.85 : 0.5;
170
+ else if (path?.includes('/cursor/') && path.endsWith('.json'))
171
+ score = 0.6;
172
+ const probe = input.content?.slice(0, 64 * 1024);
173
+ if (probe) {
174
+ if (probe.startsWith('SQLite format 3'))
175
+ score = Math.max(score, 0.55);
176
+ const markers = [/"composerId"/, /"bubbles"/, /"toolFormerData"/, /"richText"/, /"composerData"/].filter((re) => re.test(probe)).length;
177
+ if (markers >= 2)
178
+ score = Math.max(score, 0.9);
179
+ else if (markers === 1)
180
+ score = Math.max(score, 0.55);
181
+ }
182
+ return score;
183
+ }
184
+ catch {
185
+ return 0;
186
+ }
187
+ }
188
+ async parse(input) {
189
+ let content = input.content;
190
+ if (content === undefined) {
191
+ if (!input.path) {
192
+ throw new HuskError('E_IMPORT_FAILED', 'Cursor import needs a path or content.', {
193
+ hint: 'Point it at a Cursor chat export, or at globalStorage/state.vscdb.',
194
+ });
195
+ }
196
+ const files = (await isDirectory(input.path))
197
+ ? [...(await listFiles(input.path, '.json')), ...(await listFiles(input.path, '.vscdb'))]
198
+ : [input.path];
199
+ const all = [];
200
+ for (const f of files)
201
+ all.push(...(await this.parse({ path: f, content: await readFile(f, 'latin1') })));
202
+ return all;
203
+ }
204
+ const origin = input.path;
205
+ const binary = content.startsWith('SQLite format 3');
206
+ if (!binary) {
207
+ try {
208
+ return collectConversations(JSON.parse(content), origin);
209
+ }
210
+ catch {
211
+ // Not JSON. Fall through to the salvage path, which handles the case
212
+ // where a JSON blob is embedded in something else.
213
+ }
214
+ }
215
+ return collectConversations(salvageJsonObjects(content), origin);
216
+ }
217
+ defaultLocations() {
218
+ const home = homedir();
219
+ if (process.platform === 'win32') {
220
+ const appData = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
221
+ return [join(appData, 'Cursor', 'User', 'globalStorage')];
222
+ }
223
+ if (process.platform === 'darwin') {
224
+ return [join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage')];
225
+ }
226
+ return [join(home, '.config', 'Cursor', 'User', 'globalStorage')];
227
+ }
228
+ }
229
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/importers/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** A stat plus the first and last N bytes. Never reads the middle of a big file. */
2
+ export interface HeadTail {
3
+ path: string;
4
+ size: number;
5
+ mtime: Date;
6
+ head: string;
7
+ tail: string;
8
+ /** true when head + tail together cover the whole file, so counts are exact. */
9
+ complete: boolean;
10
+ }
11
+ export declare const DEFAULT_WINDOW: number;
12
+ export declare function readHeadTail(path: string, windowBytes?: number): Promise<HeadTail>;
13
+ /**
14
+ * Whole lines only. A window read almost always starts and ends mid-line, and a
15
+ * half-line of JSON is worse than no line at all.
16
+ */
17
+ export declare function wholeLines(chunk: string, dropFirst: boolean, dropLast: boolean): string[];
18
+ export declare function listFiles(dir: string, ext: string): Promise<string[]>;
19
+ export declare function listDirs(dir: string): Promise<string[]>;
20
+ export declare function isDirectory(path: string): Promise<boolean>;
21
+ export declare function exists(path: string): Promise<boolean>;
22
+ //# sourceMappingURL=fsutil.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsutil.d.ts","sourceRoot":"","sources":["../../src/importers/fsutil.ts"],"names":[],"mappings":"AAGA,oFAAoF;AACpF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,QAAY,CAAC;AAExC,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,SAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0BhG;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAKzF;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO3E;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO7D;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMhE;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3D"}
@@ -0,0 +1,79 @@
1
+ import { open, stat, readdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export const DEFAULT_WINDOW = 96 * 1024;
4
+ export async function readHeadTail(path, windowBytes = DEFAULT_WINDOW) {
5
+ const st = await stat(path);
6
+ const size = st.size;
7
+ const fh = await open(path, 'r');
8
+ try {
9
+ if (size <= windowBytes * 2) {
10
+ const buf = Buffer.allocUnsafe(size);
11
+ await fh.read(buf, 0, size, 0);
12
+ const text = buf.toString('utf8');
13
+ return { path, size, mtime: st.mtime, head: text, tail: '', complete: true };
14
+ }
15
+ const headBuf = Buffer.allocUnsafe(windowBytes);
16
+ const tailBuf = Buffer.allocUnsafe(windowBytes);
17
+ await fh.read(headBuf, 0, windowBytes, 0);
18
+ await fh.read(tailBuf, 0, windowBytes, size - windowBytes);
19
+ return {
20
+ path,
21
+ size,
22
+ mtime: st.mtime,
23
+ head: headBuf.toString('utf8'),
24
+ tail: tailBuf.toString('utf8'),
25
+ complete: false,
26
+ };
27
+ }
28
+ finally {
29
+ await fh.close();
30
+ }
31
+ }
32
+ /**
33
+ * Whole lines only. A window read almost always starts and ends mid-line, and a
34
+ * half-line of JSON is worse than no line at all.
35
+ */
36
+ export function wholeLines(chunk, dropFirst, dropLast) {
37
+ const lines = chunk.split('\n');
38
+ if (dropFirst && lines.length)
39
+ lines.shift();
40
+ if (dropLast && lines.length)
41
+ lines.pop();
42
+ return lines.filter((l) => l.trim() !== '');
43
+ }
44
+ export async function listFiles(dir, ext) {
45
+ try {
46
+ const entries = await readdir(dir, { withFileTypes: true });
47
+ return entries.filter((e) => e.isFile() && e.name.endsWith(ext)).map((e) => join(dir, e.name));
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ }
53
+ export async function listDirs(dir) {
54
+ try {
55
+ const entries = await readdir(dir, { withFileTypes: true });
56
+ return entries.filter((e) => e.isDirectory()).map((e) => join(dir, e.name));
57
+ }
58
+ catch {
59
+ return [];
60
+ }
61
+ }
62
+ export async function isDirectory(path) {
63
+ try {
64
+ return (await stat(path)).isDirectory();
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ export async function exists(path) {
71
+ try {
72
+ await stat(path);
73
+ return true;
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ //# sourceMappingURL=fsutil.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsutil.js","sourceRoot":"","sources":["../../src/importers/fsutil.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ImportInput, Transcript, TranscriptImporter } from '@husk-ai/core';
2
+ export declare function parseGeminiJson(content: string, origin?: string): Transcript[];
3
+ export declare class GeminiImporter implements TranscriptImporter {
4
+ readonly id: "gemini";
5
+ readonly displayName = "Gemini";
6
+ detect(input: {
7
+ path?: string;
8
+ content?: string;
9
+ }): Promise<number>;
10
+ parse(input: ImportInput): Promise<Transcript[]>;
11
+ defaultLocations(): string[];
12
+ }
13
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/importers/gemini.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAC;AAiIpG,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAgD9E;AAED,qBAAa,cAAe,YAAW,kBAAkB;IACvD,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAChC,QAAQ,CAAC,WAAW,YAAY;IAE1B,MAAM,CAAC,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBnE,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAatD,gBAAgB,IAAI,MAAM,EAAE;CAG7B"}
@@ -0,0 +1,228 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { HuskError, id } from '@husk-ai/core';
5
+ import { isDirectory, listFiles } from './fsutil.js';
6
+ /**
7
+ * Gemini, in the three shapes it actually ships in:
8
+ *
9
+ * 1. Gemini CLI checkpoints -- `{ messages: [{ role, parts: [{ text }] }] }`,
10
+ * the raw `generateContent` shape, also spelled `contents`.
11
+ * 2. Google Takeout "My Activity" -- `[{ header, title, time, ... }]` where the
12
+ * prompt is in `title` and the answer is in an html blob.
13
+ * 3. Ad-hoc exports keyed by `message_list` / `conversation_id`.
14
+ */
15
+ function isRecord(v) {
16
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
17
+ }
18
+ function asString(v) {
19
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
20
+ }
21
+ function mapRole(role) {
22
+ switch ((role ?? '').toLowerCase()) {
23
+ case 'model':
24
+ case 'assistant':
25
+ case 'bot':
26
+ case 'gemini':
27
+ return 'assistant';
28
+ case 'system':
29
+ return 'system';
30
+ case 'tool':
31
+ case 'function':
32
+ return 'tool';
33
+ default:
34
+ return 'user';
35
+ }
36
+ }
37
+ function partsToText(parts) {
38
+ if (typeof parts === 'string')
39
+ return { text: parts };
40
+ if (!Array.isArray(parts))
41
+ return { text: '' };
42
+ const chunks = [];
43
+ let toolName;
44
+ let toolInput;
45
+ for (const p of parts) {
46
+ if (typeof p === 'string') {
47
+ chunks.push(p);
48
+ continue;
49
+ }
50
+ if (!isRecord(p))
51
+ continue;
52
+ const t = asString(p.text);
53
+ if (t)
54
+ chunks.push(t);
55
+ if (isRecord(p.functionCall)) {
56
+ toolName = asString(p.functionCall.name) ?? toolName;
57
+ toolInput = p.functionCall.args;
58
+ chunks.push(`[tool: ${toolName ?? 'unknown'}]`);
59
+ }
60
+ if (isRecord(p.functionResponse)) {
61
+ toolName = asString(p.functionResponse.name) ?? toolName;
62
+ chunks.push(JSON.stringify(p.functionResponse.response ?? {}));
63
+ }
64
+ if (isRecord(p.inlineData))
65
+ chunks.push(`[image: ${asString(p.inlineData.mimeType) ?? 'unknown'}]`);
66
+ }
67
+ return { text: chunks.join('\n'), ...(toolName ? { toolName } : {}), ...(toolInput !== undefined ? { toolInput } : {}) };
68
+ }
69
+ function stripHtml(s) {
70
+ return s
71
+ .replace(/<br\s*\/?>/gi, '\n')
72
+ .replace(/<[^>]+>/g, '')
73
+ .replace(/&quot;/g, '"')
74
+ .replace(/&#39;/g, "'")
75
+ .replace(/&amp;/g, '&')
76
+ .replace(/&lt;/g, '<')
77
+ .replace(/&gt;/g, '>')
78
+ .trim();
79
+ }
80
+ function turnsToMessages(turns) {
81
+ const out = [];
82
+ for (const turn of turns) {
83
+ if (!isRecord(turn))
84
+ continue;
85
+ const { text, toolName, toolInput } = partsToText(turn.parts ?? turn.content ?? turn.text);
86
+ const body = (text || asString(turn.text) || asString(turn.content) || '').trim();
87
+ if (!body)
88
+ continue;
89
+ const ts = asString(turn.create_time) ?? asString(turn.timestamp) ?? asString(turn.time);
90
+ out.push({
91
+ role: toolName && !turn.role ? 'tool' : mapRole(asString(turn.role) ?? asString(turn.author)),
92
+ content: body,
93
+ ...(ts ? { ts } : {}),
94
+ ...(toolName ? { toolName } : {}),
95
+ ...(toolInput !== undefined ? { toolInput } : {}),
96
+ });
97
+ }
98
+ return out;
99
+ }
100
+ /** Takeout emits one activity record per prompt, not a threaded conversation. */
101
+ function takeoutToTranscript(records, origin) {
102
+ const messages = [];
103
+ let first;
104
+ let last;
105
+ for (const r of records) {
106
+ if (!isRecord(r))
107
+ continue;
108
+ const title = asString(r.title);
109
+ if (!title || !/^Prompted\s/i.test(title))
110
+ continue;
111
+ const ts = asString(r.time);
112
+ if (ts) {
113
+ first = first ?? ts;
114
+ last = ts;
115
+ }
116
+ messages.push({ role: 'user', content: stripHtml(title.replace(/^Prompted\s+/i, '')), ...(ts ? { ts } : {}) });
117
+ const details = Array.isArray(r.details) ? r.details : [];
118
+ const answer = details.map((d) => (isRecord(d) ? (asString(d.name) ?? '') : '')).join('\n');
119
+ if (answer)
120
+ messages.push({ role: 'assistant', content: stripHtml(answer), ...(ts ? { ts } : {}) });
121
+ }
122
+ if (!messages.length)
123
+ return undefined;
124
+ // Takeout is newest-first.
125
+ if (first && last && first > last)
126
+ messages.reverse();
127
+ return {
128
+ id: id('gemini'),
129
+ source: 'gemini',
130
+ title: 'Gemini activity',
131
+ messages,
132
+ ...(origin ? { origin } : {}),
133
+ meta: { format: 'takeout-activity' },
134
+ };
135
+ }
136
+ export function parseGeminiJson(content, origin) {
137
+ let data;
138
+ try {
139
+ data = JSON.parse(content);
140
+ }
141
+ catch (cause) {
142
+ throw new HuskError('E_IMPORT_FAILED', `${origin ?? 'input'} is not valid JSON.`, {
143
+ hint: 'Gemini imports expect a CLI checkpoint or a Takeout JSON file.',
144
+ cause,
145
+ });
146
+ }
147
+ const list = Array.isArray(data) ? data : [data];
148
+ const takeout = takeoutToTranscript(list, origin);
149
+ if (takeout)
150
+ return [takeout];
151
+ const out = [];
152
+ for (const conv of list) {
153
+ if (!isRecord(conv))
154
+ continue;
155
+ const turns = (Array.isArray(conv.messages) && conv.messages) ||
156
+ (Array.isArray(conv.contents) && conv.contents) ||
157
+ (Array.isArray(conv.message_list) && conv.message_list) ||
158
+ (Array.isArray(conv.history) && conv.history) ||
159
+ undefined;
160
+ let messages = turns ? turnsToMessages(turns) : [];
161
+ if (!messages.length && (conv.user_query || conv.model_response)) {
162
+ const q = asString(conv.user_query);
163
+ const a = asString(conv.model_response);
164
+ const ts = asString(conv.create_time) ?? asString(conv.timestamp);
165
+ messages = [
166
+ ...(q ? [{ role: 'user', content: q, ...(ts ? { ts } : {}) }] : []),
167
+ ...(a ? [{ role: 'assistant', content: a, ...(ts ? { ts } : {}) }] : []),
168
+ ];
169
+ }
170
+ if (!messages.length)
171
+ continue;
172
+ out.push({
173
+ id: asString(conv.conversation_id) ?? asString(conv.sessionId) ?? asString(conv.id) ?? id('gemini'),
174
+ source: 'gemini',
175
+ messages,
176
+ ...(asString(conv.title) ? { title: asString(conv.title) } : {}),
177
+ ...(origin ? { origin } : {}),
178
+ });
179
+ }
180
+ return out;
181
+ }
182
+ export class GeminiImporter {
183
+ id = 'gemini';
184
+ displayName = 'Gemini';
185
+ async detect(input) {
186
+ try {
187
+ const path = input.path?.replace(/\\/g, '/').toLowerCase();
188
+ let score = 0;
189
+ if (path?.includes('/.gemini/'))
190
+ score = 0.7;
191
+ else if (path?.includes('gemini') && path.endsWith('.json'))
192
+ score = 0.55;
193
+ const probe = input.content?.slice(0, 64 * 1024);
194
+ if (probe) {
195
+ if (/"role"\s*:\s*"model"/.test(probe))
196
+ score = Math.max(score, 0.9);
197
+ if (/"functionCall"|"inlineData"/.test(probe))
198
+ score = Math.max(score, 0.8);
199
+ if (/"header"\s*:\s*"Gemini/.test(probe))
200
+ score = Math.max(score, 0.95);
201
+ if (/"message_list"|"user_query"|"model_response"/.test(probe))
202
+ score = Math.max(score, 0.75);
203
+ }
204
+ return score;
205
+ }
206
+ catch {
207
+ return 0;
208
+ }
209
+ }
210
+ async parse(input) {
211
+ if (input.content !== undefined)
212
+ return parseGeminiJson(input.content, input.path);
213
+ if (!input.path) {
214
+ throw new HuskError('E_IMPORT_FAILED', 'Gemini import needs a path or content.', {
215
+ hint: 'Point it at a Gemini CLI checkpoint json or a Takeout activity file.',
216
+ });
217
+ }
218
+ const files = (await isDirectory(input.path)) ? await listFiles(input.path, '.json') : [input.path];
219
+ const out = [];
220
+ for (const f of files)
221
+ out.push(...parseGeminiJson(await readFile(f, 'utf8'), f));
222
+ return out;
223
+ }
224
+ defaultLocations() {
225
+ return [join(homedir(), '.gemini', 'tmp')];
226
+ }
227
+ }
228
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/importers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;GAQG;AAEH,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC;AAED,SAAS,OAAO,CAAC,IAAwB;IACvC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACnC,KAAK,OAAO,CAAC;QACb,KAAK,WAAW,CAAC;QACjB,KAAK,KAAK,CAAC;QACX,KAAK,QAAQ;YACX,OAAO,WAAW,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,MAAM,CAAC;QAChB;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACtD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,QAA4B,CAAC;IACjC,IAAI,SAAkB,CAAC;IACvB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAC3B,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;YACrD,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,UAAU,QAAQ,IAAI,SAAS,GAAG,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACjC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,WAAW,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3H,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC;SAC7B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,eAAe,CAAC,KAAgB;IACvC,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC9B,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3F,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAClF,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzF,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7F,OAAO,EAAE,IAAI;YACb,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iFAAiF;AACjF,SAAS,mBAAmB,CAAC,OAAkB,EAAE,MAA0B;IACzE,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,IAAI,KAAyB,CAAC;IAC9B,IAAI,IAAwB,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACpD,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,EAAE,EAAE,CAAC;YACP,KAAK,GAAG,KAAK,IAAI,EAAE,CAAC;YACpB,IAAI,GAAG,EAAE,CAAC;QACZ,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/G,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5F,IAAI,MAAM;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACvC,2BAA2B;IAC3B,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI;QAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;IACtD,OAAO;QACL,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC;QAChB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,iBAAiB;QACxB,QAAQ;QACR,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,IAAI,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,MAAe;IAC9D,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,iBAAiB,EAAE,GAAG,MAAM,IAAI,OAAO,qBAAqB,EAAE;YAChF,IAAI,EAAE,gEAAgE;YACtE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,OAAO;QAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9B,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC9B,MAAM,KAAK,GACT,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC;YAC/C,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC;YAC/C,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC;YACvD,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC;YAC7C,SAAS,CAAC;QAEZ,IAAI,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnD,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACjE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACpC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClE,QAAQ,GAAG;gBACT,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5E,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAClF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,SAAS;QAE/B,GAAG,CAAC,IAAI,CAAC;YACP,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC;YACnG,MAAM,EAAE,QAAQ;YAChB,QAAQ;YACR,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,OAAO,cAAc;IAChB,EAAE,GAAG,QAAiB,CAAC;IACvB,WAAW,GAAG,QAAQ,CAAC;IAEhC,KAAK,CAAC,MAAM,CAAC,KAA0C;QACrD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3D,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC;gBAAE,KAAK,GAAG,GAAG,CAAC;iBACxC,IAAI,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,KAAK,GAAG,IAAI,CAAC;YAE1E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;YACjD,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACrE,IAAI,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC5E,IAAI,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACxE,IAAI,8CAA8C,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAkB;QAC5B,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,SAAS,CAAC,iBAAiB,EAAE,wCAAwC,EAAE;gBAC/E,IAAI,EAAE,sEAAsE;aAC7E,CAAC,CAAC;QACL,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpG,MAAM,GAAG,GAAiB,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,MAAM,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,OAAO,GAAG,CAAC;IACb,CAAC;IAED,gBAAgB;QACd,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7C,CAAC;CACF"}