@elie-laloum/outpost 5.0.0 → 7.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 (647) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +11 -11
  3. package/SECURITY.md +10 -0
  4. package/dist/adapters/agents/antigravity-adapter.d.ts +3 -0
  5. package/dist/adapters/agents/antigravity-adapter.js +41 -0
  6. package/dist/adapters/agents/antigravity-adapter.js.map +1 -0
  7. package/dist/adapters/agents/antigravity-authentication.d.ts +2 -0
  8. package/dist/adapters/agents/antigravity-authentication.js +27 -0
  9. package/dist/adapters/agents/antigravity-authentication.js.map +1 -0
  10. package/dist/adapters/agents/antigravity-diagnostics.d.ts +1 -0
  11. package/dist/adapters/agents/antigravity-diagnostics.js +6 -0
  12. package/dist/adapters/agents/antigravity-diagnostics.js.map +1 -0
  13. package/dist/adapters/agents/antigravity-events.d.ts +2 -0
  14. package/dist/adapters/agents/antigravity-events.js +75 -0
  15. package/dist/adapters/agents/antigravity-events.js.map +1 -0
  16. package/dist/adapters/agents/antigravity-request.d.ts +5 -0
  17. package/dist/adapters/agents/antigravity-request.js +37 -0
  18. package/dist/adapters/agents/antigravity-request.js.map +1 -0
  19. package/dist/adapters/agents/antigravity.constants.d.ts +3 -0
  20. package/dist/adapters/agents/antigravity.constants.js +4 -0
  21. package/dist/adapters/agents/antigravity.constants.js.map +1 -0
  22. package/dist/adapters/agents/{gemini.types.d.ts → antigravity.types.d.ts} +2 -2
  23. package/dist/adapters/agents/antigravity.types.js +2 -0
  24. package/dist/adapters/agents/antigravity.types.js.map +1 -0
  25. package/dist/adapters/agents/authentication.constants.d.ts +19 -9
  26. package/dist/adapters/agents/authentication.constants.js +12 -9
  27. package/dist/adapters/agents/authentication.constants.js.map +1 -1
  28. package/dist/adapters/agents/authentication.d.ts +11 -2
  29. package/dist/adapters/agents/authentication.js +70 -47
  30. package/dist/adapters/agents/authentication.js.map +1 -1
  31. package/dist/adapters/agents/authentication.types.d.ts +20 -0
  32. package/dist/adapters/agents/authentication.types.js +2 -0
  33. package/dist/adapters/agents/authentication.types.js.map +1 -0
  34. package/dist/adapters/agents/claude-adapter.js +4 -2
  35. package/dist/adapters/agents/claude-adapter.js.map +1 -1
  36. package/dist/adapters/agents/claude-authentication.d.ts +2 -0
  37. package/dist/adapters/agents/claude-authentication.js +34 -0
  38. package/dist/adapters/agents/claude-authentication.js.map +1 -0
  39. package/dist/adapters/agents/claude-events.js +52 -9
  40. package/dist/adapters/agents/claude-events.js.map +1 -1
  41. package/dist/adapters/agents/claude-request.js +2 -0
  42. package/dist/adapters/agents/claude-request.js.map +1 -1
  43. package/dist/adapters/agents/cli-diagnostics.constants.d.ts +6 -6
  44. package/dist/adapters/agents/cli-diagnostics.constants.js +6 -6
  45. package/dist/adapters/agents/cli-diagnostics.constants.js.map +1 -1
  46. package/dist/adapters/agents/cli-diagnostics.d.ts +1 -0
  47. package/dist/adapters/agents/cli-diagnostics.js +18 -0
  48. package/dist/adapters/agents/cli-diagnostics.js.map +1 -1
  49. package/dist/adapters/agents/codex-adapter.js +4 -2
  50. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  51. package/dist/adapters/agents/codex-authentication.d.ts +3 -0
  52. package/dist/adapters/agents/codex-authentication.js +47 -0
  53. package/dist/adapters/agents/codex-authentication.js.map +1 -0
  54. package/dist/adapters/agents/codex-events.js +28 -2
  55. package/dist/adapters/agents/codex-events.js.map +1 -1
  56. package/dist/adapters/agents/copilot-adapter.d.ts +3 -0
  57. package/dist/adapters/agents/copilot-adapter.js +45 -0
  58. package/dist/adapters/agents/copilot-adapter.js.map +1 -0
  59. package/dist/adapters/agents/copilot-authentication.d.ts +2 -0
  60. package/dist/adapters/agents/copilot-authentication.js +46 -0
  61. package/dist/adapters/agents/copilot-authentication.js.map +1 -0
  62. package/dist/adapters/agents/copilot-diagnostics.d.ts +1 -0
  63. package/dist/adapters/agents/copilot-diagnostics.js +6 -0
  64. package/dist/adapters/agents/copilot-diagnostics.js.map +1 -0
  65. package/dist/adapters/agents/copilot-events.d.ts +2 -0
  66. package/dist/adapters/agents/copilot-events.js +66 -0
  67. package/dist/adapters/agents/copilot-events.js.map +1 -0
  68. package/dist/adapters/agents/copilot-request.d.ts +5 -0
  69. package/dist/adapters/agents/copilot-request.js +24 -0
  70. package/dist/adapters/agents/copilot-request.js.map +1 -0
  71. package/dist/adapters/agents/copilot-usage.d.ts +3 -0
  72. package/dist/adapters/agents/copilot-usage.js +19 -0
  73. package/dist/adapters/agents/copilot-usage.js.map +1 -0
  74. package/dist/adapters/agents/copilot.types.d.ts +6 -0
  75. package/dist/adapters/agents/copilot.types.js +2 -0
  76. package/dist/adapters/agents/copilot.types.js.map +1 -0
  77. package/dist/adapters/agents/event-decoder.d.ts +2 -2
  78. package/dist/adapters/agents/event-decoder.js +6 -5
  79. package/dist/adapters/agents/event-decoder.js.map +1 -1
  80. package/dist/adapters/agents/kimi-adapter.d.ts +3 -0
  81. package/dist/adapters/agents/kimi-adapter.js +51 -0
  82. package/dist/adapters/agents/kimi-adapter.js.map +1 -0
  83. package/dist/adapters/agents/kimi-authentication.d.ts +3 -0
  84. package/dist/adapters/agents/kimi-authentication.js +63 -0
  85. package/dist/adapters/agents/kimi-authentication.js.map +1 -0
  86. package/dist/adapters/agents/kimi-diagnostics.d.ts +2 -0
  87. package/dist/adapters/agents/kimi-diagnostics.js +14 -0
  88. package/dist/adapters/agents/kimi-diagnostics.js.map +1 -0
  89. package/dist/adapters/agents/kimi-events.d.ts +2 -0
  90. package/dist/adapters/agents/kimi-events.js +55 -0
  91. package/dist/adapters/agents/kimi-events.js.map +1 -0
  92. package/dist/adapters/agents/kimi-fork.d.ts +2 -0
  93. package/dist/adapters/agents/kimi-fork.js +11 -0
  94. package/dist/adapters/agents/kimi-fork.js.map +1 -0
  95. package/dist/adapters/agents/{gemini-request.d.ts → kimi-request.d.ts} +2 -2
  96. package/dist/adapters/agents/kimi-request.js +33 -0
  97. package/dist/adapters/agents/kimi-request.js.map +1 -0
  98. package/dist/adapters/agents/kimi-usage.d.ts +2 -0
  99. package/dist/adapters/agents/kimi-usage.js +7 -0
  100. package/dist/adapters/agents/kimi-usage.js.map +1 -0
  101. package/dist/adapters/agents/kimi.constants.d.ts +13 -0
  102. package/dist/adapters/agents/kimi.constants.js +14 -0
  103. package/dist/adapters/agents/kimi.constants.js.map +1 -0
  104. package/dist/adapters/agents/kimi.types.d.ts +7 -0
  105. package/dist/adapters/agents/kimi.types.js +2 -0
  106. package/dist/adapters/agents/kimi.types.js.map +1 -0
  107. package/dist/adapters/agents/model-support.constants.d.ts +3 -1
  108. package/dist/adapters/agents/model-support.constants.js +12 -2
  109. package/dist/adapters/agents/model-support.constants.js.map +1 -1
  110. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +2 -2
  111. package/dist/adapters/agents/protocol-fixtures.constants.js +131 -9
  112. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
  113. package/dist/adapters/agents/protocol-fixtures.types.d.ts +1 -0
  114. package/dist/adapters/agents/protocol-fixtures.types.js.map +1 -1
  115. package/dist/adapters/agents/protocol.d.ts +1 -0
  116. package/dist/adapters/agents/protocol.js +9 -0
  117. package/dist/adapters/agents/protocol.js.map +1 -1
  118. package/dist/adapters/agents/session-usage.constants.d.ts +10 -0
  119. package/dist/adapters/agents/session-usage.constants.js +110 -0
  120. package/dist/adapters/agents/session-usage.constants.js.map +1 -0
  121. package/dist/adapters/agents/session-usage.d.ts +5 -0
  122. package/dist/adapters/agents/session-usage.js +45 -0
  123. package/dist/adapters/agents/session-usage.js.map +1 -0
  124. package/dist/adapters/agents/settings.types.d.ts +1 -0
  125. package/dist/adapters/agents/settings.types.js.map +1 -1
  126. package/dist/adapters/agents/tool-result.d.ts +2 -0
  127. package/dist/adapters/agents/tool-result.js +17 -0
  128. package/dist/adapters/agents/tool-result.js.map +1 -0
  129. package/dist/adapters/models/anthropic-response.js +3 -0
  130. package/dist/adapters/models/anthropic-response.js.map +1 -1
  131. package/dist/adapters/models/http-provider.js +6 -1
  132. package/dist/adapters/models/http-provider.js.map +1 -1
  133. package/dist/adapters/models/openai-responses.js +10 -0
  134. package/dist/adapters/models/openai-responses.js.map +1 -1
  135. package/dist/adapters/models/retry-after.d.ts +1 -0
  136. package/dist/adapters/models/retry-after.js +16 -0
  137. package/dist/adapters/models/retry-after.js.map +1 -0
  138. package/dist/application/activity-watchdog.js +1 -2
  139. package/dist/application/activity-watchdog.js.map +1 -1
  140. package/dist/application/agent-authentication.d.ts +4 -0
  141. package/dist/application/agent-authentication.js +32 -0
  142. package/dist/application/agent-authentication.js.map +1 -0
  143. package/dist/application/agent-bootstrap.constants.d.ts +2 -5
  144. package/dist/application/agent-bootstrap.constants.js +27 -4
  145. package/dist/application/agent-bootstrap.constants.js.map +1 -1
  146. package/dist/application/agent-bootstrap.js +39 -12
  147. package/dist/application/agent-bootstrap.js.map +1 -1
  148. package/dist/application/agent-bootstrap.types.d.ts +19 -0
  149. package/dist/application/agent-bootstrap.types.js +2 -0
  150. package/dist/application/agent-bootstrap.types.js.map +1 -0
  151. package/dist/application/agent-output.js +74 -8
  152. package/dist/application/agent-output.js.map +1 -1
  153. package/dist/application/agent-request.d.ts +3 -0
  154. package/dist/application/agent-request.js +11 -0
  155. package/dist/application/agent-request.js.map +1 -0
  156. package/dist/application/agent-turn.js +74 -6
  157. package/dist/application/agent-turn.js.map +1 -1
  158. package/dist/application/agent-usage.d.ts +6 -0
  159. package/dist/application/agent-usage.js +57 -0
  160. package/dist/application/agent-usage.js.map +1 -0
  161. package/dist/application/attach.js +2 -0
  162. package/dist/application/attach.js.map +1 -1
  163. package/dist/application/credential-installer.constants.d.ts +1 -0
  164. package/dist/application/credential-installer.constants.js +22 -0
  165. package/dist/application/credential-installer.constants.js.map +1 -0
  166. package/dist/application/custom-turn.js +44 -49
  167. package/dist/application/custom-turn.js.map +1 -1
  168. package/dist/application/dispatch-observation.d.ts +1 -1
  169. package/dist/application/dispatch-observation.js +141 -21
  170. package/dist/application/dispatch-observation.js.map +1 -1
  171. package/dist/application/dispatch-observation.types.d.ts +2 -0
  172. package/dist/application/dispatch-observation.types.js.map +1 -1
  173. package/dist/application/dispatch-validation.js +2 -0
  174. package/dist/application/dispatch-validation.js.map +1 -1
  175. package/dist/application/dispatch.js +1 -1
  176. package/dist/application/dispatch.js.map +1 -1
  177. package/dist/application/doctor-agent.constants.d.ts +2 -8
  178. package/dist/application/doctor-agent.constants.js +43 -6
  179. package/dist/application/doctor-agent.constants.js.map +1 -1
  180. package/dist/application/doctor-agent.d.ts +2 -1
  181. package/dist/application/doctor-agent.js +15 -3
  182. package/dist/application/doctor-agent.js.map +1 -1
  183. package/dist/application/doctor-image.js +4 -6
  184. package/dist/application/doctor-image.js.map +1 -1
  185. package/dist/application/doctor-protocol.js +6 -11
  186. package/dist/application/doctor-protocol.js.map +1 -1
  187. package/dist/application/doctor-protocol.types.d.ts +1 -1
  188. package/dist/application/doctor-protocol.types.js.map +1 -1
  189. package/dist/application/doctor-sandbox.js +2 -5
  190. package/dist/application/doctor-sandbox.js.map +1 -1
  191. package/dist/application/doctor.js +28 -10
  192. package/dist/application/doctor.js.map +1 -1
  193. package/dist/application/doctor.types.d.ts +10 -1
  194. package/dist/application/doctor.types.js.map +1 -1
  195. package/dist/application/execution.constants.d.ts +2 -0
  196. package/dist/application/execution.constants.js +2 -0
  197. package/dist/application/execution.constants.js.map +1 -1
  198. package/dist/application/execution.types.d.ts +8 -0
  199. package/dist/application/execution.types.js.map +1 -1
  200. package/dist/application/harness-budget.d.ts +3 -0
  201. package/dist/application/harness-budget.js +42 -0
  202. package/dist/application/harness-budget.js.map +1 -0
  203. package/dist/application/harness-budget.types.d.ts +5 -0
  204. package/dist/application/harness-budget.types.js +2 -0
  205. package/dist/application/harness-budget.types.js.map +1 -0
  206. package/dist/application/harness-hooks.js +34 -3
  207. package/dist/application/harness-hooks.js.map +1 -1
  208. package/dist/application/harness-loop.js +52 -24
  209. package/dist/application/harness-loop.js.map +1 -1
  210. package/dist/application/harness-model-provider.d.ts +3 -0
  211. package/dist/application/harness-model-provider.js +49 -0
  212. package/dist/application/harness-model-provider.js.map +1 -0
  213. package/dist/application/harness-model-provider.types.d.ts +10 -0
  214. package/dist/application/harness-model-provider.types.js +2 -0
  215. package/dist/application/harness-model-provider.types.js.map +1 -0
  216. package/dist/application/harness-subagent.d.ts +4 -0
  217. package/dist/application/harness-subagent.js +110 -0
  218. package/dist/application/harness-subagent.js.map +1 -0
  219. package/dist/application/harness.types.d.ts +11 -0
  220. package/dist/application/harness.types.js.map +1 -1
  221. package/dist/application/lifecycle-hooks.d.ts +1 -1
  222. package/dist/application/lifecycle-hooks.js +5 -4
  223. package/dist/application/lifecycle-hooks.js.map +1 -1
  224. package/dist/application/observed-lease.d.ts +3 -0
  225. package/dist/application/observed-lease.js +26 -0
  226. package/dist/application/observed-lease.js.map +1 -0
  227. package/dist/application/outpost.types.d.ts +3 -1
  228. package/dist/application/outpost.types.js.map +1 -1
  229. package/dist/application/output-lines.d.ts +4 -0
  230. package/dist/application/output-lines.js +28 -0
  231. package/dist/application/output-lines.js.map +1 -0
  232. package/dist/application/queue-worker.js +1 -1
  233. package/dist/application/queue-worker.js.map +1 -1
  234. package/dist/application/queue-worker.types.d.ts +1 -0
  235. package/dist/application/queue-worker.types.js.map +1 -1
  236. package/dist/application/queued-task.js +24 -5
  237. package/dist/application/queued-task.js.map +1 -1
  238. package/dist/application/recovery-archive.d.ts +3 -2
  239. package/dist/application/recovery-archive.js +9 -2
  240. package/dist/application/recovery-archive.js.map +1 -1
  241. package/dist/application/recovery-restore.d.ts +3 -2
  242. package/dist/application/recovery-restore.js +9 -2
  243. package/dist/application/recovery-restore.js.map +1 -1
  244. package/dist/application/recovery-retention.d.ts +3 -2
  245. package/dist/application/recovery-retention.js +74 -26
  246. package/dist/application/recovery-retention.js.map +1 -1
  247. package/dist/application/remote-workspace.js +5 -4
  248. package/dist/application/remote-workspace.js.map +1 -1
  249. package/dist/application/remote-workspace.types.d.ts +1 -0
  250. package/dist/application/remote-workspace.types.js.map +1 -1
  251. package/dist/application/sandbox-agents.js +19 -19
  252. package/dist/application/sandbox-agents.js.map +1 -1
  253. package/dist/application/sandbox-attach.js +12 -3
  254. package/dist/application/sandbox-attach.js.map +1 -1
  255. package/dist/application/sandbox-dispatch.js +13 -27
  256. package/dist/application/sandbox-dispatch.js.map +1 -1
  257. package/dist/application/sandbox-provision.js +15 -9
  258. package/dist/application/sandbox-provision.js.map +1 -1
  259. package/dist/application/sandbox-session.types.d.ts +7 -2
  260. package/dist/application/sandbox-session.types.js.map +1 -1
  261. package/dist/application/sandbox.js +13 -6
  262. package/dist/application/sandbox.js.map +1 -1
  263. package/dist/application/speculation-checkpoint.d.ts +6 -0
  264. package/dist/application/speculation-checkpoint.js +206 -0
  265. package/dist/application/speculation-checkpoint.js.map +1 -0
  266. package/dist/application/speculation-checkpoint.types.d.ts +24 -0
  267. package/dist/application/speculation-checkpoint.types.js +2 -0
  268. package/dist/application/speculation-checkpoint.types.js.map +1 -0
  269. package/dist/application/speculation-integration.constants.d.ts +4 -0
  270. package/dist/application/speculation-integration.constants.js +5 -0
  271. package/dist/application/speculation-integration.constants.js.map +1 -0
  272. package/dist/application/speculation-integration.d.ts +2 -0
  273. package/dist/application/speculation-integration.js +67 -0
  274. package/dist/application/speculation-integration.js.map +1 -0
  275. package/dist/application/speculation-resume.d.ts +4 -0
  276. package/dist/application/speculation-resume.js +71 -0
  277. package/dist/application/speculation-resume.js.map +1 -0
  278. package/dist/application/speculation-run.d.ts +4 -0
  279. package/dist/application/speculation-run.js +320 -0
  280. package/dist/application/speculation-run.js.map +1 -0
  281. package/dist/application/speculation-timeout.d.ts +1 -0
  282. package/dist/application/speculation-timeout.js +15 -0
  283. package/dist/application/speculation-timeout.js.map +1 -0
  284. package/dist/application/speculation.constants.d.ts +1 -0
  285. package/dist/application/speculation.constants.js +5 -1
  286. package/dist/application/speculation.constants.js.map +1 -1
  287. package/dist/application/speculation.js +41 -149
  288. package/dist/application/speculation.js.map +1 -1
  289. package/dist/application/speculation.types.d.ts +23 -0
  290. package/dist/application/speculation.types.js.map +1 -1
  291. package/dist/application/startup-recovery.js +14 -1
  292. package/dist/application/startup-recovery.js.map +1 -1
  293. package/dist/application/startup-recovery.types.d.ts +1 -0
  294. package/dist/application/startup-recovery.types.js.map +1 -1
  295. package/dist/application/stop-reason.d.ts +2 -0
  296. package/dist/application/stop-reason.js +21 -0
  297. package/dist/application/stop-reason.js.map +1 -0
  298. package/dist/application/stop-reason.types.d.ts +4 -0
  299. package/dist/application/stop-reason.types.js +2 -0
  300. package/dist/application/stop-reason.types.js.map +1 -0
  301. package/dist/application/storage-reservation.js +9 -2
  302. package/dist/application/storage-reservation.js.map +1 -1
  303. package/dist/application/task-observation.d.ts +3 -0
  304. package/dist/application/task-observation.js +22 -0
  305. package/dist/application/task-observation.js.map +1 -0
  306. package/dist/application/task-usage.js +5 -12
  307. package/dist/application/task-usage.js.map +1 -1
  308. package/dist/application/tasks.js +41 -16
  309. package/dist/application/tasks.js.map +1 -1
  310. package/dist/application/tool-execution.js +42 -19
  311. package/dist/application/tool-execution.js.map +1 -1
  312. package/dist/application/workspace.js +6 -4
  313. package/dist/application/workspace.js.map +1 -1
  314. package/dist/cli/doctor-command.js +6 -2
  315. package/dist/cli/doctor-command.js.map +1 -1
  316. package/dist/cli/init-authentication.d.ts +4 -1
  317. package/dist/cli/init-authentication.js +28 -33
  318. package/dist/cli/init-authentication.js.map +1 -1
  319. package/dist/cli/init-command.js +3 -3
  320. package/dist/cli/init-command.js.map +1 -1
  321. package/dist/cli/main.constants.d.ts +50 -13
  322. package/dist/cli/main.constants.js +70 -8
  323. package/dist/cli/main.constants.js.map +1 -1
  324. package/dist/cli/main.js +2 -1
  325. package/dist/cli/main.js.map +1 -1
  326. package/dist/cli/scaffold-files.js +1 -1
  327. package/dist/cli/scaffold-files.js.map +1 -1
  328. package/dist/cli/scaffold-validation.js +29 -22
  329. package/dist/cli/scaffold-validation.js.map +1 -1
  330. package/dist/cli/scaffold.constants.d.ts +0 -1
  331. package/dist/cli/scaffold.constants.js +6 -2
  332. package/dist/cli/scaffold.constants.js.map +1 -1
  333. package/dist/cli/scaffold.types.d.ts +8 -2
  334. package/dist/cli/scaffold.types.js.map +1 -1
  335. package/dist/cli/starters.js +1 -3
  336. package/dist/cli/starters.js.map +1 -1
  337. package/dist/domain/agent-observation.d.ts +4 -0
  338. package/dist/domain/agent-observation.js +27 -0
  339. package/dist/domain/agent-observation.js.map +1 -0
  340. package/dist/domain/agent.types.d.ts +122 -14
  341. package/dist/domain/agent.types.js.map +1 -1
  342. package/dist/domain/authentication.constants.d.ts +3 -0
  343. package/dist/domain/authentication.constants.js +11 -0
  344. package/dist/domain/authentication.constants.js.map +1 -0
  345. package/dist/domain/authentication.d.ts +3 -0
  346. package/dist/domain/authentication.js +22 -0
  347. package/dist/domain/authentication.js.map +1 -0
  348. package/dist/domain/authentication.types.d.ts +5 -0
  349. package/dist/domain/authentication.types.js +2 -0
  350. package/dist/domain/authentication.types.js.map +1 -0
  351. package/dist/domain/harness.d.ts +2 -2
  352. package/dist/domain/harness.js +6 -0
  353. package/dist/domain/harness.js.map +1 -1
  354. package/dist/domain/harness.types.d.ts +4 -3
  355. package/dist/domain/harness.types.js.map +1 -1
  356. package/dist/domain/model.types.d.ts +8 -0
  357. package/dist/domain/model.types.js.map +1 -1
  358. package/dist/domain/observation.constants.d.ts +8 -0
  359. package/dist/domain/observation.constants.js +9 -0
  360. package/dist/domain/observation.constants.js.map +1 -0
  361. package/dist/domain/observation.d.ts +2 -0
  362. package/dist/domain/observation.js +190 -0
  363. package/dist/domain/observation.js.map +1 -0
  364. package/dist/domain/observation.types.d.ts +84 -0
  365. package/dist/domain/observation.types.js +2 -0
  366. package/dist/domain/observation.types.js.map +1 -0
  367. package/dist/domain/observed-operation.d.ts +2 -0
  368. package/dist/domain/observed-operation.js +30 -0
  369. package/dist/domain/observed-operation.js.map +1 -0
  370. package/dist/domain/sandbox.types.d.ts +2 -0
  371. package/dist/domain/sandbox.types.js.map +1 -1
  372. package/dist/domain/subagent.constants.d.ts +13 -0
  373. package/dist/domain/subagent.constants.js +9 -0
  374. package/dist/domain/subagent.constants.js.map +1 -0
  375. package/dist/domain/subagent.d.ts +4 -0
  376. package/dist/domain/subagent.js +28 -0
  377. package/dist/domain/subagent.js.map +1 -0
  378. package/dist/domain/subagent.types.d.ts +13 -0
  379. package/dist/domain/subagent.types.js +2 -0
  380. package/dist/domain/subagent.types.js.map +1 -0
  381. package/dist/domain/transcript.types.d.ts +2 -0
  382. package/dist/domain/transcript.types.js.map +1 -1
  383. package/dist/domain/usage.d.ts +1 -0
  384. package/dist/domain/usage.js +16 -0
  385. package/dist/domain/usage.js.map +1 -1
  386. package/dist/domain/workflow/budget.d.ts +7 -3
  387. package/dist/domain/workflow/budget.js +26 -0
  388. package/dist/domain/workflow/budget.js.map +1 -1
  389. package/dist/domain/workflow/budget.types.d.ts +1 -1
  390. package/dist/domain/workflow/budget.types.js.map +1 -1
  391. package/dist/domain/workflow/checkpoint-validation.js +7 -1
  392. package/dist/domain/workflow/checkpoint-validation.js.map +1 -1
  393. package/dist/domain/workflow/checkpoint.js +3 -0
  394. package/dist/domain/workflow/checkpoint.js.map +1 -1
  395. package/dist/domain/workflow/gate-validation.js +14 -1
  396. package/dist/domain/workflow/gate-validation.js.map +1 -1
  397. package/dist/domain/workflow/gates.d.ts +1 -1
  398. package/dist/domain/workflow/gates.js +52 -4
  399. package/dist/domain/workflow/gates.js.map +1 -1
  400. package/dist/domain/workflow/gates.types.d.ts +15 -1
  401. package/dist/domain/workflow/gates.types.js.map +1 -1
  402. package/dist/domain/workflow/idempotency.d.ts +1 -0
  403. package/dist/domain/workflow/idempotency.js +7 -0
  404. package/dist/domain/workflow/idempotency.js.map +1 -0
  405. package/dist/domain/workflow/retry.constants.d.ts +2 -0
  406. package/dist/domain/workflow/retry.constants.js +3 -0
  407. package/dist/domain/workflow/retry.constants.js.map +1 -0
  408. package/dist/domain/workflow/retry.d.ts +4 -0
  409. package/dist/domain/workflow/retry.js +49 -0
  410. package/dist/domain/workflow/retry.js.map +1 -0
  411. package/dist/domain/workflow/task-runner.js +9 -5
  412. package/dist/domain/workflow/task-runner.js.map +1 -1
  413. package/dist/domain/workflow/task.js +6 -6
  414. package/dist/domain/workflow/task.js.map +1 -1
  415. package/dist/domain/workflow/workflow-scheduler.js +110 -72
  416. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  417. package/dist/domain/workflow/workflow-state.js +28 -12
  418. package/dist/domain/workflow/workflow-state.js.map +1 -1
  419. package/dist/domain/workflow.d.ts +1 -1
  420. package/dist/domain/workflow.js +1 -1
  421. package/dist/domain/workflow.js.map +1 -1
  422. package/dist/domain/workflow.types.d.ts +13 -2
  423. package/dist/domain/workflow.types.js.map +1 -1
  424. package/dist/index.d.ts +16 -11
  425. package/dist/index.js +7 -4
  426. package/dist/index.js.map +1 -1
  427. package/dist/infrastructure/conversations/capture.js +10 -0
  428. package/dist/infrastructure/conversations/capture.js.map +1 -1
  429. package/dist/infrastructure/conversations/harness-transcript.js +6 -0
  430. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -1
  431. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +2 -0
  432. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -1
  433. package/dist/infrastructure/conversations/layout.js +2 -0
  434. package/dist/infrastructure/conversations/layout.js.map +1 -1
  435. package/dist/infrastructure/conversations/locate.js +7 -1
  436. package/dist/infrastructure/conversations/locate.js.map +1 -1
  437. package/dist/infrastructure/conversations/native-store.js +8 -1
  438. package/dist/infrastructure/conversations/native-store.js.map +1 -1
  439. package/dist/infrastructure/conversations/paths.js +3 -0
  440. package/dist/infrastructure/conversations/paths.js.map +1 -1
  441. package/dist/infrastructure/conversations/restore.js +7 -0
  442. package/dist/infrastructure/conversations/restore.js.map +1 -1
  443. package/dist/infrastructure/conversations/session-bundle.constants.d.ts +5 -0
  444. package/dist/infrastructure/conversations/session-bundle.constants.js +173 -0
  445. package/dist/infrastructure/conversations/session-bundle.constants.js.map +1 -0
  446. package/dist/infrastructure/conversations/session-bundle.d.ts +6 -0
  447. package/dist/infrastructure/conversations/session-bundle.js +98 -0
  448. package/dist/infrastructure/conversations/session-bundle.js.map +1 -0
  449. package/dist/infrastructure/conversations/session-bundle.types.d.ts +1 -0
  450. package/dist/infrastructure/conversations/session-bundle.types.js +2 -0
  451. package/dist/infrastructure/conversations/session-bundle.types.js.map +1 -0
  452. package/dist/infrastructure/conversations.js +4 -2
  453. package/dist/infrastructure/conversations.js.map +1 -1
  454. package/dist/infrastructure/conversations.types.d.ts +1 -1
  455. package/dist/infrastructure/conversations.types.js.map +1 -1
  456. package/dist/infrastructure/custom-reporter.js +32 -24
  457. package/dist/infrastructure/custom-reporter.js.map +1 -1
  458. package/dist/infrastructure/custom-reporter.types.d.ts +2 -0
  459. package/dist/infrastructure/custom-reporter.types.js.map +1 -1
  460. package/dist/infrastructure/git/git.constants.d.ts +1 -1
  461. package/dist/infrastructure/git/git.constants.js +1 -0
  462. package/dist/infrastructure/git/git.constants.js.map +1 -1
  463. package/dist/infrastructure/git/workspace-lease.js +4 -3
  464. package/dist/infrastructure/git/workspace-lease.js.map +1 -1
  465. package/dist/infrastructure/git/workspace.js +7 -6
  466. package/dist/infrastructure/git/workspace.js.map +1 -1
  467. package/dist/infrastructure/git/workspace.types.d.ts +1 -0
  468. package/dist/infrastructure/git/workspace.types.js.map +1 -1
  469. package/dist/infrastructure/host-credentials.constants.d.ts +1 -0
  470. package/dist/infrastructure/host-credentials.constants.js +2 -0
  471. package/dist/infrastructure/host-credentials.constants.js.map +1 -0
  472. package/dist/infrastructure/host-credentials.d.ts +4 -0
  473. package/dist/infrastructure/host-credentials.js +89 -0
  474. package/dist/infrastructure/host-credentials.js.map +1 -0
  475. package/dist/infrastructure/inspection-path.js +4 -3
  476. package/dist/infrastructure/inspection-path.js.map +1 -1
  477. package/dist/infrastructure/journal.constants.js +10 -1
  478. package/dist/infrastructure/journal.constants.js.map +1 -1
  479. package/dist/infrastructure/journal.d.ts +1 -1
  480. package/dist/infrastructure/journal.js +8 -75
  481. package/dist/infrastructure/journal.js.map +1 -1
  482. package/dist/infrastructure/journal.types.d.ts +2 -4
  483. package/dist/infrastructure/journal.types.js.map +1 -1
  484. package/dist/infrastructure/local-transport.js +9 -4
  485. package/dist/infrastructure/local-transport.js.map +1 -1
  486. package/dist/infrastructure/opentelemetry-dispatch.d.ts +3 -3
  487. package/dist/infrastructure/opentelemetry-dispatch.js +5 -4
  488. package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -1
  489. package/dist/infrastructure/opentelemetry-observation.d.ts +5 -0
  490. package/dist/infrastructure/opentelemetry-observation.js +59 -0
  491. package/dist/infrastructure/opentelemetry-observation.js.map +1 -0
  492. package/dist/infrastructure/opentelemetry.js +15 -1
  493. package/dist/infrastructure/opentelemetry.js.map +1 -1
  494. package/dist/infrastructure/opentelemetry.types.d.ts +9 -1
  495. package/dist/infrastructure/opentelemetry.types.js.map +1 -1
  496. package/dist/infrastructure/reporter.d.ts +2 -2
  497. package/dist/infrastructure/reporter.js +5 -1
  498. package/dist/infrastructure/reporter.js.map +1 -1
  499. package/dist/infrastructure/repository-transport.constants.d.ts +1 -0
  500. package/dist/infrastructure/repository-transport.constants.js +2 -0
  501. package/dist/infrastructure/repository-transport.constants.js.map +1 -0
  502. package/dist/infrastructure/repository-transport.d.ts +2 -0
  503. package/dist/infrastructure/repository-transport.js +9 -0
  504. package/dist/infrastructure/repository-transport.js.map +1 -0
  505. package/dist/infrastructure/resource-activity-inspection.js +19 -24
  506. package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
  507. package/dist/infrastructure/resource-activity.constants.d.ts +0 -1
  508. package/dist/infrastructure/resource-activity.constants.js +0 -1
  509. package/dist/infrastructure/resource-activity.constants.js.map +1 -1
  510. package/dist/infrastructure/resource-activity.js +20 -83
  511. package/dist/infrastructure/resource-activity.js.map +1 -1
  512. package/dist/infrastructure/s3-transport.constants.d.ts +2 -0
  513. package/dist/infrastructure/s3-transport.constants.js +3 -0
  514. package/dist/infrastructure/s3-transport.constants.js.map +1 -0
  515. package/dist/infrastructure/s3-transport.js +57 -3
  516. package/dist/infrastructure/s3-transport.js.map +1 -1
  517. package/dist/infrastructure/s3-transport.types.d.ts +1 -0
  518. package/dist/infrastructure/s3-transport.types.js.map +1 -1
  519. package/dist/infrastructure/speculation-store.constants.d.ts +3 -0
  520. package/dist/infrastructure/speculation-store.constants.js +2 -0
  521. package/dist/infrastructure/speculation-store.constants.js.map +1 -0
  522. package/dist/infrastructure/speculation-store.d.ts +4 -0
  523. package/dist/infrastructure/speculation-store.js +73 -0
  524. package/dist/infrastructure/speculation-store.js.map +1 -0
  525. package/dist/infrastructure/speculation-store.types.d.ts +12 -0
  526. package/dist/infrastructure/speculation-store.types.js +2 -0
  527. package/dist/infrastructure/speculation-store.types.js.map +1 -0
  528. package/dist/infrastructure/storage-inventory.constants.js +1 -0
  529. package/dist/infrastructure/storage-inventory.constants.js.map +1 -1
  530. package/dist/infrastructure/storage-inventory.types.d.ts +1 -1
  531. package/dist/infrastructure/storage-inventory.types.js.map +1 -1
  532. package/dist/infrastructure/storage-reservations.types.d.ts +0 -8
  533. package/dist/infrastructure/storage-reservations.types.js.map +1 -1
  534. package/dist/infrastructure/task-queue-bullmq-resources.js +3 -0
  535. package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -1
  536. package/dist/infrastructure/task-queue-http.js +29 -4
  537. package/dist/infrastructure/task-queue-http.js.map +1 -1
  538. package/dist/infrastructure/task-queue-http.types.d.ts +2 -2
  539. package/dist/infrastructure/task-queue-http.types.js.map +1 -1
  540. package/dist/infrastructure/transport-conversations.js +2 -0
  541. package/dist/infrastructure/transport-conversations.js.map +1 -1
  542. package/dist/infrastructure/transport-journal.d.ts +1 -1
  543. package/dist/infrastructure/transport-journal.js +8 -2
  544. package/dist/infrastructure/transport-journal.js.map +1 -1
  545. package/dist/infrastructure/transport-reservations.d.ts +1 -1
  546. package/dist/infrastructure/transport-reservations.js +14 -8
  547. package/dist/infrastructure/transport-reservations.js.map +1 -1
  548. package/dist/infrastructure/workflow-decision-signature.constants.d.ts +4 -0
  549. package/dist/infrastructure/workflow-decision-signature.constants.js +5 -0
  550. package/dist/infrastructure/workflow-decision-signature.constants.js.map +1 -0
  551. package/dist/infrastructure/workflow-decision-signature.d.ts +4 -0
  552. package/dist/infrastructure/workflow-decision-signature.js +83 -0
  553. package/dist/infrastructure/workflow-decision-signature.js.map +1 -0
  554. package/dist/infrastructure/workflow-decision-signature.types.d.ts +16 -0
  555. package/dist/infrastructure/workflow-decision-signature.types.js +2 -0
  556. package/dist/infrastructure/workflow-decision-signature.types.js.map +1 -0
  557. package/dist/providers/agents.d.ts +7 -2
  558. package/dist/providers/agents.js +4 -1
  559. package/dist/providers/agents.js.map +1 -1
  560. package/dist/providers/antigravity-install.constants.d.ts +2 -0
  561. package/dist/providers/antigravity-install.constants.js +28 -0
  562. package/dist/providers/antigravity-install.constants.js.map +1 -0
  563. package/dist/providers/antigravity-install.d.ts +2 -0
  564. package/dist/providers/antigravity-install.js +29 -0
  565. package/dist/providers/antigravity-install.js.map +1 -0
  566. package/dist/providers/antigravity-install.types.d.ts +4 -0
  567. package/dist/providers/antigravity-install.types.js +2 -0
  568. package/dist/providers/antigravity-install.types.js.map +1 -0
  569. package/dist/providers/container-recovery.d.ts +4 -0
  570. package/dist/providers/container-recovery.js +28 -0
  571. package/dist/providers/container-recovery.js.map +1 -0
  572. package/dist/providers/container.js +8 -0
  573. package/dist/providers/container.js.map +1 -1
  574. package/dist/providers/daytona-network.constants.d.ts +5 -0
  575. package/dist/providers/daytona-network.constants.js +8 -0
  576. package/dist/providers/daytona-network.constants.js.map +1 -0
  577. package/dist/providers/daytona-network.d.ts +4 -0
  578. package/dist/providers/daytona-network.js +33 -0
  579. package/dist/providers/daytona-network.js.map +1 -0
  580. package/dist/providers/daytona.d.ts +1 -0
  581. package/dist/providers/daytona.js +9 -3
  582. package/dist/providers/daytona.js.map +1 -1
  583. package/dist/providers/daytona.types.d.ts +2 -0
  584. package/dist/providers/daytona.types.js.map +1 -1
  585. package/dist/providers/firecracker-command.js +1 -1
  586. package/dist/providers/firecracker-command.js.map +1 -1
  587. package/dist/providers/firecracker-jailer.constants.d.ts +9 -0
  588. package/dist/providers/firecracker-jailer.constants.js +10 -0
  589. package/dist/providers/firecracker-jailer.constants.js.map +1 -0
  590. package/dist/providers/firecracker-jailer.d.ts +4 -0
  591. package/dist/providers/firecracker-jailer.js +171 -0
  592. package/dist/providers/firecracker-jailer.js.map +1 -0
  593. package/dist/providers/firecracker-machine.js +30 -8
  594. package/dist/providers/firecracker-machine.js.map +1 -1
  595. package/dist/providers/firecracker.types.d.ts +16 -0
  596. package/dist/providers/firecracker.types.js.map +1 -1
  597. package/dist/providers/vercel-network.js +1 -1
  598. package/dist/providers/vercel-network.js.map +1 -1
  599. package/dist/providers/vercel.js +6 -3
  600. package/dist/providers/vercel.js.map +1 -1
  601. package/dist/providers/versions.constants.d.ts +3 -1
  602. package/dist/providers/versions.constants.js +3 -1
  603. package/dist/providers/versions.constants.js.map +1 -1
  604. package/package.json +3 -3
  605. package/dist/adapters/agents/gemini-adapter.d.ts +0 -3
  606. package/dist/adapters/agents/gemini-adapter.js +0 -34
  607. package/dist/adapters/agents/gemini-adapter.js.map +0 -1
  608. package/dist/adapters/agents/gemini-diagnostics.d.ts +0 -2
  609. package/dist/adapters/agents/gemini-diagnostics.js +0 -15
  610. package/dist/adapters/agents/gemini-diagnostics.js.map +0 -1
  611. package/dist/adapters/agents/gemini-events.d.ts +0 -2
  612. package/dist/adapters/agents/gemini-events.js +0 -50
  613. package/dist/adapters/agents/gemini-events.js.map +0 -1
  614. package/dist/adapters/agents/gemini-request.js +0 -23
  615. package/dist/adapters/agents/gemini-request.js.map +0 -1
  616. package/dist/adapters/agents/gemini.types.js +0 -2
  617. package/dist/adapters/agents/gemini.types.js.map +0 -1
  618. package/dist/infrastructure/artifact-store.d.ts +0 -3
  619. package/dist/infrastructure/artifact-store.js +0 -110
  620. package/dist/infrastructure/artifact-store.js.map +0 -1
  621. package/dist/infrastructure/artifact-store.types.d.ts +0 -6
  622. package/dist/infrastructure/artifact-store.types.js +0 -2
  623. package/dist/infrastructure/artifact-store.types.js.map +0 -1
  624. package/dist/infrastructure/journal-retention.constants.d.ts +0 -4
  625. package/dist/infrastructure/journal-retention.constants.js +0 -5
  626. package/dist/infrastructure/journal-retention.constants.js.map +0 -1
  627. package/dist/infrastructure/journal-retention.d.ts +0 -2
  628. package/dist/infrastructure/journal-retention.js +0 -51
  629. package/dist/infrastructure/journal-retention.js.map +0 -1
  630. package/dist/infrastructure/storage-mutation-lock.constants.d.ts +0 -5
  631. package/dist/infrastructure/storage-mutation-lock.constants.js +0 -6
  632. package/dist/infrastructure/storage-mutation-lock.constants.js.map +0 -1
  633. package/dist/infrastructure/storage-mutation-lock.d.ts +0 -1
  634. package/dist/infrastructure/storage-mutation-lock.js +0 -21
  635. package/dist/infrastructure/storage-mutation-lock.js.map +0 -1
  636. package/dist/infrastructure/storage-reservations.constants.d.ts +0 -4
  637. package/dist/infrastructure/storage-reservations.constants.js +0 -5
  638. package/dist/infrastructure/storage-reservations.constants.js.map +0 -1
  639. package/dist/infrastructure/storage-reservations.d.ts +0 -2
  640. package/dist/infrastructure/storage-reservations.js +0 -150
  641. package/dist/infrastructure/storage-reservations.js.map +0 -1
  642. package/dist/infrastructure/workflow-checkpoint.d.ts +0 -3
  643. package/dist/infrastructure/workflow-checkpoint.js +0 -84
  644. package/dist/infrastructure/workflow-checkpoint.js.map +0 -1
  645. package/dist/infrastructure/workflow-checkpoint.types.d.ts +0 -6
  646. package/dist/infrastructure/workflow-checkpoint.types.js +0 -2
  647. package/dist/infrastructure/workflow-checkpoint.types.js.map +0 -1
@@ -0,0 +1,173 @@
1
+ export const sessionBundleLimits = Object.freeze({
2
+ bytes: 64 * 1024 * 1024,
3
+ files: 4096,
4
+ });
5
+ export const sessionBundleScript = String.raw `
6
+ const fs = require('node:fs/promises');
7
+ const path = require('node:path');
8
+ const { createHash, randomUUID } = require('node:crypto');
9
+ const [mode, format, id, home, cwd, bundleFile, maxBytesText, maxFilesText] = process.argv.slice(1);
10
+ const maxBytes = Number(maxBytesText), maxFiles = Number(maxFilesText);
11
+ function check(ok, message) { if (!ok) throw new Error(message); }
12
+ check(format === 'copilot' || format === 'kimi', 'Unsupported native session format');
13
+ check(/^[A-Za-z0-9_-]+$/.test(id), 'Invalid conversation identifier');
14
+ const base = format === 'kimi'
15
+ ? (process.env.KIMI_CODE_HOME || path.join(home, '.kimi-code'))
16
+ : (process.env.COPILOT_HOME || path.join(home, '.copilot'));
17
+ const sessions = path.join(base, format === 'kimi' ? 'sessions' : 'session-state');
18
+ async function entries(dir) {
19
+ try { return await fs.readdir(dir, { withFileTypes: true }); }
20
+ catch (error) { if (error.code === 'ENOENT') return []; throw error; }
21
+ }
22
+ async function safe(file) {
23
+ for (let at = file;; at = path.dirname(at)) {
24
+ const info = await fs.lstat(at).catch(error => { if (error.code === 'ENOENT') return; throw error; });
25
+ check(!info?.isSymbolicLink(), 'Native session paths must not traverse symlinks');
26
+ if (at === path.dirname(at)) break;
27
+ }
28
+ }
29
+ async function locate() {
30
+ await safe(sessions);
31
+ if (format === 'copilot') return path.join(sessions, id);
32
+ const found = [];
33
+ for (const bucket of await entries(sessions)) {
34
+ if (!bucket.isDirectory()) continue;
35
+ const candidate = path.join(sessions, bucket.name, id);
36
+ const info = await fs.lstat(candidate).catch(error => { if (error.code === 'ENOENT') return; throw error; });
37
+ if (info) { check(info.isDirectory(), 'Invalid native session directory'); found.push(candidate); }
38
+ }
39
+ check(found.length === 1, 'Kimi session is missing or ambiguous');
40
+ return found[0];
41
+ }
42
+ function selected(name) {
43
+ if (format === 'copilot') return /^(?:(?:events\.jsonl|workspace\.yaml|plan\.md)$|(?:checkpoints|files)(?:\/|$))/.test(name);
44
+ return !/^(logs|tasks|cron|notify)(\/|$)/.test(name) && !/(^|\/)[^/]*\.lock$/.test(name);
45
+ }
46
+ function validName(name) {
47
+ return typeof name === 'string' && name.length > 0 && !name.includes('\\') && !name.includes('\0') &&
48
+ !path.isAbsolute(name) && !name.split('/').some(p => !p || p === '.' || p === '..' || p.toLowerCase() === '.git');
49
+ }
50
+ function validate(bundle) {
51
+ check(bundle && bundle.version === 1 && bundle.format === format && bundle.id === id && typeof bundle.source === 'string' && Array.isArray(bundle.files), 'Invalid native session bundle');
52
+ check(bundle.files.length > 0, 'Native session is missing or incomplete');
53
+ check(bundle.files.length <= maxFiles, 'Native session file limit exceeded');
54
+ let bytes = 0;
55
+ const names = new Set();
56
+ for (const file of bundle.files) {
57
+ check(file && validName(file.path) && selected(file.path) && !names.has(file.path) && typeof file.data === 'string', 'Invalid native session entry');
58
+ const data = Buffer.from(file.data, 'base64');
59
+ check(data.toString('base64') === file.data, 'Invalid native session encoding');
60
+ bytes += data.length;
61
+ check(bytes <= maxBytes, 'Native session byte limit exceeded');
62
+ names.add(file.path);
63
+ }
64
+ const required = format === 'kimi' ? ['state.json', 'agents/main/wire.jsonl'] : ['events.jsonl', 'workspace.yaml'];
65
+ check(required.every(name => names.has(name)), 'Native session is incomplete or uses an unsupported format');
66
+ if (format === 'kimi') {
67
+ const meta = JSON.parse(Buffer.from(bundle.files.find(f => f.path === 'state.json').data, 'base64'));
68
+ check(meta.version === 2 && meta.id === id && typeof meta.cwd === 'string' && meta.agents && typeof meta.agents === 'object', 'Unsupported Kimi session metadata');
69
+ }
70
+ return bundle;
71
+ }
72
+ function workDirKey(dir) {
73
+ const normalized = dir.replace(/\\/g, '/').replace(/\/+$/, '');
74
+ let slug = normalized.split('/').pop().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40).replace(/^-+|-+$/g, '');
75
+ if (!slug || slug === '.' || slug === '..') slug = 'workspace';
76
+ return 'wd_' + slug + '_' + createHash('sha256').update(normalized).digest('hex').slice(0, 12);
77
+ }
78
+ async function capture() {
79
+ const source = await locate();
80
+ await safe(source);
81
+ const files = [];
82
+ let bytes = 0;
83
+ async function walk(dir, prefix = '') {
84
+ for (const entry of await entries(dir)) {
85
+ const name = prefix + entry.name;
86
+ if (!selected(name)) continue;
87
+ check(validName(name) && !entry.isSymbolicLink(), 'Unsafe native session entry');
88
+ if (entry.isDirectory()) { await walk(path.join(dir, entry.name), name + '/'); continue; }
89
+ check(entry.isFile(), 'Unsupported native session entry');
90
+ const file = path.join(dir, entry.name);
91
+ const before = await fs.stat(file);
92
+ bytes += before.size;
93
+ check(bytes <= maxBytes && files.length < maxFiles, 'Native session limits exceeded');
94
+ const data = await fs.readFile(file);
95
+ const after = await fs.stat(file);
96
+ check(before.size === data.length && before.mtimeMs === after.mtimeMs, 'Native session changed during capture');
97
+ files.push({ path: name, data: data.toString('base64') });
98
+ }
99
+ }
100
+ await walk(source);
101
+ const bundle = validate({ version: 1, format, id, source, files });
102
+ await safe(bundleFile);
103
+ await fs.mkdir(path.dirname(bundleFile), { recursive: true, mode: 0o700 });
104
+ await fs.writeFile(bundleFile, JSON.stringify(bundle), { mode: 0o600, flag: 'wx' });
105
+ }
106
+ async function readBundle() {
107
+ const info = await fs.stat(bundleFile);
108
+ check(info.size <= maxBytes * 2, 'Native session bundle exceeds byte limit');
109
+ return validate(JSON.parse(await fs.readFile(bundleFile, 'utf8')));
110
+ }
111
+ async function restore() {
112
+ const bundle = await readBundle();
113
+ const target = format === 'kimi' ? path.join(sessions, workDirKey(cwd), id) : path.join(sessions, id);
114
+ await safe(target);
115
+ if (format === 'kimi') {
116
+ for (const bucket of await entries(sessions)) {
117
+ if (!bucket.isDirectory()) continue;
118
+ const candidate = path.join(sessions, bucket.name, id);
119
+ if (candidate !== target && await fs.lstat(candidate).catch(error => { if (error.code === 'ENOENT') return; throw error; }))
120
+ throw new Error('Kimi session already exists under another workspace; restore in a private sandbox home');
121
+ }
122
+ }
123
+ await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });
124
+ const temporary = await fs.mkdtemp(path.join(path.dirname(target), '.outpost-session-'));
125
+ function relocate(text, name) {
126
+ if (format === 'copilot' && name === 'workspace.yaml')
127
+ return text.replace(/^(cwd|git_root):.*$/gm, (_, key) => key + ': ' + JSON.stringify(cwd));
128
+ if (format === 'kimi' && name === 'state.json') {
129
+ const meta = JSON.parse(text);
130
+ meta.cwd = cwd;
131
+ for (const [agent, value] of Object.entries(meta.agents)) {
132
+ check(/^[A-Za-z0-9_-]+$/.test(agent) && value && typeof value === 'object', 'Invalid Kimi agent metadata');
133
+ value.homedir = path.join(target, 'agents', agent);
134
+ }
135
+ return JSON.stringify(meta);
136
+ }
137
+ if (format === 'copilot' && name === 'events.jsonl')
138
+ return text.split('\n').map(line => {
139
+ if (!line.trim()) return line;
140
+ const event = JSON.parse(line);
141
+ if (event.type === 'session.start' && event.data?.context) {
142
+ event.data.context.cwd = cwd;
143
+ if (event.data.context.gitRoot) event.data.context.gitRoot = cwd;
144
+ }
145
+ return JSON.stringify(event);
146
+ }).join('\n');
147
+ return undefined;
148
+ }
149
+ let backup;
150
+ try {
151
+ for (const entry of bundle.files) {
152
+ const file = path.join(temporary, entry.path);
153
+ await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
154
+ const data = Buffer.from(entry.data, 'base64');
155
+ const textFile = format === 'kimi' ? entry.path === 'state.json' : ['events.jsonl', 'workspace.yaml'].includes(entry.path);
156
+ const moved = textFile ? relocate(data.toString('utf8'), entry.path) : undefined;
157
+ await fs.writeFile(file, moved === undefined ? data : moved, { mode: 0o600, flag: 'wx' });
158
+ }
159
+ if (await fs.lstat(target).catch(error => { if (error.code === 'ENOENT') return; throw error; })) {
160
+ backup = path.join(base, '.outpost-recovery', id + '-' + randomUUID());
161
+ await fs.mkdir(path.dirname(backup), { recursive: true, mode: 0o700 });
162
+ await safe(backup);
163
+ await fs.rename(target, backup);
164
+ }
165
+ await fs.rename(temporary, target);
166
+ } catch (error) {
167
+ if (backup) await fs.rename(backup, target);
168
+ throw error;
169
+ } finally { await fs.rm(temporary, { recursive: true, force: true }); }
170
+ }
171
+ ({ capture, restore, validate: readBundle }[mode]()).catch(error => { process.stderr.write(error.message + '\n'); process.exitCode = 1; });
172
+ `;
173
+ //# sourceMappingURL=session-bundle.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bundle.constants.js","sourceRoot":"","sources":["../../../src/infrastructure/conversations/session-bundle.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/C,KAAK,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IACvB,KAAK,EAAE,IAAI;CACZ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuK5C,CAAC","sourcesContent":["export const sessionBundleLimits = Object.freeze({\n bytes: 64 * 1024 * 1024,\n files: 4096,\n});\n\nexport const sessionBundleScript = String.raw`\nconst fs = require('node:fs/promises');\nconst path = require('node:path');\nconst { createHash, randomUUID } = require('node:crypto');\nconst [mode, format, id, home, cwd, bundleFile, maxBytesText, maxFilesText] = process.argv.slice(1);\nconst maxBytes = Number(maxBytesText), maxFiles = Number(maxFilesText);\nfunction check(ok, message) { if (!ok) throw new Error(message); }\ncheck(format === 'copilot' || format === 'kimi', 'Unsupported native session format');\ncheck(/^[A-Za-z0-9_-]+$/.test(id), 'Invalid conversation identifier');\nconst base = format === 'kimi'\n ? (process.env.KIMI_CODE_HOME || path.join(home, '.kimi-code'))\n : (process.env.COPILOT_HOME || path.join(home, '.copilot'));\nconst sessions = path.join(base, format === 'kimi' ? 'sessions' : 'session-state');\nasync function entries(dir) {\n try { return await fs.readdir(dir, { withFileTypes: true }); }\n catch (error) { if (error.code === 'ENOENT') return []; throw error; }\n}\nasync function safe(file) {\n for (let at = file;; at = path.dirname(at)) {\n const info = await fs.lstat(at).catch(error => { if (error.code === 'ENOENT') return; throw error; });\n check(!info?.isSymbolicLink(), 'Native session paths must not traverse symlinks');\n if (at === path.dirname(at)) break;\n }\n}\nasync function locate() {\n await safe(sessions);\n if (format === 'copilot') return path.join(sessions, id);\n const found = [];\n for (const bucket of await entries(sessions)) {\n if (!bucket.isDirectory()) continue;\n const candidate = path.join(sessions, bucket.name, id);\n const info = await fs.lstat(candidate).catch(error => { if (error.code === 'ENOENT') return; throw error; });\n if (info) { check(info.isDirectory(), 'Invalid native session directory'); found.push(candidate); }\n }\n check(found.length === 1, 'Kimi session is missing or ambiguous');\n return found[0];\n}\nfunction selected(name) {\n if (format === 'copilot') return /^(?:(?:events\\.jsonl|workspace\\.yaml|plan\\.md)$|(?:checkpoints|files)(?:\\/|$))/.test(name);\n return !/^(logs|tasks|cron|notify)(\\/|$)/.test(name) && !/(^|\\/)[^/]*\\.lock$/.test(name);\n}\nfunction validName(name) {\n return typeof name === 'string' && name.length > 0 && !name.includes('\\\\') && !name.includes('\\0') &&\n !path.isAbsolute(name) && !name.split('/').some(p => !p || p === '.' || p === '..' || p.toLowerCase() === '.git');\n}\nfunction validate(bundle) {\n check(bundle && bundle.version === 1 && bundle.format === format && bundle.id === id && typeof bundle.source === 'string' && Array.isArray(bundle.files), 'Invalid native session bundle');\n check(bundle.files.length > 0, 'Native session is missing or incomplete');\n check(bundle.files.length <= maxFiles, 'Native session file limit exceeded');\n let bytes = 0;\n const names = new Set();\n for (const file of bundle.files) {\n check(file && validName(file.path) && selected(file.path) && !names.has(file.path) && typeof file.data === 'string', 'Invalid native session entry');\n const data = Buffer.from(file.data, 'base64');\n check(data.toString('base64') === file.data, 'Invalid native session encoding');\n bytes += data.length;\n check(bytes <= maxBytes, 'Native session byte limit exceeded');\n names.add(file.path);\n }\n const required = format === 'kimi' ? ['state.json', 'agents/main/wire.jsonl'] : ['events.jsonl', 'workspace.yaml'];\n check(required.every(name => names.has(name)), 'Native session is incomplete or uses an unsupported format');\n if (format === 'kimi') {\n const meta = JSON.parse(Buffer.from(bundle.files.find(f => f.path === 'state.json').data, 'base64'));\n check(meta.version === 2 && meta.id === id && typeof meta.cwd === 'string' && meta.agents && typeof meta.agents === 'object', 'Unsupported Kimi session metadata');\n }\n return bundle;\n}\nfunction workDirKey(dir) {\n const normalized = dir.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n let slug = normalized.split('/').pop().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40).replace(/^-+|-+$/g, '');\n if (!slug || slug === '.' || slug === '..') slug = 'workspace';\n return 'wd_' + slug + '_' + createHash('sha256').update(normalized).digest('hex').slice(0, 12);\n}\nasync function capture() {\n const source = await locate();\n await safe(source);\n const files = [];\n let bytes = 0;\n async function walk(dir, prefix = '') {\n for (const entry of await entries(dir)) {\n const name = prefix + entry.name;\n if (!selected(name)) continue;\n check(validName(name) && !entry.isSymbolicLink(), 'Unsafe native session entry');\n if (entry.isDirectory()) { await walk(path.join(dir, entry.name), name + '/'); continue; }\n check(entry.isFile(), 'Unsupported native session entry');\n const file = path.join(dir, entry.name);\n const before = await fs.stat(file);\n bytes += before.size;\n check(bytes <= maxBytes && files.length < maxFiles, 'Native session limits exceeded');\n const data = await fs.readFile(file);\n const after = await fs.stat(file);\n check(before.size === data.length && before.mtimeMs === after.mtimeMs, 'Native session changed during capture');\n files.push({ path: name, data: data.toString('base64') });\n }\n }\n await walk(source);\n const bundle = validate({ version: 1, format, id, source, files });\n await safe(bundleFile);\n await fs.mkdir(path.dirname(bundleFile), { recursive: true, mode: 0o700 });\n await fs.writeFile(bundleFile, JSON.stringify(bundle), { mode: 0o600, flag: 'wx' });\n}\nasync function readBundle() {\n const info = await fs.stat(bundleFile);\n check(info.size <= maxBytes * 2, 'Native session bundle exceeds byte limit');\n return validate(JSON.parse(await fs.readFile(bundleFile, 'utf8')));\n}\nasync function restore() {\n const bundle = await readBundle();\n const target = format === 'kimi' ? path.join(sessions, workDirKey(cwd), id) : path.join(sessions, id);\n await safe(target);\n if (format === 'kimi') {\n for (const bucket of await entries(sessions)) {\n if (!bucket.isDirectory()) continue;\n const candidate = path.join(sessions, bucket.name, id);\n if (candidate !== target && await fs.lstat(candidate).catch(error => { if (error.code === 'ENOENT') return; throw error; }))\n throw new Error('Kimi session already exists under another workspace; restore in a private sandbox home');\n }\n }\n await fs.mkdir(path.dirname(target), { recursive: true, mode: 0o700 });\n const temporary = await fs.mkdtemp(path.join(path.dirname(target), '.outpost-session-'));\n function relocate(text, name) {\n if (format === 'copilot' && name === 'workspace.yaml')\n return text.replace(/^(cwd|git_root):.*$/gm, (_, key) => key + ': ' + JSON.stringify(cwd));\n if (format === 'kimi' && name === 'state.json') {\n const meta = JSON.parse(text);\n meta.cwd = cwd;\n for (const [agent, value] of Object.entries(meta.agents)) {\n check(/^[A-Za-z0-9_-]+$/.test(agent) && value && typeof value === 'object', 'Invalid Kimi agent metadata');\n value.homedir = path.join(target, 'agents', agent);\n }\n return JSON.stringify(meta);\n }\n if (format === 'copilot' && name === 'events.jsonl')\n return text.split('\\n').map(line => {\n if (!line.trim()) return line;\n const event = JSON.parse(line);\n if (event.type === 'session.start' && event.data?.context) {\n event.data.context.cwd = cwd;\n if (event.data.context.gitRoot) event.data.context.gitRoot = cwd;\n }\n return JSON.stringify(event);\n }).join('\\n');\n return undefined;\n }\n let backup;\n try {\n for (const entry of bundle.files) {\n const file = path.join(temporary, entry.path);\n await fs.mkdir(path.dirname(file), { recursive: true, mode: 0o700 });\n const data = Buffer.from(entry.data, 'base64');\n const textFile = format === 'kimi' ? entry.path === 'state.json' : ['events.jsonl', 'workspace.yaml'].includes(entry.path);\n const moved = textFile ? relocate(data.toString('utf8'), entry.path) : undefined;\n await fs.writeFile(file, moved === undefined ? data : moved, { mode: 0o600, flag: 'wx' });\n }\n if (await fs.lstat(target).catch(error => { if (error.code === 'ENOENT') return; throw error; })) {\n backup = path.join(base, '.outpost-recovery', id + '-' + randomUUID());\n await fs.mkdir(path.dirname(backup), { recursive: true, mode: 0o700 });\n await safe(backup);\n await fs.rename(target, backup);\n }\n await fs.rename(temporary, target);\n } catch (error) {\n if (backup) await fs.rename(backup, target);\n throw error;\n } finally { await fs.rm(temporary, { recursive: true, force: true }); }\n}\n({ capture, restore, validate: readBundle }[mode]()).catch(error => { process.stderr.write(error.message + '\\n'); process.exitCode = 1; });\n`;\n"]}
@@ -0,0 +1,6 @@
1
+ import type { ConversationStore } from "../../domain/conversation.types.ts";
2
+ import type { Command } from "../../domain/command.types.ts";
3
+ import type { SessionBundleFormat } from "./session-bundle.types.ts";
4
+ export declare function sessionBundleCommand(mode: "capture" | "restore" | "validate", format: SessionBundleFormat, id: string, home: string, cwd: string, file: string): Command;
5
+ export declare function sessionBundlePath(format: SessionBundleFormat, id: string, repository: string, home?: string): string;
6
+ export declare function sessionConversations(format: SessionBundleFormat): ConversationStore;
@@ -0,0 +1,98 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { access, mkdir, rename, rm } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join, posix } from "node:path";
5
+ import { invariant, OutpostError } from "../../domain/errors.js";
6
+ import { executeProcess, requireSuccess } from "../process.js";
7
+ import { validId } from "./identity.js";
8
+ import { sessionBundleLimits, sessionBundleScript, } from "./session-bundle.constants.js";
9
+ async function sessionOperation(command, invoke) {
10
+ const result = await invoke(command);
11
+ if (result.status !== 0)
12
+ throw new OutpostError("session", `Native session operation failed: ${result.stderr.trim() || "unknown failure"}`);
13
+ }
14
+ export function sessionBundleCommand(mode, format, id, home, cwd, file) {
15
+ validId(id);
16
+ return {
17
+ executable: "node",
18
+ arguments: [
19
+ "-e",
20
+ sessionBundleScript,
21
+ mode,
22
+ format,
23
+ id,
24
+ home,
25
+ cwd,
26
+ file,
27
+ String(sessionBundleLimits.bytes),
28
+ String(sessionBundleLimits.files),
29
+ ],
30
+ };
31
+ }
32
+ export function sessionBundlePath(format, id, repository, home) {
33
+ validId(id);
34
+ return join(home ?? repository, ".outpost", "conversations", format, `${id}.json`);
35
+ }
36
+ export function sessionConversations(format) {
37
+ return {
38
+ name: format,
39
+ async locate(id, repository, home) {
40
+ const file = sessionBundlePath(format, id, repository, home);
41
+ if (await access(file).then(() => true, () => false)) {
42
+ await sessionOperation(sessionBundleCommand("validate", format, id, home ?? homedir(), repository, file), executeProcess);
43
+ return { id, file, format };
44
+ }
45
+ const scratch = `${file}.${randomUUID()}`;
46
+ try {
47
+ await sessionOperation(sessionBundleCommand("capture", format, id, home ?? homedir(), repository, scratch), executeProcess);
48
+ await rename(scratch, file);
49
+ }
50
+ finally {
51
+ await rm(scratch, { force: true });
52
+ }
53
+ return { id, file, format };
54
+ },
55
+ async capture(id, context) {
56
+ const file = sessionBundlePath(format, id, context.repository, context.home);
57
+ const remote = posix.join(context.sandbox.home.replaceAll("\\", "/"), ".outpost", `session-${randomUUID()}.json`);
58
+ const scratch = `${file}.${randomUUID()}`;
59
+ await mkdir(dirname(file), { recursive: true, mode: 0o700 });
60
+ try {
61
+ await sessionOperation(sessionBundleCommand("capture", format, id, context.sandbox.home, context.sandbox.root, remote), context.sandbox.invoke);
62
+ await context.sandbox.download(remote, scratch);
63
+ await rename(scratch, file);
64
+ }
65
+ finally {
66
+ await rm(scratch, { force: true });
67
+ await requireSuccess({
68
+ executable: "node",
69
+ arguments: [
70
+ "-e",
71
+ "require('node:fs').rmSync(process.argv[1], {force:true})",
72
+ remote,
73
+ ],
74
+ }, context.sandbox.invoke);
75
+ }
76
+ return { id, file, format };
77
+ },
78
+ async restore(record, context) {
79
+ invariant(record.format === format, "Conversation format does not match its storage");
80
+ const remote = posix.join(context.sandbox.home.replaceAll("\\", "/"), ".outpost", `restore-${randomUUID()}.json`);
81
+ try {
82
+ await context.sandbox.upload(record.file, remote);
83
+ await sessionOperation(sessionBundleCommand("restore", format, record.id, context.sandbox.home, context.sandbox.root, remote), context.sandbox.invoke);
84
+ }
85
+ finally {
86
+ await requireSuccess({
87
+ executable: "node",
88
+ arguments: [
89
+ "-e",
90
+ "require('node:fs').rmSync(process.argv[1], {force:true})",
91
+ remote,
92
+ ],
93
+ }, context.sandbox.invoke);
94
+ }
95
+ },
96
+ };
97
+ }
98
+ //# sourceMappingURL=session-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bundle.js","sourceRoot":"","sources":["../../../src/infrastructure/conversations/session-bundle.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { access, mkdir, rename, rm } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, posix } from \"node:path\";\nimport type { ConversationStore } from \"../../domain/conversation.types.ts\";\nimport type { Command, CommandResult } from \"../../domain/command.types.ts\";\nimport { invariant, OutpostError } from \"../../domain/errors.ts\";\nimport { executeProcess, requireSuccess } from \"../process.ts\";\nimport { validId } from \"./identity.ts\";\nimport {\n sessionBundleLimits,\n sessionBundleScript,\n} from \"./session-bundle.constants.ts\";\nimport type { SessionBundleFormat } from \"./session-bundle.types.ts\";\n\nasync function sessionOperation(\n command: Command,\n invoke: (command: Command) => Promise<CommandResult>,\n): Promise<void> {\n const result = await invoke(command);\n if (result.status !== 0)\n throw new OutpostError(\n \"session\",\n `Native session operation failed: ${result.stderr.trim() || \"unknown failure\"}`,\n );\n}\n\nexport function sessionBundleCommand(\n mode: \"capture\" | \"restore\" | \"validate\",\n format: SessionBundleFormat,\n id: string,\n home: string,\n cwd: string,\n file: string,\n): Command {\n validId(id);\n return {\n executable: \"node\",\n arguments: [\n \"-e\",\n sessionBundleScript,\n mode,\n format,\n id,\n home,\n cwd,\n file,\n String(sessionBundleLimits.bytes),\n String(sessionBundleLimits.files),\n ],\n };\n}\n\nexport function sessionBundlePath(\n format: SessionBundleFormat,\n id: string,\n repository: string,\n home?: string,\n): string {\n validId(id);\n return join(\n home ?? repository,\n \".outpost\",\n \"conversations\",\n format,\n `${id}.json`,\n );\n}\n\nexport function sessionConversations(\n format: SessionBundleFormat,\n): ConversationStore {\n return {\n name: format,\n async locate(id, repository, home) {\n const file = sessionBundlePath(format, id, repository, home);\n if (\n await access(file).then(\n () => true,\n () => false,\n )\n ) {\n await sessionOperation(\n sessionBundleCommand(\n \"validate\",\n format,\n id,\n home ?? homedir(),\n repository,\n file,\n ),\n executeProcess,\n );\n return { id, file, format };\n }\n const scratch = `${file}.${randomUUID()}`;\n try {\n await sessionOperation(\n sessionBundleCommand(\n \"capture\",\n format,\n id,\n home ?? homedir(),\n repository,\n scratch,\n ),\n executeProcess,\n );\n await rename(scratch, file);\n } finally {\n await rm(scratch, { force: true });\n }\n return { id, file, format };\n },\n async capture(id, context) {\n const file = sessionBundlePath(\n format,\n id,\n context.repository,\n context.home,\n );\n const remote = posix.join(\n context.sandbox.home.replaceAll(\"\\\\\", \"/\"),\n \".outpost\",\n `session-${randomUUID()}.json`,\n );\n const scratch = `${file}.${randomUUID()}`;\n await mkdir(dirname(file), { recursive: true, mode: 0o700 });\n try {\n await sessionOperation(\n sessionBundleCommand(\n \"capture\",\n format,\n id,\n context.sandbox.home,\n context.sandbox.root,\n remote,\n ),\n context.sandbox.invoke,\n );\n await context.sandbox.download(remote, scratch);\n await rename(scratch, file);\n } finally {\n await rm(scratch, { force: true });\n await requireSuccess(\n {\n executable: \"node\",\n arguments: [\n \"-e\",\n \"require('node:fs').rmSync(process.argv[1], {force:true})\",\n remote,\n ],\n },\n context.sandbox.invoke,\n );\n }\n return { id, file, format };\n },\n async restore(record, context) {\n invariant(\n record.format === format,\n \"Conversation format does not match its storage\",\n );\n const remote = posix.join(\n context.sandbox.home.replaceAll(\"\\\\\", \"/\"),\n \".outpost\",\n `restore-${randomUUID()}.json`,\n );\n try {\n await context.sandbox.upload(record.file, remote);\n await sessionOperation(\n sessionBundleCommand(\n \"restore\",\n format,\n record.id,\n context.sandbox.home,\n context.sandbox.root,\n remote,\n ),\n context.sandbox.invoke,\n );\n } finally {\n await requireSuccess(\n {\n executable: \"node\",\n arguments: [\n \"-e\",\n \"require('node:fs').rmSync(process.argv[1], {force:true})\",\n remote,\n ],\n },\n context.sandbox.invoke,\n );\n }\n },\n };\n}\n"]}
@@ -0,0 +1 @@
1
+ export type SessionBundleFormat = "copilot" | "kimi";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-bundle.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-bundle.types.js","sourceRoot":"","sources":["../../../src/infrastructure/conversations/session-bundle.types.ts"],"names":[],"mappings":"","sourcesContent":["export type SessionBundleFormat = \"copilot\" | \"kimi\";\n"]}
@@ -29,8 +29,10 @@ export const conversations = {
29
29
  validId(id);
30
30
  return join(home, ".claude", "projects", projectKey(resolve(repository)), `${id}.jsonl`);
31
31
  },
32
- directory(format, repository, home = homedir()) {
33
- return conversationLayout(format).directory(repository, home);
32
+ directory(format, repository, home) {
33
+ if (format === "copilot" || format === "kimi")
34
+ return join(home ?? repository, ".outpost", "conversations", format);
35
+ return conversationLayout(format).directory(repository, home ?? homedir());
34
36
  },
35
37
  destination: remotePath,
36
38
  };
@@ -1 +1 @@
1
- {"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../src/infrastructure/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAOjE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE,sBAAsB;IACnC,MAAM,EAAE,mBAAmB;IAC3B,OAAO,EAAE,oBAAoB;IAC7B,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,kBAAkB;IAC3B,UAAU;IACV,UAAU,CAAC,EAAU,EAAE,UAAkB,EAAE,IAAI,GAAG,OAAO,EAAE;QACzD,OAAO,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAC/B,GAAG,EAAE,QAAQ,CACd,CAAC;IACJ,CAAC;IACD,SAAS,CACP,MAA0B,EAC1B,UAAkB,EAClB,IAAI,GAAG,OAAO,EAAE;QAEhB,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IACD,WAAW,EAAE,UAAU;CACxB,CAAC","sourcesContent":["import { transportConversations } from \"./transport-conversations.ts\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { ConversationFormat } from \"./conversations.types.ts\";\nimport { captureConversation } from \"./conversations/capture.ts\";\nimport { conversationLayout } from \"./conversations/layout.ts\";\nimport { locateConversation } from \"./conversations/locate.ts\";\nimport { harnessConversations } from \"./conversations/harness-store.ts\";\nimport { nativeConversations } from \"./conversations/native-store.ts\";\nimport { projectKey, remotePath, validId } from \"./conversations/paths.ts\";\nimport { relocateTranscript } from \"./conversations/relocate.ts\";\nimport { restoreConversation } from \"./conversations/restore.ts\";\n\nexport type {\n ConversationFormat,\n ConversationLocation,\n StoredConversationFormat,\n} from \"./conversations.types.ts\";\nexport {\n harnessConversations,\n harnessTranscriptPath,\n} from \"./conversations/harness-store.ts\";\nexport { captureConversation } from \"./conversations/capture.ts\";\nexport { locateConversation } from \"./conversations/locate.ts\";\nexport { nativeConversations } from \"./conversations/native-store.ts\";\nexport { projectKey } from \"./conversations/paths.ts\";\nexport { relocateTranscript } from \"./conversations/relocate.ts\";\nexport { restoreConversation } from \"./conversations/restore.ts\";\n\nexport const conversations = {\n transported: transportConversations,\n native: nativeConversations,\n harness: harnessConversations,\n locate: locateConversation,\n capture: captureConversation,\n restore: restoreConversation,\n rewrite: relocateTranscript,\n projectKey,\n claudePath(id: string, repository: string, home = homedir()): string {\n validId(id);\n return join(\n home,\n \".claude\",\n \"projects\",\n projectKey(resolve(repository)),\n `${id}.jsonl`,\n );\n },\n directory(\n format: ConversationFormat,\n repository: string,\n home = homedir(),\n ): string {\n return conversationLayout(format).directory(repository, home);\n },\n destination: remotePath,\n};\n"]}
1
+ {"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../src/infrastructure/conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAOjE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE,sBAAsB;IACnC,MAAM,EAAE,mBAAmB;IAC3B,OAAO,EAAE,oBAAoB;IAC7B,MAAM,EAAE,kBAAkB;IAC1B,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE,kBAAkB;IAC3B,UAAU;IACV,UAAU,CAAC,EAAU,EAAE,UAAkB,EAAE,IAAI,GAAG,OAAO,EAAE;QACzD,OAAO,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CACT,IAAI,EACJ,SAAS,EACT,UAAU,EACV,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAC/B,GAAG,EAAE,QAAQ,CACd,CAAC;IACJ,CAAC;IACD,SAAS,CACP,MAA0B,EAC1B,UAAkB,EAClB,IAAa;QAEb,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM;YAC3C,OAAO,IAAI,CAAC,IAAI,IAAI,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACvE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,WAAW,EAAE,UAAU;CACxB,CAAC","sourcesContent":["import { transportConversations } from \"./transport-conversations.ts\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { ConversationFormat } from \"./conversations.types.ts\";\nimport { captureConversation } from \"./conversations/capture.ts\";\nimport { conversationLayout } from \"./conversations/layout.ts\";\nimport { locateConversation } from \"./conversations/locate.ts\";\nimport { harnessConversations } from \"./conversations/harness-store.ts\";\nimport { nativeConversations } from \"./conversations/native-store.ts\";\nimport { projectKey, remotePath, validId } from \"./conversations/paths.ts\";\nimport { relocateTranscript } from \"./conversations/relocate.ts\";\nimport { restoreConversation } from \"./conversations/restore.ts\";\n\nexport type {\n ConversationFormat,\n ConversationLocation,\n StoredConversationFormat,\n} from \"./conversations.types.ts\";\nexport {\n harnessConversations,\n harnessTranscriptPath,\n} from \"./conversations/harness-store.ts\";\nexport { captureConversation } from \"./conversations/capture.ts\";\nexport { locateConversation } from \"./conversations/locate.ts\";\nexport { nativeConversations } from \"./conversations/native-store.ts\";\nexport { projectKey } from \"./conversations/paths.ts\";\nexport { relocateTranscript } from \"./conversations/relocate.ts\";\nexport { restoreConversation } from \"./conversations/restore.ts\";\n\nexport const conversations = {\n transported: transportConversations,\n native: nativeConversations,\n harness: harnessConversations,\n locate: locateConversation,\n capture: captureConversation,\n restore: restoreConversation,\n rewrite: relocateTranscript,\n projectKey,\n claudePath(id: string, repository: string, home = homedir()): string {\n validId(id);\n return join(\n home,\n \".claude\",\n \"projects\",\n projectKey(resolve(repository)),\n `${id}.jsonl`,\n );\n },\n directory(\n format: ConversationFormat,\n repository: string,\n home?: string,\n ): string {\n if (format === \"copilot\" || format === \"kimi\")\n return join(home ?? repository, \".outpost\", \"conversations\", format);\n return conversationLayout(format).directory(repository, home ?? homedir());\n },\n destination: remotePath,\n};\n"]}
@@ -1,4 +1,4 @@
1
- export type ConversationFormat = "claude" | "codex";
1
+ export type ConversationFormat = "claude" | "codex" | "copilot" | "kimi";
2
2
  export type StoredConversationFormat = ConversationFormat | "harness";
3
3
  export interface ConversationLocation {
4
4
  readonly id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"conversations.types.js","sourceRoot":"","sources":["../../src/infrastructure/conversations.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ConversationFormat = \"claude\" | \"codex\";\n\nexport type StoredConversationFormat = ConversationFormat | \"harness\";\n\nexport interface ConversationLocation {\n readonly id: string;\n readonly file: string;\n readonly format: ConversationFormat;\n}\n"]}
1
+ {"version":3,"file":"conversations.types.js","sourceRoot":"","sources":["../../src/infrastructure/conversations.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ConversationFormat = \"claude\" | \"codex\" | \"copilot\" | \"kimi\";\n\nexport type StoredConversationFormat = ConversationFormat | \"harness\";\n\nexport interface ConversationLocation {\n readonly id: string;\n readonly file: string;\n readonly format: ConversationFormat;\n}\n"]}
@@ -1,32 +1,40 @@
1
+ import { agentObservation } from "../domain/agent-observation.js";
2
+ import { createObservationHub } from "../domain/observation.js";
1
3
  export function createReporter(handlers, options = {}) {
2
- let pending = Promise.resolve();
3
- let failed = false;
4
- let failure;
4
+ const hub = createObservationHub({
5
+ ...(options.capacity === undefined ? {} : { capacity: options.capacity }),
6
+ ...(options.deliveryTimeoutMs === undefined
7
+ ? {}
8
+ : { deliveryTimeoutMs: options.deliveryTimeoutMs }),
9
+ sinks: [
10
+ {
11
+ async observe(value) {
12
+ const event = agentObservation(value);
13
+ if (!event)
14
+ return;
15
+ const handler = handlers[event.kind];
16
+ try {
17
+ await handler?.(event);
18
+ }
19
+ catch (error) {
20
+ try {
21
+ await options.onError?.(error, event);
22
+ }
23
+ catch { }
24
+ throw error;
25
+ }
26
+ },
27
+ },
28
+ ],
29
+ });
5
30
  const report = (event) => {
6
- const handler = handlers[event.kind];
7
- if (!handler)
8
- return;
9
- pending = pending.then(async () => {
10
- try {
11
- await handler(event);
12
- }
13
- catch (error) {
14
- if (!failed) {
15
- failed = true;
16
- failure = error;
17
- }
18
- try {
19
- await options.onError?.(error, event);
20
- }
21
- catch { }
22
- }
23
- });
31
+ hub.child({ pass: event.pass }).emit("agent", event);
24
32
  };
25
33
  return Object.assign(report, {
26
34
  async flush() {
27
- await pending;
28
- if (failed)
29
- throw failure;
35
+ await hub.flush();
36
+ if (hub.errors.length)
37
+ throw hub.errors[0];
30
38
  },
31
39
  });
32
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"custom-reporter.js","sourceRoot":"","sources":["../../src/infrastructure/custom-reporter.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,cAAc,CAC5B,QAA0B,EAC1B,UAAiC,EAAE;IAEnC,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAChC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,OAAgB,CAAC;IACrB,MAAM,MAAM,GAAG,CAAC,KAAuB,EAAQ,EAAE;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAC8B,CAAC;QAClE,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAChC,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,GAAG,IAAI,CAAC;oBACd,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC;gBACD,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBACxC,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAC3B,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC;YACd,IAAI,MAAM;gBAAE,MAAM,OAAO,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { AgentObservation } from \"../domain/agent.types.ts\";\nimport type {\n CustomReporter,\n CustomReporterOptions,\n ReporterHandlers,\n} from \"./custom-reporter.types.ts\";\n\nexport function createReporter(\n handlers: ReporterHandlers,\n options: CustomReporterOptions = {},\n): CustomReporter {\n let pending = Promise.resolve();\n let failed = false;\n let failure: unknown;\n const report = (event: AgentObservation): void => {\n const handler = handlers[event.kind] as\n ((event: AgentObservation) => void | Promise<void>) | undefined;\n if (!handler) return;\n pending = pending.then(async () => {\n try {\n await handler(event);\n } catch (error) {\n if (!failed) {\n failed = true;\n failure = error;\n }\n try {\n await options.onError?.(error, event);\n } catch {}\n }\n });\n };\n return Object.assign(report, {\n async flush() {\n await pending;\n if (failed) throw failure;\n },\n });\n}\n"]}
1
+ {"version":3,"file":"custom-reporter.js","sourceRoot":"","sources":["../../src/infrastructure/custom-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAQhE,MAAM,UAAU,cAAc,CAC5B,QAA0B,EAC1B,UAAiC,EAAE;IAEnC,MAAM,GAAG,GAAG,oBAAoB,CAAC;QAC/B,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzE,GAAG,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS;YACzC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACrD,KAAK,EAAE;YACL;gBACE,KAAK,CAAC,OAAO,CAAC,KAAK;oBACjB,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;oBACtC,IAAI,CAAC,KAAK;wBAAE,OAAO;oBACnB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAC8B,CAAC;oBAClE,IAAI,CAAC;wBACH,MAAM,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;oBACzB,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,IAAI,CAAC;4BACH,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;wBACxC,CAAC;wBAAC,MAAM,CAAC,CAAA,CAAC;wBACV,MAAM,KAAK,CAAC;oBACd,CAAC;gBACH,CAAC;aACF;SACF;KACF,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,CAAC,KAAuB,EAAQ,EAAE;QAC/C,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAC3B,KAAK,CAAC,KAAK;YACT,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM;gBAAE,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { agentObservation } from \"../domain/agent-observation.ts\";\nimport { createObservationHub } from \"../domain/observation.ts\";\nimport type { AgentObservation } from \"../domain/agent.types.ts\";\nimport type {\n CustomReporter,\n CustomReporterOptions,\n ReporterHandlers,\n} from \"./custom-reporter.types.ts\";\n\nexport function createReporter(\n handlers: ReporterHandlers,\n options: CustomReporterOptions = {},\n): CustomReporter {\n const hub = createObservationHub({\n ...(options.capacity === undefined ? {} : { capacity: options.capacity }),\n ...(options.deliveryTimeoutMs === undefined\n ? {}\n : { deliveryTimeoutMs: options.deliveryTimeoutMs }),\n sinks: [\n {\n async observe(value) {\n const event = agentObservation(value);\n if (!event) return;\n const handler = handlers[event.kind] as\n ((event: AgentObservation) => void | Promise<void>) | undefined;\n try {\n await handler?.(event);\n } catch (error) {\n try {\n await options.onError?.(error, event);\n } catch {}\n throw error;\n }\n },\n },\n ],\n });\n const report = (event: AgentObservation): void => {\n hub.child({ pass: event.pass }).emit(\"agent\", event);\n };\n return Object.assign(report, {\n async flush() {\n await hub.flush();\n if (hub.errors.length) throw hub.errors[0];\n },\n });\n}\n"]}
@@ -5,6 +5,8 @@ export type ReporterHandlers = {
5
5
  }>) => void | Promise<void>;
6
6
  };
7
7
  export interface CustomReporterOptions {
8
+ readonly capacity?: number;
9
+ readonly deliveryTimeoutMs?: number;
8
10
  readonly onError?: (error: unknown, event: AgentObservation) => void | Promise<void>;
9
11
  }
10
12
  export interface CustomReporter {
@@ -1 +1 @@
1
- {"version":3,"file":"custom-reporter.types.js","sourceRoot":"","sources":["../../src/infrastructure/custom-reporter.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentObservation } from \"../domain/agent.types.ts\";\n\nexport type ReporterHandlers = {\n readonly [Kind in AgentObservation[\"kind\"]]?: (\n event: Extract<AgentObservation, { kind: Kind }>,\n ) => void | Promise<void>;\n};\n\nexport interface CustomReporterOptions {\n readonly onError?: (\n error: unknown,\n event: AgentObservation,\n ) => void | Promise<void>;\n}\n\nexport interface CustomReporter {\n (event: AgentObservation): void;\n flush(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"custom-reporter.types.js","sourceRoot":"","sources":["../../src/infrastructure/custom-reporter.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentObservation } from \"../domain/agent.types.ts\";\n\nexport type ReporterHandlers = {\n readonly [Kind in AgentObservation[\"kind\"]]?: (\n event: Extract<AgentObservation, { kind: Kind }>,\n ) => void | Promise<void>;\n};\n\nexport interface CustomReporterOptions {\n readonly capacity?: number;\n readonly deliveryTimeoutMs?: number;\n readonly onError?: (\n error: unknown,\n event: AgentObservation,\n ) => void | Promise<void>;\n}\n\nexport interface CustomReporter {\n (event: AgentObservation): void;\n flush(): Promise<void>;\n}\n"]}
@@ -4,4 +4,4 @@ export declare const gitDefaults: Readonly<{
4
4
  hashLength: 12;
5
5
  labelLength: 48;
6
6
  }>;
7
- export declare const runtimeExclusions: readonly ["/.outpost/workspaces/", "/.outpost/locks/", "/.outpost/recovery/", "/.outpost/logs/", "/.outpost/conversations/"];
7
+ export declare const runtimeExclusions: readonly ["/.outpost/workspaces/", "/.outpost/locks/", "/.outpost/recovery/", "/.outpost/logs/", "/.outpost/storage/", "/.outpost/conversations/"];
@@ -9,6 +9,7 @@ export const runtimeExclusions = [
9
9
  "/.outpost/locks/",
10
10
  "/.outpost/recovery/",
11
11
  "/.outpost/logs/",
12
+ "/.outpost/storage/",
12
13
  "/.outpost/conversations/",
13
14
  ];
14
15
  //# sourceMappingURL=git.constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.constants.js","sourceRoot":"","sources":["../../../src/infrastructure/git/git.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,UAAU;IACvB,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,EAAE;CAChB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,uBAAuB;IACvB,kBAAkB;IAClB,qBAAqB;IACrB,iBAAiB;IACjB,0BAA0B;CAClB,CAAC","sourcesContent":["export const gitDefaults = Object.freeze({\n deadlineMs: 30_000,\n retainBytes: 16_777_216,\n hashLength: 12,\n labelLength: 48,\n});\nexport const runtimeExclusions = [\n \"/.outpost/workspaces/\",\n \"/.outpost/locks/\",\n \"/.outpost/recovery/\",\n \"/.outpost/logs/\",\n \"/.outpost/conversations/\",\n] as const;\n"]}
1
+ {"version":3,"file":"git.constants.js","sourceRoot":"","sources":["../../../src/infrastructure/git/git.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,UAAU;IACvB,UAAU,EAAE,EAAE;IACd,WAAW,EAAE,EAAE;CAChB,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,uBAAuB;IACvB,kBAAkB;IAClB,qBAAqB;IACrB,iBAAiB;IACjB,oBAAoB;IACpB,0BAA0B;CAClB,CAAC","sourcesContent":["export const gitDefaults = Object.freeze({\n deadlineMs: 30_000,\n retainBytes: 16_777_216,\n hashLength: 12,\n labelLength: 48,\n});\nexport const runtimeExclusions = [\n \"/.outpost/workspaces/\",\n \"/.outpost/locks/\",\n \"/.outpost/recovery/\",\n \"/.outpost/logs/\",\n \"/.outpost/storage/\",\n \"/.outpost/conversations/\",\n] as const;\n"]}
@@ -1,3 +1,4 @@
1
+ import { observedOperation } from "../../domain/observed-operation.js";
1
2
  import { join } from "node:path";
2
3
  import { OutpostError } from "../../domain/errors.js";
3
4
  import { inside } from "../files.js";
@@ -14,7 +15,7 @@ export function workspaceLease(record, options, unlock) {
14
15
  const current = (await git(repository, ["symbolic-ref", "--short", "HEAD"])).trim();
15
16
  if (current !== baseBranch)
16
17
  throw new OutpostError("conflict", "Host branch changed during the job", { expected: baseBranch, current, directory: workdir });
17
- const releaseMerge = await lock(repository, `merge:${baseBranch}`);
18
+ const releaseMerge = await observedOperation(options.observation, "git", "integration.lock", async () => lock(repository, `merge:${baseBranch}`));
18
19
  try {
19
20
  await git(repository, ["merge", "--no-edit", branch], options.limits?.mergeMs);
20
21
  }
@@ -22,7 +23,7 @@ export function workspaceLease(record, options, unlock) {
22
23
  throw new OutpostError("conflict", "Automatic integration failed; workspace retained", { directory: workdir, branch }, cause);
23
24
  }
24
25
  finally {
25
- await releaseMerge();
26
+ await observedOperation(options.observation, "git", "integration.unlock", async () => releaseMerge());
26
27
  }
27
28
  },
28
29
  dispose(preserve = false) {
@@ -57,7 +58,7 @@ export function workspaceLease(record, options, unlock) {
57
58
  return {};
58
59
  }
59
60
  finally {
60
- await unlock();
61
+ await observedOperation(options.observation, "git", "workspace.unlock", async () => unlock());
61
62
  }
62
63
  })();
63
64
  return disposal;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-lease.js","sourceRoot":"","sources":["../../../src/infrastructure/git/workspace-lease.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { OutpostError } from \"../../domain/errors.ts\";\nimport type {\n Disposal,\n WorkspaceRecord,\n} from \"../../domain/workspace.types.ts\";\nimport { inside } from \"../files.ts\";\nimport { git } from \"./command.ts\";\nimport { lock } from \"./lock.ts\";\nimport type {\n AcquireWorkspaceOptions,\n WorkspaceLease,\n} from \"./workspace.types.ts\";\n\nexport function workspaceLease(\n record: WorkspaceRecord,\n options: AcquireWorkspaceOptions,\n unlock: () => Promise<void>,\n): WorkspaceLease {\n const { policy, repository, baseBranch, branch, directory: workdir } = record;\n let disposal: Promise<Disposal> | undefined;\n return {\n ...record,\n async integrate() {\n if (policy.mode !== \"integrate\") return;\n const current = (\n await git(repository, [\"symbolic-ref\", \"--short\", \"HEAD\"])\n ).trim();\n if (current !== baseBranch)\n throw new OutpostError(\n \"conflict\",\n \"Host branch changed during the job\",\n { expected: baseBranch, current, directory: workdir },\n );\n const releaseMerge = await lock(repository, `merge:${baseBranch}`);\n try {\n await git(\n repository,\n [\"merge\", \"--no-edit\", branch],\n options.limits?.mergeMs,\n );\n } catch (cause) {\n throw new OutpostError(\n \"conflict\",\n \"Automatic integration failed; workspace retained\",\n { directory: workdir, branch },\n cause,\n );\n } finally {\n await releaseMerge();\n }\n },\n dispose(preserve = false) {\n if (disposal) return disposal;\n disposal = (async () => {\n try {\n if (policy.mode === \"current\") return {};\n if (preserve) return { retainedDirectory: workdir };\n const attached = await git(workdir, [\n \"symbolic-ref\",\n \"--quiet\",\n \"HEAD\",\n ]).catch(() => \"\");\n if (!attached.trim()) return { retainedDirectory: workdir };\n const dirty = await git(workdir, [\n \"status\",\n \"--porcelain\",\n \"--untracked-files=normal\",\n \"--ignored\",\n ]);\n if (dirty.trim()) return { retainedDirectory: workdir };\n if (!inside(join(repository, \".outpost\", \"workspaces\"), workdir))\n throw new OutpostError(\n \"workspace\",\n \"Refusing to remove an unmanaged workspace\",\n );\n await git(repository, [\"worktree\", \"remove\", workdir]);\n if (policy.mode === \"integrate\")\n await git(repository, [\"branch\", \"-d\", branch]).catch(\n () => undefined,\n );\n return {};\n } finally {\n await unlock();\n }\n })();\n return disposal;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"workspace-lease.js","sourceRoot":"","sources":["../../../src/infrastructure/git/workspace-lease.ts"],"names":[],"mappings":"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","sourcesContent":["import { observedOperation } from \"../../domain/observed-operation.ts\";\nimport { join } from \"node:path\";\nimport { OutpostError } from \"../../domain/errors.ts\";\nimport type {\n Disposal,\n WorkspaceRecord,\n} from \"../../domain/workspace.types.ts\";\nimport { inside } from \"../files.ts\";\nimport { git } from \"./command.ts\";\nimport { lock } from \"./lock.ts\";\nimport type {\n AcquireWorkspaceOptions,\n WorkspaceLease,\n} from \"./workspace.types.ts\";\n\nexport function workspaceLease(\n record: WorkspaceRecord,\n options: AcquireWorkspaceOptions,\n unlock: () => Promise<void>,\n): WorkspaceLease {\n const { policy, repository, baseBranch, branch, directory: workdir } = record;\n let disposal: Promise<Disposal> | undefined;\n return {\n ...record,\n async integrate() {\n if (policy.mode !== \"integrate\") return;\n const current = (\n await git(repository, [\"symbolic-ref\", \"--short\", \"HEAD\"])\n ).trim();\n if (current !== baseBranch)\n throw new OutpostError(\n \"conflict\",\n \"Host branch changed during the job\",\n { expected: baseBranch, current, directory: workdir },\n );\n const releaseMerge = await observedOperation(\n options.observation,\n \"git\",\n \"integration.lock\",\n async () => lock(repository, `merge:${baseBranch}`),\n );\n try {\n await git(\n repository,\n [\"merge\", \"--no-edit\", branch],\n options.limits?.mergeMs,\n );\n } catch (cause) {\n throw new OutpostError(\n \"conflict\",\n \"Automatic integration failed; workspace retained\",\n { directory: workdir, branch },\n cause,\n );\n } finally {\n await observedOperation(\n options.observation,\n \"git\",\n \"integration.unlock\",\n async () => releaseMerge(),\n );\n }\n },\n dispose(preserve = false) {\n if (disposal) return disposal;\n disposal = (async () => {\n try {\n if (policy.mode === \"current\") return {};\n if (preserve) return { retainedDirectory: workdir };\n const attached = await git(workdir, [\n \"symbolic-ref\",\n \"--quiet\",\n \"HEAD\",\n ]).catch(() => \"\");\n if (!attached.trim()) return { retainedDirectory: workdir };\n const dirty = await git(workdir, [\n \"status\",\n \"--porcelain\",\n \"--untracked-files=normal\",\n \"--ignored\",\n ]);\n if (dirty.trim()) return { retainedDirectory: workdir };\n if (!inside(join(repository, \".outpost\", \"workspaces\"), workdir))\n throw new OutpostError(\n \"workspace\",\n \"Refusing to remove an unmanaged workspace\",\n );\n await git(repository, [\"worktree\", \"remove\", workdir]);\n if (policy.mode === \"integrate\")\n await git(repository, [\"branch\", \"-d\", branch]).catch(\n () => undefined,\n );\n return {};\n } finally {\n await observedOperation(\n options.observation,\n \"git\",\n \"workspace.unlock\",\n async () => unlock(),\n );\n }\n })();\n return disposal;\n },\n };\n}\n"]}