@geminixiang/mikan 1.0.0-beta.44 → 1.0.0-beta.46

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 (422) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +12 -19
  3. package/dist/adapter.d.ts +1 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/discord/bot.d.ts +3 -1
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +143 -141
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts +2 -8
  11. package/dist/adapters/discord/context.d.ts.map +1 -1
  12. package/dist/adapters/discord/context.js +1 -1
  13. package/dist/adapters/discord/context.js.map +1 -1
  14. package/dist/adapters/discord/format.d.ts.map +1 -1
  15. package/dist/adapters/discord/format.js +2 -4
  16. package/dist/adapters/discord/format.js.map +1 -1
  17. package/dist/adapters/github/bot.d.ts.map +1 -1
  18. package/dist/adapters/github/bot.js +1 -4
  19. package/dist/adapters/github/bot.js.map +1 -1
  20. package/dist/adapters/github/context.d.ts +2 -9
  21. package/dist/adapters/github/context.d.ts.map +1 -1
  22. package/dist/adapters/github/context.js.map +1 -1
  23. package/dist/adapters/github/github-ops.d.ts +4 -17
  24. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  25. package/dist/adapters/github/github-ops.js +17 -86
  26. package/dist/adapters/github/github-ops.js.map +1 -1
  27. package/dist/adapters/github/tool-pack.d.ts.map +1 -1
  28. package/dist/adapters/github/tool-pack.js +0 -1
  29. package/dist/adapters/github/tool-pack.js.map +1 -1
  30. package/dist/adapters/github/tools/checks.d.ts +0 -1
  31. package/dist/adapters/github/tools/checks.d.ts.map +1 -1
  32. package/dist/adapters/github/tools/checks.js +3 -22
  33. package/dist/adapters/github/tools/checks.js.map +1 -1
  34. package/dist/adapters/github/types.d.ts +0 -33
  35. package/dist/adapters/github/types.d.ts.map +1 -1
  36. package/dist/adapters/github/types.js.map +1 -1
  37. package/dist/adapters/progressive-renderer.d.ts.map +1 -1
  38. package/dist/adapters/progressive-renderer.js +311 -318
  39. package/dist/adapters/progressive-renderer.js.map +1 -1
  40. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  41. package/dist/adapters/slack/blocks.js +1 -4
  42. package/dist/adapters/slack/blocks.js.map +1 -1
  43. package/dist/adapters/slack/bot.d.ts +12 -0
  44. package/dist/adapters/slack/bot.d.ts.map +1 -1
  45. package/dist/adapters/slack/bot.js +158 -178
  46. package/dist/adapters/slack/bot.js.map +1 -1
  47. package/dist/adapters/slack/context.d.ts +2 -8
  48. package/dist/adapters/slack/context.d.ts.map +1 -1
  49. package/dist/adapters/slack/context.js +1 -1
  50. package/dist/adapters/slack/context.js.map +1 -1
  51. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  52. package/dist/adapters/slack/response-lifecycle.js +135 -123
  53. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  54. package/dist/adapters/slack/stream-limits.d.ts +1 -1
  55. package/dist/adapters/slack/stream-limits.js +1 -1
  56. package/dist/adapters/slack/stream-limits.js.map +1 -1
  57. package/dist/adapters/slack/types.d.ts +4 -0
  58. package/dist/adapters/slack/types.d.ts.map +1 -1
  59. package/dist/adapters/slack/types.js.map +1 -1
  60. package/dist/adapters/telegram/context.d.ts +2 -8
  61. package/dist/adapters/telegram/context.d.ts.map +1 -1
  62. package/dist/adapters/telegram/context.js +1 -2
  63. package/dist/adapters/telegram/context.js.map +1 -1
  64. package/dist/adapters/types.d.ts +11 -5
  65. package/dist/adapters/types.d.ts.map +1 -1
  66. package/dist/adapters/types.js.map +1 -1
  67. package/dist/agent/catalog.d.ts +6 -18
  68. package/dist/agent/catalog.d.ts.map +1 -1
  69. package/dist/agent/catalog.js +19 -155
  70. package/dist/agent/catalog.js.map +1 -1
  71. package/dist/agent/execution.d.ts +0 -7
  72. package/dist/agent/execution.d.ts.map +1 -1
  73. package/dist/agent/execution.js +23 -21
  74. package/dist/agent/execution.js.map +1 -1
  75. package/dist/agent/presenter.d.ts +7 -9
  76. package/dist/agent/presenter.d.ts.map +1 -1
  77. package/dist/agent/presenter.js +355 -357
  78. package/dist/agent/presenter.js.map +1 -1
  79. package/dist/agent/prompt.d.ts +5 -12
  80. package/dist/agent/prompt.d.ts.map +1 -1
  81. package/dist/agent/prompt.js +56 -81
  82. package/dist/agent/prompt.js.map +1 -1
  83. package/dist/agent/runner.d.ts +0 -7
  84. package/dist/agent/runner.d.ts.map +1 -1
  85. package/dist/agent/runner.js +255 -308
  86. package/dist/agent/runner.js.map +1 -1
  87. package/dist/agent/types.d.ts +21 -17
  88. package/dist/agent/types.d.ts.map +1 -1
  89. package/dist/agent/types.js +0 -1
  90. package/dist/agent/types.js.map +1 -1
  91. package/dist/cli/boot.d.ts.map +1 -1
  92. package/dist/cli/boot.js +7 -10
  93. package/dist/cli/boot.js.map +1 -1
  94. package/dist/cli/onboard.d.ts +10 -0
  95. package/dist/cli/onboard.d.ts.map +1 -0
  96. package/dist/cli/onboard.js +237 -0
  97. package/dist/cli/onboard.js.map +1 -0
  98. package/dist/cli/types.d.ts +8 -3
  99. package/dist/cli/types.d.ts.map +1 -1
  100. package/dist/cli/types.js.map +1 -1
  101. package/dist/commands/auto-reply.d.ts.map +1 -1
  102. package/dist/commands/auto-reply.js +5 -12
  103. package/dist/commands/auto-reply.js.map +1 -1
  104. package/dist/commands/manifest.d.ts.map +1 -1
  105. package/dist/commands/manifest.js +9 -16
  106. package/dist/commands/manifest.js.map +1 -1
  107. package/dist/commands/new.d.ts.map +1 -1
  108. package/dist/commands/new.js +15 -10
  109. package/dist/commands/new.js.map +1 -1
  110. package/dist/commands/registry.d.ts.map +1 -1
  111. package/dist/commands/registry.js +0 -2
  112. package/dist/commands/registry.js.map +1 -1
  113. package/dist/commands/sandbox.d.ts.map +1 -1
  114. package/dist/commands/sandbox.js +89 -70
  115. package/dist/commands/sandbox.js.map +1 -1
  116. package/dist/commands/session-view.js +9 -2
  117. package/dist/commands/session-view.js.map +1 -1
  118. package/dist/commands/types.d.ts +4 -3
  119. package/dist/commands/types.d.ts.map +1 -1
  120. package/dist/commands/types.js.map +1 -1
  121. package/dist/config.d.ts +13 -17
  122. package/dist/config.d.ts.map +1 -1
  123. package/dist/config.js +39 -37
  124. package/dist/config.js.map +1 -1
  125. package/dist/dream/index.d.ts +20 -0
  126. package/dist/dream/index.d.ts.map +1 -0
  127. package/dist/dream/index.js +253 -0
  128. package/dist/dream/index.js.map +1 -0
  129. package/dist/dream/types.d.ts +30 -0
  130. package/dist/dream/types.d.ts.map +1 -0
  131. package/dist/dream/types.js.map +1 -0
  132. package/dist/env-manifest.d.ts.map +1 -1
  133. package/dist/env-manifest.js +2 -34
  134. package/dist/env-manifest.js.map +1 -1
  135. package/dist/execution-resolver.d.ts +9 -2
  136. package/dist/execution-resolver.d.ts.map +1 -1
  137. package/dist/execution-resolver.js +26 -27
  138. package/dist/execution-resolver.js.map +1 -1
  139. package/dist/harness/event-format.d.ts +1 -2
  140. package/dist/harness/event-format.d.ts.map +1 -1
  141. package/dist/harness/event-format.js +9 -15
  142. package/dist/harness/event-format.js.map +1 -1
  143. package/dist/harness/index.d.ts +1 -7
  144. package/dist/harness/index.d.ts.map +1 -1
  145. package/dist/harness/index.js +0 -4
  146. package/dist/harness/index.js.map +1 -1
  147. package/dist/harness/models.d.ts.map +1 -1
  148. package/dist/harness/models.js +15 -35
  149. package/dist/harness/models.js.map +1 -1
  150. package/dist/harness/runner.d.ts +7 -16
  151. package/dist/harness/runner.d.ts.map +1 -1
  152. package/dist/harness/runner.js +13 -131
  153. package/dist/harness/runner.js.map +1 -1
  154. package/dist/harness/session-store.d.ts +1 -1
  155. package/dist/harness/session-store.d.ts.map +1 -1
  156. package/dist/harness/session-store.js +1 -1
  157. package/dist/harness/session-store.js.map +1 -1
  158. package/dist/harness/subagent-runner.d.ts +2 -2
  159. package/dist/harness/subagent-runner.d.ts.map +1 -1
  160. package/dist/harness/subagent-runner.js +157 -162
  161. package/dist/harness/subagent-runner.js.map +1 -1
  162. package/dist/harness/types.d.ts +1 -13
  163. package/dist/harness/types.d.ts.map +1 -1
  164. package/dist/harness/types.js.map +1 -1
  165. package/dist/index.d.ts +3 -9
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +1 -5
  168. package/dist/index.js.map +1 -1
  169. package/dist/main.js +31 -212
  170. package/dist/main.js.map +1 -1
  171. package/dist/mcp/catalog.d.ts +5 -0
  172. package/dist/mcp/catalog.d.ts.map +1 -0
  173. package/dist/mcp/catalog.js +135 -0
  174. package/dist/mcp/catalog.js.map +1 -0
  175. package/dist/mcp/loader.d.ts.map +1 -1
  176. package/dist/mcp/loader.js +3 -6
  177. package/dist/mcp/loader.js.map +1 -1
  178. package/dist/mcp/types.d.ts +22 -0
  179. package/dist/mcp/types.d.ts.map +1 -1
  180. package/dist/mcp/types.js.map +1 -1
  181. package/dist/office/index.d.ts +136 -8
  182. package/dist/office/index.d.ts.map +1 -1
  183. package/dist/office/index.js +1050 -9
  184. package/dist/office/index.js.map +1 -1
  185. package/dist/office/types.d.ts +19 -1
  186. package/dist/office/types.d.ts.map +1 -1
  187. package/dist/office/types.js.map +1 -1
  188. package/dist/packages/index.d.ts +168 -5
  189. package/dist/packages/index.d.ts.map +1 -1
  190. package/dist/packages/index.js +749 -5
  191. package/dist/packages/index.js.map +1 -1
  192. package/dist/packages/types.d.ts +1 -5
  193. package/dist/packages/types.d.ts.map +1 -1
  194. package/dist/packages/types.js.map +1 -1
  195. package/dist/provisioner.d.ts +2 -9
  196. package/dist/provisioner.d.ts.map +1 -1
  197. package/dist/provisioner.js +3 -12
  198. package/dist/provisioner.js.map +1 -1
  199. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  200. package/dist/runtime/conversation-runtime.js +117 -380
  201. package/dist/runtime/conversation-runtime.js.map +1 -1
  202. package/dist/runtime/session-lifecycle.d.ts +32 -18
  203. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  204. package/dist/runtime/session-lifecycle.js +159 -46
  205. package/dist/runtime/session-lifecycle.js.map +1 -1
  206. package/dist/runtime/types.d.ts +4 -26
  207. package/dist/runtime/types.d.ts.map +1 -1
  208. package/dist/runtime/types.js.map +1 -1
  209. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  210. package/dist/sandbox/cloudflare.js +2 -3
  211. package/dist/sandbox/cloudflare.js.map +1 -1
  212. package/dist/sandbox/container.d.ts +0 -1
  213. package/dist/sandbox/container.d.ts.map +1 -1
  214. package/dist/sandbox/container.js +2 -3
  215. package/dist/sandbox/container.js.map +1 -1
  216. package/dist/sandbox/host.d.ts.map +1 -1
  217. package/dist/sandbox/host.js +4 -2
  218. package/dist/sandbox/host.js.map +1 -1
  219. package/dist/sandbox/identity.d.ts +10 -19
  220. package/dist/sandbox/identity.d.ts.map +1 -1
  221. package/dist/sandbox/identity.js +8 -8
  222. package/dist/sandbox/identity.js.map +1 -1
  223. package/dist/sandbox/index.d.ts +7 -10
  224. package/dist/sandbox/index.d.ts.map +1 -1
  225. package/dist/sandbox/index.js +45 -16
  226. package/dist/sandbox/index.js.map +1 -1
  227. package/dist/sandbox/types.d.ts +13 -45
  228. package/dist/sandbox/types.d.ts.map +1 -1
  229. package/dist/sandbox/types.js.map +1 -1
  230. package/dist/sandbox/utils.d.ts +5 -0
  231. package/dist/sandbox/utils.d.ts.map +1 -1
  232. package/dist/sandbox/utils.js +10 -0
  233. package/dist/sandbox/utils.js.map +1 -1
  234. package/dist/sessions/chat-history-sync.d.ts +1 -3
  235. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  236. package/dist/sessions/chat-history-sync.js +58 -11
  237. package/dist/sessions/chat-history-sync.js.map +1 -1
  238. package/dist/sessions/migrate-v3.d.ts +2 -5
  239. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  240. package/dist/sessions/migrate-v3.js +34 -4
  241. package/dist/sessions/migrate-v3.js.map +1 -1
  242. package/dist/sessions/store.d.ts +5 -6
  243. package/dist/sessions/store.d.ts.map +1 -1
  244. package/dist/sessions/store.js +62 -2
  245. package/dist/sessions/store.js.map +1 -1
  246. package/dist/sessions/types.d.ts +9 -0
  247. package/dist/sessions/types.d.ts.map +1 -1
  248. package/dist/sessions/types.js.map +1 -1
  249. package/dist/tools/bash.d.ts.map +1 -1
  250. package/dist/tools/bash.js +2 -10
  251. package/dist/tools/bash.js.map +1 -1
  252. package/dist/tools/read.js +2 -2
  253. package/dist/tools/read.js.map +1 -1
  254. package/dist/tools/sandbox.d.ts.map +1 -1
  255. package/dist/tools/sandbox.js +2 -3
  256. package/dist/tools/sandbox.js.map +1 -1
  257. package/dist/tools/subagent.d.ts +1 -1
  258. package/dist/tools/subagent.js.map +1 -1
  259. package/dist/types.d.ts +38 -127
  260. package/dist/types.d.ts.map +1 -1
  261. package/dist/types.js.map +1 -1
  262. package/dist/vault/index.d.ts +9 -2
  263. package/dist/vault/index.d.ts.map +1 -1
  264. package/dist/vault/index.js +29 -5
  265. package/dist/vault/index.js.map +1 -1
  266. package/dist/web/admin/portal.d.ts +12 -1
  267. package/dist/web/admin/portal.d.ts.map +1 -1
  268. package/dist/web/admin/portal.js +437 -422
  269. package/dist/web/admin/portal.js.map +1 -1
  270. package/dist/web/admin/types.d.ts +2 -2
  271. package/dist/web/admin/types.d.ts.map +1 -1
  272. package/dist/web/admin/types.js.map +1 -1
  273. package/dist/web/login/portal.d.ts +7 -1
  274. package/dist/web/login/portal.d.ts.map +1 -1
  275. package/dist/web/login/portal.js +143 -78
  276. package/dist/web/login/portal.js.map +1 -1
  277. package/dist/web/portal-shell.d.ts +1 -0
  278. package/dist/web/portal-shell.d.ts.map +1 -1
  279. package/dist/web/portal-shell.js +12 -1
  280. package/dist/web/portal-shell.js.map +1 -1
  281. package/dist/web/server.d.ts +3 -3
  282. package/dist/web/server.d.ts.map +1 -1
  283. package/dist/web/server.js.map +1 -1
  284. package/dist/web/session-view/portal.d.ts +8 -1
  285. package/dist/web/session-view/portal.d.ts.map +1 -1
  286. package/dist/web/session-view/portal.js +609 -132
  287. package/dist/web/session-view/portal.js.map +1 -1
  288. package/dist/web/session-view/types.d.ts +8 -0
  289. package/dist/web/session-view/types.d.ts.map +1 -1
  290. package/dist/web/session-view/types.js.map +1 -1
  291. package/dist/workspace-projection/index.d.ts +14 -2
  292. package/dist/workspace-projection/index.d.ts.map +1 -1
  293. package/dist/workspace-projection/index.js +102 -14
  294. package/dist/workspace-projection/index.js.map +1 -1
  295. package/dist/workspace-projection/types.d.ts +14 -1
  296. package/dist/workspace-projection/types.d.ts.map +1 -1
  297. package/dist/workspace-projection/types.js.map +1 -1
  298. package/package.json +3 -5
  299. package/dist/adapters/github/cloudbuild.d.ts +0 -19
  300. package/dist/adapters/github/cloudbuild.d.ts.map +0 -1
  301. package/dist/adapters/github/cloudbuild.js +0 -71
  302. package/dist/adapters/github/cloudbuild.js.map +0 -1
  303. package/dist/adapters/github/gcp-auth.d.ts +0 -28
  304. package/dist/adapters/github/gcp-auth.d.ts.map +0 -1
  305. package/dist/adapters/github/gcp-auth.js +0 -196
  306. package/dist/adapters/github/gcp-auth.js.map +0 -1
  307. package/dist/agent/index.d.ts +0 -9
  308. package/dist/agent/index.d.ts.map +0 -1
  309. package/dist/agent/index.js +0 -8
  310. package/dist/agent/index.js.map +0 -1
  311. package/dist/cli/ext-dev.d.ts +0 -2
  312. package/dist/cli/ext-dev.d.ts.map +0 -1
  313. package/dist/cli/ext-dev.js +0 -188
  314. package/dist/cli/ext-dev.js.map +0 -1
  315. package/dist/cli/ext.d.ts +0 -2
  316. package/dist/cli/ext.d.ts.map +0 -1
  317. package/dist/cli/ext.js +0 -324
  318. package/dist/cli/ext.js.map +0 -1
  319. package/dist/commands/extensions.d.ts +0 -26
  320. package/dist/commands/extensions.d.ts.map +0 -1
  321. package/dist/commands/extensions.js +0 -103
  322. package/dist/commands/extensions.js.map +0 -1
  323. package/dist/extension-schedules.d.ts +0 -31
  324. package/dist/extension-schedules.d.ts.map +0 -1
  325. package/dist/extension-schedules.js +0 -229
  326. package/dist/extension-schedules.js.map +0 -1
  327. package/dist/harness/auth.d.ts +0 -17
  328. package/dist/harness/auth.d.ts.map +0 -1
  329. package/dist/harness/auth.js +0 -92
  330. package/dist/harness/auth.js.map +0 -1
  331. package/dist/harness/extensions/loader.d.ts +0 -40
  332. package/dist/harness/extensions/loader.d.ts.map +0 -1
  333. package/dist/harness/extensions/loader.js +0 -723
  334. package/dist/harness/extensions/loader.js.map +0 -1
  335. package/dist/harness/extensions/registry.d.ts +0 -155
  336. package/dist/harness/extensions/registry.d.ts.map +0 -1
  337. package/dist/harness/extensions/registry.js +0 -420
  338. package/dist/harness/extensions/registry.js.map +0 -1
  339. package/dist/harness/extensions/types.d.ts +0 -665
  340. package/dist/harness/extensions/types.d.ts.map +0 -1
  341. package/dist/harness/extensions/types.js.map +0 -1
  342. package/dist/office/address.d.ts +0 -31
  343. package/dist/office/address.d.ts.map +0 -1
  344. package/dist/office/address.js +0 -113
  345. package/dist/office/address.js.map +0 -1
  346. package/dist/office/layout.d.ts +0 -27
  347. package/dist/office/layout.d.ts.map +0 -1
  348. package/dist/office/layout.js +0 -97
  349. package/dist/office/layout.js.map +0 -1
  350. package/dist/office/migration.d.ts +0 -44
  351. package/dist/office/migration.d.ts.map +0 -1
  352. package/dist/office/migration.js +0 -255
  353. package/dist/office/migration.js.map +0 -1
  354. package/dist/office/registry.d.ts +0 -75
  355. package/dist/office/registry.d.ts.map +0 -1
  356. package/dist/office/registry.js +0 -646
  357. package/dist/office/registry.js.map +0 -1
  358. package/dist/packages/admin.d.ts +0 -17
  359. package/dist/packages/admin.d.ts.map +0 -1
  360. package/dist/packages/admin.js +0 -98
  361. package/dist/packages/admin.js.map +0 -1
  362. package/dist/packages/inspect.d.ts +0 -11
  363. package/dist/packages/inspect.d.ts.map +0 -1
  364. package/dist/packages/inspect.js +0 -98
  365. package/dist/packages/inspect.js.map +0 -1
  366. package/dist/packages/materialize.d.ts +0 -40
  367. package/dist/packages/materialize.d.ts.map +0 -1
  368. package/dist/packages/materialize.js +0 -297
  369. package/dist/packages/materialize.js.map +0 -1
  370. package/dist/packages/resolve.d.ts +0 -25
  371. package/dist/packages/resolve.d.ts.map +0 -1
  372. package/dist/packages/resolve.js +0 -208
  373. package/dist/packages/resolve.js.map +0 -1
  374. package/dist/packages/source.d.ts +0 -39
  375. package/dist/packages/source.d.ts.map +0 -1
  376. package/dist/packages/source.js +0 -189
  377. package/dist/packages/source.js.map +0 -1
  378. package/dist/sandbox/errors.d.ts +0 -6
  379. package/dist/sandbox/errors.d.ts.map +0 -1
  380. package/dist/sandbox/errors.js +0 -11
  381. package/dist/sandbox/errors.js.map +0 -1
  382. package/dist/sandbox/firecracker.d.ts +0 -18
  383. package/dist/sandbox/firecracker.d.ts.map +0 -1
  384. package/dist/sandbox/firecracker.js +0 -223
  385. package/dist/sandbox/firecracker.js.map +0 -1
  386. package/dist/sandbox/gondolin.d.ts +0 -57
  387. package/dist/sandbox/gondolin.d.ts.map +0 -1
  388. package/dist/sandbox/gondolin.js +0 -764
  389. package/dist/sandbox/gondolin.js.map +0 -1
  390. package/dist/sandbox/image.d.ts +0 -3
  391. package/dist/sandbox/image.d.ts.map +0 -1
  392. package/dist/sandbox/image.js +0 -29
  393. package/dist/sandbox/image.js.map +0 -1
  394. package/dist/sessions/conversation-log.d.ts +0 -9
  395. package/dist/sessions/conversation-log.d.ts.map +0 -1
  396. package/dist/sessions/conversation-log.js +0 -50
  397. package/dist/sessions/conversation-log.js.map +0 -1
  398. package/dist/sessions/rotation.d.ts +0 -2
  399. package/dist/sessions/rotation.d.ts.map +0 -1
  400. package/dist/sessions/rotation.js +0 -41
  401. package/dist/sessions/rotation.js.map +0 -1
  402. package/dist/vault/disabled.d.ts +0 -9
  403. package/dist/vault/disabled.d.ts.map +0 -1
  404. package/dist/vault/disabled.js +0 -25
  405. package/dist/vault/disabled.js.map +0 -1
  406. package/dist/web/admin/store.d.ts +0 -13
  407. package/dist/web/admin/store.d.ts.map +0 -1
  408. package/dist/web/admin/store.js +0 -14
  409. package/dist/web/admin/store.js.map +0 -1
  410. package/dist/web/login/store.d.ts +0 -8
  411. package/dist/web/login/store.d.ts.map +0 -1
  412. package/dist/web/login/store.js +0 -15
  413. package/dist/web/login/store.js.map +0 -1
  414. package/dist/web/session-view/service.d.ts +0 -6
  415. package/dist/web/session-view/service.d.ts.map +0 -1
  416. package/dist/web/session-view/service.js +0 -517
  417. package/dist/web/session-view/service.js.map +0 -1
  418. package/dist/web/session-view/store.d.ts +0 -8
  419. package/dist/web/session-view/store.d.ts.map +0 -1
  420. package/dist/web/session-view/store.js +0 -15
  421. package/dist/web/session-view/store.js.map +0 -1
  422. /package/dist/{harness/extensions → dream}/types.js +0 -0
@@ -1,13 +1,31 @@
1
+ import { dirname, join, resolve } from "node:path";
2
+ import { existsSync, readdirSync } from "node:fs";
3
+ import { SessionStore, } from "../../harness/index.js";
4
+ import { getThreadSessionFile, resolveChannelSessionFile, tryResolveThreadSession, } from "../../sessions/store.js";
5
+ import { isPlatformHistorySession } from "../../sessions/store.js";
1
6
  import { basename } from "node:path";
7
+ import { InMemoryTokenStore } from "../token-store.js";
2
8
  import MarkdownIt from "markdown-it";
3
9
  import { createConversationEvent, createConversationMessage, } from "../../adapter.js";
4
10
  import { createOfficeAddress } from "../../office/index.js";
5
11
  import * as log from "../../log.js";
6
- import { escapeHtml, readRawBody, renderPortalShell } from "../portal-shell.js";
12
+ import { escapeHtml, jsonResponse as json, readJsonBody, renderPortalShell, } from "../portal-shell.js";
7
13
  import { reportUserFacingError } from "../../observability/sentry.js";
8
14
  import { inferConversationKind } from "../../sessions/session-key.js";
9
15
  import { isThreadSessionKey, threadSuffixOf } from "../../sessions/session-key.js";
10
- import { loadSessionViewModel, resolveRequestedSessionFile, } from "./service.js";
16
+ const SESSION_VIEW_TOKEN_TTL_MS = 24 * 60 * 60 * 1000;
17
+ export class InMemorySessionViewTokenStore extends InMemoryTokenStore {
18
+ create(options) {
19
+ return this.createRecord(SESSION_VIEW_TOKEN_TTL_MS, {
20
+ platform: options.platform,
21
+ platformUserId: options.platformUserId,
22
+ ...(options.platformUserName ? { platformUserName: options.platformUserName } : {}),
23
+ conversationId: options.conversationId,
24
+ sessionKey: options.sessionKey,
25
+ sessionFile: options.sessionFile,
26
+ });
27
+ }
28
+ }
11
29
  const markdown = new MarkdownIt({
12
30
  html: false,
13
31
  linkify: true,
@@ -61,75 +79,93 @@ export async function handleSessionViewRequest(req, res, url, sessionViewTokenSt
61
79
  if (req.method !== "GET" || url.pathname !== "/session") {
62
80
  return false;
63
81
  }
64
- const token = url.searchParams.get("token")?.trim();
65
- if (!token || !sessionViewTokenStore) {
66
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
67
- res.end(renderStatusPage("Session unavailable", "This session link is invalid or has expired."));
82
+ const target = await resolveSessionRequestTarget(sessionViewTokenStore, url.searchParams.get("token"), url.searchParams.get("session"));
83
+ if (!target.ok) {
84
+ res.writeHead(target.status, { "Content-Type": "text/html; charset=utf-8" });
85
+ res.end(renderStatusPage("Session unavailable", target.message));
68
86
  return true;
69
87
  }
70
- const entry = sessionViewTokenStore.peek(token);
71
- if (!entry) {
72
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
73
- res.end(renderStatusPage("Session unavailable", "This session link is invalid or has expired."));
74
- return true;
75
- }
76
- const requestedSession = url.searchParams.get("session");
77
- let targetSessionFile;
88
+ const { activeSessionKey, entry, targetSessionFile } = target;
78
89
  try {
79
- targetSessionFile = await resolveRequestedSessionFile(entry.sessionFile, requestedSession);
90
+ const model = await loadSessionViewModel(targetSessionFile);
91
+ const displayedSessionKey = activeSessionKey;
92
+ const isRunning = interactive?.handler.isRunning(createOfficeAddress(entry.platform, entry.conversationId), displayedSessionKey) ?? false;
93
+ res.writeHead(200, {
94
+ "Content-Type": "text/html; charset=utf-8",
95
+ "Cache-Control": "no-store",
96
+ });
97
+ res.end(renderSessionPage({
98
+ model,
99
+ token: entry.token,
100
+ expiresAt: entry.expiresAt,
101
+ isRunning,
102
+ displayedSessionKey,
103
+ conversationId: entry.conversationId,
104
+ }));
80
105
  }
81
106
  catch (error) {
82
- log.logWarning(`[${entry.conversationId}] Corrupted session file referenced for ${entry.sessionFile}`, error instanceof Error ? error.message : String(error));
107
+ log.logWarning(`[${entry.conversationId}] Failed to render session ${entry.sessionFile}`, error instanceof Error ? error.message : String(error));
83
108
  reportUserFacingError(error, {
84
109
  domain: "session_view",
85
110
  surface: "session_view",
86
- operation: "resolve_requested_session",
111
+ operation: "render_session",
87
112
  severity: "error",
88
113
  platform: entry.platform,
89
114
  context: {
90
115
  conversationId: entry.conversationId,
91
116
  sessionKey: entry.sessionKey,
92
- sessionFile: basename(entry.sessionFile),
93
- requestedSession,
117
+ sessionFile: basename(targetSessionFile),
94
118
  },
95
119
  });
96
120
  res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
97
- res.end(renderStatusPage("Session unavailable", "The selected session file appears to be corrupted."));
98
- return true;
121
+ res.end(renderStatusPage("Session unavailable", "The session could not be loaded right now."));
99
122
  }
100
- if (!targetSessionFile) {
101
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
102
- res.end(renderStatusPage("Session unavailable", "The selected session link is invalid."));
103
- return true;
123
+ return true;
124
+ }
125
+ /**
126
+ * Token/session selection is shared by HTML, SSE, and message transports.
127
+ * Invalid or expired client capabilities are 400; missing server wiring is
128
+ * 503; a selected corrupt session is a server-side storage failure and is 500.
129
+ */
130
+ async function resolveSessionRequestTarget(sessionViewTokenStore, rawToken, requestedSession) {
131
+ if (!sessionViewTokenStore) {
132
+ return { ok: false, status: 503, message: "Session view is not configured." };
133
+ }
134
+ const token = rawToken?.trim() ?? "";
135
+ const entry = token ? sessionViewTokenStore.peek(token) : undefined;
136
+ if (!entry) {
137
+ return { ok: false, status: 400, message: "This session link is invalid or has expired." };
104
138
  }
139
+ let targetSessionFile;
105
140
  try {
106
- const model = await loadSessionViewModel(targetSessionFile);
107
- const displayedSessionKey = resolveDisplayedSessionKey(entry, targetSessionFile);
108
- const isRunning = interactive?.handler.isRunning(createOfficeAddress(entry.platform, entry.conversationId), displayedSessionKey) ?? false;
109
- res.writeHead(200, {
110
- "Content-Type": "text/html; charset=utf-8",
111
- "Cache-Control": "no-store",
112
- });
113
- res.end(renderSessionPage(model, entry.token, entry.expiresAt, isRunning, displayedSessionKey, entry.conversationId));
141
+ targetSessionFile = await resolveRequestedSessionFile(entry.sessionFile, requestedSession);
114
142
  }
115
143
  catch (error) {
116
- log.logWarning(`[${entry.conversationId}] Failed to render session ${entry.sessionFile}`, error instanceof Error ? error.message : String(error));
144
+ log.logWarning(`[${entry.conversationId}] Corrupted session file referenced for ${entry.sessionFile}`, error instanceof Error ? error.message : String(error));
117
145
  reportUserFacingError(error, {
118
146
  domain: "session_view",
119
147
  surface: "session_view",
120
- operation: "render_session",
148
+ operation: "resolve_requested_session",
121
149
  severity: "error",
122
150
  platform: entry.platform,
123
151
  context: {
124
152
  conversationId: entry.conversationId,
125
153
  sessionKey: entry.sessionKey,
126
- sessionFile: basename(targetSessionFile),
154
+ sessionFile: basename(entry.sessionFile),
155
+ requestedSession,
127
156
  },
128
157
  });
129
- res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
130
- res.end(renderStatusPage("Session unavailable", "The session could not be loaded right now."));
158
+ return { ok: false, status: 500, message: "The selected session file is corrupted." };
131
159
  }
132
- return true;
160
+ if (!targetSessionFile) {
161
+ return { ok: false, status: 400, message: "The selected session is invalid." };
162
+ }
163
+ return {
164
+ ok: true,
165
+ entry,
166
+ targetSessionFile,
167
+ activeSessionKey: resolveDisplayedSessionKey(entry, targetSessionFile),
168
+ };
133
169
  }
134
170
  function resolveDisplayedSessionKey(entry, sessionFile) {
135
171
  if (entry.platform === "slack") {
@@ -149,7 +185,8 @@ function renderTimelineItems(items, token) {
149
185
  ? items.map((item) => renderItem(item, token)).join("\n")
150
186
  : `<div class="system-event"><span class="event-dot"></span><span class="event-text">No messages yet — send one to the bot, then refresh.</span></div>`;
151
187
  }
152
- function renderSessionPage(model, token, expiresAt, isRunning, displayedSessionKey, conversationId) {
188
+ function renderSessionPage(options) {
189
+ const { model, token, expiresAt, isRunning, displayedSessionKey, conversationId } = options;
153
190
  const items = renderTimelineItems(model.items, token);
154
191
  const relatedSections = model.parent
155
192
  ? `<section class="related-card stack">
@@ -364,47 +401,18 @@ function renderLiveSystemEvent(text, tone = "default") {
364
401
  return `<div class="system-event${cls}" data-live-item><span class="event-dot"></span><span class="event-text">${esc(text)}</span></div>`;
365
402
  }
366
403
  async function handleSessionStreamRequest(req, res, url, sessionViewTokenStore, interactive) {
367
- const token = url.searchParams.get("token")?.trim() ?? "";
368
- if (!token || !sessionViewTokenStore || !interactive) {
369
- res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
370
- res.end("Session stream unavailable");
371
- return;
372
- }
373
- const entry = sessionViewTokenStore.peek(token);
374
- if (!entry) {
375
- res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
376
- res.end("Invalid session token");
377
- return;
378
- }
379
- const requestedSession = url.searchParams.get("session");
380
- let targetSessionFile;
381
- try {
382
- targetSessionFile = await resolveRequestedSessionFile(entry.sessionFile, requestedSession);
383
- }
384
- catch (error) {
385
- reportUserFacingError(error, {
386
- domain: "session_view",
387
- surface: "session_view",
388
- operation: "session_stream",
389
- severity: "error",
390
- platform: entry.platform,
391
- context: {
392
- conversationId: entry.conversationId,
393
- sessionKey: entry.sessionKey,
394
- sessionFile: basename(entry.sessionFile),
395
- requestedSession,
396
- },
397
- });
398
- res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
399
- res.end("Session stream unavailable");
404
+ if (!interactive) {
405
+ res.writeHead(503, { "Content-Type": "text/plain; charset=utf-8" });
406
+ res.end("Session stream is not configured.");
400
407
  return;
401
408
  }
402
- if (!targetSessionFile) {
403
- res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
404
- res.end("Invalid session file");
409
+ const target = await resolveSessionRequestTarget(sessionViewTokenStore, url.searchParams.get("token"), url.searchParams.get("session"));
410
+ if (!target.ok) {
411
+ res.writeHead(target.status, { "Content-Type": "text/plain; charset=utf-8" });
412
+ res.end(target.message);
405
413
  return;
406
414
  }
407
- const activeSessionKey = resolveDisplayedSessionKey(entry, targetSessionFile);
415
+ const { activeSessionKey, entry } = target;
408
416
  const streamKey = sessionStreamKey({ ...entry, sessionKey: activeSessionKey });
409
417
  res.writeHead(200, {
410
418
  "Content-Type": "text/event-stream; charset=utf-8",
@@ -427,64 +435,43 @@ async function handleSessionStreamRequest(req, res, url, sessionViewTokenStore,
427
435
  });
428
436
  }
429
437
  async function handleSessionMessageRequest(req, res, sessionViewTokenStore, interactive) {
430
- if (!sessionViewTokenStore || !interactive) {
438
+ if (!interactive) {
431
439
  json(res, 503, { ok: false, error: "Session chat is not configured." });
432
440
  return;
433
441
  }
434
- const rawBody = await readRawBody(req, res, 1024 * 1024);
435
- if (rawBody === null)
436
- return;
437
- let body;
438
- try {
439
- body = JSON.parse(rawBody);
440
- }
441
- catch {
442
- json(res, 400, { ok: false, error: "Invalid request body." });
442
+ const body = await readJsonBody(req, res, 1024 * 1024);
443
+ if (!body)
443
444
  return;
444
- }
445
- const token = body.token?.trim() ?? "";
446
- const text = body.text?.trim() ?? "";
447
- const requestedSession = body.session?.trim() || null;
448
- const requestedSessionKey = body.sessionKey?.trim() || "";
445
+ const token = typeof body.token === "string" ? body.token.trim() : "";
446
+ const text = typeof body.text === "string" ? body.text.trim() : "";
447
+ const requestedSession = typeof body.session === "string" ? body.session.trim() || null : null;
448
+ const requestedSessionKey = typeof body.sessionKey === "string" ? body.sessionKey.trim() : "";
449
449
  if (!token || !text) {
450
450
  json(res, 400, { ok: false, error: "Missing token or text." });
451
451
  return;
452
452
  }
453
- const entry = sessionViewTokenStore.peek(token);
454
- if (!entry) {
455
- json(res, 400, { ok: false, error: "This session link is invalid or has expired." });
456
- return;
457
- }
458
- let targetSessionFile;
459
- try {
460
- targetSessionFile = await resolveRequestedSessionFile(entry.sessionFile, requestedSession);
461
- }
462
- catch (error) {
463
- reportUserFacingError(error, {
464
- domain: "session_view",
465
- surface: "session_view",
466
- operation: "session_message",
467
- severity: "error",
468
- platform: entry.platform,
469
- context: {
470
- conversationId: entry.conversationId,
471
- sessionKey: entry.sessionKey,
472
- sessionFile: basename(entry.sessionFile),
473
- requestedSession,
474
- },
475
- });
476
- json(res, 500, { ok: false, error: "Session file could not be loaded." });
477
- return;
478
- }
479
- if (!targetSessionFile) {
480
- json(res, 400, { ok: false, error: "Invalid session file." });
453
+ const target = await resolveSessionRequestTarget(sessionViewTokenStore, token, requestedSession);
454
+ if (!target.ok) {
455
+ json(res, target.status, { ok: false, error: target.message });
481
456
  return;
482
457
  }
483
- const activeSessionKey = resolveDisplayedSessionKey(entry, targetSessionFile);
458
+ const { activeSessionKey, entry, targetSessionFile } = target;
484
459
  if (requestedSessionKey && requestedSessionKey !== activeSessionKey) {
485
460
  json(res, 400, { ok: false, error: "Session target mismatch." });
486
461
  return;
487
462
  }
463
+ await dispatchSessionViewMessage({
464
+ res,
465
+ interactive,
466
+ token,
467
+ text,
468
+ activeSessionKey,
469
+ entry,
470
+ targetSessionFile,
471
+ });
472
+ }
473
+ async function dispatchSessionViewMessage(input) {
474
+ const { res, interactive, token, text, activeSessionKey, entry, targetSessionFile } = input;
488
475
  const bot = interactive.botsByPlatform[entry.platform];
489
476
  if (!bot) {
490
477
  json(res, 503, { ok: false, error: `No bot configured for ${entry.platform}.` });
@@ -541,10 +528,6 @@ async function handleSessionMessageRequest(req, res, sessionViewTokenStore, inte
541
528
  void interactive.handler
542
529
  .handleEvent(event, bot, context)
543
530
  .then(async () => {
544
- if (!targetSessionFile) {
545
- sessionViewStreamHub.publish(streamKey, { type: "status", running: false });
546
- return;
547
- }
548
531
  const model = await loadSessionViewModel(targetSessionFile);
549
532
  sessionViewStreamHub.publish(streamKey, {
550
533
  type: "refresh",
@@ -609,13 +592,6 @@ function createSessionViewResponseContext(publish) {
609
592
  },
610
593
  };
611
594
  }
612
- function json(res, status, body) {
613
- res.writeHead(status, {
614
- "Content-Type": "application/json; charset=utf-8",
615
- "Cache-Control": "no-store",
616
- });
617
- res.end(JSON.stringify(body));
618
- }
619
595
  function renderStatusPage(title, message) {
620
596
  return renderHtmlDocument(title, `<section class="card stack">
621
597
  <p class="eyebrow">mikan</p>
@@ -1657,4 +1633,505 @@ const sessionViewStyles = `
1657
1633
  .asst-card { border-radius: 4px 14px 14px 14px; }
1658
1634
  }
1659
1635
  `;
1636
+ // ── Session view model (formerly service.ts) ──────────────────────────────────
1637
+ function entryIsoTime(entry) {
1638
+ if (!entry || typeof entry.timestamp !== "number" || !Number.isFinite(entry.timestamp)) {
1639
+ return undefined;
1640
+ }
1641
+ return new Date(entry.timestamp).toISOString();
1642
+ }
1643
+ export function resolveExistingSessionFile(conversationDir, sessionKey) {
1644
+ if (isThreadSessionKey(sessionKey)) {
1645
+ return tryResolveThreadSession(getThreadSessionFile(conversationDir, sessionKey));
1646
+ }
1647
+ return resolveChannelSessionFile(conversationDir);
1648
+ }
1649
+ export async function loadSessionViewModel(sessionFile) {
1650
+ const resolvedFile = resolve(sessionFile);
1651
+ const sm = await SessionStore.inspect(resolvedFile);
1652
+ const header = sm.getHeader();
1653
+ const entries = await sm.getEntries();
1654
+ const updatedAt = entryIsoTime(entries.at(-1)) ?? header.timestamp;
1655
+ const title = (await sm.getSessionName()) || `Session ${header.id.slice(0, 8)}`;
1656
+ const parent = await resolveParentRelation(resolvedFile, header);
1657
+ const threadCandidates = [];
1658
+ for (const candidate of listRelatedSessionFiles(resolvedFile)) {
1659
+ if (candidate === resolvedFile)
1660
+ continue;
1661
+ const relation = await buildSessionRelation(candidate, "thread", resolvedFile, header.id, entries);
1662
+ if (relation)
1663
+ threadCandidates.push(relation);
1664
+ }
1665
+ const threads = threadCandidates.toSorted((a, b) => a.updatedAt < b.updatedAt ? -1 : a.updatedAt > b.updatedAt ? 1 : 0);
1666
+ const threadsByEntryId = new Map();
1667
+ for (const thread of threads) {
1668
+ if (!thread.anchorEntryId)
1669
+ continue;
1670
+ const bucket = threadsByEntryId.get(thread.anchorEntryId) ?? [];
1671
+ bucket.push(thread);
1672
+ threadsByEntryId.set(thread.anchorEntryId, bucket);
1673
+ }
1674
+ const items = entries.flatMap((entry) => {
1675
+ const item = mapEntryToItem(entry);
1676
+ if (!item)
1677
+ return [];
1678
+ if (item.entryId) {
1679
+ const anchoredThreads = threadsByEntryId.get(item.entryId);
1680
+ if (anchoredThreads) {
1681
+ item.threads = anchoredThreads;
1682
+ }
1683
+ }
1684
+ return [item];
1685
+ });
1686
+ return {
1687
+ sessionId: header.id,
1688
+ fileName: basename(resolvedFile),
1689
+ title,
1690
+ createdAt: header.timestamp,
1691
+ updatedAt,
1692
+ entryCount: entries.length,
1693
+ items,
1694
+ parent: parent ?? undefined,
1695
+ threads,
1696
+ };
1697
+ }
1698
+ async function resolveRequestedSessionFile(baseSessionFile, requestedFileName) {
1699
+ const resolvedBase = resolve(baseSessionFile);
1700
+ if (!requestedFileName)
1701
+ return resolvedBase;
1702
+ const trimmed = requestedFileName.trim();
1703
+ if (!trimmed)
1704
+ return resolvedBase;
1705
+ const fileName = basename(trimmed);
1706
+ if (fileName !== trimmed || !fileName.endsWith(".jsonl"))
1707
+ return null;
1708
+ const candidate = join(dirname(resolvedBase), fileName);
1709
+ if (!existsSync(candidate))
1710
+ return null;
1711
+ try {
1712
+ await SessionStore.open(candidate);
1713
+ }
1714
+ catch (err) {
1715
+ throw new Error(`Session file is corrupted: ${candidate}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
1716
+ }
1717
+ return candidate;
1718
+ }
1719
+ function listRelatedSessionFiles(sessionFile) {
1720
+ const dir = dirname(sessionFile);
1721
+ if (!existsSync(dir))
1722
+ return [];
1723
+ return readdirSync(dir)
1724
+ .filter((name) => name.endsWith(".jsonl"))
1725
+ .map((fileName) => join(dir, fileName));
1726
+ }
1727
+ async function buildSessionRelation(sessionFile, kind, expectedParent, expectedParentId, expectedParentEntries) {
1728
+ let sm;
1729
+ try {
1730
+ sm = await SessionStore.inspect(sessionFile);
1731
+ }
1732
+ catch (err) {
1733
+ log.logWarning(`Skipping corrupted session file while building ${kind} relation: ${sessionFile}`, err instanceof Error ? err.message : String(err));
1734
+ return null;
1735
+ }
1736
+ const header = sm.getHeader();
1737
+ if (kind === "thread" &&
1738
+ !isChildThreadSession(sessionFile, header.parentSession, expectedParent, expectedParentId, header.parentSessionId)) {
1739
+ return null;
1740
+ }
1741
+ const entries = await sm.getEntries();
1742
+ const updatedAt = entryIsoTime(entries.at(-1)) ?? header.timestamp;
1743
+ const threadId = kind === "thread" ? getFixedThreadSessionId(sessionFile) : null;
1744
+ const anchorEntryId = kind === "thread" && expectedParent
1745
+ ? findThreadAnchorEntryId(expectedParentEntries ??
1746
+ (await (await SessionStore.inspect(expectedParent)).getEntries()), entries, threadId)
1747
+ : undefined;
1748
+ return {
1749
+ kind,
1750
+ fileName: basename(sessionFile),
1751
+ sessionId: header.id,
1752
+ title: (await sm.getSessionName()) || `Session ${header.id.slice(0, 8)}`,
1753
+ updatedAt,
1754
+ entryCount: entries.length,
1755
+ summary: extractSessionSummary(entries),
1756
+ anchorEntryId,
1757
+ };
1758
+ }
1759
+ async function resolveParentRelation(sessionFile, header) {
1760
+ if (header.parentSession) {
1761
+ const parentPath = resolve(header.parentSession);
1762
+ if (existsSync(parentPath)) {
1763
+ return (await buildSessionRelation(parentPath, "parent")) ?? undefined;
1764
+ }
1765
+ // Path is stale — try UUID fallback before heuristic.
1766
+ if (header.parentSessionId) {
1767
+ const found = findSessionFileById(dirname(sessionFile), header.parentSessionId);
1768
+ if (found)
1769
+ return (await buildSessionRelation(found, "parent")) ?? undefined;
1770
+ }
1771
+ }
1772
+ return buildInferredThreadParentRelation(sessionFile);
1773
+ }
1774
+ function findSessionFileById(sessionDir, targetId) {
1775
+ if (!existsSync(sessionDir))
1776
+ return null;
1777
+ for (const name of readdirSync(sessionDir)) {
1778
+ if (!name.endsWith(".jsonl"))
1779
+ continue;
1780
+ try {
1781
+ const filePath = join(sessionDir, name);
1782
+ if (SessionStore.readHeader(filePath)?.id === targetId)
1783
+ return filePath;
1784
+ }
1785
+ catch {
1786
+ continue;
1787
+ }
1788
+ }
1789
+ return null;
1790
+ }
1791
+ async function buildInferredThreadParentRelation(sessionFile) {
1792
+ if (!getFixedThreadSessionId(sessionFile))
1793
+ return undefined;
1794
+ const parentSession = resolveChannelSessionFile(dirname(dirname(sessionFile)));
1795
+ if (!parentSession || parentSession === sessionFile)
1796
+ return undefined;
1797
+ return (await buildSessionRelation(parentSession, "parent")) ?? undefined;
1798
+ }
1799
+ function isChildThreadSession(sessionFile, parentSession, expectedParent, expectedParentId, threadParentSessionId) {
1800
+ if (!expectedParent)
1801
+ return false;
1802
+ if (parentSession) {
1803
+ const resolvedParent = resolve(parentSession);
1804
+ if (resolvedParent === expectedParent ||
1805
+ (isPlatformHistorySession(expectedParent) && isPlatformHistorySession(resolvedParent))) {
1806
+ return true;
1807
+ }
1808
+ // Path is stale — fall back to UUID comparison.
1809
+ if (expectedParentId && threadParentSessionId) {
1810
+ return threadParentSessionId === expectedParentId;
1811
+ }
1812
+ return false;
1813
+ }
1814
+ if (!getFixedThreadSessionId(sessionFile))
1815
+ return false;
1816
+ return resolveChannelSessionFile(dirname(dirname(sessionFile))) === expectedParent;
1817
+ }
1818
+ function getFixedThreadSessionId(sessionFile) {
1819
+ const fileName = basename(sessionFile);
1820
+ if (!fileName.endsWith(".jsonl"))
1821
+ return null;
1822
+ if (/^\d{4}-\d{2}-\d{2}T.+_[0-9a-f]{8}\.jsonl$/i.test(fileName))
1823
+ return null;
1824
+ return fileName.slice(0, -".jsonl".length);
1825
+ }
1826
+ function findThreadAnchorEntryId(parentEntries, childEntries, threadId) {
1827
+ const threadTimestamp = threadId ? Number(threadId) * 1000 : undefined;
1828
+ if (threadTimestamp !== undefined && Number.isFinite(threadTimestamp)) {
1829
+ const timestampAnchor = findEntryIdByMessageTimestamp(parentEntries, threadTimestamp);
1830
+ if (timestampAnchor)
1831
+ return timestampAnchor;
1832
+ }
1833
+ let sharedCount = 0;
1834
+ while (sharedCount < parentEntries.length &&
1835
+ sharedCount < childEntries.length &&
1836
+ parentEntries[sharedCount]?.id === childEntries[sharedCount]?.id) {
1837
+ sharedCount += 1;
1838
+ }
1839
+ if (sharedCount > 0) {
1840
+ return parentEntries[sharedCount - 1]?.id;
1841
+ }
1842
+ const contentAnchor = findSharedContentAnchorEntryId(parentEntries, childEntries);
1843
+ if (contentAnchor)
1844
+ return contentAnchor;
1845
+ const childRoot = findComparableUserMessage(childEntries);
1846
+ if (!childRoot)
1847
+ return undefined;
1848
+ return findParentAnchorByRootMessage(parentEntries, childRoot);
1849
+ }
1850
+ function findEntryIdByMessageTimestamp(entries, timestamp) {
1851
+ for (const entry of entries) {
1852
+ if (entry.type !== "message")
1853
+ continue;
1854
+ const messageTimestamp = entry.message.timestamp;
1855
+ if (messageTimestamp === timestamp)
1856
+ return entry.id;
1857
+ }
1858
+ return undefined;
1859
+ }
1860
+ function findSharedContentAnchorEntryId(parentEntries, childEntries) {
1861
+ const parentMessages = parentEntries.flatMap((entry) => {
1862
+ const comparable = getComparableSessionMessage(entry);
1863
+ return comparable ? [comparable] : [];
1864
+ });
1865
+ const childMessages = childEntries.flatMap((entry) => {
1866
+ const comparable = getComparableSessionMessage(entry);
1867
+ return comparable ? [comparable] : [];
1868
+ });
1869
+ if (parentMessages.length === 0 || childMessages.length === 0)
1870
+ return undefined;
1871
+ let bestParentEnd = -1;
1872
+ let bestLength = 0;
1873
+ for (let parentStart = 0; parentStart < parentMessages.length; parentStart++) {
1874
+ let length = 0;
1875
+ while (parentStart + length < parentMessages.length && length < childMessages.length) {
1876
+ const parentMessage = parentMessages[parentStart + length];
1877
+ const childMessage = childMessages[length];
1878
+ if (parentMessage === undefined ||
1879
+ childMessage === undefined ||
1880
+ parentMessage.role !== childMessage.role ||
1881
+ parentMessage.normalizedText !== childMessage.normalizedText) {
1882
+ break;
1883
+ }
1884
+ length += 1;
1885
+ }
1886
+ if (length > bestLength) {
1887
+ bestLength = length;
1888
+ bestParentEnd = parentStart + length - 1;
1889
+ }
1890
+ }
1891
+ return bestLength > 0 ? parentMessages[bestParentEnd]?.entryId : undefined;
1892
+ }
1893
+ function getComparableSessionMessage(entry) {
1894
+ if (entry.type !== "message")
1895
+ return null;
1896
+ const role = entry.message.role;
1897
+ if (role !== "user" && role !== "assistant")
1898
+ return null;
1899
+ const body = contentToText(entry.message.content);
1900
+ const normalizedText = normalizeComparableSessionText(body, role);
1901
+ if (!normalizedText)
1902
+ return null;
1903
+ return { entryId: entry.id, role, normalizedText };
1904
+ }
1905
+ function normalizeComparableSessionText(text, role) {
1906
+ const normalized = role === "user" ? normalizeComparableUserText(text) : text.trim();
1907
+ return normalized.replace(/\s+/g, " ").trim();
1908
+ }
1909
+ function findParentAnchorByRootMessage(parentEntries, childRoot) {
1910
+ let textMatchId;
1911
+ for (const entry of parentEntries) {
1912
+ const comparable = getComparableUserMessage(entry);
1913
+ if (!comparable)
1914
+ continue;
1915
+ if (comparable.normalizedText !== childRoot.normalizedText)
1916
+ continue;
1917
+ if (childRoot.messageTimestamp !== undefined &&
1918
+ comparable.messageTimestamp !== undefined &&
1919
+ comparable.messageTimestamp === childRoot.messageTimestamp) {
1920
+ return entry.id;
1921
+ }
1922
+ textMatchId ??= entry.id;
1923
+ }
1924
+ return textMatchId;
1925
+ }
1926
+ function findComparableUserMessage(entries) {
1927
+ for (const entry of entries) {
1928
+ const comparable = getComparableUserMessage(entry);
1929
+ if (comparable)
1930
+ return comparable;
1931
+ }
1932
+ return null;
1933
+ }
1934
+ function getComparableUserMessage(entry) {
1935
+ if (entry.type !== "message" || entry.message.role !== "user")
1936
+ return null;
1937
+ const body = contentToText(entry.message.content);
1938
+ const normalizedText = normalizeComparableUserText(body);
1939
+ if (!normalizedText)
1940
+ return null;
1941
+ const messageTimestamp = typeof entry.message.timestamp === "number" ? entry.message.timestamp : undefined;
1942
+ return { normalizedText, messageTimestamp };
1943
+ }
1944
+ function normalizeComparableUserText(text) {
1945
+ const withoutTimestamp = text.replace(/^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{2}:[0-9]{2}\]\s+(?=\[[^\]]+\](?:\s+\[in-thread:[^\]]+\])?:\s)/, "");
1946
+ return withoutTimestamp
1947
+ .replace(/\n*<slack_attachments>\n[\s\S]*?\n<\/slack_attachments>\s*$/g, "")
1948
+ .trim();
1949
+ }
1950
+ function extractSessionSummary(entries) {
1951
+ for (const entry of entries) {
1952
+ if (entry.type !== "message")
1953
+ continue;
1954
+ const item = mapEntryToItem(entry);
1955
+ if (!item?.body)
1956
+ continue;
1957
+ return collapseSummary(item.body);
1958
+ }
1959
+ return undefined;
1960
+ }
1961
+ function collapseSummary(text) {
1962
+ const singleLine = text.replace(/\s+/g, " ").trim();
1963
+ return singleLine.length > 96 ? `${singleLine.slice(0, 93)}…` : singleLine;
1964
+ }
1965
+ function mapEntryToItem(entry) {
1966
+ switch (entry.type) {
1967
+ case "message":
1968
+ return mapMessageEntry(entry);
1969
+ case "model_change":
1970
+ return {
1971
+ kind: "system",
1972
+ title: "Model changed",
1973
+ body: `${entry.provider} / ${entry.modelId}`,
1974
+ meta: entryIsoTime(entry) ?? "",
1975
+ tone: "muted",
1976
+ };
1977
+ case "thinking_level_change":
1978
+ return {
1979
+ kind: "system",
1980
+ title: "Thinking level changed",
1981
+ body: entry.thinkingLevel,
1982
+ meta: entryIsoTime(entry) ?? "",
1983
+ tone: "muted",
1984
+ };
1985
+ case "compaction":
1986
+ return mapCompactionEntry(entry);
1987
+ case "branch_summary":
1988
+ return mapSessionSummaryEntry(entry);
1989
+ case "custom":
1990
+ return {
1991
+ kind: "system",
1992
+ title: `Custom data · ${entry.customType}`,
1993
+ body: entry.data === undefined ? "(no data)" : JSON.stringify(entry.data, null, 2),
1994
+ meta: entryIsoTime(entry) ?? "",
1995
+ tone: "muted",
1996
+ };
1997
+ default:
1998
+ return null;
1999
+ }
2000
+ }
2001
+ function mapMessageEntry(entry) {
2002
+ const message = entry.message;
2003
+ switch (message.role) {
2004
+ case "user":
2005
+ return {
2006
+ kind: "user",
2007
+ title: "User",
2008
+ body: contentToText(message.content),
2009
+ meta: entryIsoTime(entry) ?? "",
2010
+ entryId: entry.id,
2011
+ };
2012
+ case "assistant": {
2013
+ const assistantBody = contentToText(message.content) || (message.errorMessage ? `_${message.errorMessage}_` : "");
2014
+ const metaParts = [message.provider, message.model, message.stopReason].filter(Boolean);
2015
+ return {
2016
+ kind: "assistant",
2017
+ title: "Assistant",
2018
+ body: assistantBody,
2019
+ meta: metaParts.length > 0
2020
+ ? `${entryIsoTime(entry) ?? ""} · ${metaParts.join(" · ")}`
2021
+ : (entryIsoTime(entry) ?? ""),
2022
+ entryId: entry.id,
2023
+ };
2024
+ }
2025
+ case "toolResult":
2026
+ return {
2027
+ kind: "tool",
2028
+ title: `Tool result · ${String(message.toolName ?? "unknown")}`,
2029
+ body: contentToText(message.content),
2030
+ meta: entryIsoTime(entry) ?? "",
2031
+ tone: message.isError ? "err" : "ok",
2032
+ entryId: entry.id,
2033
+ };
2034
+ case "bashExecution": {
2035
+ const command = String(message.command ?? "").trim();
2036
+ const output = String(message.output ?? "").trim();
2037
+ const details = [
2038
+ typeof message.exitCode === "number" ? `[exitCode] ${message.exitCode}` : "",
2039
+ message.cancelled ? `[cancelled] true` : "",
2040
+ message.truncated ? `[truncated] true` : "",
2041
+ ].filter(Boolean);
2042
+ const body = [command ? `$ ${command}` : "", output, ...details].filter(Boolean).join("\n\n");
2043
+ return {
2044
+ kind: "tool",
2045
+ title: "Bash execution",
2046
+ body: body || "(no output)",
2047
+ meta: entryIsoTime(entry) ?? "",
2048
+ entryId: entry.id,
2049
+ };
2050
+ }
2051
+ case "custom":
2052
+ return {
2053
+ kind: "system",
2054
+ title: `Custom message · ${String(message.customType ?? "custom")}`,
2055
+ body: contentToText(message.content),
2056
+ meta: entryIsoTime(entry) ?? "",
2057
+ tone: "muted",
2058
+ entryId: entry.id,
2059
+ };
2060
+ case "branchSummary":
2061
+ return {
2062
+ kind: "system",
2063
+ title: "Session summary",
2064
+ body: String(message.summary ?? ""),
2065
+ meta: entryIsoTime(entry) ?? "",
2066
+ tone: "muted",
2067
+ entryId: entry.id,
2068
+ };
2069
+ case "compactionSummary":
2070
+ return {
2071
+ kind: "system",
2072
+ title: "Compaction summary",
2073
+ body: String(message.summary ?? ""),
2074
+ meta: entryIsoTime(entry) ?? "",
2075
+ tone: "muted",
2076
+ entryId: entry.id,
2077
+ };
2078
+ default:
2079
+ return {
2080
+ kind: "system",
2081
+ title: `Message · ${String(message.role ?? "unknown")}`,
2082
+ body: contentToText(message.content),
2083
+ meta: entryIsoTime(entry) ?? "",
2084
+ tone: "muted",
2085
+ entryId: entry.id,
2086
+ };
2087
+ }
2088
+ }
2089
+ function mapCompactionEntry(entry) {
2090
+ return {
2091
+ kind: "system",
2092
+ title: "Context compacted",
2093
+ body: entry.summary,
2094
+ meta: `${entryIsoTime(entry) ?? ""} · ${entry.tokensBefore} tokens before compaction`,
2095
+ tone: "muted",
2096
+ };
2097
+ }
2098
+ function mapSessionSummaryEntry(entry) {
2099
+ return {
2100
+ kind: "system",
2101
+ title: "Session summary",
2102
+ body: entry.summary,
2103
+ meta: entryIsoTime(entry) ?? "",
2104
+ tone: "muted",
2105
+ };
2106
+ }
2107
+ function contentToText(content) {
2108
+ if (typeof content === "string")
2109
+ return content;
2110
+ if (!Array.isArray(content))
2111
+ return "";
2112
+ const lines = [];
2113
+ for (const block of content) {
2114
+ if (!block || typeof block !== "object")
2115
+ continue;
2116
+ const value = block;
2117
+ if (value.type === "text" && typeof value.text === "string") {
2118
+ lines.push(value.text);
2119
+ continue;
2120
+ }
2121
+ if (value.type === "thinking" && typeof value.thinking === "string") {
2122
+ lines.push(`[thinking]\n${value.thinking}`);
2123
+ continue;
2124
+ }
2125
+ if (value.type === "toolCall") {
2126
+ const name = typeof value.name === "string" ? value.name : "tool";
2127
+ const args = value.arguments === undefined ? "" : JSON.stringify(value.arguments, null, 2);
2128
+ lines.push([`[toolCall] ${name}`, args].filter(Boolean).join("\n"));
2129
+ continue;
2130
+ }
2131
+ if (value.type === "image") {
2132
+ lines.push(`[image ${String(value.mimeType ?? "unknown")}]`);
2133
+ }
2134
+ }
2135
+ return lines.join("\n\n");
2136
+ }
1660
2137
  //# sourceMappingURL=portal.js.map