@geminixiang/mikan 1.0.0-beta.76 → 1.0.0-beta.78

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 (535) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/adapters/commands/login.d.ts.map +1 -1
  3. package/dist/adapters/commands/login.js +0 -9
  4. package/dist/adapters/commands/login.js.map +1 -1
  5. package/dist/adapters/commands/manifest.d.ts +0 -19
  6. package/dist/adapters/commands/manifest.d.ts.map +1 -1
  7. package/dist/adapters/commands/manifest.js +0 -34
  8. package/dist/adapters/commands/manifest.js.map +1 -1
  9. package/dist/adapters/commands/model.d.ts +0 -5
  10. package/dist/adapters/commands/model.d.ts.map +1 -1
  11. package/dist/adapters/commands/model.js +0 -5
  12. package/dist/adapters/commands/model.js.map +1 -1
  13. package/dist/adapters/commands/new.d.ts.map +1 -1
  14. package/dist/adapters/commands/new.js +0 -2
  15. package/dist/adapters/commands/new.js.map +1 -1
  16. package/dist/adapters/commands/registry.d.ts +0 -1
  17. package/dist/adapters/commands/registry.d.ts.map +1 -1
  18. package/dist/adapters/commands/registry.js +0 -8
  19. package/dist/adapters/commands/registry.js.map +1 -1
  20. package/dist/adapters/commands/session-view.d.ts.map +1 -1
  21. package/dist/adapters/commands/session-view.js +0 -2
  22. package/dist/adapters/commands/session-view.js.map +1 -1
  23. package/dist/adapters/commands/types.d.ts +0 -29
  24. package/dist/adapters/commands/types.d.ts.map +1 -1
  25. package/dist/adapters/commands/types.js.map +1 -1
  26. package/dist/adapters/commands/utils.d.ts +0 -3
  27. package/dist/adapters/commands/utils.d.ts.map +1 -1
  28. package/dist/adapters/commands/utils.js +0 -3
  29. package/dist/adapters/commands/utils.js.map +1 -1
  30. package/dist/adapters/discord/bot.d.ts +0 -4
  31. package/dist/adapters/discord/bot.d.ts.map +1 -1
  32. package/dist/adapters/discord/bot.js +5 -41
  33. package/dist/adapters/discord/bot.js.map +1 -1
  34. package/dist/adapters/discord/components.d.ts +0 -23
  35. package/dist/adapters/discord/components.d.ts.map +1 -1
  36. package/dist/adapters/discord/components.js +0 -23
  37. package/dist/adapters/discord/components.js.map +1 -1
  38. package/dist/adapters/discord/context.d.ts.map +1 -1
  39. package/dist/adapters/discord/context.js +1 -11
  40. package/dist/adapters/discord/context.js.map +1 -1
  41. package/dist/adapters/discord/format.d.ts +0 -1
  42. package/dist/adapters/discord/format.d.ts.map +1 -1
  43. package/dist/adapters/discord/format.js +0 -37
  44. package/dist/adapters/discord/format.js.map +1 -1
  45. package/dist/adapters/github/bot.d.ts +0 -44
  46. package/dist/adapters/github/bot.d.ts.map +1 -1
  47. package/dist/adapters/github/bot.js +1 -120
  48. package/dist/adapters/github/bot.js.map +1 -1
  49. package/dist/adapters/github/client.d.ts +0 -57
  50. package/dist/adapters/github/client.d.ts.map +1 -1
  51. package/dist/adapters/github/client.js +0 -59
  52. package/dist/adapters/github/client.js.map +1 -1
  53. package/dist/adapters/github/context.d.ts.map +1 -1
  54. package/dist/adapters/github/context.js +1 -8
  55. package/dist/adapters/github/context.js.map +1 -1
  56. package/dist/adapters/github/github-ops.d.ts +0 -55
  57. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  58. package/dist/adapters/github/github-ops.js +0 -59
  59. package/dist/adapters/github/github-ops.js.map +1 -1
  60. package/dist/adapters/github/ids.d.ts +0 -27
  61. package/dist/adapters/github/ids.d.ts.map +1 -1
  62. package/dist/adapters/github/ids.js +0 -29
  63. package/dist/adapters/github/ids.js.map +1 -1
  64. package/dist/adapters/github/repo.d.ts +0 -25
  65. package/dist/adapters/github/repo.d.ts.map +1 -1
  66. package/dist/adapters/github/repo.js +0 -49
  67. package/dist/adapters/github/repo.js.map +1 -1
  68. package/dist/adapters/github/tool-pack.d.ts +0 -10
  69. package/dist/adapters/github/tool-pack.d.ts.map +1 -1
  70. package/dist/adapters/github/tool-pack.js +0 -10
  71. package/dist/adapters/github/tool-pack.js.map +1 -1
  72. package/dist/adapters/github/tools/checks.d.ts +0 -6
  73. package/dist/adapters/github/tools/checks.d.ts.map +1 -1
  74. package/dist/adapters/github/tools/checks.js +0 -7
  75. package/dist/adapters/github/tools/checks.js.map +1 -1
  76. package/dist/adapters/github/tools/issue.d.ts +0 -5
  77. package/dist/adapters/github/tools/issue.d.ts.map +1 -1
  78. package/dist/adapters/github/tools/issue.js +0 -5
  79. package/dist/adapters/github/tools/issue.js.map +1 -1
  80. package/dist/adapters/github/tools/pr.d.ts +0 -7
  81. package/dist/adapters/github/tools/pr.d.ts.map +1 -1
  82. package/dist/adapters/github/tools/pr.js +0 -7
  83. package/dist/adapters/github/tools/pr.js.map +1 -1
  84. package/dist/adapters/github/tools/read.d.ts +0 -6
  85. package/dist/adapters/github/tools/read.d.ts.map +1 -1
  86. package/dist/adapters/github/tools/read.js +0 -8
  87. package/dist/adapters/github/tools/read.js.map +1 -1
  88. package/dist/adapters/github/tools/review-reply.d.ts +0 -5
  89. package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
  90. package/dist/adapters/github/tools/review-reply.js +0 -5
  91. package/dist/adapters/github/tools/review-reply.js.map +1 -1
  92. package/dist/adapters/github/tools/sync.d.ts +0 -6
  93. package/dist/adapters/github/tools/sync.d.ts.map +1 -1
  94. package/dist/adapters/github/tools/sync.js +0 -6
  95. package/dist/adapters/github/tools/sync.js.map +1 -1
  96. package/dist/adapters/github/types.d.ts +0 -88
  97. package/dist/adapters/github/types.d.ts.map +1 -1
  98. package/dist/adapters/github/types.js.map +1 -1
  99. package/dist/adapters/github/webhook.d.ts +0 -13
  100. package/dist/adapters/github/webhook.d.ts.map +1 -1
  101. package/dist/adapters/github/webhook.js +0 -16
  102. package/dist/adapters/github/webhook.js.map +1 -1
  103. package/dist/adapters/index.d.ts +3 -4
  104. package/dist/adapters/index.d.ts.map +1 -1
  105. package/dist/adapters/index.js +4 -4
  106. package/dist/adapters/index.js.map +1 -1
  107. package/dist/adapters/intake.d.ts +0 -17
  108. package/dist/adapters/intake.d.ts.map +1 -1
  109. package/dist/adapters/intake.js +6 -32
  110. package/dist/adapters/intake.js.map +1 -1
  111. package/dist/adapters/markdown-tables.d.ts +0 -10
  112. package/dist/adapters/markdown-tables.d.ts.map +1 -1
  113. package/dist/adapters/markdown-tables.js +1 -42
  114. package/dist/adapters/markdown-tables.js.map +1 -1
  115. package/dist/adapters/progressive-renderer.d.ts.map +1 -1
  116. package/dist/adapters/progressive-renderer.js +3 -25
  117. package/dist/adapters/progressive-renderer.js.map +1 -1
  118. package/dist/adapters/shared.d.ts +0 -57
  119. package/dist/adapters/shared.d.ts.map +1 -1
  120. package/dist/adapters/shared.js +0 -71
  121. package/dist/adapters/shared.js.map +1 -1
  122. package/dist/adapters/slack/assistant.d.ts +0 -49
  123. package/dist/adapters/slack/assistant.d.ts.map +1 -1
  124. package/dist/adapters/slack/assistant.js +0 -97
  125. package/dist/adapters/slack/assistant.js.map +1 -1
  126. package/dist/adapters/slack/auto-reply-context.d.ts +0 -7
  127. package/dist/adapters/slack/auto-reply-context.d.ts.map +1 -1
  128. package/dist/adapters/slack/auto-reply-context.js +0 -7
  129. package/dist/adapters/slack/auto-reply-context.js.map +1 -1
  130. package/dist/adapters/slack/blocks.d.ts +0 -9
  131. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  132. package/dist/adapters/slack/blocks.js +0 -20
  133. package/dist/adapters/slack/blocks.js.map +1 -1
  134. package/dist/adapters/slack/bot.d.ts +0 -116
  135. package/dist/adapters/slack/bot.d.ts.map +1 -1
  136. package/dist/adapters/slack/bot.js +7 -231
  137. package/dist/adapters/slack/bot.js.map +1 -1
  138. package/dist/adapters/slack/context.d.ts.map +1 -1
  139. package/dist/adapters/slack/context.js +1 -3
  140. package/dist/adapters/slack/context.js.map +1 -1
  141. package/dist/adapters/slack/jev-context.d.ts +0 -13
  142. package/dist/adapters/slack/jev-context.d.ts.map +1 -1
  143. package/dist/adapters/slack/jev-context.js +0 -12
  144. package/dist/adapters/slack/jev-context.js.map +1 -1
  145. package/dist/adapters/slack/markdown.d.ts +0 -1
  146. package/dist/adapters/slack/markdown.d.ts.map +1 -1
  147. package/dist/adapters/slack/markdown.js +0 -5
  148. package/dist/adapters/slack/markdown.js.map +1 -1
  149. package/dist/adapters/slack/persona.d.ts +0 -9
  150. package/dist/adapters/slack/persona.d.ts.map +1 -1
  151. package/dist/adapters/slack/persona.js +0 -9
  152. package/dist/adapters/slack/persona.js.map +1 -1
  153. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  154. package/dist/adapters/slack/response-lifecycle.js +1 -45
  155. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  156. package/dist/adapters/slack/session.d.ts +2 -1
  157. package/dist/adapters/slack/session.d.ts.map +1 -1
  158. package/dist/adapters/slack/session.js +2 -2
  159. package/dist/adapters/slack/session.js.map +1 -1
  160. package/dist/adapters/slack/stream-limits.d.ts +0 -25
  161. package/dist/adapters/slack/stream-limits.d.ts.map +1 -1
  162. package/dist/adapters/slack/stream-limits.js +0 -34
  163. package/dist/adapters/slack/stream-limits.js.map +1 -1
  164. package/dist/adapters/slack/task-intent.d.ts +0 -13
  165. package/dist/adapters/slack/task-intent.d.ts.map +1 -1
  166. package/dist/adapters/slack/task-intent.js +0 -7
  167. package/dist/adapters/slack/task-intent.js.map +1 -1
  168. package/dist/adapters/slack/task-status.d.ts +0 -1
  169. package/dist/adapters/slack/task-status.d.ts.map +1 -1
  170. package/dist/adapters/slack/task-status.js +1 -9
  171. package/dist/adapters/slack/task-status.js.map +1 -1
  172. package/dist/adapters/slack/tool-pack.d.ts +0 -6
  173. package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
  174. package/dist/adapters/slack/tool-pack.js +0 -6
  175. package/dist/adapters/slack/tool-pack.js.map +1 -1
  176. package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -1
  177. package/dist/adapters/slack/tools/blockkit.js +0 -11
  178. package/dist/adapters/slack/tools/blockkit.js.map +1 -1
  179. package/dist/adapters/slack/types.d.ts +0 -19
  180. package/dist/adapters/slack/types.d.ts.map +1 -1
  181. package/dist/adapters/slack/types.js.map +1 -1
  182. package/dist/adapters/slack/update-diagnostics.d.ts +0 -1
  183. package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
  184. package/dist/adapters/slack/update-diagnostics.js +1 -7
  185. package/dist/adapters/slack/update-diagnostics.js.map +1 -1
  186. package/dist/adapters/telegram/bot.d.ts +0 -6
  187. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  188. package/dist/adapters/telegram/bot.js +1 -50
  189. package/dist/adapters/telegram/bot.js.map +1 -1
  190. package/dist/adapters/telegram/context.d.ts.map +1 -1
  191. package/dist/adapters/telegram/context.js +1 -8
  192. package/dist/adapters/telegram/context.js.map +1 -1
  193. package/dist/adapters/types.d.ts +0 -57
  194. package/dist/adapters/types.d.ts.map +1 -1
  195. package/dist/adapters/types.js.map +1 -1
  196. package/dist/adapters/web/admin/client-assets.d.ts +4 -0
  197. package/dist/adapters/web/admin/client-assets.d.ts.map +1 -0
  198. package/dist/adapters/web/admin/client-assets.js +1765 -0
  199. package/dist/adapters/web/admin/client-assets.js.map +1 -0
  200. package/dist/adapters/web/admin/portal.d.ts +0 -10
  201. package/dist/adapters/web/admin/portal.d.ts.map +1 -1
  202. package/dist/adapters/web/admin/portal.js +6 -1909
  203. package/dist/adapters/web/admin/portal.js.map +1 -1
  204. package/dist/adapters/web/admin/types.d.ts +0 -3
  205. package/dist/adapters/web/admin/types.d.ts.map +1 -1
  206. package/dist/adapters/web/admin/types.js.map +1 -1
  207. package/dist/adapters/web/login/oauth.d.ts.map +1 -1
  208. package/dist/adapters/web/login/oauth.js +3 -7
  209. package/dist/adapters/web/login/oauth.js.map +1 -1
  210. package/dist/adapters/web/login/portal.d.ts +0 -10
  211. package/dist/adapters/web/login/portal.d.ts.map +1 -1
  212. package/dist/adapters/web/login/portal.js +4 -37
  213. package/dist/adapters/web/login/portal.js.map +1 -1
  214. package/dist/adapters/web/login/types.d.ts +0 -5
  215. package/dist/adapters/web/login/types.d.ts.map +1 -1
  216. package/dist/adapters/web/login/types.js.map +1 -1
  217. package/dist/adapters/web/portal-shell.d.ts +0 -12
  218. package/dist/adapters/web/portal-shell.d.ts.map +1 -1
  219. package/dist/adapters/web/portal-shell.js +8 -25
  220. package/dist/adapters/web/portal-shell.js.map +1 -1
  221. package/dist/adapters/web/server.d.ts +0 -1
  222. package/dist/adapters/web/server.d.ts.map +1 -1
  223. package/dist/adapters/web/server.js +0 -2
  224. package/dist/adapters/web/server.js.map +1 -1
  225. package/dist/adapters/web/session-view/portal.d.ts.map +1 -1
  226. package/dist/adapters/web/session-view/portal.js +13 -24
  227. package/dist/adapters/web/session-view/portal.js.map +1 -1
  228. package/dist/adapters/web/session-view/types.d.ts.map +1 -1
  229. package/dist/adapters/web/session-view/types.js.map +1 -1
  230. package/dist/adapters/web/token-store.d.ts +0 -2
  231. package/dist/adapters/web/token-store.d.ts.map +1 -1
  232. package/dist/adapters/web/token-store.js +0 -2
  233. package/dist/adapters/web/token-store.js.map +1 -1
  234. package/dist/cli/arg-grammar.d.ts +0 -3
  235. package/dist/cli/arg-grammar.d.ts.map +1 -1
  236. package/dist/cli/arg-grammar.js +0 -3
  237. package/dist/cli/arg-grammar.js.map +1 -1
  238. package/dist/cli/boot.d.ts.map +1 -1
  239. package/dist/cli/boot.js +3 -12
  240. package/dist/cli/boot.js.map +1 -1
  241. package/dist/cli/download.d.ts.map +1 -1
  242. package/dist/cli/download.js +2 -6
  243. package/dist/cli/download.js.map +1 -1
  244. package/dist/cli/office.d.ts.map +1 -1
  245. package/dist/cli/office.js +0 -31
  246. package/dist/cli/office.js.map +1 -1
  247. package/dist/cli/onboard.d.ts +0 -2
  248. package/dist/cli/onboard.d.ts.map +1 -1
  249. package/dist/cli/onboard.js +0 -30
  250. package/dist/cli/onboard.js.map +1 -1
  251. package/dist/cli/process-lifecycle.d.ts +0 -5
  252. package/dist/cli/process-lifecycle.d.ts.map +1 -1
  253. package/dist/cli/process-lifecycle.js +0 -6
  254. package/dist/cli/process-lifecycle.js.map +1 -1
  255. package/dist/cli/sandbox.d.ts +3 -0
  256. package/dist/cli/sandbox.d.ts.map +1 -0
  257. package/dist/cli/sandbox.js +79 -0
  258. package/dist/cli/sandbox.js.map +1 -0
  259. package/dist/cli/sessions.d.ts.map +1 -1
  260. package/dist/cli/sessions.js +0 -11
  261. package/dist/cli/sessions.js.map +1 -1
  262. package/dist/cli/types.d.ts +2 -6
  263. package/dist/cli/types.d.ts.map +1 -1
  264. package/dist/cli/types.js.map +1 -1
  265. package/dist/env-manifest.d.ts +0 -21
  266. package/dist/env-manifest.d.ts.map +1 -1
  267. package/dist/env-manifest.js +0 -11
  268. package/dist/env-manifest.js.map +1 -1
  269. package/dist/events/index.d.ts +0 -51
  270. package/dist/events/index.d.ts.map +1 -1
  271. package/dist/events/index.js +0 -42
  272. package/dist/events/index.js.map +1 -1
  273. package/dist/events/scheduler.d.ts +0 -8
  274. package/dist/events/scheduler.d.ts.map +1 -1
  275. package/dist/events/scheduler.js +0 -8
  276. package/dist/events/scheduler.js.map +1 -1
  277. package/dist/file-guards.d.ts +0 -15
  278. package/dist/file-guards.d.ts.map +1 -1
  279. package/dist/file-guards.js +2 -26
  280. package/dist/file-guards.js.map +1 -1
  281. package/dist/harness/execution-env.d.ts +0 -15
  282. package/dist/harness/execution-env.d.ts.map +1 -1
  283. package/dist/harness/execution-env.js +4 -55
  284. package/dist/harness/execution-env.js.map +1 -1
  285. package/dist/harness/http.d.ts +0 -12
  286. package/dist/harness/http.d.ts.map +1 -1
  287. package/dist/harness/http.js +0 -34
  288. package/dist/harness/http.js.map +1 -1
  289. package/dist/harness/index.d.ts +4 -7
  290. package/dist/harness/index.d.ts.map +1 -1
  291. package/dist/harness/index.js +4 -7
  292. package/dist/harness/index.js.map +1 -1
  293. package/dist/harness/jev.d.ts +0 -28
  294. package/dist/harness/jev.d.ts.map +1 -1
  295. package/dist/harness/jev.js +0 -45
  296. package/dist/harness/jev.js.map +1 -1
  297. package/dist/harness/mcp-result.d.ts +20 -0
  298. package/dist/harness/mcp-result.d.ts.map +1 -0
  299. package/dist/harness/mcp-result.js +171 -0
  300. package/dist/harness/mcp-result.js.map +1 -0
  301. package/dist/harness/mcp.d.ts +0 -19
  302. package/dist/harness/mcp.d.ts.map +1 -1
  303. package/dist/harness/mcp.js +7 -66
  304. package/dist/harness/mcp.js.map +1 -1
  305. package/dist/harness/models.d.ts +0 -19
  306. package/dist/harness/models.d.ts.map +1 -1
  307. package/dist/harness/models.js +0 -52
  308. package/dist/harness/models.js.map +1 -1
  309. package/dist/harness/open-connector.d.ts +0 -12
  310. package/dist/harness/open-connector.d.ts.map +1 -1
  311. package/dist/harness/open-connector.js +0 -22
  312. package/dist/harness/open-connector.js.map +1 -1
  313. package/dist/harness/presenter.d.ts +1 -0
  314. package/dist/harness/presenter.d.ts.map +1 -1
  315. package/dist/harness/presenter.js +16 -66
  316. package/dist/harness/presenter.js.map +1 -1
  317. package/dist/harness/prompt.d.ts +0 -11
  318. package/dist/harness/prompt.d.ts.map +1 -1
  319. package/dist/harness/prompt.js +1 -18
  320. package/dist/harness/prompt.js.map +1 -1
  321. package/dist/harness/runner.d.ts.map +1 -1
  322. package/dist/harness/runner.js +8 -28
  323. package/dist/harness/runner.js.map +1 -1
  324. package/dist/harness/session.d.ts +11 -28
  325. package/dist/harness/session.d.ts.map +1 -1
  326. package/dist/harness/session.js +100 -38
  327. package/dist/harness/session.js.map +1 -1
  328. package/dist/harness/skills.d.ts +0 -22
  329. package/dist/harness/skills.d.ts.map +1 -1
  330. package/dist/harness/skills.js +0 -20
  331. package/dist/harness/skills.js.map +1 -1
  332. package/dist/harness/subagent-profiles.d.ts +0 -4
  333. package/dist/harness/subagent-profiles.d.ts.map +1 -1
  334. package/dist/harness/subagent-profiles.js +0 -29
  335. package/dist/harness/subagent-profiles.js.map +1 -1
  336. package/dist/harness/subagent.d.ts +0 -25
  337. package/dist/harness/subagent.d.ts.map +1 -1
  338. package/dist/harness/subagent.js +1 -70
  339. package/dist/harness/subagent.js.map +1 -1
  340. package/dist/harness/tools/event.d.ts.map +1 -1
  341. package/dist/harness/tools/event.js +0 -9
  342. package/dist/harness/tools/event.js.map +1 -1
  343. package/dist/harness/tools/generate-image.d.ts +0 -6
  344. package/dist/harness/tools/generate-image.d.ts.map +1 -1
  345. package/dist/harness/tools/generate-image.js.map +1 -1
  346. package/dist/harness/tools/host-fn-tool.d.ts +0 -17
  347. package/dist/harness/tools/host-fn-tool.d.ts.map +1 -1
  348. package/dist/harness/tools/host-fn-tool.js +0 -16
  349. package/dist/harness/tools/host-fn-tool.js.map +1 -1
  350. package/dist/harness/tools/index.d.ts +1 -7
  351. package/dist/harness/tools/index.d.ts.map +1 -1
  352. package/dist/harness/tools/index.js +3 -14
  353. package/dist/harness/tools/index.js.map +1 -1
  354. package/dist/harness/tools/jev-browser.d.ts +4 -94
  355. package/dist/harness/tools/jev-browser.d.ts.map +1 -1
  356. package/dist/harness/tools/jev-browser.js +203 -92
  357. package/dist/harness/tools/jev-browser.js.map +1 -1
  358. package/dist/harness/tools/jev.d.ts +0 -8
  359. package/dist/harness/tools/jev.d.ts.map +1 -1
  360. package/dist/harness/tools/jev.js +0 -11
  361. package/dist/harness/tools/jev.js.map +1 -1
  362. package/dist/harness/tools/pi-tools.d.ts +1 -11
  363. package/dist/harness/tools/pi-tools.d.ts.map +1 -1
  364. package/dist/harness/tools/pi-tools.js +1 -30
  365. package/dist/harness/tools/pi-tools.js.map +1 -1
  366. package/dist/harness/tools/react.d.ts +0 -5
  367. package/dist/harness/tools/react.d.ts.map +1 -1
  368. package/dist/harness/tools/react.js +0 -5
  369. package/dist/harness/tools/react.js.map +1 -1
  370. package/dist/harness/tools/secret-redaction.d.ts +0 -25
  371. package/dist/harness/tools/secret-redaction.d.ts.map +1 -1
  372. package/dist/harness/tools/secret-redaction.js +3 -36
  373. package/dist/harness/tools/secret-redaction.js.map +1 -1
  374. package/dist/harness/tools/subagent.d.ts +0 -34
  375. package/dist/harness/tools/subagent.d.ts.map +1 -1
  376. package/dist/harness/tools/subagent.js +0 -92
  377. package/dist/harness/tools/subagent.js.map +1 -1
  378. package/dist/harness/tools/task.d.ts +0 -1
  379. package/dist/harness/tools/task.d.ts.map +1 -1
  380. package/dist/harness/tools/task.js +0 -1
  381. package/dist/harness/tools/task.js.map +1 -1
  382. package/dist/harness/tools/types.d.ts +0 -16
  383. package/dist/harness/tools/types.d.ts.map +1 -1
  384. package/dist/harness/tools/types.js.map +1 -1
  385. package/dist/harness/types.d.ts +1 -77
  386. package/dist/harness/types.d.ts.map +1 -1
  387. package/dist/harness/types.js.map +1 -1
  388. package/dist/index.d.ts.map +1 -1
  389. package/dist/index.js +0 -2
  390. package/dist/index.js.map +1 -1
  391. package/dist/log.d.ts.map +1 -1
  392. package/dist/log.js +0 -13
  393. package/dist/log.js.map +1 -1
  394. package/dist/main.js +7 -52
  395. package/dist/main.js.map +1 -1
  396. package/dist/memory-capture/index.d.ts +16 -0
  397. package/dist/memory-capture/index.d.ts.map +1 -0
  398. package/dist/memory-capture/index.js +194 -0
  399. package/dist/memory-capture/index.js.map +1 -0
  400. package/dist/memory-capture/types.d.ts +27 -0
  401. package/dist/memory-capture/types.d.ts.map +1 -0
  402. package/dist/memory-capture/types.js.map +1 -0
  403. package/dist/observability/index.d.ts +0 -9
  404. package/dist/observability/index.d.ts.map +1 -1
  405. package/dist/observability/index.js +0 -9
  406. package/dist/observability/index.js.map +1 -1
  407. package/dist/observability/instrument.js +0 -5
  408. package/dist/observability/instrument.js.map +1 -1
  409. package/dist/observability/otel.js +0 -1
  410. package/dist/observability/otel.js.map +1 -1
  411. package/dist/observability/sentry.d.ts +0 -18
  412. package/dist/observability/sentry.d.ts.map +1 -1
  413. package/dist/observability/sentry.js +0 -36
  414. package/dist/observability/sentry.js.map +1 -1
  415. package/dist/observability/types.d.ts +1 -10
  416. package/dist/observability/types.d.ts.map +1 -1
  417. package/dist/observability/types.js.map +1 -1
  418. package/dist/office/index.d.ts +0 -76
  419. package/dist/office/index.d.ts.map +1 -1
  420. package/dist/office/index.js +4 -154
  421. package/dist/office/index.js.map +1 -1
  422. package/dist/office/projection.d.ts +0 -29
  423. package/dist/office/projection.d.ts.map +1 -1
  424. package/dist/office/projection.js +5 -41
  425. package/dist/office/projection.js.map +1 -1
  426. package/dist/office/types.d.ts +0 -66
  427. package/dist/office/types.d.ts.map +1 -1
  428. package/dist/office/types.js.map +1 -1
  429. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  430. package/dist/runtime/conversation-runtime.js +22 -83
  431. package/dist/runtime/conversation-runtime.js.map +1 -1
  432. package/dist/runtime/session-lifecycle.d.ts +0 -10
  433. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  434. package/dist/runtime/session-lifecycle.js +0 -12
  435. package/dist/runtime/session-lifecycle.js.map +1 -1
  436. package/dist/runtime/types.d.ts +2 -29
  437. package/dist/runtime/types.d.ts.map +1 -1
  438. package/dist/runtime/types.js.map +1 -1
  439. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  440. package/dist/sandbox/cloudflare.js +2 -1
  441. package/dist/sandbox/cloudflare.js.map +1 -1
  442. package/dist/sandbox/container.d.ts.map +1 -1
  443. package/dist/sandbox/container.js +21 -15
  444. package/dist/sandbox/container.js.map +1 -1
  445. package/dist/sandbox/host.d.ts.map +1 -1
  446. package/dist/sandbox/host.js +0 -2
  447. package/dist/sandbox/host.js.map +1 -1
  448. package/dist/sandbox/identity.d.ts +0 -28
  449. package/dist/sandbox/identity.d.ts.map +1 -1
  450. package/dist/sandbox/identity.js +0 -28
  451. package/dist/sandbox/identity.js.map +1 -1
  452. package/dist/sandbox/index.d.ts +0 -18
  453. package/dist/sandbox/index.d.ts.map +1 -1
  454. package/dist/sandbox/index.js +2 -19
  455. package/dist/sandbox/index.js.map +1 -1
  456. package/dist/sandbox/layout.d.ts +7 -0
  457. package/dist/sandbox/layout.d.ts.map +1 -0
  458. package/dist/sandbox/layout.js +13 -0
  459. package/dist/sandbox/layout.js.map +1 -0
  460. package/dist/sandbox/provisioner.d.ts +24 -65
  461. package/dist/sandbox/provisioner.d.ts.map +1 -1
  462. package/dist/sandbox/provisioner.js +213 -125
  463. package/dist/sandbox/provisioner.js.map +1 -1
  464. package/dist/sandbox/types.d.ts +0 -39
  465. package/dist/sandbox/types.d.ts.map +1 -1
  466. package/dist/sandbox/types.js.map +1 -1
  467. package/dist/sandbox/utils.d.ts +2 -5
  468. package/dist/sandbox/utils.d.ts.map +1 -1
  469. package/dist/sandbox/utils.js +31 -31
  470. package/dist/sandbox/utils.js.map +1 -1
  471. package/dist/sessions/chat-history-sync.d.ts +0 -6
  472. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  473. package/dist/sessions/chat-history-sync.js +1 -33
  474. package/dist/sessions/chat-history-sync.js.map +1 -1
  475. package/dist/sessions/history-line.d.ts +0 -20
  476. package/dist/sessions/history-line.d.ts.map +1 -1
  477. package/dist/sessions/history-line.js +0 -20
  478. package/dist/sessions/history-line.js.map +1 -1
  479. package/dist/sessions/migrate-common.d.ts +0 -15
  480. package/dist/sessions/migrate-common.d.ts.map +1 -1
  481. package/dist/sessions/migrate-common.js +0 -19
  482. package/dist/sessions/migrate-common.js.map +1 -1
  483. package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
  484. package/dist/sessions/migrate-pi-084.js +0 -7
  485. package/dist/sessions/migrate-pi-084.js.map +1 -1
  486. package/dist/sessions/migrate-v3.d.ts +0 -7
  487. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  488. package/dist/sessions/migrate-v3.js +1 -67
  489. package/dist/sessions/migrate-v3.js.map +1 -1
  490. package/dist/sessions/session-key.d.ts +3 -17
  491. package/dist/sessions/session-key.d.ts.map +1 -1
  492. package/dist/sessions/session-key.js +8 -35
  493. package/dist/sessions/session-key.js.map +1 -1
  494. package/dist/sessions/session-store.d.ts +1 -7
  495. package/dist/sessions/session-store.d.ts.map +1 -1
  496. package/dist/sessions/session-store.js +8 -50
  497. package/dist/sessions/session-store.js.map +1 -1
  498. package/dist/sessions/store.d.ts +0 -60
  499. package/dist/sessions/store.d.ts.map +1 -1
  500. package/dist/sessions/store.js +0 -113
  501. package/dist/sessions/store.js.map +1 -1
  502. package/dist/sessions/types.d.ts +0 -17
  503. package/dist/sessions/types.d.ts.map +1 -1
  504. package/dist/sessions/types.js.map +1 -1
  505. package/dist/settings/apply.d.ts +0 -6
  506. package/dist/settings/apply.d.ts.map +1 -1
  507. package/dist/settings/apply.js +0 -29
  508. package/dist/settings/apply.js.map +1 -1
  509. package/dist/settings/index.d.ts +0 -53
  510. package/dist/settings/index.d.ts.map +1 -1
  511. package/dist/settings/index.js +0 -77
  512. package/dist/settings/index.js.map +1 -1
  513. package/dist/settings/migrate.d.ts +0 -5
  514. package/dist/settings/migrate.d.ts.map +1 -1
  515. package/dist/settings/migrate.js +0 -17
  516. package/dist/settings/migrate.js.map +1 -1
  517. package/dist/types.d.ts +9 -159
  518. package/dist/types.d.ts.map +1 -1
  519. package/dist/types.js.map +1 -1
  520. package/dist/vault/index.d.ts +2 -36
  521. package/dist/vault/index.d.ts.map +1 -1
  522. package/dist/vault/index.js +135 -65
  523. package/dist/vault/index.js.map +1 -1
  524. package/dist/vault/types.d.ts +0 -15
  525. package/dist/vault/types.d.ts.map +1 -1
  526. package/dist/vault/types.js.map +1 -1
  527. package/package.json +1 -1
  528. package/dist/dream/index.d.ts +0 -20
  529. package/dist/dream/index.d.ts.map +0 -1
  530. package/dist/dream/index.js +0 -264
  531. package/dist/dream/index.js.map +0 -1
  532. package/dist/dream/types.d.ts +0 -30
  533. package/dist/dream/types.d.ts.map +0 -1
  534. package/dist/dream/types.js.map +0 -1
  535. /package/dist/{dream → memory-capture}/types.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-common.js","sourceRoot":"","sources":["../../src/sessions/migrate-common.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared mechanics for the offline session migrations (`migrate-v3.ts`,\n * `migrate-pi-084.ts`): candidate discovery, Pi v4 JSONL encoding, and the\n * verify-then-replace commit that keeps the original file as a backup.\n */\nimport {\n existsSync,\n linkSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Entry as PiEntry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport { atomicWritePrivateFile } from \"../file-guards.js\";\n\n/** Deep-copy a JSON-derived value into a `JsonValue`. */\nexport function jsonValue(value: unknown): JsonValue {\n return JSON.parse(JSON.stringify(value)) as JsonValue;\n}\n\n/**\n * `details` and `usage` are optional on v4 compaction and branch-summary\n * entries; absent keys must stay absent rather than become `undefined`.\n */\nexport function optionalAnnotations(source: { details?: unknown; usage?: unknown }): {\n details?: JsonValue;\n usage?: Usage;\n} {\n return {\n ...(source.details !== undefined ? { details: jsonValue(source.details) } : {}),\n ...(source.usage !== undefined ? { usage: source.usage as Usage } : {}),\n };\n}\n\n/** Accumulates Pi v4 JSONL lines, numbering mutations consecutively from 1. */\nexport class V4FileWriter {\n readonly #lines: string[];\n #seq = 0;\n\n constructor(header: Record<string, unknown>) {\n this.#lines = [JSON.stringify(header)];\n }\n\n entry(entry: PiEntry): void {\n this.#lines.push(JSON.stringify({ kind: \"entry\", ...entry, seq: ++this.#seq }));\n }\n\n /** Replace the value at `namespace`/`key`. */\n set(namespace: string, key: string, value: unknown): void {\n this.#write(\"value\", \"set\", namespace, key, value);\n }\n\n /** Append to the list at `namespace`/`key`. */\n append(namespace: string, key: string, value: unknown): void {\n this.#write(\"list\", \"append\", namespace, key, value);\n }\n\n #write(kind: string, op: string, namespace: string, key: string, value: unknown): void {\n this.#lines.push(JSON.stringify({ kind, op, seq: ++this.#seq, namespace, key, value }));\n }\n\n toString(): string {\n return `${this.#lines.join(\"\\n\")}\\n`;\n }\n}\n\nfunction collectSessionFiles(\n dir: string,\n isCandidate: (path: string) => boolean,\n found: string[],\n): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isSymbolicLink()) continue;\n if (entry.isDirectory()) collectSessionFiles(path, isCandidate, found);\n else if (entry.name.endsWith(\".jsonl\") && isCandidate(path)) found.push(path);\n }\n}\n\n/** Recursively collect `.jsonl` files under `root` that `isCandidate` accepts. */\nexport function findSessionFiles(root: string, isCandidate: (path: string) => boolean): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n collectSessionFiles(root, isCandidate, found);\n return found;\n}\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\n/**\n * Write `encoded` beside `filePath`, verify it, then swap it in — hard-linking\n * the untouched original to `backupPath` first. A failed verification, or a\n * source that changed while the migration ran, leaves the original in place.\n */\nexport async function commitMigration(options: {\n filePath: string;\n /** Bytes read before parsing; the source must be unchanged at swap time. */\n sourceBytes: Buffer;\n encoded: string;\n tempPath: string;\n backupPath: string;\n verify: (candidatePath: string) => Promise<void>;\n}): Promise<void> {\n const { filePath, tempPath, backupPath } = options;\n const backupLinked = backupAlreadyLinked(filePath, backupPath);\n atomicWritePrivateFile(tempPath, options.encoded);\n try {\n await options.verify(tempPath);\n if (!readFileSync(filePath).equals(options.sourceBytes)) {\n throw new Error(\"source changed during migration\");\n }\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}\n"]}
1
+ {"version":3,"file":"migrate-common.js","sourceRoot":"","sources":["../../src/sessions/migrate-common.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n existsSync,\n linkSync,\n readFileSync,\n readdirSync,\n renameSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Entry as PiEntry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport { atomicWritePrivateFile } from \"../file-guards.js\";\n\nexport function jsonValue(value: unknown): JsonValue {\n return JSON.parse(JSON.stringify(value)) as JsonValue;\n}\n\nexport function optionalAnnotations(source: { details?: unknown; usage?: unknown }): {\n details?: JsonValue;\n usage?: Usage;\n} {\n return {\n ...(source.details !== undefined ? { details: jsonValue(source.details) } : {}),\n ...(source.usage !== undefined ? { usage: source.usage as Usage } : {}),\n };\n}\n\nexport class V4FileWriter {\n readonly #lines: string[];\n #seq = 0;\n\n constructor(header: Record<string, unknown>) {\n this.#lines = [JSON.stringify(header)];\n }\n\n entry(entry: PiEntry): void {\n this.#lines.push(JSON.stringify({ kind: \"entry\", ...entry, seq: ++this.#seq }));\n }\n\n set(namespace: string, key: string, value: unknown): void {\n this.#write(\"value\", \"set\", namespace, key, value);\n }\n\n append(namespace: string, key: string, value: unknown): void {\n this.#write(\"list\", \"append\", namespace, key, value);\n }\n\n #write(kind: string, op: string, namespace: string, key: string, value: unknown): void {\n this.#lines.push(JSON.stringify({ kind, op, seq: ++this.#seq, namespace, key, value }));\n }\n\n toString(): string {\n return `${this.#lines.join(\"\\n\")}\\n`;\n }\n}\n\nfunction collectSessionFiles(\n dir: string,\n isCandidate: (path: string) => boolean,\n found: string[],\n): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isSymbolicLink()) continue;\n if (entry.isDirectory()) collectSessionFiles(path, isCandidate, found);\n else if (entry.name.endsWith(\".jsonl\") && isCandidate(path)) found.push(path);\n }\n}\n\nexport function findSessionFiles(root: string, isCandidate: (path: string) => boolean): string[] {\n if (!existsSync(root)) return [];\n const found: string[] = [];\n collectSessionFiles(root, isCandidate, found);\n return found;\n}\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 commitMigration(options: {\n filePath: string;\n sourceBytes: Buffer;\n encoded: string;\n tempPath: string;\n backupPath: string;\n verify: (candidatePath: string) => Promise<void>;\n}): Promise<void> {\n const { filePath, tempPath, backupPath } = options;\n const backupLinked = backupAlreadyLinked(filePath, backupPath);\n atomicWritePrivateFile(tempPath, options.encoded);\n try {\n await options.verify(tempPath);\n if (!readFileSync(filePath).equals(options.sourceBytes)) {\n throw new Error(\"source changed during migration\");\n }\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}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-pi-084.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsDvD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO5D;AAiQD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAsB/B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D"}
1
+ {"version":3,"file":"migrate-pi-084.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAqDvD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO5D;AAyPD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAsB/B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D"}
@@ -83,7 +83,6 @@ function convertEntry(record) {
83
83
  throw new Error(`Unsupported Pi 0.84 entry type: ${String(raw.type)}`);
84
84
  }
85
85
  }
86
- /** Apply a `fact` mutation; `false` means the fact is not one we understand. */
87
86
  function applyFact(state, value) {
88
87
  if (value.fact === "name") {
89
88
  state.name = typeof value.name === "string" ? value.name : undefined;
@@ -97,7 +96,6 @@ function applyFact(state, value) {
97
96
  state.labels.delete(value.targetId);
98
97
  return true;
99
98
  }
100
- /** Apply one non-header line; `false` means the mutation is unrecognized. */
101
99
  function applyMutation(state, value) {
102
100
  switch (value.kind) {
103
101
  case "entry": {
@@ -122,7 +120,6 @@ function applyMutation(state, value) {
122
120
  return false;
123
121
  }
124
122
  }
125
- /** mikan metadata, with the legacy parent path folded in when it is missing. */
126
123
  function sessionMetadata(header) {
127
124
  const metadata = header.metadata ? structuredClone(header.metadata) : undefined;
128
125
  if (!header.legacyParentSessionPath || metadata?.parentSessionPath !== undefined)
@@ -138,7 +135,6 @@ function readLines(filePath) {
138
135
  lines.pop();
139
136
  return { lines, torn: !source.endsWith("\n"), filePath };
140
137
  }
141
- /** One JSONL line; `undefined` marks a torn final line — a crash tail, not corruption. */
142
138
  function parseLine({ lines, torn, filePath }, index) {
143
139
  try {
144
140
  return JSON.parse(lines[index] ?? "");
@@ -149,7 +145,6 @@ function parseLine({ lines, torn, filePath }, index) {
149
145
  throw new Error(`Invalid JSON on line ${index + 1}: ${filePath}`, { cause: error });
150
146
  }
151
147
  }
152
- /** Replay every non-header line into `state`, stopping at a torn tail. */
153
148
  function replayMutations(state, file) {
154
149
  for (let index = 1; index < file.lines.length; index++) {
155
150
  const value = parseLine(file, index);
@@ -221,7 +216,6 @@ function valueWritten(writes, namespace, key) {
221
216
  write.namespace === namespace &&
222
217
  write.key === key)?.value;
223
218
  }
224
- /** Entries must survive the rewrite unchanged apart from their renumbered seq. */
225
219
  function verifyEntries(entries, source) {
226
220
  if (entries.length !== source.length)
227
221
  throw new Error("entry count changed");
@@ -242,7 +236,6 @@ function verifyValues(writes, namespace, expected, describe) {
242
236
  throw new Error(describe(key));
243
237
  }
244
238
  }
245
- /** Branch tips, labels, metadata and audit records must round-trip as written. */
246
239
  function verifyValueWrites(path, source) {
247
240
  const writes = currentWrites(path);
248
241
  verifyValues(writes, "pi.branch.tip", source.branchTips, (key) => `branch ${key} tip changed`);
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-pi-084.js","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type { AgentMessage, Entry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"./session-store.js\";\nimport { isRecord } from \"../file-guards.js\";\nimport {\n commitMigration,\n findSessionFiles,\n jsonValue,\n optionalAnnotations,\n V4FileWriter,\n} from \"./migrate-common.js\";\nimport type { Pi084MigrationResult } from \"./types.js\";\nexport type { Pi084MigrationResult } from \"./types.js\";\n\ninterface Pi084Header {\n kind: \"header\";\n version: 4;\n id: string;\n createdAt: number;\n cwd: string;\n parentSessionId?: string;\n legacyParentSessionPath?: string;\n metadata?: Record<string, JsonValue>;\n}\n\n/** The mutation state a Pi 0.84 file folds into as its lines are replayed. */\ninterface Pi084Mutations {\n entries: Entry[];\n branchTips: Map<string, string | null>;\n labels: Map<string, string>;\n records: JsonValue[];\n name?: string;\n}\n\ninterface ParsedPi084Session extends Pi084Mutations {\n header: Pi084Header;\n metadata?: Record<string, JsonValue>;\n}\n\nfunction firstLine(filePath: string): string {\n return readFileSync(filePath, \"utf8\").split(\"\\n\", 1)[0]?.trim() ?? \"\";\n}\n\nfunction parseHeader(value: unknown, filePath: string): Pi084Header {\n if (\n !isRecord(value) ||\n value.kind !== \"header\" ||\n value.version !== 4 ||\n typeof value.id !== \"string\" ||\n typeof value.createdAt !== \"number\" ||\n typeof value.cwd !== \"string\"\n ) {\n throw new Error(`Invalid Pi 0.84 session header: ${filePath}`);\n }\n return value as unknown as Pi084Header;\n}\n\nfunction isCurrentHeader(value: unknown): boolean {\n return (\n isRecord(value) &&\n value.kind === \"header\" &&\n value.v === 4 &&\n typeof value.storageVersion === \"number\"\n );\n}\n\nexport function isPi084SessionFile(filePath: string): boolean {\n try {\n const value: unknown = JSON.parse(firstLine(filePath));\n return isRecord(value) && value.kind === \"header\" && value.version === 4;\n } catch {\n return false;\n }\n}\n\nfunction convertEntry(record: Record<string, unknown>): Entry {\n const { kind: _kind, lane: _lane, ...raw } = record;\n const base = {\n id: String(raw.id),\n parentId: typeof raw.parentId === \"string\" ? raw.parentId : null,\n seq: Number(raw.seq),\n timestamp: Number(raw.timestamp),\n };\n switch (raw.type) {\n case \"message\":\n return { ...base, type: \"message\", message: raw.message as AgentMessage };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: String(raw.summary ?? \"\"),\n retainedTail: jsonValue(raw.retainedTail ?? []) as unknown as AgentMessage[],\n tokensBefore: Number(raw.tokensBefore ?? 0),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: typeof raw.fromId === \"string\" ? raw.fromId : null,\n summary: String(raw.summary ?? \"\"),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"custom\":\n return {\n ...base,\n type: \"custom\",\n customType: String(raw.customType ?? \"legacy\"),\n ...(raw.data !== undefined ? { data: jsonValue(raw.data) } : {}),\n };\n case \"model_change\":\n case \"thinking_level_change\":\n case \"active_tools_change\": {\n const { id: _id, parentId: _parentId, seq: _seq, timestamp: _timestamp, type, ...data } = raw;\n return {\n ...base,\n type: \"custom\",\n customType: `mikan.pi084.${String(type)}`,\n data: jsonValue(data),\n };\n }\n default:\n throw new Error(`Unsupported Pi 0.84 entry type: ${String(raw.type)}`);\n }\n}\n\n/** Apply a `fact` mutation; `false` means the fact is not one we understand. */\nfunction applyFact(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n if (value.fact === \"name\") {\n state.name = typeof value.name === \"string\" ? value.name : undefined;\n return true;\n }\n if (value.fact !== \"label\" || typeof value.targetId !== \"string\") return false;\n if (typeof value.label === \"string\") state.labels.set(value.targetId, value.label);\n else state.labels.delete(value.targetId);\n return true;\n}\n\n/** Apply one non-header line; `false` means the mutation is unrecognized. */\nfunction applyMutation(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n switch (value.kind) {\n case \"entry\": {\n const entry = convertEntry(value);\n state.entries.push(entry);\n if (typeof value.lane === \"string\") state.branchTips.set(value.lane, entry.id);\n return true;\n }\n case \"lane\": {\n if (typeof value.lane !== \"string\") return false;\n state.branchTips.set(value.lane, typeof value.leafId === \"string\" ? value.leafId : null);\n return true;\n }\n case \"fact\":\n return applyFact(state, value);\n case \"record\":\n state.records.push(jsonValue(value));\n return true;\n default:\n return false;\n }\n}\n\n/** mikan metadata, with the legacy parent path folded in when it is missing. */\nfunction sessionMetadata(header: Pi084Header): Record<string, JsonValue> | undefined {\n const metadata = header.metadata ? structuredClone(header.metadata) : undefined;\n if (!header.legacyParentSessionPath || metadata?.parentSessionPath !== undefined) return metadata;\n const withParent = metadata ?? {};\n withParent.parentSessionPath = header.legacyParentSessionPath;\n return withParent;\n}\n\ninterface Pi084Lines {\n lines: string[];\n /** A file without a trailing newline may end in a torn line (a crash tail). */\n torn: boolean;\n filePath: string;\n}\n\nfunction readLines(filePath: string): Pi084Lines {\n const source = readFileSync(filePath, \"utf8\");\n const lines = source.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return { lines, torn: !source.endsWith(\"\\n\"), filePath };\n}\n\n/** One JSONL line; `undefined` marks a torn final line — a crash tail, not corruption. */\nfunction parseLine({ lines, torn, filePath }: Pi084Lines, index: number): unknown {\n try {\n return JSON.parse(lines[index] ?? \"\");\n } catch (error) {\n if (index === lines.length - 1 && torn) return undefined;\n throw new Error(`Invalid JSON on line ${index + 1}: ${filePath}`, { cause: error });\n }\n}\n\n/** Replay every non-header line into `state`, stopping at a torn tail. */\nfunction replayMutations(state: Pi084Mutations, file: Pi084Lines): void {\n for (let index = 1; index < file.lines.length; index++) {\n const value = parseLine(file, index);\n if (value === undefined) return;\n const where = `line ${index + 1}: ${file.filePath}`;\n if (!isRecord(value)) throw new Error(`Invalid mutation on ${where}`);\n if (!applyMutation(state, value)) throw new Error(`Unknown Pi 0.84 mutation on ${where}`);\n }\n}\n\nfunction parsePi084Session(filePath: string): ParsedPi084Session {\n const file = readLines(filePath);\n const headerValue = file.lines.length === 0 ? undefined : parseLine(file, 0);\n if (headerValue === undefined) throw new Error(`Missing Pi 0.84 session header: ${filePath}`);\n const header = parseHeader(headerValue, filePath);\n const state: Pi084Mutations = {\n entries: [],\n branchTips: new Map([[\"main\", null]]),\n labels: new Map(),\n records: [],\n };\n replayMutations(state, file);\n return { ...state, header, metadata: sessionMetadata(header) };\n}\n\nfunction encodeCurrentSession(source: ParsedPi084Session): string {\n const { header } = source;\n const writer = new V4FileWriter({\n v: 4,\n kind: \"header\",\n id: header.id,\n storageVersion: 1,\n createdAt: header.createdAt,\n cwd: header.cwd,\n ...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),\n ...(header.legacyParentSessionPath !== undefined\n ? { legacyParentSessionPath: header.legacyParentSessionPath }\n : {}),\n });\n for (const entry of source.entries) writer.entry(entry);\n for (const [branch, tip] of source.branchTips) writer.set(\"pi.branch.tip\", branch, tip);\n if (source.name !== undefined) writer.set(\"pi.session.name\", \"\", source.name);\n for (const [targetId, label] of source.labels) writer.set(\"pi.entry.label\", targetId, label);\n if (source.metadata !== undefined) writer.set(\"mikan\", \"metadata\", source.metadata);\n for (const record of source.records) writer.append(\"mikan.pi084.records\", \"\", record);\n return writer.toString();\n}\n\nfunction currentWrites(path: string): Array<Record<string, unknown>> {\n return readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .slice(1)\n .filter(Boolean)\n .flatMap((line) => {\n const parsed = JSON.parse(line) as Record<string, unknown> | Array<Record<string, unknown>>;\n return Array.isArray(parsed) ? parsed : [parsed];\n });\n}\n\nfunction valueWritten(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n key: string,\n): unknown {\n return writes.findLast(\n (write) =>\n write.kind === \"value\" &&\n write.op === \"set\" &&\n write.namespace === namespace &&\n write.key === key,\n )?.value;\n}\n\n/** Entries must survive the rewrite unchanged apart from their renumbered seq. */\nfunction verifyEntries(entries: Entry[], source: Entry[]): void {\n if (entries.length !== source.length) throw new Error(\"entry count changed\");\n for (const [index, entry] of entries.entries()) {\n const original = source[index];\n if (!original) throw new Error(`entry ${index + 1} changed`);\n const { seq: _entrySeq, ...entryData } = entry;\n const { seq: _originalSeq, ...originalData } = original;\n if (JSON.stringify(entryData) !== JSON.stringify(originalData)) {\n throw new Error(`entry ${index + 1} changed`);\n }\n }\n}\n\nfunction verifyValues(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n expected: ReadonlyMap<string, string | null>,\n describe: (key: string) => string,\n): void {\n for (const [key, value] of expected) {\n if (valueWritten(writes, namespace, key) !== value) throw new Error(describe(key));\n }\n}\n\n/** Branch tips, labels, metadata and audit records must round-trip as written. */\nfunction verifyValueWrites(path: string, source: ParsedPi084Session): void {\n const writes = currentWrites(path);\n verifyValues(writes, \"pi.branch.tip\", source.branchTips, (key) => `branch ${key} tip changed`);\n verifyValues(writes, \"pi.entry.label\", source.labels, (key) => `label ${key} changed`);\n if (\n JSON.stringify(valueWritten(writes, \"mikan\", \"metadata\")) !== JSON.stringify(source.metadata)\n ) {\n throw new Error(\"mikan metadata changed\");\n }\n const auditRecords = writes.filter(\n (write) => write.kind === \"list\" && write.namespace === \"mikan.pi084.records\",\n );\n if (auditRecords.length !== source.records.length) throw new Error(\"audit records changed\");\n}\n\nasync function verifyCandidate(path: string, source: ParsedPi084Session): Promise<void> {\n const inspection = await SessionStore.inspect(path);\n verifyEntries(await inspection.getEntries(), source.entries);\n const branch = await inspection.getBranch();\n if ((branch.at(-1)?.id ?? null) !== (source.branchTips.get(\"main\") ?? null)) {\n throw new Error(\"main branch tip changed\");\n }\n if ((await inspection.getSessionName()) !== source.name) throw new Error(\"session name changed\");\n const header = inspection.getHeader();\n if (\n header.id !== source.header.id ||\n header.timestamp !== new Date(source.header.createdAt).toISOString()\n ) {\n throw new Error(\"session identity changed\");\n }\n verifyValueWrites(path, source);\n}\n\nexport async function migratePi084SessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<Pi084MigrationResult> {\n let headerValue: unknown;\n try {\n headerValue = JSON.parse(firstLine(filePath));\n } catch {\n return { file: filePath, status: \"not-pi-084\" };\n }\n if (isCurrentHeader(headerValue)) return { file: filePath, status: \"already-current\" };\n if (!isPi084SessionFile(filePath)) return { file: filePath, status: \"not-pi-084\" };\n const sourceBytes = readFileSync(filePath);\n const source = parsePi084Session(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n await commitMigration({\n filePath,\n sourceBytes,\n encoded: encodeCurrentSession(source),\n tempPath: `${filePath}.pi-085.tmp`,\n backupPath: `${filePath}.pi-084.bak`,\n verify: (candidatePath) => verifyCandidate(candidatePath, source),\n });\n return { file: filePath, status: \"migrated\" };\n}\n\nexport function findPi084SessionFiles(root: string): string[] {\n return findSessionFiles(root, isPi084SessionFile);\n}\n"]}
1
+ {"version":3,"file":"migrate-pi-084.js","sourceRoot":"","sources":["../../src/sessions/migrate-pi-084.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport type { AgentMessage, Entry, JsonValue } from \"@earendil-works/pi-agent-core\";\nimport { SessionStore } from \"./session-store.js\";\nimport { isRecord } from \"../file-guards.js\";\nimport {\n commitMigration,\n findSessionFiles,\n jsonValue,\n optionalAnnotations,\n V4FileWriter,\n} from \"./migrate-common.js\";\nimport type { Pi084MigrationResult } from \"./types.js\";\nexport type { Pi084MigrationResult } from \"./types.js\";\n\ninterface Pi084Header {\n kind: \"header\";\n version: 4;\n id: string;\n createdAt: number;\n cwd: string;\n parentSessionId?: string;\n legacyParentSessionPath?: string;\n metadata?: Record<string, JsonValue>;\n}\n\ninterface Pi084Mutations {\n entries: Entry[];\n branchTips: Map<string, string | null>;\n labels: Map<string, string>;\n records: JsonValue[];\n name?: string;\n}\n\ninterface ParsedPi084Session extends Pi084Mutations {\n header: Pi084Header;\n metadata?: Record<string, JsonValue>;\n}\n\nfunction firstLine(filePath: string): string {\n return readFileSync(filePath, \"utf8\").split(\"\\n\", 1)[0]?.trim() ?? \"\";\n}\n\nfunction parseHeader(value: unknown, filePath: string): Pi084Header {\n if (\n !isRecord(value) ||\n value.kind !== \"header\" ||\n value.version !== 4 ||\n typeof value.id !== \"string\" ||\n typeof value.createdAt !== \"number\" ||\n typeof value.cwd !== \"string\"\n ) {\n throw new Error(`Invalid Pi 0.84 session header: ${filePath}`);\n }\n return value as unknown as Pi084Header;\n}\n\nfunction isCurrentHeader(value: unknown): boolean {\n return (\n isRecord(value) &&\n value.kind === \"header\" &&\n value.v === 4 &&\n typeof value.storageVersion === \"number\"\n );\n}\n\nexport function isPi084SessionFile(filePath: string): boolean {\n try {\n const value: unknown = JSON.parse(firstLine(filePath));\n return isRecord(value) && value.kind === \"header\" && value.version === 4;\n } catch {\n return false;\n }\n}\n\nfunction convertEntry(record: Record<string, unknown>): Entry {\n const { kind: _kind, lane: _lane, ...raw } = record;\n const base = {\n id: String(raw.id),\n parentId: typeof raw.parentId === \"string\" ? raw.parentId : null,\n seq: Number(raw.seq),\n timestamp: Number(raw.timestamp),\n };\n switch (raw.type) {\n case \"message\":\n return { ...base, type: \"message\", message: raw.message as AgentMessage };\n case \"compaction\":\n return {\n ...base,\n type: \"compaction\",\n summary: String(raw.summary ?? \"\"),\n retainedTail: jsonValue(raw.retainedTail ?? []) as unknown as AgentMessage[],\n tokensBefore: Number(raw.tokensBefore ?? 0),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"branch_summary\":\n return {\n ...base,\n type: \"branch_summary\",\n fromId: typeof raw.fromId === \"string\" ? raw.fromId : null,\n summary: String(raw.summary ?? \"\"),\n fromHook: false,\n ...optionalAnnotations(raw),\n };\n case \"custom\":\n return {\n ...base,\n type: \"custom\",\n customType: String(raw.customType ?? \"legacy\"),\n ...(raw.data !== undefined ? { data: jsonValue(raw.data) } : {}),\n };\n case \"model_change\":\n case \"thinking_level_change\":\n case \"active_tools_change\": {\n const { id: _id, parentId: _parentId, seq: _seq, timestamp: _timestamp, type, ...data } = raw;\n return {\n ...base,\n type: \"custom\",\n customType: `mikan.pi084.${String(type)}`,\n data: jsonValue(data),\n };\n }\n default:\n throw new Error(`Unsupported Pi 0.84 entry type: ${String(raw.type)}`);\n }\n}\n\nfunction applyFact(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n if (value.fact === \"name\") {\n state.name = typeof value.name === \"string\" ? value.name : undefined;\n return true;\n }\n if (value.fact !== \"label\" || typeof value.targetId !== \"string\") return false;\n if (typeof value.label === \"string\") state.labels.set(value.targetId, value.label);\n else state.labels.delete(value.targetId);\n return true;\n}\n\nfunction applyMutation(state: Pi084Mutations, value: Record<string, unknown>): boolean {\n switch (value.kind) {\n case \"entry\": {\n const entry = convertEntry(value);\n state.entries.push(entry);\n if (typeof value.lane === \"string\") state.branchTips.set(value.lane, entry.id);\n return true;\n }\n case \"lane\": {\n if (typeof value.lane !== \"string\") return false;\n state.branchTips.set(value.lane, typeof value.leafId === \"string\" ? value.leafId : null);\n return true;\n }\n case \"fact\":\n return applyFact(state, value);\n case \"record\":\n state.records.push(jsonValue(value));\n return true;\n default:\n return false;\n }\n}\n\nfunction sessionMetadata(header: Pi084Header): Record<string, JsonValue> | undefined {\n const metadata = header.metadata ? structuredClone(header.metadata) : undefined;\n if (!header.legacyParentSessionPath || metadata?.parentSessionPath !== undefined) return metadata;\n const withParent = metadata ?? {};\n withParent.parentSessionPath = header.legacyParentSessionPath;\n return withParent;\n}\n\ninterface Pi084Lines {\n lines: string[];\n torn: boolean;\n filePath: string;\n}\n\nfunction readLines(filePath: string): Pi084Lines {\n const source = readFileSync(filePath, \"utf8\");\n const lines = source.split(\"\\n\");\n if (lines.at(-1) === \"\") lines.pop();\n return { lines, torn: !source.endsWith(\"\\n\"), filePath };\n}\n\nfunction parseLine({ lines, torn, filePath }: Pi084Lines, index: number): unknown {\n try {\n return JSON.parse(lines[index] ?? \"\");\n } catch (error) {\n if (index === lines.length - 1 && torn) return undefined;\n throw new Error(`Invalid JSON on line ${index + 1}: ${filePath}`, { cause: error });\n }\n}\n\nfunction replayMutations(state: Pi084Mutations, file: Pi084Lines): void {\n for (let index = 1; index < file.lines.length; index++) {\n const value = parseLine(file, index);\n if (value === undefined) return;\n const where = `line ${index + 1}: ${file.filePath}`;\n if (!isRecord(value)) throw new Error(`Invalid mutation on ${where}`);\n if (!applyMutation(state, value)) throw new Error(`Unknown Pi 0.84 mutation on ${where}`);\n }\n}\n\nfunction parsePi084Session(filePath: string): ParsedPi084Session {\n const file = readLines(filePath);\n const headerValue = file.lines.length === 0 ? undefined : parseLine(file, 0);\n if (headerValue === undefined) throw new Error(`Missing Pi 0.84 session header: ${filePath}`);\n const header = parseHeader(headerValue, filePath);\n const state: Pi084Mutations = {\n entries: [],\n branchTips: new Map([[\"main\", null]]),\n labels: new Map(),\n records: [],\n };\n replayMutations(state, file);\n return { ...state, header, metadata: sessionMetadata(header) };\n}\n\nfunction encodeCurrentSession(source: ParsedPi084Session): string {\n const { header } = source;\n const writer = new V4FileWriter({\n v: 4,\n kind: \"header\",\n id: header.id,\n storageVersion: 1,\n createdAt: header.createdAt,\n cwd: header.cwd,\n ...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),\n ...(header.legacyParentSessionPath !== undefined\n ? { legacyParentSessionPath: header.legacyParentSessionPath }\n : {}),\n });\n for (const entry of source.entries) writer.entry(entry);\n for (const [branch, tip] of source.branchTips) writer.set(\"pi.branch.tip\", branch, tip);\n if (source.name !== undefined) writer.set(\"pi.session.name\", \"\", source.name);\n for (const [targetId, label] of source.labels) writer.set(\"pi.entry.label\", targetId, label);\n if (source.metadata !== undefined) writer.set(\"mikan\", \"metadata\", source.metadata);\n for (const record of source.records) writer.append(\"mikan.pi084.records\", \"\", record);\n return writer.toString();\n}\n\nfunction currentWrites(path: string): Array<Record<string, unknown>> {\n return readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .slice(1)\n .filter(Boolean)\n .flatMap((line) => {\n const parsed = JSON.parse(line) as Record<string, unknown> | Array<Record<string, unknown>>;\n return Array.isArray(parsed) ? parsed : [parsed];\n });\n}\n\nfunction valueWritten(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n key: string,\n): unknown {\n return writes.findLast(\n (write) =>\n write.kind === \"value\" &&\n write.op === \"set\" &&\n write.namespace === namespace &&\n write.key === key,\n )?.value;\n}\n\nfunction verifyEntries(entries: Entry[], source: Entry[]): void {\n if (entries.length !== source.length) throw new Error(\"entry count changed\");\n for (const [index, entry] of entries.entries()) {\n const original = source[index];\n if (!original) throw new Error(`entry ${index + 1} changed`);\n const { seq: _entrySeq, ...entryData } = entry;\n const { seq: _originalSeq, ...originalData } = original;\n if (JSON.stringify(entryData) !== JSON.stringify(originalData)) {\n throw new Error(`entry ${index + 1} changed`);\n }\n }\n}\n\nfunction verifyValues(\n writes: Array<Record<string, unknown>>,\n namespace: string,\n expected: ReadonlyMap<string, string | null>,\n describe: (key: string) => string,\n): void {\n for (const [key, value] of expected) {\n if (valueWritten(writes, namespace, key) !== value) throw new Error(describe(key));\n }\n}\n\nfunction verifyValueWrites(path: string, source: ParsedPi084Session): void {\n const writes = currentWrites(path);\n verifyValues(writes, \"pi.branch.tip\", source.branchTips, (key) => `branch ${key} tip changed`);\n verifyValues(writes, \"pi.entry.label\", source.labels, (key) => `label ${key} changed`);\n if (\n JSON.stringify(valueWritten(writes, \"mikan\", \"metadata\")) !== JSON.stringify(source.metadata)\n ) {\n throw new Error(\"mikan metadata changed\");\n }\n const auditRecords = writes.filter(\n (write) => write.kind === \"list\" && write.namespace === \"mikan.pi084.records\",\n );\n if (auditRecords.length !== source.records.length) throw new Error(\"audit records changed\");\n}\n\nasync function verifyCandidate(path: string, source: ParsedPi084Session): Promise<void> {\n const inspection = await SessionStore.inspect(path);\n verifyEntries(await inspection.getEntries(), source.entries);\n const branch = await inspection.getBranch();\n if ((branch.at(-1)?.id ?? null) !== (source.branchTips.get(\"main\") ?? null)) {\n throw new Error(\"main branch tip changed\");\n }\n if ((await inspection.getSessionName()) !== source.name) throw new Error(\"session name changed\");\n const header = inspection.getHeader();\n if (\n header.id !== source.header.id ||\n header.timestamp !== new Date(source.header.createdAt).toISOString()\n ) {\n throw new Error(\"session identity changed\");\n }\n verifyValueWrites(path, source);\n}\n\nexport async function migratePi084SessionFile(\n filePath: string,\n options?: { dryRun?: boolean },\n): Promise<Pi084MigrationResult> {\n let headerValue: unknown;\n try {\n headerValue = JSON.parse(firstLine(filePath));\n } catch {\n return { file: filePath, status: \"not-pi-084\" };\n }\n if (isCurrentHeader(headerValue)) return { file: filePath, status: \"already-current\" };\n if (!isPi084SessionFile(filePath)) return { file: filePath, status: \"not-pi-084\" };\n const sourceBytes = readFileSync(filePath);\n const source = parsePi084Session(filePath);\n if (options?.dryRun) return { file: filePath, status: \"migrated\", detail: \"dry run\" };\n\n await commitMigration({\n filePath,\n sourceBytes,\n encoded: encodeCurrentSession(source),\n tempPath: `${filePath}.pi-085.tmp`,\n backupPath: `${filePath}.pi-084.bak`,\n verify: (candidatePath) => verifyCandidate(candidatePath, source),\n });\n return { file: filePath, status: \"migrated\" };\n}\n\nexport function findPi084SessionFiles(root: string): string[] {\n return findSessionFiles(root, isPi084SessionFile);\n}\n"]}
@@ -1,15 +1,8 @@
1
1
  import type { MigrateResult } from "./types.js";
2
2
  export type { MigrateResult } from "./types.js";
3
- /** Whether a file's first non-empty line is a v3 session header. */
4
3
  export declare function isV3SessionFile(filePath: string): boolean;
5
- /**
6
- * Migrate one session file in place. The migrated file is verified against
7
- * the v3 reference semantics before it replaces the original; the original
8
- * is preserved as `<file>.v3.bak`.
9
- */
10
4
  export declare function migrateSessionFile(filePath: string, options?: {
11
5
  dryRun?: boolean;
12
6
  }): Promise<MigrateResult>;
13
- /** Recursively find candidate session files (.jsonl with a v3 header). */
14
7
  export declare function findV3SessionFiles(root: string): string[];
15
8
  //# sourceMappingURL=migrate-v3.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate-v3.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAsEhD,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUzD;AAiYD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAexB;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD"}
1
+ {"version":3,"file":"migrate-v3.d.ts","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmEhD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAUzD;AAsVD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,aAAa,CAAC,CAexB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD"}
@@ -1,30 +1,10 @@
1
- /**
2
- * One-time migration of legacy v3 session files to pi's v4 JSONL format.
3
- *
4
- * v3 is the entry family mikan wrote up to pi 0.83: a `{"type":"session"}`
5
- * header followed by tree entries with string ISO timestamps and compaction
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.
9
- *
10
- * The migration preserves entry ids, parent links, and timestamps, converts
11
- * `custom_message` entries into v4 `custom`-role messages, folds
12
- * `session_info` into the v4 name fact, `label` entries into label facts,
13
- * and rewrites each compaction's kept range into its inline `retainedTail`.
14
- * Every migrated file is verified before it replaces the original: the v4
15
- * file is re-opened with pi's reader and its built context must equal the
16
- * v3 context computed by the reference converter below. The original file
17
- * is kept beside the migrated one as `<name>.v3.bak`.
18
- */
19
1
  import { readFileSync } from "node:fs";
20
2
  import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "@earendil-works/pi-agent-core";
21
3
  import { SessionStore } from "./session-store.js";
22
4
  import { commitMigration, findSessionFiles, optionalAnnotations, V4FileWriter, } from "./migrate-common.js";
23
- /** `session_info`, `label` and `leaf` become v4 values, not tree entries. */
24
5
  function isFactEntry(entry) {
25
6
  return entry.type === "session_info" || entry.type === "label" || entry.type === "leaf";
26
7
  }
27
- /** Whether a file's first non-empty line is a v3 session header. */
28
8
  export function isV3SessionFile(filePath) {
29
9
  try {
30
10
  const content = readFileSync(filePath, "utf-8");
@@ -38,7 +18,6 @@ export function isV3SessionFile(filePath) {
38
18
  return false;
39
19
  }
40
20
  }
41
- /** Parse every non-empty line, tolerating a torn final line (crash tail). */
42
21
  function parseJsonLines(filePath) {
43
22
  const lines = readFileSync(filePath, "utf-8")
44
23
  .split("\n")
@@ -57,13 +36,6 @@ function parseJsonLines(filePath) {
57
36
  }
58
37
  return records;
59
38
  }
60
- /**
61
- * Crash-era v3 files can contain duplicated lines (a retried append wrote the
62
- * header+entry pair twice). The v3 runtime read entries into a Map, so
63
- * duplicates were silently collapsed; v4 rejects duplicate mutation ids.
64
- * Reproduce the v3 Map semantics: a repeated id replaces its payload while
65
- * retaining the id's original insertion position.
66
- */
67
39
  function dedupeEntries(records) {
68
40
  const entriesById = new Map();
69
41
  for (const record of records) {
@@ -75,7 +47,6 @@ function dedupeEntries(records) {
75
47
  }
76
48
  return [...entriesById.values()];
77
49
  }
78
- /** Read a v3 session file, ignoring a torn final line (crash tail). */
79
50
  function readV3SessionFile(filePath) {
80
51
  const records = parseJsonLines(filePath);
81
52
  const header = records[0];
@@ -91,7 +62,6 @@ function toEpochMillis(timestamp) {
91
62
  const parsed = Date.parse(timestamp);
92
63
  return Number.isNaN(parsed) ? 0 : parsed;
93
64
  }
94
- /** Walk a v3 tree from an entry to the root; returns root-first path order. */
95
65
  function v3Branch(entries, fromId) {
96
66
  const byId = new Map(entries.map((entry) => [entry.id, entry]));
97
67
  const path = [];
@@ -112,15 +82,13 @@ function v3LeafId(entries) {
112
82
  }
113
83
  return leafId;
114
84
  }
115
- /** v3 kept `custom_message` payloads out of band; v4 stores a real message. */
116
85
  function customMessageOf(entry) {
117
86
  return createCustomMessage(entry.customType, entry.content, entry.display, entry.details, toEpochMillis(entry.timestamp));
118
87
  }
119
- /** Convert one tree-shaping v3 entry to its v4 counterpart (facts excluded). */
120
88
  function convertEntry(entry, entries) {
121
89
  const base = {
122
90
  id: entry.id,
123
- seq: 0, // assigned at mutation-encoding time
91
+ seq: 0,
124
92
  parentId: resolveV4Parent(entry, entries),
125
93
  timestamp: toEpochMillis(entry.timestamp),
126
94
  };
@@ -167,15 +135,9 @@ function convertEntry(entry, entries) {
167
135
  ...(entry.data !== undefined ? { data: entry.data } : {}),
168
136
  };
169
137
  default:
170
- // session_info / label / leaf become facts and the lane pointer.
171
138
  return null;
172
139
  }
173
140
  }
174
- /**
175
- * Skip fact-only ancestors (session_info/label/leaf) when re-linking the v4
176
- * tree: those entries disappear from the entry stream, so children re-attach
177
- * to the nearest surviving ancestor.
178
- */
179
141
  function resolveV4Parent(entry, entries) {
180
142
  const byId = new Map(entries.map((item) => [item.id, item]));
181
143
  let parentId = entry.parentId;
@@ -189,10 +151,6 @@ function resolveV4Parent(entry, entries) {
189
151
  }
190
152
  return null;
191
153
  }
192
- /**
193
- * Messages of the v3 kept range (`firstKeptEntryId` .. compaction parent),
194
- * which v4 stores inline on the compaction entry.
195
- */
196
154
  function compactionKeptMessages(compaction, entries) {
197
155
  if (!compaction.firstKeptEntryId)
198
156
  return [];
@@ -209,12 +167,6 @@ function compactionKeptMessages(compaction, entries) {
209
167
  }
210
168
  return messages;
211
169
  }
212
- // ── reference converter (verification oracle) ───────────────────────────────
213
- /**
214
- * Reorder a v3 branch the way the pi-0.83 context shim did: the last
215
- * compaction moves ahead of its kept range. The branch is returned unchanged
216
- * when there is no such compaction or it already carries a `retainedTail`.
217
- */
218
170
  function orderForReference(branch) {
219
171
  const lastIndex = branch.findLastIndex((entry) => entry.type === "compaction");
220
172
  const lastCompaction = branch[lastIndex];
@@ -231,7 +183,6 @@ function orderForReference(branch) {
231
183
  repositioned: lastCompaction,
232
184
  };
233
185
  }
234
- /** A repositioned compaction drops its kept range: the range now follows it. */
235
186
  function emptiedCompaction(entry) {
236
187
  return {
237
188
  type: "compaction",
@@ -245,12 +196,6 @@ function emptiedCompaction(entry) {
245
196
  fromHook: false,
246
197
  };
247
198
  }
248
- /**
249
- * Convert a v3 branch to v4 entries with the pi-0.83 context semantics, so
250
- * pi's v4 transform reproduces the v3 context exactly. This mirrors what the
251
- * runtime shim did before mikan moved to native v4 files, and serves as the
252
- * verification oracle for migrated output.
253
- */
254
199
  function referenceContextEntries(branch) {
255
200
  const { ordered, repositioned } = orderForReference(branch);
256
201
  const converted = [];
@@ -293,7 +238,6 @@ function referenceContextMessages(entries) {
293
238
  const visible = compactionIndex === -1 ? entries : entries.slice(compactionIndex);
294
239
  return visible.flatMap(contextMessagesOf);
295
240
  }
296
- // ── v4 encoding ─────────────────────────────────────────────────────────────
297
241
  function buildV4Header(header) {
298
242
  return {
299
243
  v: 4,
@@ -308,7 +252,6 @@ function buildV4Header(header) {
308
252
  : {}),
309
253
  };
310
254
  }
311
- /** Split a v3 entry stream into tree entries and the facts v4 stores as values. */
312
255
  function partitionEntries(entries) {
313
256
  const tree = [];
314
257
  const labels = [];
@@ -329,7 +272,6 @@ function partitionEntries(entries) {
329
272
  }
330
273
  return { tree, name, labels };
331
274
  }
332
- /** The v4 branch tip: the v3 leaf, walked back past fact-only entries. */
333
275
  function resolveV4Leaf(entries) {
334
276
  const byId = new Map(entries.map((entry) => [entry.id, entry]));
335
277
  let leafId = v3LeafId(entries);
@@ -343,7 +285,6 @@ function resolveV4Leaf(entries) {
343
285
  }
344
286
  return null;
345
287
  }
346
- /** Header fields v4 does not model survive as the durable `mikan/metadata` value. */
347
288
  function headerMetadata(header) {
348
289
  const { type: _type, version: _version, id: _id, timestamp: _timestamp, cwd: _cwd, parentSession, parentSessionId: _parentSessionId, ...extras } = header;
349
290
  const metadata = extras;
@@ -371,7 +312,6 @@ function encodeV4File(file) {
371
312
  writer.set("mikan", "metadata", metadata);
372
313
  return writer.toString();
373
314
  }
374
- // ── migration driver ────────────────────────────────────────────────────────
375
315
  async function verifyMigratedFile(v4Path, source) {
376
316
  const store = await SessionStore.inspect(v4Path);
377
317
  const migratedContext = await store.buildSessionContext();
@@ -390,11 +330,6 @@ async function verifyMigratedFile(v4Path, source) {
390
330
  throw new Error("migrated session name does not match the v3 session name");
391
331
  }
392
332
  }
393
- /**
394
- * Migrate one session file in place. The migrated file is verified against
395
- * the v3 reference semantics before it replaces the original; the original
396
- * is preserved as `<file>.v3.bak`.
397
- */
398
333
  export async function migrateSessionFile(filePath, options) {
399
334
  if (!isV3SessionFile(filePath))
400
335
  return { file: filePath, status: "already-v4" };
@@ -412,7 +347,6 @@ export async function migrateSessionFile(filePath, options) {
412
347
  });
413
348
  return { file: filePath, status: "migrated" };
414
349
  }
415
- /** Recursively find candidate session files (.jsonl with a v3 header). */
416
350
  export function findV3SessionFiles(root) {
417
351
  return findSessionFiles(root, isV3SessionFile);
418
352
  }
@@ -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`. 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 { readFileSync } from \"node:fs\";\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 \"./session-store.js\";\nimport {\n commitMigration,\n findSessionFiles,\n optionalAnnotations,\n V4FileWriter,\n} from \"./migrate-common.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\ntype V3Compaction = Extract<V3Entry, { type: \"compaction\" }>;\ntype V3CustomMessage = Extract<V3Entry, { type: \"custom_message\" }>;\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/** `session_info`, `label` and `leaf` become v4 values, not tree entries. */\nfunction isFactEntry(entry: V3Entry): boolean {\n return entry.type === \"session_info\" || entry.type === \"label\" || entry.type === \"leaf\";\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/** Parse every non-empty line, tolerating a torn final line (crash tail). */\nfunction parseJsonLines(filePath: string): Record<string, unknown>[] {\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 return records;\n}\n\n/**\n * Crash-era v3 files can contain duplicated lines (a retried append wrote the\n * 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 */\nfunction dedupeEntries(records: Record<string, unknown>[]): V3Entry[] {\n const entriesById = new Map<string, V3Entry>();\n for (const record of records) {\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 [...entriesById.values()];\n}\n\n/** Read a v3 session file, ignoring a torn final line (crash tail). */\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const records = parseJsonLines(filePath);\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 return {\n header: header as unknown as V3SessionHeader,\n entries: dedupeEntries(records.slice(1)),\n };\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/** v3 kept `custom_message` payloads out of band; v4 stores a real message. */\nfunction customMessageOf(entry: V3CustomMessage): AgentMessage {\n return createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n );\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 { ...base, type: \"message\", message: customMessageOf(entry) };\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 ...optionalAnnotations(entry),\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 ...optionalAnnotations(entry),\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 (!isFactEntry(parent)) return parentId;\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(compaction: V3Compaction, entries: V3Entry[]): 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\") messages.push(customMessageOf(entry));\n }\n return messages;\n}\n\n// ── reference converter (verification oracle) ───────────────────────────────\n\n/**\n * Reorder a v3 branch the way the pi-0.83 context shim did: the last\n * compaction moves ahead of its kept range. The branch is returned unchanged\n * when there is no such compaction or it already carries a `retainedTail`.\n */\nfunction orderForReference(branch: V3Entry[]): {\n ordered: V3Entry[];\n repositioned?: V3Compaction;\n} {\n const lastIndex = branch.findLastIndex((entry) => entry.type === \"compaction\");\n const lastCompaction = branch[lastIndex] as V3Compaction | undefined;\n const firstKeptId = lastCompaction?.retainedTail ? undefined : lastCompaction?.firstKeptEntryId;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n if (firstKeptIndex === -1 || !lastCompaction) return { ordered: branch };\n return {\n ordered: [\n ...branch.slice(0, firstKeptIndex),\n lastCompaction,\n ...branch.filter((_, index) => index >= firstKeptIndex && index !== lastIndex),\n ],\n repositioned: lastCompaction,\n };\n}\n\n/** A repositioned compaction drops its kept range: the range now follows it. */\nfunction emptiedCompaction(entry: V3Compaction): PiEntry {\n return {\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}\n\n/**\n * Convert a v3 branch to v4 entries with the pi-0.83 context semantics, so\n * pi's v4 transform reproduces the v3 context exactly. This mirrors what the\n * runtime shim did before mikan moved to native v4 files, and serves as the\n * verification oracle for migrated output.\n */\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n const { ordered, repositioned } = orderForReference(branch);\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n const piEntry =\n repositioned === entry ? emptiedCompaction(repositioned) : 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 contextMessagesOf(entry: PiEntry): AgentMessage[] {\n if (entry.type === \"message\") {\n return isCurrentContextMessage(entry.message) ? [entry.message] : [];\n }\n if (entry.type === \"compaction\") {\n return [\n createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp),\n ...entry.retainedTail.filter(isCurrentContextMessage),\n ];\n }\n if (entry.type === \"branch_summary\" && entry.summary) {\n return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];\n }\n return [];\n}\n\nfunction referenceContextMessages(entries: PiEntry[]): AgentMessage[] {\n const compactionIndex = entries.findLastIndex((entry) => entry.type === \"compaction\");\n const visible = compactionIndex === -1 ? entries : entries.slice(compactionIndex);\n return visible.flatMap(contextMessagesOf);\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\n/** Split a v3 entry stream into tree entries and the facts v4 stores as values. */\nfunction partitionEntries(entries: V3Entry[]): {\n tree: V3Entry[];\n name?: string;\n labels: Array<{ targetId: string; label: string | undefined }>;\n} {\n const tree: V3Entry[] = [];\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n let name: string | undefined;\n for (const entry of entries) {\n switch (entry.type) {\n case \"session_info\":\n name = entry.name?.trim() || undefined;\n break;\n case \"label\":\n labels.push({ targetId: entry.targetId, label: entry.label });\n break;\n case \"leaf\":\n break;\n default:\n tree.push(entry);\n }\n }\n return { tree, name, labels };\n}\n\n/** The v4 branch tip: the v3 leaf, walked back past fact-only entries. */\nfunction resolveV4Leaf(entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n let leafId = v3LeafId(entries);\n while (leafId !== null) {\n const target = byId.get(leafId);\n if (!target) return null;\n if (!isFactEntry(target)) return leafId;\n leafId = target.parentId;\n }\n return null;\n}\n\n/** Header fields v4 does not model survive as the durable `mikan/metadata` value. */\nfunction headerMetadata(header: V3SessionHeader): Record<string, JsonValue> | undefined {\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 } = header;\n const metadata: Record<string, JsonValue> = extras as Record<string, JsonValue>;\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const writer = new V4FileWriter(buildV4Header(file.header));\n const { tree, name, labels } = partitionEntries(file.entries);\n for (const entry of tree) {\n const converted = convertEntry(entry, file.entries);\n if (converted) writer.entry(converted);\n }\n writer.set(\"pi.branch.tip\", \"main\", resolveV4Leaf(file.entries));\n if (name !== undefined) writer.set(\"pi.session.name\", \"\", name);\n for (const { targetId, label } of labels) {\n if (label !== undefined) writer.set(\"pi.entry.label\", targetId, label);\n }\n const metadata = headerMetadata(file.header);\n if (metadata) writer.set(\"mikan\", \"metadata\", metadata);\n return writer.toString();\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 */\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 await commitMigration({\n filePath,\n sourceBytes,\n encoded: encodeV4File(source),\n tempPath: `${filePath}.v4.tmp`,\n backupPath: `${filePath}.v3.bak`,\n verify: (candidatePath) => verifyMigratedFile(candidatePath, source),\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 return findSessionFiles(root, isV3SessionFile);\n}\n"]}
1
+ {"version":3,"file":"migrate-v3.js","sourceRoot":"","sources":["../../src/sessions/migrate-v3.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\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 \"./session-store.js\";\nimport {\n commitMigration,\n findSessionFiles,\n optionalAnnotations,\n V4FileWriter,\n} from \"./migrate-common.js\";\nimport type { MigrateResult } from \"./types.js\";\nexport type { MigrateResult } from \"./types.js\";\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\ntype V3Compaction = Extract<V3Entry, { type: \"compaction\" }>;\ntype V3CustomMessage = Extract<V3Entry, { type: \"custom_message\" }>;\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\nfunction isFactEntry(entry: V3Entry): boolean {\n return entry.type === \"session_info\" || entry.type === \"label\" || entry.type === \"leaf\";\n}\n\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\nfunction parseJsonLines(filePath: string): Record<string, unknown>[] {\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 return records;\n}\n\nfunction dedupeEntries(records: Record<string, unknown>[]): V3Entry[] {\n const entriesById = new Map<string, V3Entry>();\n for (const record of records) {\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 [...entriesById.values()];\n}\n\nfunction readV3SessionFile(filePath: string): V3SessionFile {\n const records = parseJsonLines(filePath);\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 return {\n header: header as unknown as V3SessionHeader,\n entries: dedupeEntries(records.slice(1)),\n };\n}\n\nfunction toEpochMillis(timestamp: string): number {\n const parsed = Date.parse(timestamp);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\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\nfunction customMessageOf(entry: V3CustomMessage): AgentMessage {\n return createCustomMessage(\n entry.customType,\n entry.content,\n entry.display,\n entry.details,\n toEpochMillis(entry.timestamp),\n );\n}\n\nfunction convertEntry(entry: V3Entry, entries: V3Entry[]): PiEntry | null {\n const base = {\n id: entry.id,\n seq: 0,\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 { ...base, type: \"message\", message: customMessageOf(entry) };\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 ...optionalAnnotations(entry),\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 ...optionalAnnotations(entry),\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 return null;\n }\n}\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 (!isFactEntry(parent)) return parentId;\n parentId = parent.parentId;\n }\n return null;\n}\n\nfunction compactionKeptMessages(compaction: V3Compaction, entries: V3Entry[]): 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\") messages.push(customMessageOf(entry));\n }\n return messages;\n}\n\nfunction orderForReference(branch: V3Entry[]): {\n ordered: V3Entry[];\n repositioned?: V3Compaction;\n} {\n const lastIndex = branch.findLastIndex((entry) => entry.type === \"compaction\");\n const lastCompaction = branch[lastIndex] as V3Compaction | undefined;\n const firstKeptId = lastCompaction?.retainedTail ? undefined : lastCompaction?.firstKeptEntryId;\n const firstKeptIndex =\n firstKeptId === undefined ? -1 : branch.findIndex((entry) => entry.id === firstKeptId);\n if (firstKeptIndex === -1 || !lastCompaction) return { ordered: branch };\n return {\n ordered: [\n ...branch.slice(0, firstKeptIndex),\n lastCompaction,\n ...branch.filter((_, index) => index >= firstKeptIndex && index !== lastIndex),\n ],\n repositioned: lastCompaction,\n };\n}\n\nfunction emptiedCompaction(entry: V3Compaction): PiEntry {\n return {\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}\n\nfunction referenceContextEntries(branch: V3Entry[]): PiEntry[] {\n const { ordered, repositioned } = orderForReference(branch);\n const converted: PiEntry[] = [];\n for (const entry of ordered) {\n const piEntry =\n repositioned === entry ? emptiedCompaction(repositioned) : 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 contextMessagesOf(entry: PiEntry): AgentMessage[] {\n if (entry.type === \"message\") {\n return isCurrentContextMessage(entry.message) ? [entry.message] : [];\n }\n if (entry.type === \"compaction\") {\n return [\n createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp),\n ...entry.retainedTail.filter(isCurrentContextMessage),\n ];\n }\n if (entry.type === \"branch_summary\" && entry.summary) {\n return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];\n }\n return [];\n}\n\nfunction referenceContextMessages(entries: PiEntry[]): AgentMessage[] {\n const compactionIndex = entries.findLastIndex((entry) => entry.type === \"compaction\");\n const visible = compactionIndex === -1 ? entries : entries.slice(compactionIndex);\n return visible.flatMap(contextMessagesOf);\n}\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 partitionEntries(entries: V3Entry[]): {\n tree: V3Entry[];\n name?: string;\n labels: Array<{ targetId: string; label: string | undefined }>;\n} {\n const tree: V3Entry[] = [];\n const labels: Array<{ targetId: string; label: string | undefined }> = [];\n let name: string | undefined;\n for (const entry of entries) {\n switch (entry.type) {\n case \"session_info\":\n name = entry.name?.trim() || undefined;\n break;\n case \"label\":\n labels.push({ targetId: entry.targetId, label: entry.label });\n break;\n case \"leaf\":\n break;\n default:\n tree.push(entry);\n }\n }\n return { tree, name, labels };\n}\n\nfunction resolveV4Leaf(entries: V3Entry[]): string | null {\n const byId = new Map(entries.map((entry) => [entry.id, entry]));\n let leafId = v3LeafId(entries);\n while (leafId !== null) {\n const target = byId.get(leafId);\n if (!target) return null;\n if (!isFactEntry(target)) return leafId;\n leafId = target.parentId;\n }\n return null;\n}\n\nfunction headerMetadata(header: V3SessionHeader): Record<string, JsonValue> | undefined {\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 } = header;\n const metadata: Record<string, JsonValue> = extras as Record<string, JsonValue>;\n if (parentSession !== undefined) metadata.parentSessionPath = parentSession;\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction encodeV4File(file: V3SessionFile): string {\n const writer = new V4FileWriter(buildV4Header(file.header));\n const { tree, name, labels } = partitionEntries(file.entries);\n for (const entry of tree) {\n const converted = convertEntry(entry, file.entries);\n if (converted) writer.entry(converted);\n }\n writer.set(\"pi.branch.tip\", \"main\", resolveV4Leaf(file.entries));\n if (name !== undefined) writer.set(\"pi.session.name\", \"\", name);\n for (const { targetId, label } of labels) {\n if (label !== undefined) writer.set(\"pi.entry.label\", targetId, label);\n }\n const metadata = headerMetadata(file.header);\n if (metadata) writer.set(\"mikan\", \"metadata\", metadata);\n return writer.toString();\n}\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\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 await commitMigration({\n filePath,\n sourceBytes,\n encoded: encodeV4File(source),\n tempPath: `${filePath}.v4.tmp`,\n backupPath: `${filePath}.v3.bak`,\n verify: (candidatePath) => verifyMigratedFile(candidatePath, source),\n });\n return { file: filePath, status: \"migrated\" };\n}\n\nexport function findV3SessionFiles(root: string): string[] {\n return findSessionFiles(root, isV3SessionFile);\n}\n"]}