@shipfox/api-logs 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/.turbo/turbo-type$colon$emit.log +1 -0
  3. package/.turbo/turbo-type.log +1 -0
  4. package/CHANGELOG.md +179 -0
  5. package/LICENSE +21 -0
  6. package/README.md +151 -0
  7. package/dist/api/object-storage.d.ts +69 -0
  8. package/dist/api/object-storage.d.ts.map +1 -0
  9. package/dist/api/object-storage.js +199 -0
  10. package/dist/api/object-storage.js.map +1 -0
  11. package/dist/config.d.ts +20 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +108 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/core/append-logs.d.ts +28 -0
  16. package/dist/core/append-logs.d.ts.map +1 -0
  17. package/dist/core/append-logs.js +318 -0
  18. package/dist/core/append-logs.js.map +1 -0
  19. package/dist/core/budget.d.ts +12 -0
  20. package/dist/core/budget.d.ts.map +1 -0
  21. package/dist/core/budget.js +9 -0
  22. package/dist/core/budget.js.map +1 -0
  23. package/dist/core/close-stream.d.ts +27 -0
  24. package/dist/core/close-stream.d.ts.map +1 -0
  25. package/dist/core/close-stream.js +59 -0
  26. package/dist/core/close-stream.js.map +1 -0
  27. package/dist/core/compaction.d.ts +28 -0
  28. package/dist/core/compaction.d.ts.map +1 -0
  29. package/dist/core/compaction.js +49 -0
  30. package/dist/core/compaction.js.map +1 -0
  31. package/dist/core/entities/attempt-stream.d.ts +37 -0
  32. package/dist/core/entities/attempt-stream.d.ts.map +1 -0
  33. package/dist/core/entities/attempt-stream.js +15 -0
  34. package/dist/core/entities/attempt-stream.js.map +1 -0
  35. package/dist/core/entities/job-accounting.d.ts +12 -0
  36. package/dist/core/entities/job-accounting.d.ts.map +1 -0
  37. package/dist/core/entities/job-accounting.js +6 -0
  38. package/dist/core/entities/job-accounting.js.map +1 -0
  39. package/dist/core/entities/log-object.d.ts +13 -0
  40. package/dist/core/entities/log-object.d.ts.map +1 -0
  41. package/dist/core/entities/log-object.js +9 -0
  42. package/dist/core/entities/log-object.js.map +1 -0
  43. package/dist/core/errors.d.ts +26 -0
  44. package/dist/core/errors.d.ts.map +1 -0
  45. package/dist/core/errors.js +31 -0
  46. package/dist/core/errors.js.map +1 -0
  47. package/dist/core/finalize-attempt-stream.d.ts +22 -0
  48. package/dist/core/finalize-attempt-stream.d.ts.map +1 -0
  49. package/dist/core/finalize-attempt-stream.js +48 -0
  50. package/dist/core/finalize-attempt-stream.js.map +1 -0
  51. package/dist/core/read-logs.d.ts +33 -0
  52. package/dist/core/read-logs.d.ts.map +1 -0
  53. package/dist/core/read-logs.js +49 -0
  54. package/dist/core/read-logs.js.map +1 -0
  55. package/dist/core/reap-stale-open-streams.d.ts +27 -0
  56. package/dist/core/reap-stale-open-streams.d.ts.map +1 -0
  57. package/dist/core/reap-stale-open-streams.js +50 -0
  58. package/dist/core/reap-stale-open-streams.js.map +1 -0
  59. package/dist/core/retention.d.ts +32 -0
  60. package/dist/core/retention.d.ts.map +1 -0
  61. package/dist/core/retention.js +148 -0
  62. package/dist/core/retention.js.map +1 -0
  63. package/dist/core/session/claude/rows.d.ts +6 -0
  64. package/dist/core/session/claude/rows.d.ts.map +1 -0
  65. package/dist/core/session/claude/rows.js +145 -0
  66. package/dist/core/session/claude/rows.js.map +1 -0
  67. package/dist/core/session/claude-parser.d.ts +4 -0
  68. package/dist/core/session/claude-parser.d.ts.map +1 -0
  69. package/dist/core/session/claude-parser.js +42 -0
  70. package/dist/core/session/claude-parser.js.map +1 -0
  71. package/dist/core/session/entry-schema.d.ts +51 -0
  72. package/dist/core/session/entry-schema.d.ts.map +1 -0
  73. package/dist/core/session/entry-schema.js +61 -0
  74. package/dist/core/session/entry-schema.js.map +1 -0
  75. package/dist/core/session/object.d.ts +12 -0
  76. package/dist/core/session/object.d.ts.map +1 -0
  77. package/dist/core/session/object.js +50 -0
  78. package/dist/core/session/object.js.map +1 -0
  79. package/dist/core/session/parse-session.d.ts +5 -0
  80. package/dist/core/session/parse-session.d.ts.map +1 -0
  81. package/dist/core/session/parse-session.js +18 -0
  82. package/dist/core/session/parse-session.js.map +1 -0
  83. package/dist/core/session/pi/message-rows.d.ts +4 -0
  84. package/dist/core/session/pi/message-rows.d.ts.map +1 -0
  85. package/dist/core/session/pi/message-rows.js +113 -0
  86. package/dist/core/session/pi/message-rows.js.map +1 -0
  87. package/dist/core/session/pi/metadata.d.ts +18 -0
  88. package/dist/core/session/pi/metadata.d.ts.map +1 -0
  89. package/dist/core/session/pi/metadata.js +120 -0
  90. package/dist/core/session/pi/metadata.js.map +1 -0
  91. package/dist/core/session/pi/text.d.ts +12 -0
  92. package/dist/core/session/pi/text.d.ts.map +1 -0
  93. package/dist/core/session/pi/text.js +59 -0
  94. package/dist/core/session/pi/text.js.map +1 -0
  95. package/dist/core/session/pi-parser.d.ts +5 -0
  96. package/dist/core/session/pi-parser.d.ts.map +1 -0
  97. package/dist/core/session/pi-parser.js +73 -0
  98. package/dist/core/session/pi-parser.js.map +1 -0
  99. package/dist/core/session/rows.d.ts +7 -0
  100. package/dist/core/session/rows.d.ts.map +1 -0
  101. package/dist/core/session/rows.js +39 -0
  102. package/dist/core/session/rows.js.map +1 -0
  103. package/dist/core/session/session-record.d.ts +5 -0
  104. package/dist/core/session/session-record.d.ts.map +1 -0
  105. package/dist/core/session/session-record.js +3 -0
  106. package/dist/core/session/session-record.js.map +1 -0
  107. package/dist/db/accounting.d.ts +33 -0
  108. package/dist/db/accounting.d.ts.map +1 -0
  109. package/dist/db/accounting.js +52 -0
  110. package/dist/db/accounting.js.map +1 -0
  111. package/dist/db/chunks.d.ts +62 -0
  112. package/dist/db/chunks.d.ts.map +1 -0
  113. package/dist/db/chunks.js +88 -0
  114. package/dist/db/chunks.js.map +1 -0
  115. package/dist/db/db.d.ts +752 -0
  116. package/dist/db/db.d.ts.map +1 -0
  117. package/dist/db/db.js +24 -0
  118. package/dist/db/db.js.map +1 -0
  119. package/dist/db/index.d.ts +2 -0
  120. package/dist/db/index.d.ts.map +1 -0
  121. package/dist/db/index.js +5 -0
  122. package/dist/db/index.js.map +1 -0
  123. package/dist/db/schema/attempt-streams.d.ts +304 -0
  124. package/dist/db/schema/attempt-streams.d.ts.map +1 -0
  125. package/dist/db/schema/attempt-streams.js +100 -0
  126. package/dist/db/schema/attempt-streams.js.map +1 -0
  127. package/dist/db/schema/chunks.d.ts +166 -0
  128. package/dist/db/schema/chunks.d.ts.map +1 -0
  129. package/dist/db/schema/chunks.js +47 -0
  130. package/dist/db/schema/chunks.js.map +1 -0
  131. package/dist/db/schema/common.d.ts +29 -0
  132. package/dist/db/schema/common.d.ts.map +1 -0
  133. package/dist/db/schema/common.js +11 -0
  134. package/dist/db/schema/common.js.map +1 -0
  135. package/dist/db/schema/job-accounting.d.ts +143 -0
  136. package/dist/db/schema/job-accounting.d.ts.map +1 -0
  137. package/dist/db/schema/job-accounting.js +43 -0
  138. package/dist/db/schema/job-accounting.js.map +1 -0
  139. package/dist/db/schema/outbox.d.ts +195 -0
  140. package/dist/db/schema/outbox.d.ts.map +1 -0
  141. package/dist/db/schema/outbox.js +5 -0
  142. package/dist/db/schema/outbox.js.map +1 -0
  143. package/dist/db/streams.d.ts +141 -0
  144. package/dist/db/streams.d.ts.map +1 -0
  145. package/dist/db/streams.js +197 -0
  146. package/dist/db/streams.js.map +1 -0
  147. package/dist/index.d.ts +4 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +81 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/metrics/index.d.ts +2 -0
  152. package/dist/metrics/index.d.ts.map +1 -0
  153. package/dist/metrics/index.js +3 -0
  154. package/dist/metrics/index.js.map +1 -0
  155. package/dist/metrics/instance.d.ts +14 -0
  156. package/dist/metrics/instance.d.ts.map +1 -0
  157. package/dist/metrics/instance.js +16 -0
  158. package/dist/metrics/instance.js.map +1 -0
  159. package/dist/metrics/service.d.ts +2 -0
  160. package/dist/metrics/service.d.ts.map +1 -0
  161. package/dist/metrics/service.js +20 -0
  162. package/dist/metrics/service.js.map +1 -0
  163. package/dist/presentation/dto/read-logs.d.ts +4 -0
  164. package/dist/presentation/dto/read-logs.d.ts.map +1 -0
  165. package/dist/presentation/dto/read-logs.js +22 -0
  166. package/dist/presentation/dto/read-logs.js.map +1 -0
  167. package/dist/presentation/routes/append-logs.d.ts +2 -0
  168. package/dist/presentation/routes/append-logs.d.ts.map +1 -0
  169. package/dist/presentation/routes/append-logs.js +71 -0
  170. package/dist/presentation/routes/append-logs.js.map +1 -0
  171. package/dist/presentation/routes/index.d.ts +3 -0
  172. package/dist/presentation/routes/index.d.ts.map +1 -0
  173. package/dist/presentation/routes/index.js +32 -0
  174. package/dist/presentation/routes/index.js.map +1 -0
  175. package/dist/presentation/routes/read-logs.d.ts +2 -0
  176. package/dist/presentation/routes/read-logs.d.ts.map +1 -0
  177. package/dist/presentation/routes/read-logs.js +41 -0
  178. package/dist/presentation/routes/read-logs.js.map +1 -0
  179. package/dist/presentation/subscribers/on-job-terminated.d.ts +8 -0
  180. package/dist/presentation/subscribers/on-job-terminated.d.ts.map +1 -0
  181. package/dist/presentation/subscribers/on-job-terminated.js +32 -0
  182. package/dist/presentation/subscribers/on-job-terminated.js.map +1 -0
  183. package/dist/presentation/subscribers/on-log-stream-closed.d.ts +9 -0
  184. package/dist/presentation/subscribers/on-log-stream-closed.d.ts.map +1 -0
  185. package/dist/presentation/subscribers/on-log-stream-closed.js +31 -0
  186. package/dist/presentation/subscribers/on-log-stream-closed.js.map +1 -0
  187. package/dist/presentation/subscribers/on-step-attempt-terminated.d.ts +3 -0
  188. package/dist/presentation/subscribers/on-step-attempt-terminated.d.ts.map +1 -0
  189. package/dist/presentation/subscribers/on-step-attempt-terminated.js +14 -0
  190. package/dist/presentation/subscribers/on-step-attempt-terminated.js.map +1 -0
  191. package/dist/temporal/activities/close-abandoned-streams.d.ts +12 -0
  192. package/dist/temporal/activities/close-abandoned-streams.d.ts.map +1 -0
  193. package/dist/temporal/activities/close-abandoned-streams.js +33 -0
  194. package/dist/temporal/activities/close-abandoned-streams.js.map +1 -0
  195. package/dist/temporal/activities/compact-stream.d.ts +33 -0
  196. package/dist/temporal/activities/compact-stream.d.ts.map +1 -0
  197. package/dist/temporal/activities/compact-stream.js +95 -0
  198. package/dist/temporal/activities/compact-stream.js.map +1 -0
  199. package/dist/temporal/activities/compaction-reconcile.d.ts +16 -0
  200. package/dist/temporal/activities/compaction-reconcile.d.ts.map +1 -0
  201. package/dist/temporal/activities/compaction-reconcile.js +52 -0
  202. package/dist/temporal/activities/compaction-reconcile.js.map +1 -0
  203. package/dist/temporal/activities/index.d.ts +14 -0
  204. package/dist/temporal/activities/index.d.ts.map +1 -0
  205. package/dist/temporal/activities/index.js +16 -0
  206. package/dist/temporal/activities/index.js.map +1 -0
  207. package/dist/temporal/activities/reap-stale-open-streams.d.ts +4 -0
  208. package/dist/temporal/activities/reap-stale-open-streams.d.ts.map +1 -0
  209. package/dist/temporal/activities/reap-stale-open-streams.js +11 -0
  210. package/dist/temporal/activities/reap-stale-open-streams.js.map +1 -0
  211. package/dist/temporal/activities/retention-sweep.d.ts +7 -0
  212. package/dist/temporal/activities/retention-sweep.d.ts.map +1 -0
  213. package/dist/temporal/activities/retention-sweep.js +19 -0
  214. package/dist/temporal/activities/retention-sweep.js.map +1 -0
  215. package/dist/temporal/constants.d.ts +7 -0
  216. package/dist/temporal/constants.d.ts.map +1 -0
  217. package/dist/temporal/constants.js +13 -0
  218. package/dist/temporal/constants.js.map +1 -0
  219. package/dist/temporal/workflows/close-abandoned-streams.d.ts +11 -0
  220. package/dist/temporal/workflows/close-abandoned-streams.d.ts.map +1 -0
  221. package/dist/temporal/workflows/close-abandoned-streams.js +22 -0
  222. package/dist/temporal/workflows/close-abandoned-streams.js.map +1 -0
  223. package/dist/temporal/workflows/compact-stream.d.ts +6 -0
  224. package/dist/temporal/workflows/compact-stream.d.ts.map +1 -0
  225. package/dist/temporal/workflows/compact-stream.js +25 -0
  226. package/dist/temporal/workflows/compact-stream.js.map +1 -0
  227. package/dist/temporal/workflows/compaction-reconcile-cron.d.ts +3 -0
  228. package/dist/temporal/workflows/compaction-reconcile-cron.d.ts.map +1 -0
  229. package/dist/temporal/workflows/compaction-reconcile-cron.js +15 -0
  230. package/dist/temporal/workflows/compaction-reconcile-cron.js.map +1 -0
  231. package/dist/temporal/workflows/index.d.ts +6 -0
  232. package/dist/temporal/workflows/index.d.ts.map +1 -0
  233. package/dist/temporal/workflows/index.js +7 -0
  234. package/dist/temporal/workflows/index.js.map +1 -0
  235. package/dist/temporal/workflows/reap-stale-open-streams-cron.d.ts +2 -0
  236. package/dist/temporal/workflows/reap-stale-open-streams-cron.d.ts.map +1 -0
  237. package/dist/temporal/workflows/reap-stale-open-streams-cron.js +15 -0
  238. package/dist/temporal/workflows/reap-stale-open-streams-cron.js.map +1 -0
  239. package/dist/temporal/workflows/retention-sweep-cron.d.ts +2 -0
  240. package/dist/temporal/workflows/retention-sweep-cron.d.ts.map +1 -0
  241. package/dist/temporal/workflows/retention-sweep-cron.js +23 -0
  242. package/dist/temporal/workflows/retention-sweep-cron.js.map +1 -0
  243. package/dist/tsconfig.test.tsbuildinfo +1 -0
  244. package/drizzle/0000_initial.sql +65 -0
  245. package/drizzle/meta/0000_snapshot.json +529 -0
  246. package/drizzle/meta/_journal.json +13 -0
  247. package/drizzle.config.ts +7 -0
  248. package/package.json +84 -0
  249. package/src/api/object-storage-credentials.test.ts +70 -0
  250. package/src/api/object-storage.test.ts +64 -0
  251. package/src/api/object-storage.ts +226 -0
  252. package/src/config.test.ts +118 -0
  253. package/src/config.ts +130 -0
  254. package/src/core/append-logs.test.ts +563 -0
  255. package/src/core/append-logs.ts +384 -0
  256. package/src/core/budget.test.ts +30 -0
  257. package/src/core/budget.ts +19 -0
  258. package/src/core/close-stream.ts +72 -0
  259. package/src/core/compaction.ts +68 -0
  260. package/src/core/entities/attempt-stream.ts +38 -0
  261. package/src/core/entities/job-accounting.ts +11 -0
  262. package/src/core/entities/log-object.test.ts +25 -0
  263. package/src/core/entities/log-object.ts +18 -0
  264. package/src/core/errors.ts +37 -0
  265. package/src/core/finalize-attempt-stream.test.ts +90 -0
  266. package/src/core/finalize-attempt-stream.ts +59 -0
  267. package/src/core/read-logs.ts +77 -0
  268. package/src/core/reap-stale-open-streams.test.ts +137 -0
  269. package/src/core/reap-stale-open-streams.ts +60 -0
  270. package/src/core/retention.test.ts +388 -0
  271. package/src/core/retention.ts +184 -0
  272. package/src/core/session/claude/rows.ts +223 -0
  273. package/src/core/session/claude-parser.test.ts +199 -0
  274. package/src/core/session/claude-parser.ts +38 -0
  275. package/src/core/session/entry-schema.ts +82 -0
  276. package/src/core/session/object.ts +57 -0
  277. package/src/core/session/parse-session.ts +23 -0
  278. package/src/core/session/pi/message-rows.ts +211 -0
  279. package/src/core/session/pi/metadata.ts +148 -0
  280. package/src/core/session/pi/text.ts +83 -0
  281. package/src/core/session/pi-parser.test.ts +451 -0
  282. package/src/core/session/pi-parser.ts +107 -0
  283. package/src/core/session/rows.ts +38 -0
  284. package/src/core/session/session-record.ts +4 -0
  285. package/src/db/accounting.ts +81 -0
  286. package/src/db/chunks.ts +143 -0
  287. package/src/db/db.ts +22 -0
  288. package/src/db/index.ts +4 -0
  289. package/src/db/schema/attempt-streams.ts +106 -0
  290. package/src/db/schema/chunks.ts +43 -0
  291. package/src/db/schema/common.ts +12 -0
  292. package/src/db/schema/job-accounting.ts +38 -0
  293. package/src/db/schema/outbox.ts +4 -0
  294. package/src/db/streams.test.ts +47 -0
  295. package/src/db/streams.ts +368 -0
  296. package/src/index.ts +77 -0
  297. package/src/metrics/index.ts +1 -0
  298. package/src/metrics/instance.ts +33 -0
  299. package/src/metrics/service.ts +23 -0
  300. package/src/presentation/dto/read-logs.ts +24 -0
  301. package/src/presentation/routes/append-logs.test.ts +279 -0
  302. package/src/presentation/routes/append-logs.ts +66 -0
  303. package/src/presentation/routes/index.ts +27 -0
  304. package/src/presentation/routes/read-logs.test.ts +504 -0
  305. package/src/presentation/routes/read-logs.ts +38 -0
  306. package/src/presentation/subscribers/on-job-terminated.test.ts +64 -0
  307. package/src/presentation/subscribers/on-job-terminated.ts +26 -0
  308. package/src/presentation/subscribers/on-log-stream-closed.test.ts +63 -0
  309. package/src/presentation/subscribers/on-log-stream-closed.ts +26 -0
  310. package/src/presentation/subscribers/on-step-attempt-terminated.ts +16 -0
  311. package/src/temporal/activities/close-abandoned-streams.test.ts +84 -0
  312. package/src/temporal/activities/close-abandoned-streams.ts +30 -0
  313. package/src/temporal/activities/compact-stream.test.ts +221 -0
  314. package/src/temporal/activities/compact-stream.ts +123 -0
  315. package/src/temporal/activities/compaction-reconcile.test.ts +143 -0
  316. package/src/temporal/activities/compaction-reconcile.ts +48 -0
  317. package/src/temporal/activities/index.ts +15 -0
  318. package/src/temporal/activities/reap-stale-open-streams.test.ts +48 -0
  319. package/src/temporal/activities/reap-stale-open-streams.ts +14 -0
  320. package/src/temporal/activities/retention-sweep.test.ts +38 -0
  321. package/src/temporal/activities/retention-sweep.ts +23 -0
  322. package/src/temporal/constants.ts +14 -0
  323. package/src/temporal/workflows/close-abandoned-streams.ts +25 -0
  324. package/src/temporal/workflows/compact-stream.ts +26 -0
  325. package/src/temporal/workflows/compaction-reconcile-cron.ts +14 -0
  326. package/src/temporal/workflows/index.ts +5 -0
  327. package/src/temporal/workflows/reap-stale-open-streams-cron.ts +13 -0
  328. package/src/temporal/workflows/retention-sweep-cron.ts +23 -0
  329. package/test/env.ts +37 -0
  330. package/test/factories/job-accounting.ts +38 -0
  331. package/test/fixtures/closed-stream.ts +53 -0
  332. package/test/fixtures/lease-token.ts +42 -0
  333. package/test/fixtures/ndjson.ts +34 -0
  334. package/test/globalSetup.ts +44 -0
  335. package/test/index.ts +9 -0
  336. package/test/queries.ts +54 -0
  337. package/test/setup.ts +17 -0
  338. package/tsconfig.build.json +9 -0
  339. package/tsconfig.build.tsbuildinfo +1 -0
  340. package/tsconfig.json +3 -0
  341. package/tsconfig.test.json +8 -0
  342. package/vitest.config.ts +13 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/session/entry-schema.ts"],"sourcesContent":["import {z} from 'zod';\n\nconst looseObjectSchema = z.object({}).catchall(z.unknown());\n\nexport const sessionEntrySchema = z\n .object({\n type: z.string().min(1),\n })\n .catchall(z.unknown());\n\nexport const agentMessageSchema = z\n .object({\n type: z.string().optional(),\n role: z.string().optional(),\n content: z.unknown().optional(),\n model: z.string().optional(),\n provider: z.string().optional(),\n stopReason: z.string().optional(),\n errorMessage: z.string().optional(),\n toolCallId: z.string().optional(),\n toolName: z.string().optional(),\n isError: z.boolean().optional(),\n })\n .catchall(z.unknown());\n\nexport const sessionMessageEntrySchema = z\n .object({\n type: z.literal('message'),\n message: agentMessageSchema,\n })\n .catchall(z.unknown());\n\nexport const contentBlockSchema = z\n .object({\n type: z.string().optional(),\n })\n .catchall(z.unknown());\n\nexport type SessionEntry = z.infer<typeof sessionEntrySchema>;\nexport type AgentMessage = z.infer<typeof agentMessageSchema>;\nexport type ContentBlock = z.infer<typeof contentBlockSchema>;\n\nexport interface ParsedSessionEntry {\n ok: true;\n entry: SessionEntry;\n}\n\nexport interface MalformedSessionEntry {\n ok: false;\n raw: string;\n reason: 'invalid-json' | 'invalid-entry';\n}\n\nexport type SessionEntryParseResult = ParsedSessionEntry | MalformedSessionEntry;\n\nexport function parseSessionEntry(data: string): SessionEntryParseResult {\n let json: unknown;\n try {\n json = JSON.parse(data);\n } catch {\n return {ok: false, raw: data, reason: 'invalid-json'};\n }\n\n const parsed = sessionEntrySchema.safeParse(json);\n if (!parsed.success) return {ok: false, raw: data, reason: 'invalid-entry'};\n\n return {ok: true, entry: parsed.data};\n}\n\nexport function asLooseObject(value: unknown): Record<string, unknown> | null {\n const parsed = looseObjectSchema.safeParse(value);\n return parsed.success ? parsed.data : null;\n}\n\nexport function asContentBlocks(value: unknown): ContentBlock[] {\n if (!Array.isArray(value)) return [];\n\n return value.flatMap((item) => {\n const parsed = contentBlockSchema.safeParse(item);\n return parsed.success ? [parsed.data] : [];\n });\n}\n"],"names":["z","looseObjectSchema","object","catchall","unknown","sessionEntrySchema","type","string","min","agentMessageSchema","optional","role","content","model","provider","stopReason","errorMessage","toolCallId","toolName","isError","boolean","sessionMessageEntrySchema","literal","message","contentBlockSchema","parseSessionEntry","data","json","JSON","parse","ok","raw","reason","parsed","safeParse","success","entry","asLooseObject","value","asContentBlocks","Array","isArray","flatMap","item"],"mappings":"AAAA,SAAQA,CAAC,QAAO,MAAM;AAEtB,MAAMC,oBAAoBD,EAAEE,MAAM,CAAC,CAAC,GAAGC,QAAQ,CAACH,EAAEI,OAAO;AAEzD,OAAO,MAAMC,qBAAqBL,EAC/BE,MAAM,CAAC;IACNI,MAAMN,EAAEO,MAAM,GAAGC,GAAG,CAAC;AACvB,GACCL,QAAQ,CAACH,EAAEI,OAAO,IAAI;AAEzB,OAAO,MAAMK,qBAAqBT,EAC/BE,MAAM,CAAC;IACNI,MAAMN,EAAEO,MAAM,GAAGG,QAAQ;IACzBC,MAAMX,EAAEO,MAAM,GAAGG,QAAQ;IACzBE,SAASZ,EAAEI,OAAO,GAAGM,QAAQ;IAC7BG,OAAOb,EAAEO,MAAM,GAAGG,QAAQ;IAC1BI,UAAUd,EAAEO,MAAM,GAAGG,QAAQ;IAC7BK,YAAYf,EAAEO,MAAM,GAAGG,QAAQ;IAC/BM,cAAchB,EAAEO,MAAM,GAAGG,QAAQ;IACjCO,YAAYjB,EAAEO,MAAM,GAAGG,QAAQ;IAC/BQ,UAAUlB,EAAEO,MAAM,GAAGG,QAAQ;IAC7BS,SAASnB,EAAEoB,OAAO,GAAGV,QAAQ;AAC/B,GACCP,QAAQ,CAACH,EAAEI,OAAO,IAAI;AAEzB,OAAO,MAAMiB,4BAA4BrB,EACtCE,MAAM,CAAC;IACNI,MAAMN,EAAEsB,OAAO,CAAC;IAChBC,SAASd;AACX,GACCN,QAAQ,CAACH,EAAEI,OAAO,IAAI;AAEzB,OAAO,MAAMoB,qBAAqBxB,EAC/BE,MAAM,CAAC;IACNI,MAAMN,EAAEO,MAAM,GAAGG,QAAQ;AAC3B,GACCP,QAAQ,CAACH,EAAEI,OAAO,IAAI;AAmBzB,OAAO,SAASqB,kBAAkBC,IAAY;IAC5C,IAAIC;IACJ,IAAI;QACFA,OAAOC,KAAKC,KAAK,CAACH;IACpB,EAAE,OAAM;QACN,OAAO;YAACI,IAAI;YAAOC,KAAKL;YAAMM,QAAQ;QAAc;IACtD;IAEA,MAAMC,SAAS5B,mBAAmB6B,SAAS,CAACP;IAC5C,IAAI,CAACM,OAAOE,OAAO,EAAE,OAAO;QAACL,IAAI;QAAOC,KAAKL;QAAMM,QAAQ;IAAe;IAE1E,OAAO;QAACF,IAAI;QAAMM,OAAOH,OAAOP,IAAI;IAAA;AACtC;AAEA,OAAO,SAASW,cAAcC,KAAc;IAC1C,MAAML,SAAShC,kBAAkBiC,SAAS,CAACI;IAC3C,OAAOL,OAAOE,OAAO,GAAGF,OAAOP,IAAI,GAAG;AACxC;AAEA,OAAO,SAASa,gBAAgBD,KAAc;IAC5C,IAAI,CAACE,MAAMC,OAAO,CAACH,QAAQ,OAAO,EAAE;IAEpC,OAAOA,MAAMI,OAAO,CAAC,CAACC;QACpB,MAAMV,SAAST,mBAAmBU,SAAS,CAACS;QAC5C,OAAOV,OAAOE,OAAO,GAAG;YAACF,OAAOP,IAAI;SAAC,GAAG,EAAE;IAC5C;AACF"}
@@ -0,0 +1,12 @@
1
+ import type { SessionViewRowMeta } from '@shipfox/api-logs-dto';
2
+ export declare function field(value: unknown, key: string): unknown;
3
+ export declare function stringField(value: unknown, key: string): string | undefined;
4
+ export declare function numberField(value: unknown, key: string): number | undefined;
5
+ export declare function booleanField(value: unknown, key: string): boolean;
6
+ export declare function stringifyValue(value: unknown): string;
7
+ export declare function toJson(value: unknown): string;
8
+ export declare function formatNumber(value: number): string;
9
+ export declare function formatCount(value: number, unit: string): string;
10
+ export declare function metaItem(label: string, value: string | null | undefined, inline?: boolean): SessionViewRowMeta | null;
11
+ export declare function isMeta(value: SessionViewRowMeta | null | undefined): value is SessionViewRowMeta;
12
+ //# sourceMappingURL=object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../../../src/core/session/object.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,uBAAuB,CAAC;AAK9D,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG3E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG3E;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGrD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAG7C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,MAAM,UAAO,GACZ,kBAAkB,GAAG,IAAI,CAG3B;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,kBAAkB,CAEhG"}
@@ -0,0 +1,50 @@
1
+ import { asLooseObject } from './entry-schema.js';
2
+ const SESSION_META_NUMBER_LOCALE = 'en-US';
3
+ export function field(value, key) {
4
+ const object = asLooseObject(value);
5
+ return object?.[key];
6
+ }
7
+ export function stringField(value, key) {
8
+ const fieldValue = field(value, key);
9
+ return typeof fieldValue === 'string' && fieldValue.length > 0 ? fieldValue : undefined;
10
+ }
11
+ export function numberField(value, key) {
12
+ const fieldValue = field(value, key);
13
+ return typeof fieldValue === 'number' && Number.isFinite(fieldValue) ? fieldValue : undefined;
14
+ }
15
+ export function booleanField(value, key) {
16
+ return field(value, key) === true;
17
+ }
18
+ export function stringifyValue(value) {
19
+ if (typeof value === 'string') return value;
20
+ return toJson(value);
21
+ }
22
+ export function toJson(value) {
23
+ const json = JSON.stringify(value, null, 2);
24
+ return json === undefined ? String(value) : json;
25
+ }
26
+ export function formatNumber(value) {
27
+ return new Intl.NumberFormat(SESSION_META_NUMBER_LOCALE, {
28
+ maximumFractionDigits: 1,
29
+ notation: value >= 10000 ? 'compact' : 'standard'
30
+ }).format(value);
31
+ }
32
+ export function formatCount(value, unit) {
33
+ return `${formatNumber(value)} ${unit}${value === 1 ? '' : 's'}`;
34
+ }
35
+ export function metaItem(label, value, inline = true) {
36
+ if (value == null || value.length === 0) return null;
37
+ return inline ? {
38
+ label,
39
+ value
40
+ } : {
41
+ label,
42
+ value,
43
+ inline
44
+ };
45
+ }
46
+ export function isMeta(value) {
47
+ return value != null;
48
+ }
49
+
50
+ //# sourceMappingURL=object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/session/object.ts"],"sourcesContent":["import type {SessionViewRowMeta} from '@shipfox/api-logs-dto';\nimport {asLooseObject} from './entry-schema.js';\n\nconst SESSION_META_NUMBER_LOCALE = 'en-US';\n\nexport function field(value: unknown, key: string): unknown {\n const object = asLooseObject(value);\n return object?.[key];\n}\n\nexport function stringField(value: unknown, key: string): string | undefined {\n const fieldValue = field(value, key);\n return typeof fieldValue === 'string' && fieldValue.length > 0 ? fieldValue : undefined;\n}\n\nexport function numberField(value: unknown, key: string): number | undefined {\n const fieldValue = field(value, key);\n return typeof fieldValue === 'number' && Number.isFinite(fieldValue) ? fieldValue : undefined;\n}\n\nexport function booleanField(value: unknown, key: string): boolean {\n return field(value, key) === true;\n}\n\nexport function stringifyValue(value: unknown): string {\n if (typeof value === 'string') return value;\n return toJson(value);\n}\n\nexport function toJson(value: unknown): string {\n const json = JSON.stringify(value, null, 2);\n return json === undefined ? String(value) : json;\n}\n\nexport function formatNumber(value: number): string {\n return new Intl.NumberFormat(SESSION_META_NUMBER_LOCALE, {\n maximumFractionDigits: 1,\n notation: value >= 10000 ? 'compact' : 'standard',\n }).format(value);\n}\n\nexport function formatCount(value: number, unit: string): string {\n return `${formatNumber(value)} ${unit}${value === 1 ? '' : 's'}`;\n}\n\nexport function metaItem(\n label: string,\n value: string | null | undefined,\n inline = true,\n): SessionViewRowMeta | null {\n if (value == null || value.length === 0) return null;\n return inline ? {label, value} : {label, value, inline};\n}\n\nexport function isMeta(value: SessionViewRowMeta | null | undefined): value is SessionViewRowMeta {\n return value != null;\n}\n"],"names":["asLooseObject","SESSION_META_NUMBER_LOCALE","field","value","key","object","stringField","fieldValue","length","undefined","numberField","Number","isFinite","booleanField","stringifyValue","toJson","json","JSON","stringify","String","formatNumber","Intl","NumberFormat","maximumFractionDigits","notation","format","formatCount","unit","metaItem","label","inline","isMeta"],"mappings":"AACA,SAAQA,aAAa,QAAO,oBAAoB;AAEhD,MAAMC,6BAA6B;AAEnC,OAAO,SAASC,MAAMC,KAAc,EAAEC,GAAW;IAC/C,MAAMC,SAASL,cAAcG;IAC7B,OAAOE,QAAQ,CAACD,IAAI;AACtB;AAEA,OAAO,SAASE,YAAYH,KAAc,EAAEC,GAAW;IACrD,MAAMG,aAAaL,MAAMC,OAAOC;IAChC,OAAO,OAAOG,eAAe,YAAYA,WAAWC,MAAM,GAAG,IAAID,aAAaE;AAChF;AAEA,OAAO,SAASC,YAAYP,KAAc,EAAEC,GAAW;IACrD,MAAMG,aAAaL,MAAMC,OAAOC;IAChC,OAAO,OAAOG,eAAe,YAAYI,OAAOC,QAAQ,CAACL,cAAcA,aAAaE;AACtF;AAEA,OAAO,SAASI,aAAaV,KAAc,EAAEC,GAAW;IACtD,OAAOF,MAAMC,OAAOC,SAAS;AAC/B;AAEA,OAAO,SAASU,eAAeX,KAAc;IAC3C,IAAI,OAAOA,UAAU,UAAU,OAAOA;IACtC,OAAOY,OAAOZ;AAChB;AAEA,OAAO,SAASY,OAAOZ,KAAc;IACnC,MAAMa,OAAOC,KAAKC,SAAS,CAACf,OAAO,MAAM;IACzC,OAAOa,SAASP,YAAYU,OAAOhB,SAASa;AAC9C;AAEA,OAAO,SAASI,aAAajB,KAAa;IACxC,OAAO,IAAIkB,KAAKC,YAAY,CAACrB,4BAA4B;QACvDsB,uBAAuB;QACvBC,UAAUrB,SAAS,QAAQ,YAAY;IACzC,GAAGsB,MAAM,CAACtB;AACZ;AAEA,OAAO,SAASuB,YAAYvB,KAAa,EAAEwB,IAAY;IACrD,OAAO,GAAGP,aAAajB,OAAO,CAAC,EAAEwB,OAAOxB,UAAU,IAAI,KAAK,KAAK;AAClE;AAEA,OAAO,SAASyB,SACdC,KAAa,EACb1B,KAAgC,EAChC2B,SAAS,IAAI;IAEb,IAAI3B,SAAS,QAAQA,MAAMK,MAAM,KAAK,GAAG,OAAO;IAChD,OAAOsB,SAAS;QAACD;QAAO1B;IAAK,IAAI;QAAC0B;QAAO1B;QAAO2B;IAAM;AACxD;AAEA,OAAO,SAASC,OAAO5B,KAA4C;IACjE,OAAOA,SAAS;AAClB"}
@@ -0,0 +1,5 @@
1
+ import type { Harness } from '@shipfox/api-agent-dto';
2
+ import type { SessionViewRow } from '@shipfox/api-logs-dto';
3
+ import type { AgentSessionRecord } from './session-record.js';
4
+ export declare function parseSessionRecord(record: AgentSessionRecord, harness: Harness): readonly SessionViewRow[];
5
+ //# sourceMappingURL=parse-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-session.d.ts","sourceRoot":"","sources":["../../../src/core/session/parse-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAG1D,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAE5D,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,OAAO,GACf,SAAS,cAAc,EAAE,CAa3B"}
@@ -0,0 +1,18 @@
1
+ import { parseClaudeSessionRecord } from './claude-parser.js';
2
+ import { parsePiSessionRecord } from './pi-parser.js';
3
+ export function parseSessionRecord(record, harness) {
4
+ try {
5
+ return harness === 'claude' ? parseClaudeSessionRecord(record) : parsePiSessionRecord(record);
6
+ } catch {
7
+ return [
8
+ {
9
+ kind: 'raw',
10
+ timestamp: record.ts,
11
+ label: 'Unsupported session entry',
12
+ raw: record.data
13
+ }
14
+ ];
15
+ }
16
+ }
17
+
18
+ //# sourceMappingURL=parse-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/session/parse-session.ts"],"sourcesContent":["import type {Harness} from '@shipfox/api-agent-dto';\nimport type {SessionViewRow} from '@shipfox/api-logs-dto';\nimport {parseClaudeSessionRecord} from './claude-parser.js';\nimport {parsePiSessionRecord} from './pi-parser.js';\nimport type {AgentSessionRecord} from './session-record.js';\n\nexport function parseSessionRecord(\n record: AgentSessionRecord,\n harness: Harness,\n): readonly SessionViewRow[] {\n try {\n return harness === 'claude' ? parseClaudeSessionRecord(record) : parsePiSessionRecord(record);\n } catch {\n return [\n {\n kind: 'raw',\n timestamp: record.ts,\n label: 'Unsupported session entry',\n raw: record.data,\n },\n ];\n }\n}\n"],"names":["parseClaudeSessionRecord","parsePiSessionRecord","parseSessionRecord","record","harness","kind","timestamp","ts","label","raw","data"],"mappings":"AAEA,SAAQA,wBAAwB,QAAO,qBAAqB;AAC5D,SAAQC,oBAAoB,QAAO,iBAAiB;AAGpD,OAAO,SAASC,mBACdC,MAA0B,EAC1BC,OAAgB;IAEhB,IAAI;QACF,OAAOA,YAAY,WAAWJ,yBAAyBG,UAAUF,qBAAqBE;IACxF,EAAE,OAAM;QACN,OAAO;YACL;gBACEE,MAAM;gBACNC,WAAWH,OAAOI,EAAE;gBACpBC,OAAO;gBACPC,KAAKN,OAAOO,IAAI;YAClB;SACD;IACH;AACF"}
@@ -0,0 +1,4 @@
1
+ import type { SessionViewRow } from '@shipfox/api-logs-dto';
2
+ import { type AgentMessage } from '../entry-schema.js';
3
+ export declare function expandMessageEntry(timestamp: number, message: AgentMessage): readonly SessionViewRow[];
4
+ //# sourceMappingURL=message-rows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-rows.d.ts","sourceRoot":"","sources":["../../../../src/core/session/pi/message-rows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,KAAK,YAAY,EAAqC,MAAM,oBAAoB,CAAC;AA4BzF,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,GACpB,SAAS,cAAc,EAAE,CAmE3B"}
@@ -0,0 +1,113 @@
1
+ import { asContentBlocks } from '../entry-schema.js';
2
+ import { field, stringField, stringifyValue, toJson } from '../object.js';
3
+ import { messageRow } from '../rows.js';
4
+ import { assistantMeta, bashExecutionMeta, branchSummaryDetail, branchSummaryMeta, compactionDetail, compactionMeta, customEntryLabel, customEntryMeta, customEntryText, messageMeta } from './metadata.js';
5
+ import { bashExecutionText, blockText, isTerminalStop, isThinkingBlock, isToolCallBlock, isToolResultMessage, messageText, normalizeRole, roleLabel, terminalStopDetail } from './text.js';
6
+ export function expandMessageEntry(timestamp, message) {
7
+ const role = normalizeRole(message);
8
+ if (isToolResultMessage(message)) return [
9
+ toolResultRow(timestamp, message)
10
+ ];
11
+ if (role === 'assistant') return expandAssistantMessage(timestamp, message);
12
+ if (role === 'bash-execution') {
13
+ return [
14
+ messageRow(timestamp, role, 'bash execution', bashExecutionText(message), isTerminalStop(message), bashExecutionMeta(message))
15
+ ];
16
+ }
17
+ if (role === 'branch-summary') {
18
+ return [
19
+ messageRow(timestamp, role, 'branch summary', branchSummaryDetail(message) ?? toJson(message), isTerminalStop(message), branchSummaryMeta(message))
20
+ ];
21
+ }
22
+ if (role === 'compaction-summary') {
23
+ return [
24
+ messageRow(timestamp, role, 'compaction summary', compactionDetail(message) ?? toJson(message), isTerminalStop(message), compactionMeta(message))
25
+ ];
26
+ }
27
+ if (role === 'custom') {
28
+ return [
29
+ messageRow(timestamp, role, customEntryLabel('custom'), customEntryText(message) ?? toJson(message), isTerminalStop(message), customEntryMeta(message))
30
+ ];
31
+ }
32
+ const text = messageText(message);
33
+ return [
34
+ messageRow(timestamp, role, roleLabel(role), text || toJson(message), isTerminalStop(message), messageMeta(message))
35
+ ];
36
+ }
37
+ function expandAssistantMessage(timestamp, message) {
38
+ const blocks = asContentBlocks(message.content);
39
+ const terminalFailure = isTerminalStop(message);
40
+ const meta = assistantMeta(message);
41
+ if (blocks.length === 0) {
42
+ const text = messageText(message);
43
+ return [
44
+ messageRow(timestamp, 'assistant', 'assistant', text || terminalStopDetail(message) || toJson(message), terminalFailure, meta)
45
+ ];
46
+ }
47
+ const rows = [];
48
+ const textParts = [];
49
+ const thinkingParts = [];
50
+ const pushTextParts = ()=>{
51
+ if (textParts.length === 0) return;
52
+ rows.push(messageRow(timestamp, 'assistant', 'assistant', textParts.join('\n\n'), terminalFailure, meta));
53
+ textParts.length = 0;
54
+ };
55
+ const pushThinkingParts = ()=>{
56
+ if (thinkingParts.length === 0) return;
57
+ rows.push({
58
+ kind: 'thinking',
59
+ timestamp,
60
+ text: thinkingParts.join('\n\n')
61
+ });
62
+ thinkingParts.length = 0;
63
+ };
64
+ for (const block of blocks){
65
+ if (isToolCallBlock(block)) {
66
+ pushTextParts();
67
+ pushThinkingParts();
68
+ rows.push(toolCallRow(timestamp, block));
69
+ continue;
70
+ }
71
+ if (isThinkingBlock(block)) {
72
+ pushTextParts();
73
+ const text = blockText(block);
74
+ if (text) thinkingParts.push(text);
75
+ continue;
76
+ }
77
+ pushThinkingParts();
78
+ const text = blockText(block);
79
+ if (text) textParts.push(text);
80
+ }
81
+ pushTextParts();
82
+ pushThinkingParts();
83
+ if (terminalFailure && !rows.some((row)=>row.kind === 'message' && row.terminalFailure)) {
84
+ rows.push(messageRow(timestamp, 'assistant', 'assistant', terminalStopDetail(message) || toJson(message), true, meta));
85
+ }
86
+ if (rows.length === 0) rows.push(messageRow(timestamp, 'assistant', 'assistant', toJson(message), terminalFailure, meta));
87
+ return rows;
88
+ }
89
+ function toolCallRow(timestamp, block) {
90
+ const id = stringField(block, 'id') ?? stringField(block, 'toolCallId') ?? null;
91
+ const name = stringField(block, 'name') ?? stringField(block, 'toolName') ?? 'tool';
92
+ const args = field(block, 'arguments') ?? field(block, 'input') ?? field(block, 'args') ?? {};
93
+ return {
94
+ kind: 'tool-call',
95
+ timestamp,
96
+ id,
97
+ name,
98
+ input: stringifyValue(args)
99
+ };
100
+ }
101
+ function toolResultRow(timestamp, message) {
102
+ const output = messageText(message) || stringifyValue(message.content ?? '');
103
+ return {
104
+ kind: 'tool-result',
105
+ timestamp,
106
+ toolCallId: message.toolCallId ?? null,
107
+ toolName: message.toolName ?? 'tool',
108
+ output,
109
+ isError: message.isError === true
110
+ };
111
+ }
112
+
113
+ //# sourceMappingURL=message-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/session/pi/message-rows.ts"],"sourcesContent":["import type {\n SessionViewRow,\n SessionViewToolCallRow,\n SessionViewToolResultRow,\n} from '@shipfox/api-logs-dto';\nimport {type AgentMessage, asContentBlocks, type ContentBlock} from '../entry-schema.js';\nimport {field, stringField, stringifyValue, toJson} from '../object.js';\nimport {messageRow} from '../rows.js';\nimport {\n assistantMeta,\n bashExecutionMeta,\n branchSummaryDetail,\n branchSummaryMeta,\n compactionDetail,\n compactionMeta,\n customEntryLabel,\n customEntryMeta,\n customEntryText,\n messageMeta,\n} from './metadata.js';\nimport {\n bashExecutionText,\n blockText,\n isTerminalStop,\n isThinkingBlock,\n isToolCallBlock,\n isToolResultMessage,\n messageText,\n normalizeRole,\n roleLabel,\n terminalStopDetail,\n} from './text.js';\n\nexport function expandMessageEntry(\n timestamp: number,\n message: AgentMessage,\n): readonly SessionViewRow[] {\n const role = normalizeRole(message);\n\n if (isToolResultMessage(message)) return [toolResultRow(timestamp, message)];\n\n if (role === 'assistant') return expandAssistantMessage(timestamp, message);\n\n if (role === 'bash-execution') {\n return [\n messageRow(\n timestamp,\n role,\n 'bash execution',\n bashExecutionText(message),\n isTerminalStop(message),\n bashExecutionMeta(message),\n ),\n ];\n }\n if (role === 'branch-summary') {\n return [\n messageRow(\n timestamp,\n role,\n 'branch summary',\n branchSummaryDetail(message) ?? toJson(message),\n isTerminalStop(message),\n branchSummaryMeta(message),\n ),\n ];\n }\n if (role === 'compaction-summary') {\n return [\n messageRow(\n timestamp,\n role,\n 'compaction summary',\n compactionDetail(message) ?? toJson(message),\n isTerminalStop(message),\n compactionMeta(message),\n ),\n ];\n }\n if (role === 'custom') {\n return [\n messageRow(\n timestamp,\n role,\n customEntryLabel('custom'),\n customEntryText(message) ?? toJson(message),\n isTerminalStop(message),\n customEntryMeta(message),\n ),\n ];\n }\n\n const text = messageText(message);\n return [\n messageRow(\n timestamp,\n role,\n roleLabel(role),\n text || toJson(message),\n isTerminalStop(message),\n messageMeta(message),\n ),\n ];\n}\n\nfunction expandAssistantMessage(\n timestamp: number,\n message: AgentMessage,\n): readonly SessionViewRow[] {\n const blocks = asContentBlocks(message.content);\n const terminalFailure = isTerminalStop(message);\n const meta = assistantMeta(message);\n if (blocks.length === 0) {\n const text = messageText(message);\n return [\n messageRow(\n timestamp,\n 'assistant',\n 'assistant',\n text || terminalStopDetail(message) || toJson(message),\n terminalFailure,\n meta,\n ),\n ];\n }\n\n const rows: SessionViewRow[] = [];\n const textParts: string[] = [];\n const thinkingParts: string[] = [];\n const pushTextParts = () => {\n if (textParts.length === 0) return;\n rows.push(\n messageRow(\n timestamp,\n 'assistant',\n 'assistant',\n textParts.join('\\n\\n'),\n terminalFailure,\n meta,\n ),\n );\n textParts.length = 0;\n };\n const pushThinkingParts = () => {\n if (thinkingParts.length === 0) return;\n rows.push({kind: 'thinking', timestamp, text: thinkingParts.join('\\n\\n')});\n thinkingParts.length = 0;\n };\n\n for (const block of blocks) {\n if (isToolCallBlock(block)) {\n pushTextParts();\n pushThinkingParts();\n rows.push(toolCallRow(timestamp, block));\n continue;\n }\n\n if (isThinkingBlock(block)) {\n pushTextParts();\n const text = blockText(block);\n if (text) thinkingParts.push(text);\n continue;\n }\n\n pushThinkingParts();\n const text = blockText(block);\n if (text) textParts.push(text);\n }\n\n pushTextParts();\n pushThinkingParts();\n if (terminalFailure && !rows.some((row) => row.kind === 'message' && row.terminalFailure)) {\n rows.push(\n messageRow(\n timestamp,\n 'assistant',\n 'assistant',\n terminalStopDetail(message) || toJson(message),\n true,\n meta,\n ),\n );\n }\n if (rows.length === 0)\n rows.push(\n messageRow(timestamp, 'assistant', 'assistant', toJson(message), terminalFailure, meta),\n );\n\n return rows;\n}\n\nfunction toolCallRow(timestamp: number, block: ContentBlock): SessionViewToolCallRow {\n const id = stringField(block, 'id') ?? stringField(block, 'toolCallId') ?? null;\n const name = stringField(block, 'name') ?? stringField(block, 'toolName') ?? 'tool';\n const args = field(block, 'arguments') ?? field(block, 'input') ?? field(block, 'args') ?? {};\n\n return {kind: 'tool-call', timestamp, id, name, input: stringifyValue(args)};\n}\n\nfunction toolResultRow(timestamp: number, message: AgentMessage): SessionViewToolResultRow {\n const output = messageText(message) || stringifyValue(message.content ?? '');\n\n return {\n kind: 'tool-result',\n timestamp,\n toolCallId: message.toolCallId ?? null,\n toolName: message.toolName ?? 'tool',\n output,\n isError: message.isError === true,\n };\n}\n"],"names":["asContentBlocks","field","stringField","stringifyValue","toJson","messageRow","assistantMeta","bashExecutionMeta","branchSummaryDetail","branchSummaryMeta","compactionDetail","compactionMeta","customEntryLabel","customEntryMeta","customEntryText","messageMeta","bashExecutionText","blockText","isTerminalStop","isThinkingBlock","isToolCallBlock","isToolResultMessage","messageText","normalizeRole","roleLabel","terminalStopDetail","expandMessageEntry","timestamp","message","role","toolResultRow","expandAssistantMessage","text","blocks","content","terminalFailure","meta","length","rows","textParts","thinkingParts","pushTextParts","push","join","pushThinkingParts","kind","block","toolCallRow","some","row","id","name","args","input","output","toolCallId","toolName","isError"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { SessionViewRowMeta } from '@shipfox/api-logs-dto';
2
+ import type { AgentMessage, SessionEntry } from '../entry-schema.js';
3
+ export declare function sessionDetail(entry: SessionEntry): string | null;
4
+ export declare function modelChangeDetail(entry: SessionEntry): string | null;
5
+ export declare function compactionDetail(entry: SessionEntry | AgentMessage): string | null;
6
+ export declare function compactionMeta(entry: SessionEntry | AgentMessage): readonly SessionViewRowMeta[];
7
+ export declare function branchSummaryDetail(entry: SessionEntry | AgentMessage): string | null;
8
+ export declare function branchSummaryMeta(entry: SessionEntry | AgentMessage): readonly SessionViewRowMeta[];
9
+ export declare function customEntryLabel(fallback: string): string;
10
+ export declare function customEntryMeta(entry: SessionEntry | AgentMessage): readonly SessionViewRowMeta[];
11
+ export declare function customEntryText(entry: SessionEntry | AgentMessage): string | null;
12
+ export declare function bashExecutionMeta(message: AgentMessage): readonly SessionViewRowMeta[];
13
+ export declare function labelDetail(entry: SessionEntry): string | null;
14
+ export declare function labelMeta(entry: SessionEntry): readonly SessionViewRowMeta[];
15
+ export declare function assistantMeta(message: AgentMessage): readonly SessionViewRowMeta[];
16
+ export declare function messageMeta(message: AgentMessage): readonly SessionViewRowMeta[];
17
+ export declare function entryDetail(entry: SessionEntry | AgentMessage): string | null;
18
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../../src/core/session/pi/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAanE,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAQhE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAKpE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,IAAI,CAElF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAKhG;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,IAAI,CAErF;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,GAAG,YAAY,GACjC,SAAS,kBAAkB,EAAE,CAG/B;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAMjG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,IAAI,CAMjF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAStF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAE9D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAG5E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAQlF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,kBAAkB,EAAE,CAEhF;AA2BD,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,IAAI,CAe7E"}
@@ -0,0 +1,120 @@
1
+ import { booleanField, field, formatCount, isMeta, metaItem, numberField, stringField, stringifyValue } from '../object.js';
2
+ import { messageText } from './text.js';
3
+ export function sessionDetail(entry) {
4
+ const version = numberField(entry, 'version');
5
+ const id = stringField(entry, 'id') ?? stringField(entry, 'sessionId');
6
+ const cwd = stringField(entry, 'cwd');
7
+ return [
8
+ version == null ? null : `v${version}`,
9
+ id,
10
+ cwd
11
+ ].filter(Boolean).join(' · ') || entryDetail(entry);
12
+ }
13
+ export function modelChangeDetail(entry) {
14
+ const model = stringField(entry, 'model') ?? stringField(entry, 'to') ?? stringField(entry, 'modelId');
15
+ const provider = stringField(entry, 'provider');
16
+ return [
17
+ model,
18
+ provider
19
+ ].filter(Boolean).join(' · ') || entryDetail(entry);
20
+ }
21
+ export function compactionDetail(entry) {
22
+ return stringField(entry, 'summary') ?? stringField(entry, 'message') ?? entryDetail(entry);
23
+ }
24
+ export function compactionMeta(entry) {
25
+ const tokensBefore = numberField(entry, 'tokensBefore');
26
+ return [
27
+ tokensBefore == null ? null : metaItem('tokens before', formatCount(tokensBefore, 'token'))
28
+ ].filter(isMeta);
29
+ }
30
+ export function branchSummaryDetail(entry) {
31
+ return stringField(entry, 'summary') ?? stringField(entry, 'message') ?? entryDetail(entry);
32
+ }
33
+ export function branchSummaryMeta(entry) {
34
+ const fromId = stringField(entry, 'fromId');
35
+ return [
36
+ fromId == null ? null : metaItem('from', fromId)
37
+ ].filter(isMeta);
38
+ }
39
+ export function customEntryLabel(fallback) {
40
+ return fallback;
41
+ }
42
+ export function customEntryMeta(entry) {
43
+ const display = field(entry, 'display');
44
+ return [
45
+ metaItem('type', stringField(entry, 'customType')),
46
+ typeof display === 'boolean' ? metaItem('display', display ? 'on' : 'off') : null
47
+ ].filter(isMeta);
48
+ }
49
+ export function customEntryText(entry) {
50
+ const text = messageText(entry);
51
+ if (text) return text;
52
+ const data = field(entry, 'data') ?? field(entry, 'details');
53
+ return data === undefined ? entryDetail(entry) : stringifyValue(data);
54
+ }
55
+ export function bashExecutionMeta(message) {
56
+ const exitCode = field(message, 'exitCode');
57
+ return [
58
+ typeof exitCode === 'number' ? metaItem('exit', String(exitCode)) : null,
59
+ booleanField(message, 'cancelled') ? metaItem('cancelled', 'yes') : null,
60
+ booleanField(message, 'truncated') ? metaItem('truncated', 'yes') : null,
61
+ booleanField(message, 'excludeFromContext') ? metaItem('context', 'excluded') : null,
62
+ metaItem('full output', stringField(message, 'fullOutputPath'), false)
63
+ ].filter(isMeta);
64
+ }
65
+ export function labelDetail(entry) {
66
+ return stringField(entry, 'label') ?? entryDetail(entry);
67
+ }
68
+ export function labelMeta(entry) {
69
+ const targetId = stringField(entry, 'targetId');
70
+ return [
71
+ targetId == null ? null : metaItem('target', targetId, false)
72
+ ].filter(isMeta);
73
+ }
74
+ export function assistantMeta(message) {
75
+ return [
76
+ providerModelMeta(message),
77
+ metaItem('api', stringField(message, 'api'), false),
78
+ usageMeta(message),
79
+ costMeta(message),
80
+ stopReasonMeta(message)
81
+ ].filter(isMeta);
82
+ }
83
+ export function messageMeta(message) {
84
+ return [
85
+ stopReasonMeta(message)
86
+ ].filter(isMeta);
87
+ }
88
+ function providerModelMeta(message) {
89
+ const model = stringField(message, 'model') ?? stringField(message, 'modelId');
90
+ const provider = stringField(message, 'provider');
91
+ const value = [
92
+ provider,
93
+ model
94
+ ].filter(Boolean).join('/');
95
+ return value ? metaItem('model', value) : null;
96
+ }
97
+ function usageMeta(message) {
98
+ const usage = field(message, 'usage');
99
+ const totalTokens = numberField(usage, 'totalTokens');
100
+ return totalTokens == null ? null : metaItem('tokens', formatCount(totalTokens, 'token'));
101
+ }
102
+ function costMeta(message) {
103
+ const usage = field(message, 'usage');
104
+ const cost = field(usage, 'cost');
105
+ const total = numberField(cost, 'total');
106
+ return total == null ? null : metaItem('cost', `$${total.toFixed(total < 0.01 ? 4 : 2)}`);
107
+ }
108
+ function stopReasonMeta(message) {
109
+ const stopReason = stringField(message, 'stopReason');
110
+ return stopReason == null ? null : metaItem('stop', stopReason);
111
+ }
112
+ export function entryDetail(entry) {
113
+ const detail = stringField(entry, 'message') ?? stringField(entry, 'text') ?? stringField(entry, 'content') ?? stringField(entry, 'summary') ?? stringField(entry, 'label') ?? stringField(entry, 'thinkingLevel') ?? stringField(entry, 'level') ?? stringField(entry, 'reason');
114
+ if (detail) return detail;
115
+ const value = field(entry, 'data') ?? field(entry, 'payload');
116
+ if (value === undefined) return null;
117
+ return stringifyValue(value);
118
+ }
119
+
120
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/session/pi/metadata.ts"],"sourcesContent":["import type {SessionViewRowMeta} from '@shipfox/api-logs-dto';\nimport type {AgentMessage, SessionEntry} from '../entry-schema.js';\nimport {\n booleanField,\n field,\n formatCount,\n isMeta,\n metaItem,\n numberField,\n stringField,\n stringifyValue,\n} from '../object.js';\nimport {messageText} from './text.js';\n\nexport function sessionDetail(entry: SessionEntry): string | null {\n const version = numberField(entry, 'version');\n const id = stringField(entry, 'id') ?? stringField(entry, 'sessionId');\n const cwd = stringField(entry, 'cwd');\n return (\n [version == null ? null : `v${version}`, id, cwd].filter(Boolean).join(' · ') ||\n entryDetail(entry)\n );\n}\n\nexport function modelChangeDetail(entry: SessionEntry): string | null {\n const model =\n stringField(entry, 'model') ?? stringField(entry, 'to') ?? stringField(entry, 'modelId');\n const provider = stringField(entry, 'provider');\n return [model, provider].filter(Boolean).join(' · ') || entryDetail(entry);\n}\n\nexport function compactionDetail(entry: SessionEntry | AgentMessage): string | null {\n return stringField(entry, 'summary') ?? stringField(entry, 'message') ?? entryDetail(entry);\n}\n\nexport function compactionMeta(entry: SessionEntry | AgentMessage): readonly SessionViewRowMeta[] {\n const tokensBefore = numberField(entry, 'tokensBefore');\n return [\n tokensBefore == null ? null : metaItem('tokens before', formatCount(tokensBefore, 'token')),\n ].filter(isMeta);\n}\n\nexport function branchSummaryDetail(entry: SessionEntry | AgentMessage): string | null {\n return stringField(entry, 'summary') ?? stringField(entry, 'message') ?? entryDetail(entry);\n}\n\nexport function branchSummaryMeta(\n entry: SessionEntry | AgentMessage,\n): readonly SessionViewRowMeta[] {\n const fromId = stringField(entry, 'fromId');\n return [fromId == null ? null : metaItem('from', fromId)].filter(isMeta);\n}\n\nexport function customEntryLabel(fallback: string): string {\n return fallback;\n}\n\nexport function customEntryMeta(entry: SessionEntry | AgentMessage): readonly SessionViewRowMeta[] {\n const display = field(entry, 'display');\n return [\n metaItem('type', stringField(entry, 'customType')),\n typeof display === 'boolean' ? metaItem('display', display ? 'on' : 'off') : null,\n ].filter(isMeta);\n}\n\nexport function customEntryText(entry: SessionEntry | AgentMessage): string | null {\n const text = messageText(entry);\n if (text) return text;\n\n const data = field(entry, 'data') ?? field(entry, 'details');\n return data === undefined ? entryDetail(entry) : stringifyValue(data);\n}\n\nexport function bashExecutionMeta(message: AgentMessage): readonly SessionViewRowMeta[] {\n const exitCode = field(message, 'exitCode');\n return [\n typeof exitCode === 'number' ? metaItem('exit', String(exitCode)) : null,\n booleanField(message, 'cancelled') ? metaItem('cancelled', 'yes') : null,\n booleanField(message, 'truncated') ? metaItem('truncated', 'yes') : null,\n booleanField(message, 'excludeFromContext') ? metaItem('context', 'excluded') : null,\n metaItem('full output', stringField(message, 'fullOutputPath'), false),\n ].filter(isMeta);\n}\n\nexport function labelDetail(entry: SessionEntry): string | null {\n return stringField(entry, 'label') ?? entryDetail(entry);\n}\n\nexport function labelMeta(entry: SessionEntry): readonly SessionViewRowMeta[] {\n const targetId = stringField(entry, 'targetId');\n return [targetId == null ? null : metaItem('target', targetId, false)].filter(isMeta);\n}\n\nexport function assistantMeta(message: AgentMessage): readonly SessionViewRowMeta[] {\n return [\n providerModelMeta(message),\n metaItem('api', stringField(message, 'api'), false),\n usageMeta(message),\n costMeta(message),\n stopReasonMeta(message),\n ].filter(isMeta);\n}\n\nexport function messageMeta(message: AgentMessage): readonly SessionViewRowMeta[] {\n return [stopReasonMeta(message)].filter(isMeta);\n}\n\nfunction providerModelMeta(message: AgentMessage): SessionViewRowMeta | null {\n const model = stringField(message, 'model') ?? stringField(message, 'modelId');\n const provider = stringField(message, 'provider');\n const value = [provider, model].filter(Boolean).join('/');\n return value ? metaItem('model', value) : null;\n}\n\nfunction usageMeta(message: AgentMessage): SessionViewRowMeta | null {\n const usage = field(message, 'usage');\n const totalTokens = numberField(usage, 'totalTokens');\n return totalTokens == null ? null : metaItem('tokens', formatCount(totalTokens, 'token'));\n}\n\nfunction costMeta(message: AgentMessage): SessionViewRowMeta | null {\n const usage = field(message, 'usage');\n const cost = field(usage, 'cost');\n const total = numberField(cost, 'total');\n return total == null ? null : metaItem('cost', `$${total.toFixed(total < 0.01 ? 4 : 2)}`);\n}\n\nfunction stopReasonMeta(message: AgentMessage): SessionViewRowMeta | null {\n const stopReason = stringField(message, 'stopReason');\n return stopReason == null ? null : metaItem('stop', stopReason);\n}\n\nexport function entryDetail(entry: SessionEntry | AgentMessage): string | null {\n const detail =\n stringField(entry, 'message') ??\n stringField(entry, 'text') ??\n stringField(entry, 'content') ??\n stringField(entry, 'summary') ??\n stringField(entry, 'label') ??\n stringField(entry, 'thinkingLevel') ??\n stringField(entry, 'level') ??\n stringField(entry, 'reason');\n if (detail) return detail;\n\n const value = field(entry, 'data') ?? field(entry, 'payload');\n if (value === undefined) return null;\n return stringifyValue(value);\n}\n"],"names":["booleanField","field","formatCount","isMeta","metaItem","numberField","stringField","stringifyValue","messageText","sessionDetail","entry","version","id","cwd","filter","Boolean","join","entryDetail","modelChangeDetail","model","provider","compactionDetail","compactionMeta","tokensBefore","branchSummaryDetail","branchSummaryMeta","fromId","customEntryLabel","fallback","customEntryMeta","display","customEntryText","text","data","undefined","bashExecutionMeta","message","exitCode","String","labelDetail","labelMeta","targetId","assistantMeta","providerModelMeta","usageMeta","costMeta","stopReasonMeta","messageMeta","value","usage","totalTokens","cost","total","toFixed","stopReason","detail"],"mappings":"AAEA,SACEA,YAAY,EACZC,KAAK,EACLC,WAAW,EACXC,MAAM,EACNC,QAAQ,EACRC,WAAW,EACXC,WAAW,EACXC,cAAc,QACT,eAAe;AACtB,SAAQC,WAAW,QAAO,YAAY;AAEtC,OAAO,SAASC,cAAcC,KAAmB;IAC/C,MAAMC,UAAUN,YAAYK,OAAO;IACnC,MAAME,KAAKN,YAAYI,OAAO,SAASJ,YAAYI,OAAO;IAC1D,MAAMG,MAAMP,YAAYI,OAAO;IAC/B,OACE;QAACC,WAAW,OAAO,OAAO,CAAC,CAAC,EAAEA,SAAS;QAAEC;QAAIC;KAAI,CAACC,MAAM,CAACC,SAASC,IAAI,CAAC,UACvEC,YAAYP;AAEhB;AAEA,OAAO,SAASQ,kBAAkBR,KAAmB;IACnD,MAAMS,QACJb,YAAYI,OAAO,YAAYJ,YAAYI,OAAO,SAASJ,YAAYI,OAAO;IAChF,MAAMU,WAAWd,YAAYI,OAAO;IACpC,OAAO;QAACS;QAAOC;KAAS,CAACN,MAAM,CAACC,SAASC,IAAI,CAAC,UAAUC,YAAYP;AACtE;AAEA,OAAO,SAASW,iBAAiBX,KAAkC;IACjE,OAAOJ,YAAYI,OAAO,cAAcJ,YAAYI,OAAO,cAAcO,YAAYP;AACvF;AAEA,OAAO,SAASY,eAAeZ,KAAkC;IAC/D,MAAMa,eAAelB,YAAYK,OAAO;IACxC,OAAO;QACLa,gBAAgB,OAAO,OAAOnB,SAAS,iBAAiBF,YAAYqB,cAAc;KACnF,CAACT,MAAM,CAACX;AACX;AAEA,OAAO,SAASqB,oBAAoBd,KAAkC;IACpE,OAAOJ,YAAYI,OAAO,cAAcJ,YAAYI,OAAO,cAAcO,YAAYP;AACvF;AAEA,OAAO,SAASe,kBACdf,KAAkC;IAElC,MAAMgB,SAASpB,YAAYI,OAAO;IAClC,OAAO;QAACgB,UAAU,OAAO,OAAOtB,SAAS,QAAQsB;KAAQ,CAACZ,MAAM,CAACX;AACnE;AAEA,OAAO,SAASwB,iBAAiBC,QAAgB;IAC/C,OAAOA;AACT;AAEA,OAAO,SAASC,gBAAgBnB,KAAkC;IAChE,MAAMoB,UAAU7B,MAAMS,OAAO;IAC7B,OAAO;QACLN,SAAS,QAAQE,YAAYI,OAAO;QACpC,OAAOoB,YAAY,YAAY1B,SAAS,WAAW0B,UAAU,OAAO,SAAS;KAC9E,CAAChB,MAAM,CAACX;AACX;AAEA,OAAO,SAAS4B,gBAAgBrB,KAAkC;IAChE,MAAMsB,OAAOxB,YAAYE;IACzB,IAAIsB,MAAM,OAAOA;IAEjB,MAAMC,OAAOhC,MAAMS,OAAO,WAAWT,MAAMS,OAAO;IAClD,OAAOuB,SAASC,YAAYjB,YAAYP,SAASH,eAAe0B;AAClE;AAEA,OAAO,SAASE,kBAAkBC,OAAqB;IACrD,MAAMC,WAAWpC,MAAMmC,SAAS;IAChC,OAAO;QACL,OAAOC,aAAa,WAAWjC,SAAS,QAAQkC,OAAOD,aAAa;QACpErC,aAAaoC,SAAS,eAAehC,SAAS,aAAa,SAAS;QACpEJ,aAAaoC,SAAS,eAAehC,SAAS,aAAa,SAAS;QACpEJ,aAAaoC,SAAS,wBAAwBhC,SAAS,WAAW,cAAc;QAChFA,SAAS,eAAeE,YAAY8B,SAAS,mBAAmB;KACjE,CAACtB,MAAM,CAACX;AACX;AAEA,OAAO,SAASoC,YAAY7B,KAAmB;IAC7C,OAAOJ,YAAYI,OAAO,YAAYO,YAAYP;AACpD;AAEA,OAAO,SAAS8B,UAAU9B,KAAmB;IAC3C,MAAM+B,WAAWnC,YAAYI,OAAO;IACpC,OAAO;QAAC+B,YAAY,OAAO,OAAOrC,SAAS,UAAUqC,UAAU;KAAO,CAAC3B,MAAM,CAACX;AAChF;AAEA,OAAO,SAASuC,cAAcN,OAAqB;IACjD,OAAO;QACLO,kBAAkBP;QAClBhC,SAAS,OAAOE,YAAY8B,SAAS,QAAQ;QAC7CQ,UAAUR;QACVS,SAAST;QACTU,eAAeV;KAChB,CAACtB,MAAM,CAACX;AACX;AAEA,OAAO,SAAS4C,YAAYX,OAAqB;IAC/C,OAAO;QAACU,eAAeV;KAAS,CAACtB,MAAM,CAACX;AAC1C;AAEA,SAASwC,kBAAkBP,OAAqB;IAC9C,MAAMjB,QAAQb,YAAY8B,SAAS,YAAY9B,YAAY8B,SAAS;IACpE,MAAMhB,WAAWd,YAAY8B,SAAS;IACtC,MAAMY,QAAQ;QAAC5B;QAAUD;KAAM,CAACL,MAAM,CAACC,SAASC,IAAI,CAAC;IACrD,OAAOgC,QAAQ5C,SAAS,SAAS4C,SAAS;AAC5C;AAEA,SAASJ,UAAUR,OAAqB;IACtC,MAAMa,QAAQhD,MAAMmC,SAAS;IAC7B,MAAMc,cAAc7C,YAAY4C,OAAO;IACvC,OAAOC,eAAe,OAAO,OAAO9C,SAAS,UAAUF,YAAYgD,aAAa;AAClF;AAEA,SAASL,SAAST,OAAqB;IACrC,MAAMa,QAAQhD,MAAMmC,SAAS;IAC7B,MAAMe,OAAOlD,MAAMgD,OAAO;IAC1B,MAAMG,QAAQ/C,YAAY8C,MAAM;IAChC,OAAOC,SAAS,OAAO,OAAOhD,SAAS,QAAQ,CAAC,CAAC,EAAEgD,MAAMC,OAAO,CAACD,QAAQ,OAAO,IAAI,IAAI;AAC1F;AAEA,SAASN,eAAeV,OAAqB;IAC3C,MAAMkB,aAAahD,YAAY8B,SAAS;IACxC,OAAOkB,cAAc,OAAO,OAAOlD,SAAS,QAAQkD;AACtD;AAEA,OAAO,SAASrC,YAAYP,KAAkC;IAC5D,MAAM6C,SACJjD,YAAYI,OAAO,cACnBJ,YAAYI,OAAO,WACnBJ,YAAYI,OAAO,cACnBJ,YAAYI,OAAO,cACnBJ,YAAYI,OAAO,YACnBJ,YAAYI,OAAO,oBACnBJ,YAAYI,OAAO,YACnBJ,YAAYI,OAAO;IACrB,IAAI6C,QAAQ,OAAOA;IAEnB,MAAMP,QAAQ/C,MAAMS,OAAO,WAAWT,MAAMS,OAAO;IACnD,IAAIsC,UAAUd,WAAW,OAAO;IAChC,OAAO3B,eAAeyC;AACxB"}
@@ -0,0 +1,12 @@
1
+ import type { AgentMessage, ContentBlock } from '../entry-schema.js';
2
+ export declare function normalizeRole(message: AgentMessage): string;
3
+ export declare function roleLabel(role: string): string;
4
+ export declare function isToolResultMessage(message: AgentMessage): boolean;
5
+ export declare function isToolCallBlock(block: ContentBlock): boolean;
6
+ export declare function isThinkingBlock(block: ContentBlock): boolean;
7
+ export declare function blockText(block: ContentBlock): string;
8
+ export declare function messageText(message: AgentMessage): string;
9
+ export declare function isTerminalStop(message: AgentMessage): boolean;
10
+ export declare function terminalStopDetail(message: AgentMessage): string | null;
11
+ export declare function bashExecutionText(message: AgentMessage): string;
12
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../../src/core/session/pi/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAMnE,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAG3D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAGlE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAG5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAG5D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CASrD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAYzD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAM7D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAKvE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAK/D"}
@@ -0,0 +1,59 @@
1
+ import { stringField, toJson } from '../object.js';
2
+ const MESSAGE_SUFFIX = /Message$/;
3
+ const CAMEL_CASE_BOUNDARY = /([a-z])([A-Z])/g;
4
+ export function normalizeRole(message) {
5
+ const raw = message.role ?? message.type ?? 'message';
6
+ return raw.replace(MESSAGE_SUFFIX, '').replace(CAMEL_CASE_BOUNDARY, '$1-$2').toLowerCase();
7
+ }
8
+ export function roleLabel(role) {
9
+ if (role === 'user') return 'user';
10
+ if (role === 'assistant') return 'assistant';
11
+ return role.replaceAll('-', ' ');
12
+ }
13
+ export function isToolResultMessage(message) {
14
+ const role = normalizeRole(message);
15
+ return typeof message.toolCallId === 'string' || role === 'tool' || role === 'tool-result';
16
+ }
17
+ export function isToolCallBlock(block) {
18
+ const type = stringField(block, 'type');
19
+ return type === 'toolCall' || type === 'tool_call' || type === 'tool-call';
20
+ }
21
+ export function isThinkingBlock(block) {
22
+ const type = stringField(block, 'type');
23
+ return type === 'thinking' || type === 'thought' || type === 'reasoning';
24
+ }
25
+ export function blockText(block) {
26
+ if (stringField(block, 'type') === 'image') return imagePlaceholder(block);
27
+ return stringField(block, 'text') ?? stringField(block, 'content') ?? stringField(block, 'thinking') ?? '';
28
+ }
29
+ export function messageText(message) {
30
+ if (typeof message.content === 'string') return message.content;
31
+ const blocks = Array.isArray(message.content) ? message.content : [];
32
+ if (blocks.length > 0) {
33
+ return blocks.map((block)=>blockText(block)).filter(Boolean).join('\n\n');
34
+ }
35
+ return '';
36
+ }
37
+ export function isTerminalStop(message) {
38
+ return message.errorMessage != null || message.stopReason === 'error' || message.stopReason === 'aborted';
39
+ }
40
+ export function terminalStopDetail(message) {
41
+ if (message.errorMessage) return message.errorMessage;
42
+ if (message.stopReason === 'error') return 'Assistant stopped with an error.';
43
+ if (message.stopReason === 'aborted') return 'Assistant run was aborted.';
44
+ return null;
45
+ }
46
+ export function bashExecutionText(message) {
47
+ const command = stringField(message, 'command');
48
+ const output = stringField(message, 'output');
49
+ return [
50
+ `$ ${command ?? ''}`.trim(),
51
+ output
52
+ ].filter(Boolean).join('\n') || toJson(message);
53
+ }
54
+ function imagePlaceholder(block) {
55
+ const mimeType = stringField(block, 'mimeType');
56
+ return mimeType == null ? '[image]' : `[${mimeType} image]`;
57
+ }
58
+
59
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/session/pi/text.ts"],"sourcesContent":["import type {AgentMessage, ContentBlock} from '../entry-schema.js';\nimport {stringField, toJson} from '../object.js';\n\nconst MESSAGE_SUFFIX = /Message$/;\nconst CAMEL_CASE_BOUNDARY = /([a-z])([A-Z])/g;\n\nexport function normalizeRole(message: AgentMessage): string {\n const raw = message.role ?? message.type ?? 'message';\n return raw.replace(MESSAGE_SUFFIX, '').replace(CAMEL_CASE_BOUNDARY, '$1-$2').toLowerCase();\n}\n\nexport function roleLabel(role: string): string {\n if (role === 'user') return 'user';\n if (role === 'assistant') return 'assistant';\n return role.replaceAll('-', ' ');\n}\n\nexport function isToolResultMessage(message: AgentMessage): boolean {\n const role = normalizeRole(message);\n return typeof message.toolCallId === 'string' || role === 'tool' || role === 'tool-result';\n}\n\nexport function isToolCallBlock(block: ContentBlock): boolean {\n const type = stringField(block, 'type');\n return type === 'toolCall' || type === 'tool_call' || type === 'tool-call';\n}\n\nexport function isThinkingBlock(block: ContentBlock): boolean {\n const type = stringField(block, 'type');\n return type === 'thinking' || type === 'thought' || type === 'reasoning';\n}\n\nexport function blockText(block: ContentBlock): string {\n if (stringField(block, 'type') === 'image') return imagePlaceholder(block);\n\n return (\n stringField(block, 'text') ??\n stringField(block, 'content') ??\n stringField(block, 'thinking') ??\n ''\n );\n}\n\nexport function messageText(message: AgentMessage): string {\n if (typeof message.content === 'string') return message.content;\n\n const blocks = Array.isArray(message.content) ? message.content : [];\n if (blocks.length > 0) {\n return blocks\n .map((block) => blockText(block))\n .filter(Boolean)\n .join('\\n\\n');\n }\n\n return '';\n}\n\nexport function isTerminalStop(message: AgentMessage): boolean {\n return (\n message.errorMessage != null ||\n message.stopReason === 'error' ||\n message.stopReason === 'aborted'\n );\n}\n\nexport function terminalStopDetail(message: AgentMessage): string | null {\n if (message.errorMessage) return message.errorMessage;\n if (message.stopReason === 'error') return 'Assistant stopped with an error.';\n if (message.stopReason === 'aborted') return 'Assistant run was aborted.';\n return null;\n}\n\nexport function bashExecutionText(message: AgentMessage): string {\n const command = stringField(message, 'command');\n const output = stringField(message, 'output');\n\n return [`$ ${command ?? ''}`.trim(), output].filter(Boolean).join('\\n') || toJson(message);\n}\n\nfunction imagePlaceholder(block: ContentBlock): string {\n const mimeType = stringField(block, 'mimeType');\n return mimeType == null ? '[image]' : `[${mimeType} image]`;\n}\n"],"names":["stringField","toJson","MESSAGE_SUFFIX","CAMEL_CASE_BOUNDARY","normalizeRole","message","raw","role","type","replace","toLowerCase","roleLabel","replaceAll","isToolResultMessage","toolCallId","isToolCallBlock","block","isThinkingBlock","blockText","imagePlaceholder","messageText","content","blocks","Array","isArray","length","map","filter","Boolean","join","isTerminalStop","errorMessage","stopReason","terminalStopDetail","bashExecutionText","command","output","trim","mimeType"],"mappings":"AACA,SAAQA,WAAW,EAAEC,MAAM,QAAO,eAAe;AAEjD,MAAMC,iBAAiB;AACvB,MAAMC,sBAAsB;AAE5B,OAAO,SAASC,cAAcC,OAAqB;IACjD,MAAMC,MAAMD,QAAQE,IAAI,IAAIF,QAAQG,IAAI,IAAI;IAC5C,OAAOF,IAAIG,OAAO,CAACP,gBAAgB,IAAIO,OAAO,CAACN,qBAAqB,SAASO,WAAW;AAC1F;AAEA,OAAO,SAASC,UAAUJ,IAAY;IACpC,IAAIA,SAAS,QAAQ,OAAO;IAC5B,IAAIA,SAAS,aAAa,OAAO;IACjC,OAAOA,KAAKK,UAAU,CAAC,KAAK;AAC9B;AAEA,OAAO,SAASC,oBAAoBR,OAAqB;IACvD,MAAME,OAAOH,cAAcC;IAC3B,OAAO,OAAOA,QAAQS,UAAU,KAAK,YAAYP,SAAS,UAAUA,SAAS;AAC/E;AAEA,OAAO,SAASQ,gBAAgBC,KAAmB;IACjD,MAAMR,OAAOR,YAAYgB,OAAO;IAChC,OAAOR,SAAS,cAAcA,SAAS,eAAeA,SAAS;AACjE;AAEA,OAAO,SAASS,gBAAgBD,KAAmB;IACjD,MAAMR,OAAOR,YAAYgB,OAAO;IAChC,OAAOR,SAAS,cAAcA,SAAS,aAAaA,SAAS;AAC/D;AAEA,OAAO,SAASU,UAAUF,KAAmB;IAC3C,IAAIhB,YAAYgB,OAAO,YAAY,SAAS,OAAOG,iBAAiBH;IAEpE,OACEhB,YAAYgB,OAAO,WACnBhB,YAAYgB,OAAO,cACnBhB,YAAYgB,OAAO,eACnB;AAEJ;AAEA,OAAO,SAASI,YAAYf,OAAqB;IAC/C,IAAI,OAAOA,QAAQgB,OAAO,KAAK,UAAU,OAAOhB,QAAQgB,OAAO;IAE/D,MAAMC,SAASC,MAAMC,OAAO,CAACnB,QAAQgB,OAAO,IAAIhB,QAAQgB,OAAO,GAAG,EAAE;IACpE,IAAIC,OAAOG,MAAM,GAAG,GAAG;QACrB,OAAOH,OACJI,GAAG,CAAC,CAACV,QAAUE,UAAUF,QACzBW,MAAM,CAACC,SACPC,IAAI,CAAC;IACV;IAEA,OAAO;AACT;AAEA,OAAO,SAASC,eAAezB,OAAqB;IAClD,OACEA,QAAQ0B,YAAY,IAAI,QACxB1B,QAAQ2B,UAAU,KAAK,WACvB3B,QAAQ2B,UAAU,KAAK;AAE3B;AAEA,OAAO,SAASC,mBAAmB5B,OAAqB;IACtD,IAAIA,QAAQ0B,YAAY,EAAE,OAAO1B,QAAQ0B,YAAY;IACrD,IAAI1B,QAAQ2B,UAAU,KAAK,SAAS,OAAO;IAC3C,IAAI3B,QAAQ2B,UAAU,KAAK,WAAW,OAAO;IAC7C,OAAO;AACT;AAEA,OAAO,SAASE,kBAAkB7B,OAAqB;IACrD,MAAM8B,UAAUnC,YAAYK,SAAS;IACrC,MAAM+B,SAASpC,YAAYK,SAAS;IAEpC,OAAO;QAAC,CAAC,EAAE,EAAE8B,WAAW,IAAI,CAACE,IAAI;QAAID;KAAO,CAACT,MAAM,CAACC,SAASC,IAAI,CAAC,SAAS5B,OAAOI;AACpF;AAEA,SAASc,iBAAiBH,KAAmB;IAC3C,MAAMsB,WAAWtC,YAAYgB,OAAO;IACpC,OAAOsB,YAAY,OAAO,YAAY,CAAC,CAAC,EAAEA,SAAS,OAAO,CAAC;AAC7D"}
@@ -0,0 +1,5 @@
1
+ import type { SessionViewRow } from '@shipfox/api-logs-dto';
2
+ import type { AgentSessionRecord } from './session-record.js';
3
+ export type { AgentSessionRecord } from './session-record.js';
4
+ export declare function parsePiSessionRecord(record: AgentSessionRecord): readonly SessionViewRow[];
5
+ //# sourceMappingURL=pi-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-parser.d.ts","sourceRoot":"","sources":["../../../src/core/session/pi-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAmB1D,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAE5D,YAAY,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAE5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,cAAc,EAAE,CAmF1F"}
@@ -0,0 +1,73 @@
1
+ import { parseSessionEntry, sessionMessageEntrySchema } from './entry-schema.js';
2
+ import { toJson } from './object.js';
3
+ import { expandMessageEntry } from './pi/message-rows.js';
4
+ import { branchSummaryDetail, branchSummaryMeta, compactionDetail, compactionMeta, customEntryLabel, customEntryMeta, customEntryText, entryDetail, labelDetail, labelMeta, modelChangeDetail, sessionDetail } from './pi/metadata.js';
5
+ import { lifecycleRow, messageRow, rawRecordRow } from './rows.js';
6
+ export function parsePiSessionRecord(record) {
7
+ const parsed = parseSessionEntry(record.data);
8
+ if (!parsed.ok) {
9
+ return [
10
+ rawRecordRow(record, parsed.reason === 'invalid-json' ? 'Malformed session entry' : 'Unsupported entry')
11
+ ];
12
+ }
13
+ const entry = parsed.entry;
14
+ switch(entry.type){
15
+ case 'message':
16
+ {
17
+ const parsedEntry = sessionMessageEntrySchema.safeParse(entry);
18
+ if (!parsedEntry.success) {
19
+ return [
20
+ {
21
+ kind: 'raw',
22
+ timestamp: record.ts,
23
+ label: 'Unsupported message entry',
24
+ raw: record.data
25
+ }
26
+ ];
27
+ }
28
+ return expandMessageEntry(record.ts, parsedEntry.data.message);
29
+ }
30
+ case 'session':
31
+ return [
32
+ lifecycleRow(record.ts, 'Session started', sessionDetail(entry), 'default', false)
33
+ ];
34
+ case 'session_info':
35
+ return [
36
+ lifecycleRow(record.ts, 'Session info', entryDetail(entry), 'default', false)
37
+ ];
38
+ case 'thinking_level_change':
39
+ return [
40
+ lifecycleRow(record.ts, 'Thinking level changed', entryDetail(entry), 'default', false)
41
+ ];
42
+ case 'model_change':
43
+ return [
44
+ lifecycleRow(record.ts, 'Model changed', modelChangeDetail(entry), 'default', false)
45
+ ];
46
+ case 'compaction':
47
+ return [
48
+ lifecycleRow(record.ts, 'Context compacted', compactionDetail(entry), 'default', false, compactionMeta(entry))
49
+ ];
50
+ case 'branch_summary':
51
+ return [
52
+ messageRow(record.ts, 'system', 'branch summary', branchSummaryDetail(entry) ?? toJson(entry), false, branchSummaryMeta(entry))
53
+ ];
54
+ case 'custom':
55
+ return [
56
+ messageRow(record.ts, 'custom', customEntryLabel('custom'), customEntryText(entry) ?? toJson(entry), false, customEntryMeta(entry))
57
+ ];
58
+ case 'custom_message':
59
+ return [
60
+ messageRow(record.ts, 'custom', customEntryLabel('custom message'), customEntryText(entry) ?? toJson(entry), false, customEntryMeta(entry))
61
+ ];
62
+ case 'label':
63
+ return [
64
+ lifecycleRow(record.ts, 'Label', labelDetail(entry), 'default', false, labelMeta(entry))
65
+ ];
66
+ default:
67
+ return [
68
+ rawRecordRow(record, `Unknown session entry: ${entry.type}`)
69
+ ];
70
+ }
71
+ }
72
+
73
+ //# sourceMappingURL=pi-parser.js.map