@geminixiang/mikan 1.0.0-beta.47 → 1.0.0-beta.49

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 (78) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/adapters/discord/context.d.ts.map +1 -1
  3. package/dist/adapters/discord/context.js +2 -6
  4. package/dist/adapters/discord/context.js.map +1 -1
  5. package/dist/adapters/telegram/context.d.ts.map +1 -1
  6. package/dist/adapters/telegram/context.js +2 -4
  7. package/dist/adapters/telegram/context.js.map +1 -1
  8. package/dist/agent/presenter.d.ts +3 -10
  9. package/dist/agent/presenter.d.ts.map +1 -1
  10. package/dist/agent/presenter.js +35 -32
  11. package/dist/agent/presenter.js.map +1 -1
  12. package/dist/agent/runner.d.ts.map +1 -1
  13. package/dist/agent/runner.js +16 -22
  14. package/dist/agent/runner.js.map +1 -1
  15. package/dist/agent/types.d.ts +4 -6
  16. package/dist/agent/types.d.ts.map +1 -1
  17. package/dist/agent/types.js.map +1 -1
  18. package/dist/cli/boot.js +1 -1
  19. package/dist/cli/boot.js.map +1 -1
  20. package/dist/cli/sessions.d.ts.map +1 -1
  21. package/dist/cli/sessions.js +18 -13
  22. package/dist/cli/sessions.js.map +1 -1
  23. package/dist/config.d.ts.map +1 -1
  24. package/dist/config.js +4 -2
  25. package/dist/config.js.map +1 -1
  26. package/dist/env-manifest.js +2 -2
  27. package/dist/env-manifest.js.map +1 -1
  28. package/dist/harness/models.d.ts.map +1 -1
  29. package/dist/harness/models.js +1 -4
  30. package/dist/harness/models.js.map +1 -1
  31. package/dist/harness/runner.d.ts.map +1 -1
  32. package/dist/harness/runner.js +2 -2
  33. package/dist/harness/runner.js.map +1 -1
  34. package/dist/harness/session-store.d.ts +3 -45
  35. package/dist/harness/session-store.d.ts.map +1 -1
  36. package/dist/harness/session-store.js +293 -198
  37. package/dist/harness/session-store.js.map +1 -1
  38. package/dist/harness/subagent-runner.d.ts.map +1 -1
  39. package/dist/harness/subagent-runner.js +1 -8
  40. package/dist/harness/subagent-runner.js.map +1 -1
  41. package/dist/harness/types.d.ts +11 -11
  42. package/dist/harness/types.d.ts.map +1 -1
  43. package/dist/harness/types.js.map +1 -1
  44. package/dist/main.js +5 -0
  45. package/dist/main.js.map +1 -1
  46. package/dist/mcp/catalog.d.ts.map +1 -1
  47. package/dist/mcp/catalog.js +0 -88
  48. package/dist/mcp/catalog.js.map +1 -1
  49. package/dist/mcp/open-connector.d.ts +1 -1
  50. package/dist/mcp/open-connector.d.ts.map +1 -1
  51. package/dist/mcp/open-connector.js +23 -22
  52. package/dist/mcp/open-connector.js.map +1 -1
  53. package/dist/runtime/conversation-runtime.js +1 -0
  54. package/dist/runtime/conversation-runtime.js.map +1 -1
  55. package/dist/runtime/session-lifecycle.d.ts +0 -1
  56. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  57. package/dist/runtime/session-lifecycle.js +1 -4
  58. package/dist/runtime/session-lifecycle.js.map +1 -1
  59. package/dist/runtime/types.d.ts +3 -0
  60. package/dist/runtime/types.d.ts.map +1 -1
  61. package/dist/runtime/types.js.map +1 -1
  62. package/dist/sessions/migrate-pi-084.d.ts +8 -0
  63. package/dist/sessions/migrate-pi-084.d.ts.map +1 -0
  64. package/dist/sessions/migrate-pi-084.js +353 -0
  65. package/dist/sessions/migrate-pi-084.js.map +1 -0
  66. package/dist/sessions/migrate-v3.d.ts +0 -5
  67. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  68. package/dist/sessions/migrate-v3.js +129 -51
  69. package/dist/sessions/migrate-v3.js.map +1 -1
  70. package/dist/sessions/types.d.ts +6 -1
  71. package/dist/sessions/types.d.ts.map +1 -1
  72. package/dist/sessions/types.js.map +1 -1
  73. package/dist/types.d.ts +5 -1
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js.map +1 -1
  76. package/dist/web/session-view/portal.js +0 -16
  77. package/dist/web/session-view/portal.js.map +1 -1
  78. package/package.json +3 -3
@@ -3,10 +3,9 @@
3
3
  *
4
4
  * v3 is the entry family mikan wrote up to pi 0.83: a `{"type":"session"}`
5
5
  * header followed by tree entries with string ISO timestamps and compaction
6
- * entries that point at `firstKeptEntryId`. v4 (pi 0.84+) uses a
7
- * `{"kind":"header","version":4}` header followed by mutation lines whose
8
- * entries carry numeric timestamps and a consecutive `seq`, with compaction
9
- * retention stored inline as `retainedTail`.
6
+ * entries that point at `firstKeptEntryId`. Current Pi v4 uses a
7
+ * `{"v":4,"kind":"header","storageVersion":1}` header followed by
8
+ * transactional writes with numeric timestamps and consecutive sequences.
10
9
  *
11
10
  * The migration preserves entry ids, parent links, and timestamps, converts
12
11
  * `custom_message` entries into v4 `custom`-role messages, folds
@@ -17,9 +16,9 @@
17
16
  * v3 context computed by the reference converter below. The original file
18
17
  * is kept beside the migrated one as `<name>.v3.bak`.
19
18
  */
20
- import { existsSync, readdirSync, readFileSync, renameSync, rmSync, statSync } from "node:fs";
19
+ import { existsSync, linkSync, lstatSync, readdirSync, readFileSync, renameSync, rmSync, statSync, } from "node:fs";
21
20
  import { join } from "node:path";
22
- import { buildSessionContext, createCustomMessage, } from "@earendil-works/pi-agent-core";
21
+ import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "@earendil-works/pi-agent-core";
23
22
  import { SessionStore } from "../harness/session-store.js";
24
23
  import { atomicWritePrivateFile } from "../utils/file-guards.js";
25
24
  /** Whether a file's first non-empty line is a v3 session header. */
@@ -60,21 +59,17 @@ function readV3SessionFile(filePath) {
60
59
  // Crash-era v3 files can contain duplicated lines (a retried append wrote
61
60
  // the header+entry pair twice). The v3 runtime read entries into a Map, so
62
61
  // duplicates were silently collapsed; v4 rejects duplicate mutation ids.
63
- // Reproduce the v3 semantics: keep one entry per id, drop stray repeated
64
- // session headers.
65
- const seen = new Set();
66
- const entries = [];
62
+ // Reproduce the v3 Map semantics: a repeated id replaces its payload while
63
+ // retaining the id's original insertion position.
64
+ const entriesById = new Map();
67
65
  for (const record of records.slice(1)) {
68
66
  if (typeof record.type !== "string" || typeof record.id !== "string")
69
67
  continue;
70
68
  if (record.type === "session")
71
69
  continue;
72
- if (seen.has(record.id))
73
- continue;
74
- seen.add(record.id);
75
- entries.push(record);
70
+ entriesById.set(record.id, record);
76
71
  }
77
- return { header: header, entries };
72
+ return { header: header, entries: [...entriesById.values()] };
78
73
  }
79
74
  function toEpochMillis(timestamp) {
80
75
  const parsed = Date.parse(timestamp);
@@ -119,11 +114,16 @@ function convertEntry(entry, entries) {
119
114
  message: createCustomMessage(entry.customType, entry.content, entry.display, entry.details, toEpochMillis(entry.timestamp)),
120
115
  };
121
116
  case "thinking_level_change":
122
- return { ...base, type: "thinking_level_change", thinkingLevel: entry.thinkingLevel };
123
117
  case "model_change":
124
- return { ...base, type: "model_change", provider: entry.provider, modelId: entry.modelId };
125
- case "active_tools_change":
126
- return { ...base, type: "active_tools_change", activeToolNames: entry.activeToolNames };
118
+ case "active_tools_change": {
119
+ const { id: _id, parentId: _parentId, timestamp: _timestamp, type, ...data } = entry;
120
+ return {
121
+ ...base,
122
+ type: "custom",
123
+ customType: `mikan.legacy.${type}`,
124
+ data: data,
125
+ };
126
+ }
127
127
  case "compaction":
128
128
  return {
129
129
  ...base,
@@ -131,6 +131,7 @@ function convertEntry(entry, entries) {
131
131
  summary: entry.summary,
132
132
  retainedTail: entry.retainedTail ?? compactionKeptMessages(entry, entries),
133
133
  tokensBefore: entry.tokensBefore,
134
+ fromHook: false,
134
135
  ...(entry.details !== undefined ? { details: entry.details } : {}),
135
136
  ...(entry.usage !== undefined ? { usage: entry.usage } : {}),
136
137
  };
@@ -138,13 +139,19 @@ function convertEntry(entry, entries) {
138
139
  return {
139
140
  ...base,
140
141
  type: "branch_summary",
141
- fromId: entry.fromId,
142
+ fromId: entry.fromId ?? null,
142
143
  summary: entry.summary,
144
+ fromHook: false,
143
145
  ...(entry.details !== undefined ? { details: entry.details } : {}),
144
146
  ...(entry.usage !== undefined ? { usage: entry.usage } : {}),
145
147
  };
146
148
  case "custom":
147
- return { ...base, type: "custom", customType: entry.customType, data: entry.data };
149
+ return {
150
+ ...base,
151
+ type: "custom",
152
+ customType: entry.customType,
153
+ ...(entry.data !== undefined ? { data: entry.data } : {}),
154
+ };
148
155
  default:
149
156
  // session_info / label / leaf become facts and the lane pointer.
150
157
  return null;
@@ -233,6 +240,7 @@ function referenceContextEntries(branch) {
233
240
  summary: entry.summary,
234
241
  retainedTail: [],
235
242
  tokensBefore: entry.tokensBefore,
243
+ fromHook: false,
236
244
  });
237
245
  continue;
238
246
  }
@@ -248,30 +256,51 @@ function referenceContextEntries(branch) {
248
256
  }
249
257
  return converted;
250
258
  }
259
+ function isCurrentContextMessage(message) {
260
+ return (message.role !== "assistant" ||
261
+ (message.stopReason !== "error" &&
262
+ message.stopReason !== "aborted" &&
263
+ message.stopReason !== "deferred"));
264
+ }
265
+ function referenceContextMessages(entries) {
266
+ const compactionIndex = entries.findLastIndex((entry) => entry.type === "compaction");
267
+ const visible = compactionIndex === -1
268
+ ? entries
269
+ : [entries[compactionIndex], ...entries.slice(compactionIndex + 1)];
270
+ const messages = [];
271
+ for (const entry of visible) {
272
+ if (entry.type === "message") {
273
+ if (isCurrentContextMessage(entry.message))
274
+ messages.push(entry.message);
275
+ }
276
+ else if (entry.type === "compaction") {
277
+ messages.push(createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp), ...entry.retainedTail.filter(isCurrentContextMessage));
278
+ }
279
+ else if (entry.type === "branch_summary" && entry.summary) {
280
+ messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
281
+ }
282
+ }
283
+ return messages;
284
+ }
251
285
  // ── v4 encoding ─────────────────────────────────────────────────────────────
252
286
  function buildV4Header(header) {
253
- const { type: _type, version: _version, id, timestamp, cwd, parentSession, parentSessionId, ...extras } = header;
254
- const metadata = { ...extras };
255
- if (parentSession !== undefined)
256
- metadata.parentSessionPath = parentSession;
257
287
  return {
288
+ v: 4,
258
289
  kind: "header",
259
- version: 4,
260
- id,
261
- createdAt: toEpochMillis(timestamp),
262
- cwd,
263
- ...(parentSessionId !== undefined ? { parentSessionId } : {}),
264
- ...(Object.keys(metadata).length > 0
265
- ? { metadata: metadata }
290
+ id: header.id,
291
+ storageVersion: 1,
292
+ createdAt: toEpochMillis(header.timestamp),
293
+ cwd: header.cwd,
294
+ ...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),
295
+ ...(header.parentSession !== undefined
296
+ ? { legacyParentSessionPath: header.parentSession }
266
297
  : {}),
267
298
  };
268
299
  }
269
300
  function encodeV4File(file) {
270
301
  const lines = [JSON.stringify(buildV4Header(file.header))];
271
302
  let seq = 0;
272
- const push = (mutation) => {
273
- lines.push(JSON.stringify(mutation));
274
- };
303
+ const push = (write) => lines.push(JSON.stringify(write));
275
304
  let name;
276
305
  const labels = [];
277
306
  for (const entry of file.entries) {
@@ -289,12 +318,8 @@ function encodeV4File(file) {
289
318
  if (!converted)
290
319
  continue;
291
320
  converted.seq = ++seq;
292
- // Entry mutations are encoded flat: {kind:"entry", ...entry fields}.
293
321
  push({ kind: "entry", ...converted });
294
322
  }
295
- // The v3 leaf may point at a fact-only entry (session_info/label) that
296
- // does not survive as a v4 entry; re-aim the lane at its nearest surviving
297
- // ancestor, mirroring resolveV4Parent.
298
323
  let leafId = v3LeafId(file.entries);
299
324
  const byId = new Map(file.entries.map((entry) => [entry.id, entry]));
300
325
  while (leafId !== null) {
@@ -303,16 +328,53 @@ function encodeV4File(file) {
303
328
  leafId = null;
304
329
  break;
305
330
  }
306
- if (target.type !== "session_info" && target.type !== "label" && target.type !== "leaf") {
331
+ if (target.type !== "session_info" && target.type !== "label" && target.type !== "leaf")
307
332
  break;
308
- }
309
333
  leafId = target.parentId;
310
334
  }
311
- push({ kind: "lane", seq: ++seq, lane: "main", leafId });
312
- if (name !== undefined)
313
- push({ kind: "fact", seq: ++seq, fact: "name", name });
335
+ push({
336
+ kind: "value",
337
+ op: "set",
338
+ seq: ++seq,
339
+ namespace: "pi.branch.tip",
340
+ key: "main",
341
+ value: leafId,
342
+ });
343
+ if (name !== undefined) {
344
+ push({
345
+ kind: "value",
346
+ op: "set",
347
+ seq: ++seq,
348
+ namespace: "pi.session.name",
349
+ key: "",
350
+ value: name,
351
+ });
352
+ }
314
353
  for (const { targetId, label } of labels) {
315
- push({ kind: "fact", seq: ++seq, fact: "label", targetId, label });
354
+ if (label === undefined)
355
+ continue;
356
+ push({
357
+ kind: "value",
358
+ op: "set",
359
+ seq: ++seq,
360
+ namespace: "pi.entry.label",
361
+ key: targetId,
362
+ value: label,
363
+ });
364
+ }
365
+ const { type: _type, version: _version, id: _id, timestamp: _timestamp, cwd: _cwd, parentSession, parentSessionId: _parentSessionId, ...extras } = file.header;
366
+ const metadata = extras;
367
+ if (parentSession !== undefined)
368
+ metadata.parentSessionPath = parentSession;
369
+ if (Object.keys(metadata).length > 0) {
370
+ push({
371
+ kind: "value",
372
+ op: "set",
373
+ seq: ++seq,
374
+ namespace: "mikan",
375
+ key: "metadata",
376
+ value: metadata,
377
+ });
316
378
  }
317
379
  return `${lines.join("\n")}\n`;
318
380
  }
@@ -321,9 +383,8 @@ async function verifyMigratedFile(v4Path, source) {
321
383
  const store = await SessionStore.inspect(v4Path);
322
384
  const migratedContext = await store.buildSessionContext();
323
385
  const branch = v3Branch(source.entries, v3LeafId(source.entries));
324
- const referenceContext = buildSessionContext(referenceContextEntries(branch));
325
386
  const migrated = JSON.stringify(migratedContext.messages);
326
- const reference = JSON.stringify(referenceContext.messages);
387
+ const reference = JSON.stringify(referenceContextMessages(referenceContextEntries(branch)));
327
388
  if (migrated !== reference) {
328
389
  throw new Error("migrated context does not match the v3 reference context");
329
390
  }
@@ -341,23 +402,38 @@ async function verifyMigratedFile(v4Path, source) {
341
402
  * the v3 reference semantics before it replaces the original; the original
342
403
  * is preserved as `<file>.v3.bak`.
343
404
  */
405
+ function backupAlreadyLinked(sourcePath, backupPath) {
406
+ if (!existsSync(backupPath))
407
+ return false;
408
+ const source = statSync(sourcePath);
409
+ const backup = statSync(backupPath);
410
+ if (source.dev === backup.dev && source.ino === backup.ino)
411
+ return true;
412
+ throw new Error(`Backup already exists: ${backupPath}`);
413
+ }
344
414
  export async function migrateSessionFile(filePath, options) {
345
415
  if (!isV3SessionFile(filePath))
346
416
  return { file: filePath, status: "already-v4" };
417
+ const sourceBytes = readFileSync(filePath);
347
418
  const source = readV3SessionFile(filePath);
348
419
  if (options?.dryRun)
349
420
  return { file: filePath, status: "migrated", detail: "dry run" };
350
421
  const tempPath = `${filePath}.v4.tmp`;
422
+ const backupPath = `${filePath}.v3.bak`;
423
+ const backupLinked = backupAlreadyLinked(filePath, backupPath);
351
424
  atomicWritePrivateFile(tempPath, encodeV4File(source));
352
425
  try {
353
426
  await verifyMigratedFile(tempPath, source);
427
+ if (!readFileSync(filePath).equals(sourceBytes))
428
+ throw new Error("source changed during migration");
429
+ if (!backupLinked)
430
+ linkSync(filePath, backupPath);
431
+ renameSync(tempPath, filePath);
354
432
  }
355
433
  catch (error) {
356
434
  rmSync(tempPath, { force: true });
357
- throw new Error(`Verification failed for ${filePath}`, { cause: error });
435
+ throw new Error(`Migration failed for ${filePath}`, { cause: error });
358
436
  }
359
- renameSync(filePath, `${filePath}.v3.bak`);
360
- renameSync(tempPath, filePath);
361
437
  return { file: filePath, status: "migrated" };
362
438
  }
363
439
  /** Recursively find candidate session files (.jsonl with a v3 header). */
@@ -370,11 +446,13 @@ export function findV3SessionFiles(root) {
370
446
  const path = join(dir, name);
371
447
  let stats;
372
448
  try {
373
- stats = statSync(path);
449
+ stats = lstatSync(path);
374
450
  }
375
451
  catch {
376
452
  continue;
377
453
  }
454
+ if (stats.isSymbolicLink())
455
+ continue;
378
456
  if (stats.isDirectory()) {
379
457
  walk(path);
380
458
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-v3.js","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migration of legacy v3 session files to pi's v4 JSONL format.\n *\n * v3 is the entry family mikan wrote up to pi 0.83: a `{\"type\":\"session\"}`\n * header followed by tree entries with string ISO timestamps and compaction\n * entries that point at `firstKeptEntryId`. v4 (pi 0.84+) uses a\n * `{\"kind\":\"header\",\"version\":4}` header followed by mutation lines whose\n * entries carry numeric timestamps and a consecutive `seq`, with compaction\n * retention stored inline as `retainedTail`.\n *\n * The migration preserves entry ids, parent links, and timestamps, converts\n * `custom_message` entries into v4 `custom`-role messages, folds\n * `session_info` into the v4 name fact, `label` entries into label facts,\n * and rewrites each compaction's kept range into its inline `retainedTail`.\n * Every migrated file is verified before it replaces the original: the v4\n * file is re-opened with pi's reader and its built context must equal the\n * v3 context computed by the reference converter below. The original file\n * is kept beside the migrated one as `<name>.v3.bak`.\n */\nimport { existsSync, readdirSync, readFileSync, renameSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n buildSessionContext,\n createCustomMessage,\n type AgentMessage,\n type Entry as PiEntry,\n type JsonlV4Header,\n} from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"../harness/session-store.js\";\nimport { atomicWritePrivateFile } from \"../utils/file-guards.js\";\nimport type { MigrateResult } from \"./types.js\";\nexport type { MigrateResult } from \"./types.js\";\n\n// ── v3 shapes ────────────────────────────────────────────────────────────────\n\ninterface V3EntryBase {\n type: string;\n id: string;\n parentId: string | null;\n timestamp: string;\n}\n\ntype V3Entry = V3EntryBase &\n (\n | { type: \"message\"; message: AgentMessage }\n | { type: \"thinking_level_change\"; thinkingLevel: string }\n | { type: \"model_change\"; provider: string; modelId: string }\n | { type: \"active_tools_change\"; activeToolNames: string[] }\n | {\n type: \"compaction\";\n summary: string;\n firstKeptEntryId?: string;\n tokensBefore: number;\n retainedTail?: AgentMessage[];\n details?: unknown;\n usage?: unknown;\n }\n | {\n type: \"branch_summary\";\n fromId: string;\n summary: string;\n details?: unknown;\n usage?: unknown;\n }\n | { type: \"custom\"; customType: string; data?: unknown }\n | {\n type: \"custom_message\";\n customType: string;\n content: Parameters<typeof createCustomMessage>[1];\n display: boolean;\n details?: unknown;\n }\n | { type: \"label\"; targetId: string; label: string | undefined }\n | { type: \"session_info\"; name?: string }\n | { type: \"leaf\"; targetId: string | null }\n );\n\ninterface V3SessionHeader {\n type: \"session\";\n version?: number;\n id: string;\n timestamp: string;\n cwd: string;\n parentSession?: string;\n parentSessionId?: string;\n [extra: string]: unknown;\n}\n\ninterface V3SessionFile {\n header: V3SessionHeader;\n entries: V3Entry[];\n}\n\n/** Whether a file's first non-empty line is a v3 session header. */\nexport function isV3SessionFile(filePath: string): boolean {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const firstLine = content.split(\"\\n\").find((line) => line.trim().length > 0);\n if (!firstLine) return false;\n const parsed = JSON.parse(firstLine) as { type?: unknown };\n return parsed.type === \"session\";\n } catch {\n return false;\n }\n}\n\n/** Read a v3 session file, ignoring a torn final line (crash tail). */\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const lines = readFileSync(filePath, \"utf-8\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const records: Record<string, unknown>[] = [];\n for (const [index, line] of lines.entries()) {\n try {\n records.push(JSON.parse(line) as Record<string, unknown>);\n } catch (error) {\n if (index === lines.length - 1 && index > 0) continue;\n throw new Error(`Invalid JSON on line ${index + 1} of ${filePath}`, { cause: error });\n }\n }\n const header = records[0];\n if (!header || header.type !== \"session\" || typeof header.id !== \"string\") {\n throw new Error(`Not a v3 session file: ${filePath}`);\n }\n // Crash-era v3 files can contain duplicated lines (a retried append wrote\n // the header+entry pair twice). The v3 runtime read entries into a Map, so\n // duplicates were silently collapsed; v4 rejects duplicate mutation ids.\n // Reproduce the v3 semantics: keep one entry per id, drop stray repeated\n // session headers.\n const seen = new Set<string>();\n const entries: V3Entry[] = [];\n for (const record of records.slice(1)) {\n if (typeof record.type !== \"string\" || typeof record.id !== \"string\") continue;\n if (record.type === \"session\") continue;\n if (seen.has(record.id)) continue;\n seen.add(record.id);\n entries.push(record as unknown as V3Entry);\n }\n return { header: header as unknown as V3SessionHeader, entries };\n}\n\nfunction toEpochMillis(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\n/** Walk a v3 tree from an entry to the root; returns root-first path order. */\nfunction v3Branch(entries: V3Entry[], fromId: string | null): V3Entry[] {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const path: V3Entry[] = [];\n let currentId = fromId;\n while (currentId) {\n const entry = byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n}\n\nfunction v3LeafId(entries: V3Entry[]): string | null {\n let leafId: string | null = null;\n for (const entry of entries) {\n leafId = entry.type === \"leaf\" ? entry.targetId : entry.id;\n }\n return leafId;\n}\n\n/** Convert one tree-shaping v3 entry to its v4 counterpart (facts excluded). */\nfunction convertEntry(entry: V3Entry, entries: V3Entry[]): PiEntry | null {\n const base = {\n id: entry.id,\n seq: 0, // assigned at mutation-encoding time\n parentId: resolveV4Parent(entry, entries),\n timestamp: toEpochMillis(entry.timestamp),\n };\n switch (entry.type) {\n case \"message\":\n return { ...base, type: \"message\", message: entry.message };\n case \"custom_message\":\n return {\n ...base,\n type: \"message\",\n message: createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n };\n case \"thinking_level_change\":\n return { ...base, type: \"thinking_level_change\", thinkingLevel: entry.thinkingLevel };\n case \"model_change\":\n return { ...base, type: \"model_change\", provider: entry.provider, modelId: entry.modelId };\n case \"active_tools_change\":\n return { ...base, type: \"active_tools_change\", activeToolNames: entry.activeToolNames };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: entry.summary,\n retainedTail: entry.retainedTail ?? compactionKeptMessages(entry, entries),\n tokensBefore: entry.tokensBefore,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage as PiEntry & object } : {}),\n } as unknown as PiEntry;\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: entry.fromId,\n summary: entry.summary,\n ...(entry.details !== undefined ? { details: entry.details } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage } : {}),\n } as unknown as PiEntry;\n case \"custom\":\n return { ...base, type: \"custom\", customType: entry.customType, data: entry.data };\n default:\n // session_info / label / leaf become facts and the lane pointer.\n return null;\n }\n}\n\n/**\n * Skip fact-only ancestors (session_info/label/leaf) when re-linking the v4\n * tree: those entries disappear from the entry stream, so children re-attach\n * to the nearest surviving ancestor.\n */\nfunction resolveV4Parent(entry: V3Entry, entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((item) => [item.id, item]));\n let parentId = entry.parentId;\n while (parentId !== null) {\n const parent = byId.get(parentId);\n if (!parent) return null;\n if (parent.type !== \"session_info\" && parent.type !== \"label\" && parent.type !== \"leaf\") {\n return parentId;\n }\n parentId = parent.parentId;\n }\n return null;\n}\n\n/**\n * Messages of the v3 kept range (`firstKeptEntryId` .. compaction parent),\n * which v4 stores inline on the compaction entry.\n */\nfunction compactionKeptMessages(\n compaction: Extract<V3Entry, { type: \"compaction\" }>,\n entries: V3Entry[],\n): AgentMessage[] {\n if (!compaction.firstKeptEntryId) return [];\n const ancestors = v3Branch(entries, compaction.parentId);\n const keptStart = ancestors.findIndex((entry) => entry.id === compaction.firstKeptEntryId);\n if (keptStart === -1) return [];\n const messages: AgentMessage[] = [];\n for (const entry of ancestors.slice(keptStart)) {\n if (entry.type === \"message\") messages.push(entry.message);\n else if (entry.type === \"custom_message\") {\n messages.push(\n createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n );\n }\n }\n return messages;\n}\n\n// ── reference converter (verification oracle) ───────────────────────────────\n\n/**\n * Convert a v3 branch to v4 entries with the pi-0.83 context semantics:\n * the last compaction is repositioned ahead of its kept range so pi's v4\n * transform reproduces the v3 context exactly. This mirrors what the\n * runtime shim did before mikan moved to native v4 files, and serves as\n * the verification oracle for migrated output.\n */\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n let lastCompactionIndex = -1;\n for (let i = branch.length - 1; i >= 0; i--) {\n if (branch[i]?.type === \"compaction\") {\n lastCompactionIndex = i;\n break;\n }\n }\n const lastCompaction = branch[lastCompactionIndex] as\n | Extract<V3Entry, { type: \"compaction\" }>\n | undefined;\n const firstKeptId =\n lastCompaction && !lastCompaction.retainedTail ? lastCompaction.firstKeptEntryId : undefined;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n\n const ordered: V3Entry[] = [];\n if (firstKeptIndex !== -1 && lastCompaction) {\n ordered.push(...branch.slice(0, firstKeptIndex));\n ordered.push(lastCompaction);\n for (const [index, entry] of branch.entries()) {\n if (index >= firstKeptIndex && index !== lastCompactionIndex) ordered.push(entry);\n }\n } else {\n ordered.push(...branch);\n }\n\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n if (entry.type === \"compaction\" && entry === lastCompaction && firstKeptIndex !== -1) {\n converted.push({\n type: \"compaction\",\n id: entry.id,\n seq: 0,\n parentId: null,\n timestamp: toEpochMillis(entry.timestamp),\n summary: entry.summary,\n retainedTail: [],\n tokensBefore: entry.tokensBefore,\n });\n continue;\n }\n const piEntry = convertEntry(entry, []);\n if (piEntry) converted.push(piEntry);\n }\n let previousId: string | null = null;\n for (const [index, entry] of converted.entries()) {\n entry.seq = index;\n entry.parentId = previousId;\n previousId = entry.id;\n }\n return converted;\n}\n\n// ── v4 encoding ─────────────────────────────────────────────────────────────\n\nfunction buildV4Header(header: V3SessionHeader): JsonlV4Header {\n const {\n type: _type,\n version: _version,\n id,\n timestamp,\n cwd,\n parentSession,\n parentSessionId,\n ...extras\n } = header;\n const metadata: Record<string, unknown> = { ...extras };\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n return {\n kind: \"header\",\n version: 4,\n id,\n createdAt: toEpochMillis(timestamp),\n cwd,\n ...(parentSessionId !== undefined ? { parentSessionId } : {}),\n ...(Object.keys(metadata).length > 0\n ? { metadata: metadata as JsonlV4Header[\"metadata\"] }\n : {}),\n };\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const lines: string[] = [JSON.stringify(buildV4Header(file.header))];\n let seq = 0;\n const push = (mutation: Record<string, unknown>) => {\n lines.push(JSON.stringify(mutation));\n };\n\n let name: string | undefined;\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n for (const entry of file.entries) {\n if (entry.type === \"session_info\") {\n name = entry.name?.trim() || undefined;\n continue;\n }\n if (entry.type === \"label\") {\n labels.push({ targetId: entry.targetId, label: entry.label });\n continue;\n }\n if (entry.type === \"leaf\") continue;\n const converted = convertEntry(entry, file.entries);\n if (!converted) continue;\n converted.seq = ++seq;\n // Entry mutations are encoded flat: {kind:\"entry\", ...entry fields}.\n push({ kind: \"entry\", ...converted });\n }\n\n // The v3 leaf may point at a fact-only entry (session_info/label) that\n // does not survive as a v4 entry; re-aim the lane at its nearest surviving\n // ancestor, mirroring resolveV4Parent.\n let leafId = v3LeafId(file.entries);\n const byId = new Map(file.entries.map((entry) => [entry.id, entry]));\n while (leafId !== null) {\n const target = byId.get(leafId);\n if (!target) {\n leafId = null;\n break;\n }\n if (target.type !== \"session_info\" && target.type !== \"label\" && target.type !== \"leaf\") {\n break;\n }\n leafId = target.parentId;\n }\n push({ kind: \"lane\", seq: ++seq, lane: \"main\", leafId });\n if (name !== undefined) push({ kind: \"fact\", seq: ++seq, fact: \"name\", name });\n for (const { targetId, label } of labels) {\n push({ kind: \"fact\", seq: ++seq, fact: \"label\", targetId, label });\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ── migration driver ────────────────────────────────────────────────────────\n\nasync function verifyMigratedFile(v4Path: string, source: V3SessionFile): Promise<void> {\n const store = await SessionStore.inspect(v4Path);\n const migratedContext = await store.buildSessionContext();\n const branch = v3Branch(source.entries, v3LeafId(source.entries));\n const referenceContext = buildSessionContext(referenceContextEntries(branch));\n const migrated = JSON.stringify(migratedContext.messages);\n const reference = JSON.stringify(referenceContext.messages);\n if (migrated !== reference) {\n throw new Error(\"migrated context does not match the v3 reference context\");\n }\n const migratedName = await store.getSessionName();\n const v3Name = [...source.entries]\n .toReversed()\n .find((entry) => entry.type === \"session_info\")\n ?.name?.trim();\n if ((migratedName ?? \"\") !== (v3Name || \"\")) {\n throw new Error(\"migrated session name does not match the v3 session name\");\n }\n}\n\n/**\n * Migrate one session file in place. The migrated file is verified against\n * the v3 reference semantics before it replaces the original; the original\n * is preserved as `<file>.v3.bak`.\n */\nexport async function migrateSessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<MigrateResult> {\n if (!isV3SessionFile(filePath)) return { file: filePath, status: \"already-v4\" };\n const source = readV3SessionFile(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n const tempPath = `${filePath}.v4.tmp`;\n atomicWritePrivateFile(tempPath, encodeV4File(source));\n try {\n await verifyMigratedFile(tempPath, source);\n } catch (error) {\n rmSync(tempPath, { force: true });\n throw new Error(`Verification failed for ${filePath}`, { cause: error });\n }\n renameSync(filePath, `${filePath}.v3.bak`);\n renameSync(tempPath, filePath);\n return { file: filePath, status: \"migrated\" };\n}\n\n/** Recursively find candidate session files (.jsonl with a v3 header). */\nexport function findV3SessionFiles(root: string): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const name of readdirSync(dir)) {\n const path = join(dir, name);\n let stats;\n try {\n stats = statSync(path);\n } catch {\n continue;\n }\n if (stats.isDirectory()) {\n walk(path);\n } else if (name.endsWith(\".jsonl\") && isV3SessionFile(path)) {\n found.push(path);\n }\n }\n };\n walk(root);\n return found;\n}\n"]}
1
+ {"version":3,"file":"migrate-v3.js","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,mBAAmB,GAIpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAgEjE,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAuB,CAAC;QAC3D,OAAO,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;SAC1C,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,OAAO,GAA8B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC;gBAAE,SAAS;YACtD,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,GAAG,CAAC,OAAO,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,kDAAkD;IAClD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC/C,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAS;QAC/E,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACxC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAA4B,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAoC,EAAE,OAAO,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED,+EAA+E;AAC/E,SAAS,QAAQ,CAAC,OAAkB,EAAE,MAAqB;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,MAAM,CAAC;IACvB,OAAO,SAAS,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,MAAM;QAClB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,QAAQ,CAAC,OAAkB;IAClC,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gFAAgF;AAChF,SAAS,YAAY,CAAC,KAAc,EAAE,OAAkB;IACtD,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,GAAG,EAAE,CAAC,EAAE,qCAAqC;QAC7C,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC;QACzC,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;KAC1C,CAAC;IACF,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC9D,KAAK,gBAAgB;YACnB,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,mBAAmB,CAC1B,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAC/B;aACF,CAAC;QACJ,KAAK,uBAAuB,CAAC;QAC7B,KAAK,cAAc,CAAC;QACpB,KAAK,qBAAqB,EAAE,CAAC;YAC3B,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;YACrF,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,gBAAgB,IAAI,EAAE;gBAClC,IAAI,EAAE,IAAiB;aACxB,CAAC;QACJ,CAAC;QACD,KAAK,YAAY;YACf,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC;gBAC1E,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,QAAQ,EAAE,KAAK;gBACf,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvC,CAAC;QAC1B,KAAK,gBAAgB;YACnB,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;gBAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,QAAQ,EAAE,KAAK;gBACf,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvC,CAAC;QAC1B,KAAK,QAAQ;YACX,OAAO;gBACL,GAAG,IAAI;gBACP,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvE,CAAC;QACJ;YACE,iEAAiE;YACjE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAc,EAAE,OAAkB;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,OAAO,QAAQ,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,sBAAsB,CAC7B,UAAoD,EACpD,OAAkB;IAElB,IAAI,CAAC,UAAU,CAAC,gBAAgB;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC3F,IAAI,SAAS,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;aACtD,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CACX,mBAAmB,CACjB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,OAAO,EACb,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAC/B,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E;;;;;;GAMG;AACH,SAAS,uBAAuB,CAAC,MAAiB;IAChD,IAAI,mBAAmB,GAAG,CAAC,CAAC,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;YACrC,mBAAmB,GAAG,CAAC,CAAC;YACxB,MAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAEpC,CAAC;IACd,MAAM,WAAW,GACf,cAAc,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/F,MAAM,cAAc,GAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;IAEzF,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,IAAI,cAAc,KAAK,CAAC,CAAC,IAAI,cAAc,EAAE,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,IAAI,KAAK,IAAI,cAAc,IAAI,KAAK,KAAK,mBAAmB;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,SAAS,GAAc,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,KAAK,cAAc,IAAI,cAAc,KAAK,CAAC,CAAC,EAAE,CAAC;YACrF,SAAS,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,YAAY;gBAClB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,GAAG,EAAE,CAAC;gBACN,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC;gBACzC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,YAAY,EAAE,EAAE;gBAChB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACxC,IAAI,OAAO;YAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC;QAClB,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;QAC5B,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,uBAAuB,CAAC,OAAqB;IACpD,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,WAAW;QAC5B,CAAC,OAAO,CAAC,UAAU,KAAK,OAAO;YAC7B,OAAO,CAAC,UAAU,KAAK,SAAS;YAChC,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC,CACrC,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,OAAkB;IAClD,MAAM,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IACtF,MAAM,OAAO,GACX,eAAe,KAAK,CAAC,CAAC;QACpB,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,uBAAuB,CAAC,KAAK,CAAC,OAAO,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACvC,QAAQ,CAAC,IAAI,CACX,8BAA8B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,EAClF,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,uBAAuB,CAAC,CACtD,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC5D,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,+EAA+E;AAE/E,SAAS,aAAa,CAAC,MAAuB;IAC5C,OAAO;QACL,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,QAAQ;QACd,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,cAAc,EAAE,CAAC;QACjB,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC;QAC1C,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,GAAG,CAAC,MAAM,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,GAAG,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS;YACpC,CAAC,CAAC,EAAE,uBAAuB,EAAE,MAAM,CAAC,aAAa,EAAE;YACnD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB;IACvC,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,IAAI,GAAG,CAAC,KAA8B,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAEnF,IAAI,IAAwB,CAAC;IAC7B,MAAM,MAAM,GAA2D,EAAE,CAAC;IAC1E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC9D,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACpC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,SAAS,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC;QACtB,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACrE,OAAO,MAAM,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,CAAC;YACd,MAAM;QACR,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM;QAC/F,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC;QACH,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,KAAK;QACT,GAAG,EAAE,EAAE,GAAG;QACV,SAAS,EAAE,eAAe;QAC1B,GAAG,EAAE,MAAM;QACX,KAAK,EAAE,MAAM;KACd,CAAC,CAAC;IACH,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,KAAK;YACT,GAAG,EAAE,EAAE,GAAG;YACV,SAAS,EAAE,iBAAiB;YAC5B,GAAG,EAAE,EAAE;YACP,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QACzC,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,CAAC;YACH,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,KAAK;YACT,GAAG,EAAE,EAAE,GAAG;YACV,SAAS,EAAE,gBAAgB;YAC3B,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;IACD,MAAM,EACJ,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,QAAQ,EACjB,EAAE,EAAE,GAAG,EACP,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,IAAI,EACT,aAAa,EACb,eAAe,EAAE,gBAAgB,EACjC,GAAG,MAAM,EACV,GAAG,IAAI,CAAC,MAAM,CAAC;IAChB,MAAM,QAAQ,GAA8B,MAAmC,CAAC;IAChF,IAAI,aAAa,KAAK,SAAS;QAAE,QAAQ,CAAC,iBAAiB,GAAG,aAAa,CAAC;IAC5E,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,IAAI,EAAE,OAAO;YACb,EAAE,EAAE,KAAK;YACT,GAAG,EAAE,EAAE,GAAG;YACV,SAAS,EAAE,OAAO;YAClB,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,+EAA+E;AAE/E,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAqB;IACrE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,MAAM,KAAK,CAAC,mBAAmB,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5F,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;SAC/B,UAAU,EAAE;SACZ,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;QAC/C,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjB,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,UAAkB,EAAE,UAAkB;IACjE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACxE,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,OAA8B;IAE9B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAChF,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,OAAO,EAAE,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAEtF,MAAM,QAAQ,GAAG,GAAG,QAAQ,SAAS,CAAC;IACtC,MAAM,UAAU,GAAG,GAAG,QAAQ,SAAS,CAAC;IACxC,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/D,sBAAsB,CAAC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY;YAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAClD,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE;QAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,KAAK,CAAC;YACV,IAAI,CAAC;gBACH,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,SAAS;YACrC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * One-time migration of legacy v3 session files to pi's v4 JSONL format.\n *\n * v3 is the entry family mikan wrote up to pi 0.83: a `{\"type\":\"session\"}`\n * header followed by tree entries with string ISO timestamps and compaction\n * entries that point at `firstKeptEntryId`. Current Pi v4 uses a\n * `{\"v\":4,\"kind\":\"header\",\"storageVersion\":1}` header followed by\n * transactional writes with numeric timestamps and consecutive sequences.\n *\n * The migration preserves entry ids, parent links, and timestamps, converts\n * `custom_message` entries into v4 `custom`-role messages, folds\n * `session_info` into the v4 name fact, `label` entries into label facts,\n * and rewrites each compaction's kept range into its inline `retainedTail`.\n * Every migrated file is verified before it replaces the original: the v4\n * file is re-opened with pi's reader and its built context must equal the\n * v3 context computed by the reference converter below. The original file\n * is kept beside the migrated one as `<name>.v3.bak`.\n */\nimport {\n existsSync,\n linkSync,\n lstatSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n createBranchSummaryMessage,\n createCompactionSummaryMessage,\n createCustomMessage,\n type AgentMessage,\n type Entry as PiEntry,\n type JsonValue,\n} from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"../harness/session-store.js\";\nimport { atomicWritePrivateFile } from \"../utils/file-guards.js\";\nimport type { MigrateResult } from \"./types.js\";\nexport type { MigrateResult } from \"./types.js\";\n\n// ── v3 shapes ────────────────────────────────────────────────────────────────\n\ninterface V3EntryBase {\n type: string;\n id: string;\n parentId: string | null;\n timestamp: string;\n}\n\ntype V3Entry = V3EntryBase &\n (\n | { type: \"message\"; message: AgentMessage }\n | { type: \"thinking_level_change\"; thinkingLevel: string }\n | { type: \"model_change\"; provider: string; modelId: string }\n | { type: \"active_tools_change\"; activeToolNames: string[] }\n | {\n type: \"compaction\";\n summary: string;\n firstKeptEntryId?: string;\n tokensBefore: number;\n retainedTail?: AgentMessage[];\n details?: unknown;\n usage?: unknown;\n }\n | {\n type: \"branch_summary\";\n fromId: string;\n summary: string;\n details?: unknown;\n usage?: unknown;\n }\n | { type: \"custom\"; customType: string; data?: unknown }\n | {\n type: \"custom_message\";\n customType: string;\n content: Parameters<typeof createCustomMessage>[1];\n display: boolean;\n details?: unknown;\n }\n | { type: \"label\"; targetId: string; label: string | undefined }\n | { type: \"session_info\"; name?: string }\n | { type: \"leaf\"; targetId: string | null }\n );\n\ninterface V3SessionHeader {\n type: \"session\";\n version?: number;\n id: string;\n timestamp: string;\n cwd: string;\n parentSession?: string;\n parentSessionId?: string;\n [extra: string]: unknown;\n}\n\ninterface V3SessionFile {\n header: V3SessionHeader;\n entries: V3Entry[];\n}\n\n/** Whether a file's first non-empty line is a v3 session header. */\nexport function isV3SessionFile(filePath: string): boolean {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const firstLine = content.split(\"\\n\").find((line) => line.trim().length > 0);\n if (!firstLine) return false;\n const parsed = JSON.parse(firstLine) as { type?: unknown };\n return parsed.type === \"session\";\n } catch {\n return false;\n }\n}\n\n/** Read a v3 session file, ignoring a torn final line (crash tail). */\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const lines = readFileSync(filePath, \"utf-8\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const records: Record<string, unknown>[] = [];\n for (const [index, line] of lines.entries()) {\n try {\n records.push(JSON.parse(line) as Record<string, unknown>);\n } catch (error) {\n if (index === lines.length - 1 && index > 0) continue;\n throw new Error(`Invalid JSON on line ${index + 1} of ${filePath}`, { cause: error });\n }\n }\n const header = records[0];\n if (!header || header.type !== \"session\" || typeof header.id !== \"string\") {\n throw new Error(`Not a v3 session file: ${filePath}`);\n }\n // Crash-era v3 files can contain duplicated lines (a retried append wrote\n // the header+entry pair twice). The v3 runtime read entries into a Map, so\n // duplicates were silently collapsed; v4 rejects duplicate mutation ids.\n // Reproduce the v3 Map semantics: a repeated id replaces its payload while\n // retaining the id's original insertion position.\n const entriesById = new Map<string, V3Entry>();\n for (const record of records.slice(1)) {\n if (typeof record.type !== \"string\" || typeof record.id !== \"string\") continue;\n if (record.type === \"session\") continue;\n entriesById.set(record.id, record as unknown as V3Entry);\n }\n return { header: header as unknown as V3SessionHeader, entries: [...entriesById.values()] };\n}\n\nfunction toEpochMillis(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\n/** Walk a v3 tree from an entry to the root; returns root-first path order. */\nfunction v3Branch(entries: V3Entry[], fromId: string | null): V3Entry[] {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n const path: V3Entry[] = [];\n let currentId = fromId;\n while (currentId) {\n const entry = byId.get(currentId);\n if (!entry) break;\n path.push(entry);\n currentId = entry.parentId;\n }\n return path.toReversed();\n}\n\nfunction v3LeafId(entries: V3Entry[]): string | null {\n let leafId: string | null = null;\n for (const entry of entries) {\n leafId = entry.type === \"leaf\" ? entry.targetId : entry.id;\n }\n return leafId;\n}\n\n/** Convert one tree-shaping v3 entry to its v4 counterpart (facts excluded). */\nfunction convertEntry(entry: V3Entry, entries: V3Entry[]): PiEntry | null {\n const base = {\n id: entry.id,\n seq: 0, // assigned at mutation-encoding time\n parentId: resolveV4Parent(entry, entries),\n timestamp: toEpochMillis(entry.timestamp),\n };\n switch (entry.type) {\n case \"message\":\n return { ...base, type: \"message\", message: entry.message };\n case \"custom_message\":\n return {\n ...base,\n type: \"message\",\n message: createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n };\n case \"thinking_level_change\":\n case \"model_change\":\n case \"active_tools_change\": {\n const { id: _id, parentId: _parentId, timestamp: _timestamp, type, ...data } = entry;\n return {\n ...base,\n type: \"custom\",\n customType: `mikan.legacy.${type}`,\n data: data as JsonValue,\n };\n }\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: entry.summary,\n retainedTail: entry.retainedTail ?? compactionKeptMessages(entry, entries),\n tokensBefore: entry.tokensBefore,\n fromHook: false,\n ...(entry.details !== undefined ? { details: entry.details as JsonValue } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage } : {}),\n } as unknown as PiEntry;\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: entry.fromId ?? null,\n summary: entry.summary,\n fromHook: false,\n ...(entry.details !== undefined ? { details: entry.details as JsonValue } : {}),\n ...(entry.usage !== undefined ? { usage: entry.usage } : {}),\n } as unknown as PiEntry;\n case \"custom\":\n return {\n ...base,\n type: \"custom\",\n customType: entry.customType,\n ...(entry.data !== undefined ? { data: entry.data as JsonValue } : {}),\n };\n default:\n // session_info / label / leaf become facts and the lane pointer.\n return null;\n }\n}\n\n/**\n * Skip fact-only ancestors (session_info/label/leaf) when re-linking the v4\n * tree: those entries disappear from the entry stream, so children re-attach\n * to the nearest surviving ancestor.\n */\nfunction resolveV4Parent(entry: V3Entry, entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((item) => [item.id, item]));\n let parentId = entry.parentId;\n while (parentId !== null) {\n const parent = byId.get(parentId);\n if (!parent) return null;\n if (parent.type !== \"session_info\" && parent.type !== \"label\" && parent.type !== \"leaf\") {\n return parentId;\n }\n parentId = parent.parentId;\n }\n return null;\n}\n\n/**\n * Messages of the v3 kept range (`firstKeptEntryId` .. compaction parent),\n * which v4 stores inline on the compaction entry.\n */\nfunction compactionKeptMessages(\n compaction: Extract<V3Entry, { type: \"compaction\" }>,\n entries: V3Entry[],\n): AgentMessage[] {\n if (!compaction.firstKeptEntryId) return [];\n const ancestors = v3Branch(entries, compaction.parentId);\n const keptStart = ancestors.findIndex((entry) => entry.id === compaction.firstKeptEntryId);\n if (keptStart === -1) return [];\n const messages: AgentMessage[] = [];\n for (const entry of ancestors.slice(keptStart)) {\n if (entry.type === \"message\") messages.push(entry.message);\n else if (entry.type === \"custom_message\") {\n messages.push(\n createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n ),\n );\n }\n }\n return messages;\n}\n\n// ── reference converter (verification oracle) ───────────────────────────────\n\n/**\n * Convert a v3 branch to v4 entries with the pi-0.83 context semantics:\n * the last compaction is repositioned ahead of its kept range so pi's v4\n * transform reproduces the v3 context exactly. This mirrors what the\n * runtime shim did before mikan moved to native v4 files, and serves as\n * the verification oracle for migrated output.\n */\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n let lastCompactionIndex = -1;\n for (let i = branch.length - 1; i >= 0; i--) {\n if (branch[i]?.type === \"compaction\") {\n lastCompactionIndex = i;\n break;\n }\n }\n const lastCompaction = branch[lastCompactionIndex] as\n | Extract<V3Entry, { type: \"compaction\" }>\n | undefined;\n const firstKeptId =\n lastCompaction && !lastCompaction.retainedTail ? lastCompaction.firstKeptEntryId : undefined;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n\n const ordered: V3Entry[] = [];\n if (firstKeptIndex !== -1 && lastCompaction) {\n ordered.push(...branch.slice(0, firstKeptIndex));\n ordered.push(lastCompaction);\n for (const [index, entry] of branch.entries()) {\n if (index >= firstKeptIndex && index !== lastCompactionIndex) ordered.push(entry);\n }\n } else {\n ordered.push(...branch);\n }\n\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n if (entry.type === \"compaction\" && entry === lastCompaction && firstKeptIndex !== -1) {\n converted.push({\n type: \"compaction\",\n id: entry.id,\n seq: 0,\n parentId: null,\n timestamp: toEpochMillis(entry.timestamp),\n summary: entry.summary,\n retainedTail: [],\n tokensBefore: entry.tokensBefore,\n fromHook: false,\n });\n continue;\n }\n const piEntry = convertEntry(entry, []);\n if (piEntry) converted.push(piEntry);\n }\n let previousId: string | null = null;\n for (const [index, entry] of converted.entries()) {\n entry.seq = index;\n entry.parentId = previousId;\n previousId = entry.id;\n }\n return converted;\n}\n\nfunction isCurrentContextMessage(message: AgentMessage): boolean {\n return (\n message.role !== \"assistant\" ||\n (message.stopReason !== \"error\" &&\n message.stopReason !== \"aborted\" &&\n message.stopReason !== \"deferred\")\n );\n}\n\nfunction referenceContextMessages(entries: PiEntry[]): AgentMessage[] {\n const compactionIndex = entries.findLastIndex((entry) => entry.type === \"compaction\");\n const visible =\n compactionIndex === -1\n ? entries\n : [entries[compactionIndex]!, ...entries.slice(compactionIndex + 1)];\n const messages: AgentMessage[] = [];\n for (const entry of visible) {\n if (entry.type === \"message\") {\n if (isCurrentContextMessage(entry.message)) messages.push(entry.message);\n } else if (entry.type === \"compaction\") {\n messages.push(\n createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp),\n ...entry.retainedTail.filter(isCurrentContextMessage),\n );\n } else if (entry.type === \"branch_summary\" && entry.summary) {\n messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));\n }\n }\n return messages;\n}\n\n// ── v4 encoding ─────────────────────────────────────────────────────────────\n\nfunction buildV4Header(header: V3SessionHeader): Record<string, unknown> {\n return {\n v: 4,\n kind: \"header\",\n id: header.id,\n storageVersion: 1,\n createdAt: toEpochMillis(header.timestamp),\n cwd: header.cwd,\n ...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),\n ...(header.parentSession !== undefined\n ? { legacyParentSessionPath: header.parentSession }\n : {}),\n };\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const lines: string[] = [JSON.stringify(buildV4Header(file.header))];\n let seq = 0;\n const push = (write: Record<string, unknown>) => lines.push(JSON.stringify(write));\n\n let name: string | undefined;\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n for (const entry of file.entries) {\n if (entry.type === \"session_info\") {\n name = entry.name?.trim() || undefined;\n continue;\n }\n if (entry.type === \"label\") {\n labels.push({ targetId: entry.targetId, label: entry.label });\n continue;\n }\n if (entry.type === \"leaf\") continue;\n const converted = convertEntry(entry, file.entries);\n if (!converted) continue;\n converted.seq = ++seq;\n push({ kind: \"entry\", ...converted });\n }\n\n let leafId = v3LeafId(file.entries);\n const byId = new Map(file.entries.map((entry) => [entry.id, entry]));\n while (leafId !== null) {\n const target = byId.get(leafId);\n if (!target) {\n leafId = null;\n break;\n }\n if (target.type !== \"session_info\" && target.type !== \"label\" && target.type !== \"leaf\") break;\n leafId = target.parentId;\n }\n push({\n kind: \"value\",\n op: \"set\",\n seq: ++seq,\n namespace: \"pi.branch.tip\",\n key: \"main\",\n value: leafId,\n });\n if (name !== undefined) {\n push({\n kind: \"value\",\n op: \"set\",\n seq: ++seq,\n namespace: \"pi.session.name\",\n key: \"\",\n value: name,\n });\n }\n for (const { targetId, label } of labels) {\n if (label === undefined) continue;\n push({\n kind: \"value\",\n op: \"set\",\n seq: ++seq,\n namespace: \"pi.entry.label\",\n key: targetId,\n value: label,\n });\n }\n const {\n type: _type,\n version: _version,\n id: _id,\n timestamp: _timestamp,\n cwd: _cwd,\n parentSession,\n parentSessionId: _parentSessionId,\n ...extras\n } = file.header;\n const metadata: Record<string, JsonValue> = extras as Record<string, JsonValue>;\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n if (Object.keys(metadata).length > 0) {\n push({\n kind: \"value\",\n op: \"set\",\n seq: ++seq,\n namespace: \"mikan\",\n key: \"metadata\",\n value: metadata,\n });\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ── migration driver ────────────────────────────────────────────────────────\n\nasync function verifyMigratedFile(v4Path: string, source: V3SessionFile): Promise<void> {\n const store = await SessionStore.inspect(v4Path);\n const migratedContext = await store.buildSessionContext();\n const branch = v3Branch(source.entries, v3LeafId(source.entries));\n const migrated = JSON.stringify(migratedContext.messages);\n const reference = JSON.stringify(referenceContextMessages(referenceContextEntries(branch)));\n if (migrated !== reference) {\n throw new Error(\"migrated context does not match the v3 reference context\");\n }\n const migratedName = await store.getSessionName();\n const v3Name = [...source.entries]\n .toReversed()\n .find((entry) => entry.type === \"session_info\")\n ?.name?.trim();\n if ((migratedName ?? \"\") !== (v3Name || \"\")) {\n throw new Error(\"migrated session name does not match the v3 session name\");\n }\n}\n\n/**\n * Migrate one session file in place. The migrated file is verified against\n * the v3 reference semantics before it replaces the original; the original\n * is preserved as `<file>.v3.bak`.\n */\nfunction backupAlreadyLinked(sourcePath: string, backupPath: string): boolean {\n if (!existsSync(backupPath)) return false;\n const source = statSync(sourcePath);\n const backup = statSync(backupPath);\n if (source.dev === backup.dev && source.ino === backup.ino) return true;\n throw new Error(`Backup already exists: ${backupPath}`);\n}\n\nexport async function migrateSessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<MigrateResult> {\n if (!isV3SessionFile(filePath)) return { file: filePath, status: \"already-v4\" };\n const sourceBytes = readFileSync(filePath);\n const source = readV3SessionFile(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n const tempPath = `${filePath}.v4.tmp`;\n const backupPath = `${filePath}.v3.bak`;\n const backupLinked = backupAlreadyLinked(filePath, backupPath);\n atomicWritePrivateFile(tempPath, encodeV4File(source));\n try {\n await verifyMigratedFile(tempPath, source);\n if (!readFileSync(filePath).equals(sourceBytes))\n throw new Error(\"source changed during migration\");\n if (!backupLinked) linkSync(filePath, backupPath);\n renameSync(tempPath, filePath);\n } catch (error) {\n rmSync(tempPath, { force: true });\n throw new Error(`Migration failed for ${filePath}`, { cause: error });\n }\n return { file: filePath, status: \"migrated\" };\n}\n\n/** Recursively find candidate session files (.jsonl with a v3 header). */\nexport function findV3SessionFiles(root: string): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const name of readdirSync(dir)) {\n const path = join(dir, name);\n let stats;\n try {\n stats = lstatSync(path);\n } catch {\n continue;\n }\n if (stats.isSymbolicLink()) continue;\n if (stats.isDirectory()) {\n walk(path);\n } else if (name.endsWith(\".jsonl\") && isV3SessionFile(path)) {\n found.push(path);\n }\n }\n };\n walk(root);\n return found;\n}\n"]}
@@ -8,7 +8,7 @@ export interface MikanSessionHeader {
8
8
  timestamp?: string;
9
9
  cwd?: string;
10
10
  parentSession?: string;
11
- /** Legacy platform-history marker; preserved in v4 header metadata. */
11
+ /** Legacy platform-history marker; preserved in mikan's durable session metadata. */
12
12
  source?: {
13
13
  kind?: string;
14
14
  file?: string;
@@ -97,4 +97,9 @@ export interface MigrateResult {
97
97
  status: "migrated" | "already-v4" | "skipped";
98
98
  detail?: string;
99
99
  }
100
+ export interface Pi084MigrationResult {
101
+ file: string;
102
+ status: "migrated" | "already-current" | "not-pi-084";
103
+ detail?: string;
104
+ }
100
105
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ConversationKind } from \"../adapter.js\";\nimport type { SessionStore } from \"../harness/index.js\";\nimport type { ConversationLogMessage } from \"../types.js\";\n\n// ── session metadata ─────────────────────────────────────────────────────────\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n /** Legacy platform-history marker; preserved in v4 header metadata. */\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\n// ── session policy ───────────────────────────────────────────────────────────\n\nexport interface ResolveSessionKeyOptions {\n conversationId: string;\n conversationKind: ConversationKind;\n messageId: string;\n threadTs?: string;\n persistentTopLevel?: boolean;\n scopeDirectThreads?: boolean;\n}\n\n// ── session store ────────────────────────────────────────────────────────────\n\nexport interface ParentSessionRef {\n path: string;\n id: string;\n}\n\nexport interface ThreadRootMessage {\n text?: string;\n userName?: string;\n user?: string;\n loggedAt?: number;\n isMessagingBot?: boolean;\n}\n\nexport interface ResolvedSessionScope {\n sessionDir: string;\n contextFile: string;\n threadRootMessage: ThreadRootMessage | null;\n}\n\n/** One parsed log.jsonl entry with its original line index. */\nexport interface LogRecord {\n message: ConversationLogMessage;\n index: number;\n}\n\n// ── chat history sync ────────────────────────────────────────────────────────\n\n/** What one sync pass actually did — the inspectable result of a sync. */\nexport interface ChatSyncReport {\n /** Log messages appended to the session in this pass. */\n appended: number;\n /** The log message id recorded as the new sync watermark. */\n lastMessageId?: string;\n}\n\nexport interface ChatHistorySyncOptions {\n recentDays?: number;\n maxTopLevelMessages?: number;\n now?: () => Date;\n}\n\nexport interface ResolveChatSessionScopeOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n /** The triggering platform message ID. History is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface SyncChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n sessionManager: SessionStore;\n /** The triggering platform message ID. Sync is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface ResetChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface RegisterThreadSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface HasMaterializedSessionOptions {\n conversationDir: string;\n sessionKey: string;\n}\n\nexport interface ThreadBootstrapWaitOptions {\n parentSessionKey: string;\n sessionKey: string;\n hasThreadSession: () => boolean;\n isParentRunning: () => boolean;\n sleep?: (ms: number) => Promise<void>;\n pollMs?: number;\n}\n\n// ── v3 migration ─────────────────────────────────────────────────────────────\n\nexport interface MigrateResult {\n file: string;\n status: \"migrated\" | \"already-v4\" | \"skipped\";\n detail?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ConversationKind } from \"../adapter.js\";\nimport type { SessionStore } from \"../harness/index.js\";\nimport type { ConversationLogMessage } from \"../types.js\";\n\n// ── session metadata ─────────────────────────────────────────────────────────\n\nexport interface MikanSessionHeader {\n type?: string;\n version?: number;\n id?: string;\n timestamp?: string;\n cwd?: string;\n parentSession?: string;\n /** Legacy platform-history marker; preserved in mikan's durable session metadata. */\n source?: {\n kind?: string;\n file?: string;\n recentDays?: number;\n };\n}\n\n// ── session policy ───────────────────────────────────────────────────────────\n\nexport interface ResolveSessionKeyOptions {\n conversationId: string;\n conversationKind: ConversationKind;\n messageId: string;\n threadTs?: string;\n persistentTopLevel?: boolean;\n scopeDirectThreads?: boolean;\n}\n\n// ── session store ────────────────────────────────────────────────────────────\n\nexport interface ParentSessionRef {\n path: string;\n id: string;\n}\n\nexport interface ThreadRootMessage {\n text?: string;\n userName?: string;\n user?: string;\n loggedAt?: number;\n isMessagingBot?: boolean;\n}\n\nexport interface ResolvedSessionScope {\n sessionDir: string;\n contextFile: string;\n threadRootMessage: ThreadRootMessage | null;\n}\n\n/** One parsed log.jsonl entry with its original line index. */\nexport interface LogRecord {\n message: ConversationLogMessage;\n index: number;\n}\n\n// ── chat history sync ────────────────────────────────────────────────────────\n\n/** What one sync pass actually did — the inspectable result of a sync. */\nexport interface ChatSyncReport {\n /** Log messages appended to the session in this pass. */\n appended: number;\n /** The log message id recorded as the new sync watermark. */\n lastMessageId?: string;\n}\n\nexport interface ChatHistorySyncOptions {\n recentDays?: number;\n maxTopLevelMessages?: number;\n now?: () => Date;\n}\n\nexport interface ResolveChatSessionScopeOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n /** The triggering platform message ID. History is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface SyncChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n sessionManager: SessionStore;\n /** The triggering platform message ID. Sync is capped before this turn to avoid future queued turns. */\n currentMessageId?: string;\n}\n\nexport interface ResetChatSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface RegisterThreadSessionOptions {\n conversationDir: string;\n sessionKey: string;\n cwd?: string;\n}\n\nexport interface HasMaterializedSessionOptions {\n conversationDir: string;\n sessionKey: string;\n}\n\nexport interface ThreadBootstrapWaitOptions {\n parentSessionKey: string;\n sessionKey: string;\n hasThreadSession: () => boolean;\n isParentRunning: () => boolean;\n sleep?: (ms: number) => Promise<void>;\n pollMs?: number;\n}\n\n// ── v3 migration ─────────────────────────────────────────────────────────────\n\nexport interface MigrateResult {\n file: string;\n status: \"migrated\" | \"already-v4\" | \"skipped\";\n detail?: string;\n}\n\nexport interface Pi084MigrationResult {\n file: string;\n status: \"migrated\" | \"already-current\" | \"not-pi-084\";\n detail?: string;\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -427,7 +427,9 @@ export interface AgentConfig {
427
427
  /**
428
428
  * MCP servers available to this scope, keyed by server name. Global and
429
429
  * conversation entries merge per key (conversation wins); an entry with
430
- * `disabled: true` turns off the inherited server. See `src/mcp`.
430
+ * `disabled: true` turns off the inherited server. The reserved
431
+ * `open-connector` entry is ignored at runner construction; its startup
432
+ * configuration is authoritative. See `src/mcp`.
431
433
  */
432
434
  mcpServers?: Record<string, McpServerConfig>;
433
435
  }
@@ -625,6 +627,8 @@ export interface CreateRunnerOptions {
625
627
  trustModel: PlatformTrustModel;
626
628
  /** Platform workspace/team identity used by host-side integration provisioning. */
627
629
  platformWorkspaceId?: string;
630
+ /** Startup-owned OpenConnector MCP endpoint; settings cannot replace it. */
631
+ openConnector?: McpServerConfig;
628
632
  sessionScope: ResolvedSessionScope;
629
633
  /** Cancels construction during process shutdown; acquired resources still roll back before rejection. */
630
634
  signal?: AbortSignal;