lastlight 0.1.15 → 0.2.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 (478) hide show
  1. package/README.md +265 -118
  2. package/agent-context/rules.md +62 -9
  3. package/agent-context/security.md +69 -0
  4. package/config/default.yaml +89 -0
  5. package/deploy/.env.production.example +20 -2
  6. package/deploy/entrypoint.sh +16 -17
  7. package/deploy/native/README.md +160 -0
  8. package/deploy/native/install.sh +110 -0
  9. package/deploy/native/lastlight.env.example +95 -0
  10. package/deploy/native/lastlight.service +50 -0
  11. package/deploy/sandbox-entrypoint.sh +59 -42
  12. package/dist/admin/auth.d.ts +1 -1
  13. package/dist/admin/auth.js +3 -1
  14. package/dist/admin/auth.js.map +1 -1
  15. package/dist/admin/chat-session-reader.d.ts +11 -14
  16. package/dist/admin/chat-session-reader.js +27 -51
  17. package/dist/admin/chat-session-reader.js.map +1 -1
  18. package/dist/admin/docker.d.ts +37 -0
  19. package/dist/admin/docker.js +86 -1
  20. package/dist/admin/docker.js.map +1 -1
  21. package/dist/admin/index.js +38 -3
  22. package/dist/admin/index.js.map +1 -1
  23. package/dist/admin/log-search.test.d.ts +1 -0
  24. package/dist/admin/log-search.test.js +78 -0
  25. package/dist/admin/log-search.test.js.map +1 -0
  26. package/dist/admin/routes.d.ts +52 -3
  27. package/dist/admin/routes.js +780 -63
  28. package/dist/admin/routes.js.map +1 -1
  29. package/dist/admin/routes.test.js +680 -14
  30. package/dist/admin/routes.test.js.map +1 -1
  31. package/dist/admin/server-logs.test.d.ts +1 -0
  32. package/dist/admin/server-logs.test.js +58 -0
  33. package/dist/admin/server-logs.test.js.map +1 -0
  34. package/dist/admin/sessions.d.ts +26 -39
  35. package/dist/admin/sessions.js +86 -310
  36. package/dist/admin/sessions.js.map +1 -1
  37. package/dist/admin/sessions.test.d.ts +1 -0
  38. package/dist/admin/sessions.test.js +78 -0
  39. package/dist/admin/sessions.test.js.map +1 -0
  40. package/dist/admin/version.d.ts +15 -0
  41. package/dist/admin/version.js +73 -0
  42. package/dist/admin/version.js.map +1 -0
  43. package/dist/admin/version.test.d.ts +1 -0
  44. package/dist/admin/version.test.js +71 -0
  45. package/dist/admin/version.test.js.map +1 -0
  46. package/dist/cli-config.d.ts +55 -0
  47. package/dist/cli-config.js +119 -0
  48. package/dist/cli-config.js.map +1 -0
  49. package/dist/cli-config.test.d.ts +1 -0
  50. package/dist/cli-config.test.js +92 -0
  51. package/dist/cli-config.test.js.map +1 -0
  52. package/dist/cli-format.d.ts +19 -0
  53. package/dist/cli-format.js +107 -0
  54. package/dist/cli-format.js.map +1 -0
  55. package/dist/cli-server.d.ts +73 -0
  56. package/dist/cli-server.js +347 -0
  57. package/dist/cli-server.js.map +1 -0
  58. package/dist/cli-server.test.d.ts +1 -0
  59. package/dist/cli-server.test.js +38 -0
  60. package/dist/cli-server.test.js.map +1 -0
  61. package/dist/cli-timeline.d.ts +35 -0
  62. package/dist/cli-timeline.js +373 -0
  63. package/dist/cli-timeline.js.map +1 -0
  64. package/dist/cli-timeline.test.d.ts +1 -0
  65. package/dist/cli-timeline.test.js +104 -0
  66. package/dist/cli-timeline.test.js.map +1 -0
  67. package/dist/cli.d.ts +0 -19
  68. package/dist/cli.js +910 -194
  69. package/dist/cli.js.map +1 -1
  70. package/dist/config-overlay.test.d.ts +1 -0
  71. package/dist/config-overlay.test.js +112 -0
  72. package/dist/config-overlay.test.js.map +1 -0
  73. package/dist/config-resolve.d.ts +28 -0
  74. package/dist/config-resolve.js +47 -0
  75. package/dist/config-resolve.js.map +1 -0
  76. package/dist/config-resolve.test.d.ts +1 -0
  77. package/dist/config-resolve.test.js +68 -0
  78. package/dist/config-resolve.test.js.map +1 -0
  79. package/dist/config.d.ts +62 -49
  80. package/dist/config.js +452 -76
  81. package/dist/config.js.map +1 -1
  82. package/dist/config.test.js +201 -32
  83. package/dist/config.test.js.map +1 -1
  84. package/dist/connectors/github-webhook.js +83 -5
  85. package/dist/connectors/github-webhook.js.map +1 -1
  86. package/dist/connectors/github-webhook.test.d.ts +1 -0
  87. package/dist/connectors/github-webhook.test.js +156 -0
  88. package/dist/connectors/github-webhook.test.js.map +1 -0
  89. package/dist/connectors/messaging/session-manager.d.ts +18 -0
  90. package/dist/connectors/messaging/session-manager.js +83 -2
  91. package/dist/connectors/messaging/session-manager.js.map +1 -1
  92. package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
  93. package/dist/connectors/messaging/session-manager.test.js +144 -0
  94. package/dist/connectors/messaging/session-manager.test.js.map +1 -0
  95. package/dist/connectors/slack/connector.d.ts +9 -0
  96. package/dist/connectors/slack/connector.js +15 -0
  97. package/dist/connectors/slack/connector.js.map +1 -1
  98. package/dist/connectors/slack/mrkdwn.js +81 -0
  99. package/dist/connectors/slack/mrkdwn.js.map +1 -1
  100. package/dist/connectors/slack/mrkdwn.test.js +49 -0
  101. package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
  102. package/dist/connectors/types.d.ts +1 -1
  103. package/dist/cron/fanout.d.ts +33 -0
  104. package/dist/cron/fanout.js +55 -0
  105. package/dist/cron/fanout.js.map +1 -0
  106. package/dist/cron/fanout.test.d.ts +1 -0
  107. package/dist/cron/fanout.test.js +73 -0
  108. package/dist/cron/fanout.test.js.map +1 -0
  109. package/dist/cron/jobs.d.ts +5 -0
  110. package/dist/cron/jobs.js +10 -3
  111. package/dist/cron/jobs.js.map +1 -1
  112. package/dist/cron/scheduler.d.ts +12 -0
  113. package/dist/cron/scheduler.js +27 -1
  114. package/dist/cron/scheduler.js.map +1 -1
  115. package/dist/engine/agent-executor.d.ts +158 -0
  116. package/dist/engine/agent-executor.js +1140 -0
  117. package/dist/engine/agent-executor.js.map +1 -0
  118. package/dist/engine/agent-executor.test.d.ts +1 -0
  119. package/dist/engine/agent-executor.test.js +395 -0
  120. package/dist/engine/agent-executor.test.js.map +1 -0
  121. package/dist/engine/chat-runner.d.ts +123 -0
  122. package/dist/engine/chat-runner.js +379 -0
  123. package/dist/engine/chat-runner.js.map +1 -0
  124. package/dist/engine/chat-runner.test.d.ts +1 -0
  125. package/dist/engine/chat-runner.test.js +104 -0
  126. package/dist/engine/chat-runner.test.js.map +1 -0
  127. package/dist/engine/chat-skills.d.ts +45 -0
  128. package/dist/engine/chat-skills.js +184 -0
  129. package/dist/engine/chat-skills.js.map +1 -0
  130. package/dist/engine/chat-skills.test.d.ts +1 -0
  131. package/dist/engine/chat-skills.test.js +20 -0
  132. package/dist/engine/chat-skills.test.js.map +1 -0
  133. package/dist/engine/chat.d.ts +20 -23
  134. package/dist/engine/chat.js +251 -155
  135. package/dist/engine/chat.js.map +1 -1
  136. package/dist/engine/chat.test.d.ts +1 -0
  137. package/dist/engine/chat.test.js +42 -0
  138. package/dist/engine/chat.test.js.map +1 -0
  139. package/dist/engine/classifier.d.ts +35 -2
  140. package/dist/engine/classifier.js +170 -31
  141. package/dist/engine/classifier.js.map +1 -1
  142. package/dist/engine/classifier.test.d.ts +1 -0
  143. package/dist/engine/classifier.test.js +115 -0
  144. package/dist/engine/classifier.test.js.map +1 -0
  145. package/dist/engine/dispatcher.d.ts +60 -0
  146. package/dist/engine/dispatcher.js +601 -0
  147. package/dist/engine/dispatcher.js.map +1 -0
  148. package/dist/engine/dispatcher.test.d.ts +1 -0
  149. package/dist/engine/dispatcher.test.js +511 -0
  150. package/dist/engine/dispatcher.test.js.map +1 -0
  151. package/dist/engine/event-shim.d.ts +117 -0
  152. package/dist/engine/event-shim.js +435 -0
  153. package/dist/engine/event-shim.js.map +1 -0
  154. package/dist/engine/event-shim.test.d.ts +1 -0
  155. package/dist/engine/event-shim.test.js +194 -0
  156. package/dist/engine/event-shim.test.js.map +1 -0
  157. package/dist/engine/git-auth.d.ts +13 -17
  158. package/dist/engine/git-auth.js +99 -42
  159. package/dist/engine/git-auth.js.map +1 -1
  160. package/dist/engine/git-auth.test.d.ts +1 -0
  161. package/dist/engine/git-auth.test.js +117 -0
  162. package/dist/engine/git-auth.test.js.map +1 -0
  163. package/dist/engine/github-app-client.d.ts +7 -0
  164. package/dist/engine/github-app-client.js +16 -0
  165. package/dist/engine/github-app-client.js.map +1 -0
  166. package/dist/engine/github-app-client.test.d.ts +1 -0
  167. package/dist/engine/github-app-client.test.js +44 -0
  168. package/dist/engine/github-app-client.test.js.map +1 -0
  169. package/dist/engine/github-tools.d.ts +12 -0
  170. package/dist/engine/github-tools.js +261 -0
  171. package/dist/engine/github-tools.js.map +1 -0
  172. package/dist/engine/github.d.ts +1027 -43
  173. package/dist/engine/github.js +153 -14
  174. package/dist/engine/github.js.map +1 -1
  175. package/dist/engine/llm.d.ts +47 -0
  176. package/dist/engine/llm.js +221 -0
  177. package/dist/engine/llm.js.map +1 -0
  178. package/dist/engine/llm.test.d.ts +1 -0
  179. package/dist/engine/llm.test.js +189 -0
  180. package/dist/engine/llm.test.js.map +1 -0
  181. package/dist/engine/profiles.d.ts +249 -0
  182. package/dist/engine/profiles.js +42 -0
  183. package/dist/engine/profiles.js.map +1 -0
  184. package/dist/engine/router.d.ts +12 -6
  185. package/dist/engine/router.js +339 -81
  186. package/dist/engine/router.js.map +1 -1
  187. package/dist/engine/router.test.js +428 -78
  188. package/dist/engine/router.test.js.map +1 -1
  189. package/dist/engine/screen.d.ts +41 -0
  190. package/dist/engine/screen.js +93 -0
  191. package/dist/engine/screen.js.map +1 -0
  192. package/dist/engine/screen.test.d.ts +1 -0
  193. package/dist/engine/screen.test.js +82 -0
  194. package/dist/engine/screen.test.js.map +1 -0
  195. package/dist/index.js +377 -432
  196. package/dist/index.js.map +1 -1
  197. package/dist/managed-repos.d.ts +7 -9
  198. package/dist/managed-repos.js +12 -15
  199. package/dist/managed-repos.js.map +1 -1
  200. package/dist/managed-repos.test.js +24 -19
  201. package/dist/managed-repos.test.js.map +1 -1
  202. package/dist/notify/index.d.ts +15 -0
  203. package/dist/notify/index.js +6 -0
  204. package/dist/notify/index.js.map +1 -0
  205. package/dist/notify/model.d.ts +57 -0
  206. package/dist/notify/model.js +89 -0
  207. package/dist/notify/model.js.map +1 -0
  208. package/dist/notify/model.test.d.ts +1 -0
  209. package/dist/notify/model.test.js +109 -0
  210. package/dist/notify/model.test.js.map +1 -0
  211. package/dist/notify/notifier.d.ts +17 -0
  212. package/dist/notify/notifier.js +87 -0
  213. package/dist/notify/notifier.js.map +1 -0
  214. package/dist/notify/notifier.test.d.ts +1 -0
  215. package/dist/notify/notifier.test.js +100 -0
  216. package/dist/notify/notifier.test.js.map +1 -0
  217. package/dist/notify/render.d.ts +21 -0
  218. package/dist/notify/render.js +59 -0
  219. package/dist/notify/render.js.map +1 -0
  220. package/dist/notify/render.test.d.ts +1 -0
  221. package/dist/notify/render.test.js +65 -0
  222. package/dist/notify/render.test.js.map +1 -0
  223. package/dist/notify/transports/github.d.ts +26 -0
  224. package/dist/notify/transports/github.js +26 -0
  225. package/dist/notify/transports/github.js.map +1 -0
  226. package/dist/notify/transports/slack.d.ts +26 -0
  227. package/dist/notify/transports/slack.js +28 -0
  228. package/dist/notify/transports/slack.js.map +1 -0
  229. package/dist/notify/transports.test.d.ts +1 -0
  230. package/dist/notify/transports.test.js +71 -0
  231. package/dist/notify/transports.test.js.map +1 -0
  232. package/dist/notify/types.d.ts +95 -0
  233. package/dist/notify/types.js +16 -0
  234. package/dist/notify/types.js.map +1 -0
  235. package/dist/sandbox/docker-compose.test.d.ts +1 -0
  236. package/dist/sandbox/docker-compose.test.js +128 -0
  237. package/dist/sandbox/docker-compose.test.js.map +1 -0
  238. package/dist/sandbox/docker.d.ts +97 -9
  239. package/dist/sandbox/docker.js +192 -41
  240. package/dist/sandbox/docker.js.map +1 -1
  241. package/dist/sandbox/docker.test.d.ts +1 -0
  242. package/dist/sandbox/docker.test.js +137 -0
  243. package/dist/sandbox/docker.test.js.map +1 -0
  244. package/dist/sandbox/egress-allowlist.d.ts +69 -0
  245. package/dist/sandbox/egress-allowlist.js +164 -0
  246. package/dist/sandbox/egress-allowlist.js.map +1 -0
  247. package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
  248. package/dist/sandbox/egress-allowlist.test.js +65 -0
  249. package/dist/sandbox/egress-allowlist.test.js.map +1 -0
  250. package/dist/sandbox/egress-firewall-config.d.ts +127 -0
  251. package/dist/sandbox/egress-firewall-config.js +434 -0
  252. package/dist/sandbox/egress-firewall-config.js.map +1 -0
  253. package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
  254. package/dist/sandbox/egress-firewall-config.test.js +244 -0
  255. package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
  256. package/dist/sandbox/images.d.ts +23 -0
  257. package/dist/sandbox/images.js +55 -0
  258. package/dist/sandbox/images.js.map +1 -0
  259. package/dist/sandbox/index.d.ts +82 -3
  260. package/dist/sandbox/index.js +223 -93
  261. package/dist/sandbox/index.js.map +1 -1
  262. package/dist/sandbox/index.test.d.ts +1 -0
  263. package/dist/sandbox/index.test.js +157 -0
  264. package/dist/sandbox/index.test.js.map +1 -0
  265. package/dist/session-log.d.ts +63 -0
  266. package/dist/session-log.js +290 -0
  267. package/dist/session-log.js.map +1 -0
  268. package/dist/session-log.test.d.ts +1 -0
  269. package/dist/session-log.test.js +85 -0
  270. package/dist/session-log.test.js.map +1 -0
  271. package/dist/setup.d.ts +30 -1
  272. package/dist/setup.js +241 -25
  273. package/dist/setup.js.map +1 -1
  274. package/dist/setup.test.js +138 -6
  275. package/dist/setup.test.js.map +1 -1
  276. package/dist/state/approval-store.d.ts +86 -0
  277. package/dist/state/approval-store.js +140 -0
  278. package/dist/state/approval-store.js.map +1 -0
  279. package/dist/state/build-assets.d.ts +50 -0
  280. package/dist/state/build-assets.js +154 -0
  281. package/dist/state/build-assets.js.map +1 -0
  282. package/dist/state/build-assets.test.d.ts +1 -0
  283. package/dist/state/build-assets.test.js +106 -0
  284. package/dist/state/build-assets.test.js.map +1 -0
  285. package/dist/state/db.d.ts +65 -333
  286. package/dist/state/db.js +112 -835
  287. package/dist/state/db.js.map +1 -1
  288. package/dist/state/db.test.js +127 -91
  289. package/dist/state/db.test.js.map +1 -1
  290. package/dist/state/execution-store.d.ts +257 -0
  291. package/dist/state/execution-store.js +527 -0
  292. package/dist/state/execution-store.js.map +1 -0
  293. package/dist/state/migrate.d.ts +15 -0
  294. package/dist/state/migrate.js +175 -0
  295. package/dist/state/migrate.js.map +1 -0
  296. package/dist/state/workflow-run-store.d.ts +195 -0
  297. package/dist/state/workflow-run-store.js +363 -0
  298. package/dist/state/workflow-run-store.js.map +1 -0
  299. package/dist/state/workflow-run-store.test.d.ts +1 -0
  300. package/dist/state/workflow-run-store.test.js +264 -0
  301. package/dist/state/workflow-run-store.test.js.map +1 -0
  302. package/dist/telemetry/index.d.ts +38 -0
  303. package/dist/telemetry/index.js +253 -0
  304. package/dist/telemetry/index.js.map +1 -0
  305. package/dist/telemetry/index.test.d.ts +1 -0
  306. package/dist/telemetry/index.test.js +73 -0
  307. package/dist/telemetry/index.test.js.map +1 -0
  308. package/dist/telemetry/pi-events.d.ts +12 -0
  309. package/dist/telemetry/pi-events.js +134 -0
  310. package/dist/telemetry/pi-events.js.map +1 -0
  311. package/dist/telemetry/pi-events.test.d.ts +1 -0
  312. package/dist/telemetry/pi-events.test.js +69 -0
  313. package/dist/telemetry/pi-events.test.js.map +1 -0
  314. package/dist/workflows/dag.d.ts +13 -1
  315. package/dist/workflows/dag.js +7 -3
  316. package/dist/workflows/dag.js.map +1 -1
  317. package/dist/workflows/dag.test.js +22 -0
  318. package/dist/workflows/dag.test.js.map +1 -1
  319. package/dist/workflows/golden-build.test.d.ts +1 -0
  320. package/dist/workflows/golden-build.test.js +45 -0
  321. package/dist/workflows/golden-build.test.js.map +1 -0
  322. package/dist/workflows/loader-overlay.test.d.ts +1 -0
  323. package/dist/workflows/loader-overlay.test.js +101 -0
  324. package/dist/workflows/loader-overlay.test.js.map +1 -0
  325. package/dist/workflows/loader.d.ts +36 -11
  326. package/dist/workflows/loader.js +311 -87
  327. package/dist/workflows/loader.js.map +1 -1
  328. package/dist/workflows/loader.test.js +114 -10
  329. package/dist/workflows/loader.test.js.map +1 -1
  330. package/dist/workflows/loop-eval.js +2 -0
  331. package/dist/workflows/loop-eval.js.map +1 -1
  332. package/dist/workflows/loop-eval.test.js +14 -0
  333. package/dist/workflows/loop-eval.test.js.map +1 -1
  334. package/dist/workflows/phase-executor.d.ts +145 -0
  335. package/dist/workflows/phase-executor.js +691 -0
  336. package/dist/workflows/phase-executor.js.map +1 -0
  337. package/dist/workflows/phase-executor.test.d.ts +1 -0
  338. package/dist/workflows/phase-executor.test.js +434 -0
  339. package/dist/workflows/phase-executor.test.js.map +1 -0
  340. package/dist/workflows/phase-ref.d.ts +44 -0
  341. package/dist/workflows/phase-ref.js +78 -0
  342. package/dist/workflows/phase-ref.js.map +1 -0
  343. package/dist/workflows/phase-ref.test.d.ts +1 -0
  344. package/dist/workflows/phase-ref.test.js +24 -0
  345. package/dist/workflows/phase-ref.test.js.map +1 -0
  346. package/dist/workflows/resume.d.ts +5 -11
  347. package/dist/workflows/resume.js +88 -7
  348. package/dist/workflows/resume.js.map +1 -1
  349. package/dist/workflows/runner.d.ts +34 -27
  350. package/dist/workflows/runner.js +252 -930
  351. package/dist/workflows/runner.js.map +1 -1
  352. package/dist/workflows/runner.test.js +346 -35
  353. package/dist/workflows/runner.test.js.map +1 -1
  354. package/dist/workflows/schema.d.ts +52 -10
  355. package/dist/workflows/schema.js +147 -7
  356. package/dist/workflows/schema.js.map +1 -1
  357. package/dist/workflows/simple.d.ts +67 -3
  358. package/dist/workflows/simple.js +248 -87
  359. package/dist/workflows/simple.js.map +1 -1
  360. package/dist/workflows/simple.test.d.ts +1 -0
  361. package/dist/workflows/simple.test.js +107 -0
  362. package/dist/workflows/simple.test.js.map +1 -0
  363. package/dist/workflows/templates.d.ts +29 -0
  364. package/dist/workflows/templates.js +42 -4
  365. package/dist/workflows/templates.js.map +1 -1
  366. package/dist/workflows/templates.test.js +103 -0
  367. package/dist/workflows/templates.test.js.map +1 -1
  368. package/dist/workflows/triggers.d.ts +21 -0
  369. package/dist/workflows/triggers.js +44 -0
  370. package/dist/workflows/triggers.js.map +1 -0
  371. package/dist/workflows/verdict.d.ts +19 -0
  372. package/dist/workflows/verdict.js +30 -0
  373. package/dist/workflows/verdict.js.map +1 -0
  374. package/dist/workflows/verdict.test.d.ts +1 -0
  375. package/dist/workflows/verdict.test.js +44 -0
  376. package/dist/workflows/verdict.test.js.map +1 -0
  377. package/dist/worktree/manager.d.ts +1 -1
  378. package/dist/worktree/manager.js +14 -14
  379. package/dist/worktree/manager.js.map +1 -1
  380. package/dist/worktree/manager.test.d.ts +1 -0
  381. package/dist/worktree/manager.test.js +87 -0
  382. package/dist/worktree/manager.test.js.map +1 -0
  383. package/docker-compose.yml +206 -5
  384. package/package.json +17 -7
  385. package/sandbox.Dockerfile +97 -18
  386. package/skills/README.md +40 -0
  387. package/skills/browser-qa/SKILL.md +193 -0
  388. package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
  389. package/skills/building/SKILL.md +95 -0
  390. package/skills/chat/SKILL.md +30 -11
  391. package/skills/code-review/SKILL.md +59 -0
  392. package/skills/debug-production/SKILL.md +108 -0
  393. package/skills/demo/SKILL.md +194 -0
  394. package/skills/demo/scripts/compose-demo.sh +205 -0
  395. package/skills/issue-answer/SKILL.md +90 -0
  396. package/skills/issue-comment/SKILL.md +38 -24
  397. package/skills/issue-triage/SKILL.md +103 -37
  398. package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
  399. package/skills/pr-comment/SKILL.md +64 -0
  400. package/skills/pr-review/SKILL.md +65 -49
  401. package/skills/qa-test/SKILL.md +97 -0
  402. package/skills/repo-health/SKILL.md +48 -45
  403. package/skills/security-feedback/SKILL.md +173 -0
  404. package/skills/security-feedback/references/templates.md +77 -0
  405. package/skills/security-review/SKILL.md +213 -0
  406. package/skills/security-review/references/issue-format.md +302 -0
  407. package/skills/verify/SKILL.md +118 -0
  408. package/workflows/answer.yaml +37 -0
  409. package/workflows/build.yaml +32 -22
  410. package/workflows/cron-security.yaml +6 -0
  411. package/workflows/demo.yaml +55 -0
  412. package/workflows/explore.yaml +9 -0
  413. package/workflows/pr-comment.yaml +16 -0
  414. package/workflows/pr-fix.yaml +3 -0
  415. package/workflows/pr-review.yaml +4 -1
  416. package/workflows/prompts/answer.md +67 -0
  417. package/workflows/prompts/architect.md +24 -7
  418. package/workflows/prompts/demo.md +100 -0
  419. package/workflows/prompts/executor.md +29 -20
  420. package/workflows/prompts/explore-ask.md +51 -22
  421. package/workflows/prompts/explore-publish.md +2 -2
  422. package/workflows/prompts/explore-read.md +24 -10
  423. package/workflows/prompts/explore-synthesize.md +15 -8
  424. package/workflows/prompts/fix.md +9 -10
  425. package/workflows/prompts/guardrails.md +26 -8
  426. package/workflows/prompts/pr-fix.md +6 -7
  427. package/workflows/prompts/pr.md +11 -10
  428. package/workflows/prompts/qa-browser.md +95 -0
  429. package/workflows/prompts/qa-synth.md +44 -0
  430. package/workflows/prompts/qa-test.md +60 -0
  431. package/workflows/prompts/re-reviewer.md +8 -9
  432. package/workflows/prompts/reviewer.md +10 -9
  433. package/workflows/prompts/verify-browser.md +93 -0
  434. package/workflows/prompts/verify-synth.md +44 -0
  435. package/workflows/prompts/verify.md +63 -0
  436. package/workflows/qa-test.yaml +87 -0
  437. package/workflows/security-feedback.yaml +25 -0
  438. package/workflows/security-review.yaml +29 -0
  439. package/workflows/verify.yaml +85 -0
  440. package/deploy/mcp-config.tmpl.json +0 -14
  441. package/dist/cron/rate-limits.d.ts +0 -26
  442. package/dist/cron/rate-limits.js +0 -193
  443. package/dist/cron/rate-limits.js.map +0 -1
  444. package/dist/engine/executor.d.ts +0 -75
  445. package/dist/engine/executor.js +0 -292
  446. package/dist/engine/executor.js.map +0 -1
  447. package/mcp-github-app/package.json +0 -18
  448. package/mcp-github-app/src/auth.js +0 -66
  449. package/mcp-github-app/src/github.js +0 -371
  450. package/mcp-github-app/src/index.js +0 -534
  451. package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
  452. package/skills/github/DESCRIPTION.md +0 -3
  453. package/skills/github/codebase-inspection/SKILL.md +0 -115
  454. package/skills/github/github-auth/SKILL.md +0 -54
  455. package/skills/github/github-auth/scripts/gh-env.sh +0 -66
  456. package/skills/github/github-code-review/SKILL.md +0 -480
  457. package/skills/github/github-code-review/references/review-output-template.md +0 -74
  458. package/skills/github/github-issues/SKILL.md +0 -369
  459. package/skills/github/github-issues/templates/bug-report.md +0 -35
  460. package/skills/github/github-issues/templates/feature-request.md +0 -31
  461. package/skills/github/github-pr-workflow/SKILL.md +0 -395
  462. package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
  463. package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
  464. package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
  465. package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
  466. package/skills/github/github-repo-management/SKILL.md +0 -515
  467. package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
  468. package/skills/github-orchestrator/SKILL.md +0 -103
  469. package/skills/mcp/DESCRIPTION.md +0 -3
  470. package/skills/mcp/mcporter/SKILL.md +0 -122
  471. package/skills/mcp/native-mcp/SKILL.md +0 -356
  472. package/skills/software-development/architect/SKILL.md +0 -154
  473. package/skills/software-development/assure-guardrails/SKILL.md +0 -239
  474. package/skills/software-development/plan/SKILL.md +0 -64
  475. package/skills/software-development/requesting-code-review/SKILL.md +0 -291
  476. package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
  477. package/skills/software-development/systematic-debugging/SKILL.md +0 -366
  478. package/skills/software-development/test-driven-development/SKILL.md +0 -342
@@ -0,0 +1,95 @@
1
+ # ── Last Light — Native deploy env (systemd EnvironmentFile) ────────────
2
+ # Path on the host: /etc/lastlight/lastlight.env
3
+ # Mode 0640, owned by root:lastlight.
4
+ #
5
+ # Anything marked CHANGE_ME must be replaced before the service will start
6
+ # (install.sh refuses to start the unit while placeholders are present).
7
+
8
+ # ── GitHub App (required) ─────────────────────────────────────────────────
9
+ GITHUB_APP_ID=CHANGE_ME
10
+ GITHUB_APP_INSTALLATION_ID=CHANGE_ME
11
+ # PEM is read by the harness at boot. install.sh locks down permissions if
12
+ # you place it at /etc/lastlight/app.pem before running.
13
+ GITHUB_APP_PRIVATE_KEY_PATH=/etc/lastlight/app.pem
14
+
15
+ # Webhook receiver
16
+ WEBHOOK_SECRET=CHANGE_ME
17
+ # Listener port — Caddy/Nginx should reverse-proxy 443 → 127.0.0.1:PORT.
18
+ PORT=8644
19
+
20
+ # ── Model + provider API key ─────────────────────────────────────────────
21
+ # pi-ai supports anthropic/…, openai/…, openrouter/<vendor>/<model>.
22
+ LASTLIGHT_MODEL=anthropic/claude-sonnet-4-6
23
+ # Set whichever matches LASTLIGHT_MODEL (or several if LASTLIGHT_MODELS
24
+ # routes different phases to different providers).
25
+ ANTHROPIC_API_KEY=CHANGE_ME
26
+ # OPENAI_API_KEY=
27
+ # OPENROUTER_API_KEY=
28
+
29
+ # ── OpenTelemetry (optional, disabled by default) ────────────────────────
30
+ # LASTLIGHT_OTEL_ENABLED=false
31
+ # LASTLIGHT_OTEL_SERVICE_NAME=lastlight
32
+ # LASTLIGHT_OTEL_INCLUDE_CONTENT=false
33
+ # LASTLIGHT_OTEL_FORWARD_TO_SANDBOX=true
34
+ # LASTLIGHT_OTEL_STRICT=false
35
+ # OTEL_EXPORTER_OTLP_ENDPOINT=https://CHANGE_ME
36
+ # OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer CHANGE_ME
37
+ # docker backend routes sandbox telemetry through an in-network otel-collector
38
+ # (re-exports to the endpoint above; headers stay host-side, any port works).
39
+ # LASTLIGHT_OTEL_COLLECTOR_HOSTS is only used by the gondolin egress allowlist.
40
+ # LASTLIGHT_OTEL_COLLECTOR_HOSTS=CHANGE_ME
41
+
42
+ # Per-task model overrides (optional). JSON keyed by phase/skill name.
43
+ # LASTLIGHT_MODELS={"architect":"openai/gpt-5.5","triage":"anthropic/claude-haiku-4-5-20251001"}
44
+
45
+ # ── Web search (optional, explore workflow only) ─────────────────────────
46
+ # Set any one to enable agentic-pi's `web_search` / `web_fetch` tools for
47
+ # the explore workflow. Provider auto-detected from whichever key is set
48
+ # (Tavily > Exa > Brave). Other workflows ignore these keys.
49
+ # TAVILY_API_KEY=tvly-...
50
+ # BRAVE_SEARCH_API_KEY=BSA...
51
+ # EXA_API_KEY=...
52
+
53
+ # Reasoning-effort default + per-task overrides (optional).
54
+ # Values: off | minimal | low | medium | high | xhigh
55
+ # LASTLIGHT_THINKING=medium
56
+ # LASTLIGHT_THINKINGS={"architect":"high","reviewer":"high"}
57
+
58
+ # ── Sandbox backend ───────────────────────────────────────────────────────
59
+ # gondolin = agentic-pi's QEMU micro-VM (default, requires /dev/kvm).
60
+ # docker = sibling docker containers (requires docker socket access).
61
+ # none = unsandboxed in-process (dev only — agent reads/writes host fs).
62
+ LASTLIGHT_SANDBOX=gondolin
63
+
64
+ # ── State paths ───────────────────────────────────────────────────────────
65
+ # systemd's StateDirectory= grants /var/lib/lastlight with the right mode.
66
+ STATE_DIR=/var/lib/lastlight
67
+ DB_PATH=/var/lib/lastlight/lastlight.db
68
+ LASTLIGHT_SESSIONS_DIR=/var/lib/lastlight/agent-sessions
69
+
70
+ # ── Admin dashboard ───────────────────────────────────────────────────────
71
+ # HMAC secret for session tokens. Generate with: openssl rand -hex 32
72
+ ADMIN_SECRET=CHANGE_ME
73
+ # Optional: require a password for the dashboard. Leave unset to allow
74
+ # anyone who can reach the listener (i.e. anyone past Caddy).
75
+ # ADMIN_PASSWORD=
76
+
77
+ # ── Slack (optional) ──────────────────────────────────────────────────────
78
+ # Setting SLACK_BOT_TOKEN enables the chat skill and the Slack connector.
79
+ # SLACK_BOT_TOKEN=xoxb-…
80
+ # SLACK_APP_TOKEN=xapp-…
81
+ # SLACK_DELIVERY_CHANNEL=C0123456789
82
+ # SLACK_ALLOWED_USERS=U0123,U0456
83
+
84
+ # Slack OAuth for dashboard login (optional)
85
+ # SLACK_OAUTH_CLIENT_ID=
86
+ # SLACK_OAUTH_CLIENT_SECRET=
87
+ # SLACK_OAUTH_REDIRECT_URI=https://your-domain/admin/auth/slack/callback
88
+ # SLACK_ALLOWED_WORKSPACE=
89
+
90
+ # ── Approval gates (optional) ─────────────────────────────────────────────
91
+ # Comma-separated list of gate names that should pause the runner.
92
+ # APPROVAL_GATES=post_architect,post_reviewer
93
+
94
+ # ── Bootstrap label (optional) ────────────────────────────────────────────
95
+ # BOOTSTRAP_LABEL=lastlight:bootstrap
@@ -0,0 +1,50 @@
1
+ [Unit]
2
+ Description=Last Light — GitHub repository maintenance agent
3
+ Documentation=https://github.com/cliftonc/lastlight
4
+ After=network-online.target
5
+ Wants=network-online.target
6
+
7
+ [Service]
8
+ Type=simple
9
+ User=lastlight
10
+ Group=lastlight
11
+ # gondolin needs /dev/kvm — group `kvm` is the standard accessor on Debian/Ubuntu.
12
+ SupplementaryGroups=kvm
13
+
14
+ WorkingDirectory=/opt/lastlight
15
+ ExecStart=/usr/bin/node /opt/lastlight/dist/index.js
16
+ EnvironmentFile=/etc/lastlight/lastlight.env
17
+
18
+ # HOME drives where agentic-pi caches the gondolin guest image
19
+ # (~/.cache/agentic-pi/images/). Pin it to the StateDirectory so the cache
20
+ # survives redeploys and isn't recomputed on every restart.
21
+ Environment=HOME=/var/lib/lastlight
22
+ Environment=NODE_ENV=production
23
+
24
+ Restart=on-failure
25
+ RestartSec=5s
26
+ LimitNOFILE=65536
27
+ # 2 GB matches the docker-compose limit. Bursts during webhook fan-out +
28
+ # in-process pi-ai chat; per-task gondolin VMs have their own memory budget.
29
+ MemoryMax=2G
30
+
31
+ # /var/lib/lastlight created with mode 0750, owned by lastlight:lastlight
32
+ StateDirectory=lastlight
33
+ StateDirectoryMode=0750
34
+ LogsDirectory=lastlight
35
+ LogsDirectoryMode=0750
36
+
37
+ # Security hardening — the harness only writes to its state dir and logs.
38
+ NoNewPrivileges=true
39
+ PrivateTmp=true
40
+ ProtectSystem=strict
41
+ ProtectHome=true
42
+ ProtectKernelTunables=true
43
+ ProtectKernelModules=true
44
+ ProtectControlGroups=true
45
+ ReadWritePaths=/var/lib/lastlight /var/log/lastlight
46
+ # Explicit /dev/kvm rule — ProtectSystem=strict alone doesn't gate /dev.
47
+ DeviceAllow=/dev/kvm rw
48
+
49
+ [Install]
50
+ WantedBy=multi-user.target
@@ -1,76 +1,93 @@
1
1
  #!/usr/bin/env bash
2
2
  # Sandbox container entrypoint — runs as root after volumes are mounted.
3
- # Sets up permissions, Claude auth, skills, agent-context, MCP config,
4
- # git identity, then drops to agent user via gosu.
3
+ # Used only when LASTLIGHT_SANDBOX=docker (the gondolin sandbox runs in
4
+ # process and doesn't go through this script). Fixes permissions, writes
5
+ # AGENTS.md, sets up git identity, then drops to the agent user via gosu.
5
6
  set -euo pipefail
6
7
 
7
8
  AGENT_HOME="/home/agent"
8
9
  WORKSPACE="$AGENT_HOME/workspace"
10
+ # LASTLIGHT_WORKSPACE and LASTLIGHT_GIT_CREDENTIALS are set as image-level
11
+ # ENV in sandbox.Dockerfile so they're visible to every `docker exec` call
12
+ # the harness makes (not just the entrypoint's PID-1 tree). They show up in
13
+ # this shell's env via that mechanism; no export needed here.
9
14
 
10
15
  # ── Fix workspace ownership (bind-mounts may be root-owned on macOS) ──
11
16
  chown -R agent:agent "$WORKSPACE" 2>/dev/null || true
12
17
  chown agent:agent "$AGENT_HOME"
13
18
 
14
- # ── ~/.claude as a real directory ──
15
- # Skills symlinked from baked-in /app/skills. Auth linked from shared volume.
16
- mkdir -p "$AGENT_HOME/.claude"
17
- chown agent:agent "$AGENT_HOME/.claude"
19
+ # Ensure ~/.config exists and is agent-owned before any root-side mkdir
20
+ # below claims it (some tools write here at startup).
21
+ mkdir -p "$AGENT_HOME/.config"
22
+ chown agent:agent "$AGENT_HOME/.config"
18
23
 
19
- # Skills: direct symlink to baked-in path
20
- ln -sfn /app/skills "$AGENT_HOME/.claude/skills"
24
+ # ── Shared package-manager cache (issue #107) ──
25
+ # /cache is a Docker named volume shared across every sandbox so npm / pnpm /
26
+ # yarn reuse already-downloaded tarballs. A freshly-created volume is root-owned,
27
+ # and a cache seeded by an older image (when `agent` had a different UID) leaves
28
+ # children owned by the wrong UID — which blocks npm/pnpm/yarn writes (e.g.
29
+ # /cache/npm/_logs). Self-heal: if the subdir OR any immediate child isn't
30
+ # agent-owned, chown -R it. The recursive pass runs only when something is
31
+ # actually wrong, so a warm, correctly-owned cache stays cheap.
32
+ if [ -d /cache ]; then
33
+ for sub in npm pnpm yarn; do
34
+ mkdir -p "/cache/$sub"
35
+ if [ -n "$(find "/cache/$sub" -maxdepth 1 ! -user agent -print -quit 2>/dev/null)" ]; then
36
+ chown -R agent:agent "/cache/$sub" 2>/dev/null || true
37
+ fi
38
+ done
39
+ fi
21
40
 
22
- # Keep the shared app PEM unreadable by the unprivileged agent by default.
41
+ # ── App PEM: keep shared copy unreadable by the agent by default ──
23
42
  if [ -f /data/secrets/app.pem ]; then
24
43
  chmod 600 /data/secrets/app.pem 2>/dev/null || true
25
44
  fi
26
45
 
27
46
  # Optionally materialize an agent-readable PEM for high-trust runs only.
47
+ # The harness forwards GITHUB_APP_PRIVATE_KEY_PATH into the sandbox env so
48
+ # any tool inside that needs the App key can find it.
28
49
  if [ "${ALLOW_APP_PEM:-0}" = "1" ] && [ -f /data/secrets/app.pem ]; then
29
- cp /data/secrets/app.pem "$AGENT_HOME/.claude/app.pem"
30
- chown agent:agent "$AGENT_HOME/.claude/app.pem"
31
- chmod 600 "$AGENT_HOME/.claude/app.pem"
32
- export GITHUB_APP_PRIVATE_KEY_PATH="$AGENT_HOME/.claude/app.pem"
50
+ cp /data/secrets/app.pem "$AGENT_HOME/.config/app.pem"
51
+ chown agent:agent "$AGENT_HOME/.config/app.pem"
52
+ chmod 600 "$AGENT_HOME/.config/app.pem"
53
+ export GITHUB_APP_PRIVATE_KEY_PATH="$AGENT_HOME/.config/app.pem"
33
54
  else
34
55
  export GITHUB_APP_PRIVATE_KEY_PATH=""
35
56
  fi
36
57
 
37
- # Auth: link children of shared claude-home (sessions, settings, etc.)
38
- if [ -d /data/claude-home ]; then
39
- # Ensure auth files are readable by agent (they may be owned by a different user)
40
- chmod -R a+rX /data/claude-home/ 2>/dev/null || true
41
- chmod a+r /data/claude-home/.credentials.json 2>/dev/null || true
42
-
43
- for item in /data/claude-home/* /data/claude-home/.credentials.json /data/claude-home/.claude.json; do
44
- [ ! -e "$item" ] && continue
45
- base="$(basename "$item")"
46
- [ "$base" = "skills" ] && continue # don't override our skills
47
- ln -sfn "$item" "$AGENT_HOME/.claude/$base"
48
- done
49
-
50
- # Ensure session logs are written to the shared volume so the dashboard can read them
51
- mkdir -p /data/claude-home/projects
52
- chown agent:agent /data/claude-home/projects
53
- ln -sfn /data/claude-home/projects "$AGENT_HOME/.claude/projects"
58
+ # ── AGENTS.md agentic-pi auto-loads this from cwd as the agent's
59
+ # system context (same convention as CLAUDE.md). ──
60
+ if [ ! -f "$WORKSPACE/AGENTS.md" ]; then
61
+ cat /app/agent-context/*.md > "$WORKSPACE/AGENTS.md" 2>/dev/null || true
54
62
  fi
55
-
56
- # ── Agent context (CLAUDE.md) into workspace root ──
57
- cat /app/agent-context/*.md > "$WORKSPACE/CLAUDE.md" 2>/dev/null || true
58
- chown agent:agent "$WORKSPACE/CLAUDE.md" 2>/dev/null || true
59
-
60
- # ── MCP config from template ──
61
- envsubst '$GITHUB_APP_ID $GITHUB_APP_INSTALLATION_ID $GITHUB_APP_PRIVATE_KEY_PATH $GITHUB_TOKEN' \
62
- < /app/mcp-config.tmpl.json > "$WORKSPACE/.mcp.json"
63
- chown agent:agent "$WORKSPACE/.mcp.json"
63
+ chown agent:agent "$WORKSPACE/AGENTS.md" 2>/dev/null || true
64
64
 
65
65
  # ── Git identity and auth (system-wide so it applies regardless of exec user) ──
66
66
  git config --system user.name "last-light[bot]"
67
67
  git config --system user.email "last-light[bot]@users.noreply.github.com"
68
68
 
69
- # If the harness passed a GIT_TOKEN, set up credential helper so git just works
70
69
  if [ -n "${GIT_TOKEN:-}" ]; then
71
- git config --system credential.helper \
72
- '!f() { echo "username=x-access-token"; echo "password='"$GIT_TOKEN"'"; }; f'
70
+ # Reject tokens containing characters that would break the URL line in
71
+ # the credentials file (newline, '@', ':', '/', whitespace). Real GitHub
72
+ # tokens are alphanumeric + underscore — the wider charset here is
73
+ # defensive against future format changes.
74
+ if ! printf %s "$GIT_TOKEN" | grep -Eq '^[A-Za-z0-9_-]+$'; then
75
+ echo "ERROR: GIT_TOKEN contains characters outside [A-Za-z0-9_-]; refusing to write credentials file" >&2
76
+ exit 1
77
+ fi
78
+ # Write the file as the agent user (mode 600) so the helper can read it
79
+ # after the entrypoint drops privileges. Path is set by us above; the
80
+ # `store --file=<path>` value goes into git's config as argv-split (no
81
+ # shell), so the only constraint is no-whitespace in the path.
82
+ install -m 600 -o agent -g agent /dev/null "$LASTLIGHT_GIT_CREDENTIALS"
83
+ printf 'https://x-access-token:%s@github.com\n' "$GIT_TOKEN" > "$LASTLIGHT_GIT_CREDENTIALS"
84
+ chown agent:agent "$LASTLIGHT_GIT_CREDENTIALS"
85
+ git config --system credential.helper "store --file=$LASTLIGHT_GIT_CREDENTIALS"
73
86
  fi
74
87
 
88
+ # ── Sentinel for harness waitForReady() ──
89
+ touch "$WORKSPACE/.ready"
90
+ chown agent:agent "$WORKSPACE/.ready"
91
+
75
92
  # ── Drop to agent user ──
76
93
  exec gosu agent "$@"
@@ -1,5 +1,5 @@
1
1
  import type { Context, Next } from "hono";
2
- export declare function createToken(secret: string, method?: "password" | "slack"): string;
2
+ export declare function createToken(secret: string, method?: "password" | "slack" | "github"): string;
3
3
  export declare function verifyToken(token: string, secret: string): boolean;
4
4
  export declare function authMiddleware(password: string, secret: string): (c: Context, next: Next) => Promise<void | (Response & import("hono").TypedResponse<{
5
5
  error: string;
@@ -41,7 +41,9 @@ export function authMiddleware(password, secret) {
41
41
  path.endsWith("/health") ||
42
42
  path.endsWith("/auth-required") ||
43
43
  path.endsWith("/oauth/slack/authorize") ||
44
- path.endsWith("/oauth/slack/callback")) {
44
+ path.endsWith("/oauth/slack/callback") ||
45
+ path.endsWith("/oauth/github/authorize") ||
46
+ path.endsWith("/oauth/github/callback")) {
45
47
  return next();
46
48
  }
47
49
  const header = c.req.header("Authorization");
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/admin/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/admin/auth.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,25 @@
1
1
  import type { StateDb } from "../state/db.js";
2
- import type { SessionSource, SessionMeta, JsonlMessage } from "./sessions.js";
2
+ import { SessionLog, type JsonlMessage } from "../session-log.js";
3
+ import type { SessionSource, SessionMeta } from "./sessions.js";
3
4
  /**
4
5
  * DB-backed chat-session reader. Drop-in replacement for SessionReader on
5
6
  * the chat path: same public surface (`mountSessionRoutes` works against it
6
7
  * unchanged), but listing comes from the executions table grouped by Slack
7
8
  * thread, and message reads target the single jsonl file owned by that
8
- * thread's agent SDK session id no scanning of unrelated `agent-*.jsonl`
9
- * sidechain files in `claude-home/projects/-app/`.
9
+ * thread's pi-ai session id. SessionLog owns the on-disk CHAT_PROJECT_SLUG
10
+ * path resolution, so this reader does not scan unrelated `agent-*.jsonl`
11
+ * sidechain files from other in-process Agent SDK runs.
10
12
  *
11
13
  * Conceptual mapping:
12
14
  * - SessionMeta.id ← messaging_session.id (= Slack thread / executions.trigger_id)
13
- * - jsonl on disk ← claude-home/projects/-app/<agent_session_id>.jsonl
14
- * (resolved via messaging_sessions.agent_session_id)
15
+ * - jsonl on disk ← SessionLog CHAT_PROJECT_SLUG file for
16
+ * messaging_sessions.agent_session_id
15
17
  */
16
18
  export declare class ChatSessionReader implements SessionSource {
17
19
  private db;
18
- private claudeHomeDir;
19
- constructor(db: StateDb, claudeHomeDir: string);
20
+ private sessionLog;
21
+ constructor(db: StateDb, sessionsHomeDir: string);
22
+ constructor(db: StateDb, sessionLog: SessionLog);
20
23
  /** All chat thread ids (= Slack threads) that have at least one chat execution. */
21
24
  listSessionIds(): string[];
22
25
  exists(id: string): boolean;
@@ -32,11 +35,5 @@ export declare class ChatSessionReader implements SessionSource {
32
35
  * Agent SDK installation).
33
36
  */
34
37
  getFilePath(id: string): string | null;
35
- /**
36
- * Read one specific jsonl file end-to-end. Crucially, we DO NOT walk
37
- * sibling `agent-*.jsonl` files like SessionReader does — those are
38
- * unrelated sidechain spawns from other in-process Agent SDK runs and
39
- * would pollute the conversation view.
40
- */
41
- private readSingleFile;
38
+ normalizeRawLine(raw: Record<string, unknown>): JsonlMessage[];
42
39
  }
@@ -1,38 +1,38 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import * as readline from "node:readline";
4
- import { unwrapLine } from "./sessions.js";
1
+ import { CHAT_PROJECT_SLUG, SessionLog, } from "../session-log.js";
5
2
  /**
6
3
  * DB-backed chat-session reader. Drop-in replacement for SessionReader on
7
4
  * the chat path: same public surface (`mountSessionRoutes` works against it
8
5
  * unchanged), but listing comes from the executions table grouped by Slack
9
6
  * thread, and message reads target the single jsonl file owned by that
10
- * thread's agent SDK session id no scanning of unrelated `agent-*.jsonl`
11
- * sidechain files in `claude-home/projects/-app/`.
7
+ * thread's pi-ai session id. SessionLog owns the on-disk CHAT_PROJECT_SLUG
8
+ * path resolution, so this reader does not scan unrelated `agent-*.jsonl`
9
+ * sidechain files from other in-process Agent SDK runs.
12
10
  *
13
11
  * Conceptual mapping:
14
12
  * - SessionMeta.id ← messaging_session.id (= Slack thread / executions.trigger_id)
15
- * - jsonl on disk ← claude-home/projects/-app/<agent_session_id>.jsonl
16
- * (resolved via messaging_sessions.agent_session_id)
13
+ * - jsonl on disk ← SessionLog CHAT_PROJECT_SLUG file for
14
+ * messaging_sessions.agent_session_id
17
15
  */
18
16
  export class ChatSessionReader {
19
17
  db;
20
- claudeHomeDir;
21
- constructor(db, claudeHomeDir) {
18
+ sessionLog;
19
+ constructor(db, sessionsHomeDirOrLog) {
22
20
  this.db = db;
23
- this.claudeHomeDir = claudeHomeDir;
21
+ this.sessionLog = typeof sessionsHomeDirOrLog === "string"
22
+ ? new SessionLog(sessionsHomeDirOrLog)
23
+ : sessionsHomeDirOrLog;
24
24
  }
25
25
  /** All chat thread ids (= Slack threads) that have at least one chat execution. */
26
26
  listSessionIds() {
27
27
  // Soft cap at 500 — anything older than that almost certainly won't be
28
28
  // surfaced after the dashboard's per-tab filters anyway.
29
- return this.db.listChatThreads(500).map((t) => t.triggerId);
29
+ return this.db.executions.listChatThreads(500).map((t) => t.triggerId);
30
30
  }
31
31
  exists(id) {
32
- return this.db.getChatThread(id) !== null;
32
+ return this.db.executions.getChatThread(id) !== null;
33
33
  }
34
34
  async getSessionMeta(id) {
35
- const t = this.db.getChatThread(id);
35
+ const t = this.db.executions.getChatThread(id);
36
36
  if (!t)
37
37
  return null;
38
38
  const startedAt = new Date(t.firstStartedAt).getTime() / 1000;
@@ -51,13 +51,17 @@ export class ChatSessionReader {
51
51
  conversation_message_count: t.turnCount,
52
52
  last_assistant_content: t.lastAssistantContent,
53
53
  agentIds: [],
54
+ platform: t.platform,
54
55
  };
55
56
  }
56
57
  async read(id) {
57
- const file = this.getFilePath(id);
58
- if (!file)
58
+ const thread = this.db.executions.getChatThread(id);
59
+ if (!thread?.agentSessionId)
59
60
  return [];
60
- return this.readSingleFile(file);
61
+ return this.sessionLog.readNormalizedSession("chat", thread.agentSessionId, {
62
+ includeAgents: false,
63
+ skipEmptySystem: true,
64
+ });
61
65
  }
62
66
  /**
63
67
  * Resolve a thread id to its on-disk Agent SDK jsonl. Returns null if
@@ -66,43 +70,15 @@ export class ChatSessionReader {
66
70
  * Agent SDK installation).
67
71
  */
68
72
  getFilePath(id) {
69
- const thread = this.db.getChatThread(id);
73
+ const thread = this.db.executions.getChatThread(id);
70
74
  if (!thread || !thread.agentSessionId)
71
75
  return null;
72
- const file = path.join(this.claudeHomeDir, "projects", "-app", `${thread.agentSessionId}.jsonl`);
73
- if (!fs.existsSync(file))
74
- return null;
75
- return file;
76
+ return this.sessionLog.pathForProject(CHAT_PROJECT_SLUG, thread.agentSessionId, {
77
+ requireExists: true,
78
+ });
76
79
  }
77
- /**
78
- * Read one specific jsonl file end-to-end. Crucially, we DO NOT walk
79
- * sibling `agent-*.jsonl` files like SessionReader does — those are
80
- * unrelated sidechain spawns from other in-process Agent SDK runs and
81
- * would pollute the conversation view.
82
- */
83
- async readSingleFile(file) {
84
- const out = [];
85
- const stream = fs.createReadStream(file, { encoding: "utf8" });
86
- const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
87
- for await (const line of rl) {
88
- if (!line.trim())
89
- continue;
90
- try {
91
- const raw = JSON.parse(line);
92
- const msgs = unwrapLine(raw);
93
- for (const msg of msgs) {
94
- if (msg.role === "system" && !msg.content)
95
- continue;
96
- const timestamp = msg.timestamp ?? raw.timestamp ?? "";
97
- out.push({ timestamp, msg });
98
- }
99
- }
100
- catch {
101
- // skip malformed line
102
- }
103
- }
104
- out.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
105
- return out.map((m, i) => ({ index: i, msg: m.msg }));
80
+ normalizeRawLine(raw) {
81
+ return this.sessionLog.normalizeLine(raw);
106
82
  }
107
83
  }
108
84
  //# sourceMappingURL=chat-session-reader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session-reader.js","sourceRoot":"","sources":["../../src/admin/chat-session-reader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-session-reader.js","sourceRoot":"","sources":["../../src/admin/chat-session-reader.ts"],"names":[],"mappings":"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"}
@@ -22,3 +22,40 @@ export declare function killContainer(containerName: string): Promise<void>;
22
22
  */
23
23
  export declare function getContainerStats(): Promise<ContainerStats[]>;
24
24
  export declare function listRunningContainers(): Promise<ContainerInfo[]>;
25
+ export interface ServerContainer {
26
+ name: string;
27
+ /** Short label derived from the compose name: lastlight-<service>-<n>. */
28
+ service: string;
29
+ status: string;
30
+ image: string;
31
+ }
32
+ /**
33
+ * Every `lastlight-*` container (the agent plus the egress sidecars,
34
+ * otel-collector, dozzle, and any live sandboxes) — running or stopped. Used
35
+ * by the server-logs endpoints so an operator can read the harness/docker logs
36
+ * over the admin API instead of SSHing to the host.
37
+ */
38
+ export declare function listServerContainers(): Promise<ServerContainer[]>;
39
+ /**
40
+ * Resolve a requested container (by full name OR short service label) to a real
41
+ * `lastlight-*` container name, validated against the live list. Returns null
42
+ * if nothing matches — callers reject the request, so an arbitrary container
43
+ * name can never reach `docker logs`. With no request, defaults to the agent.
44
+ */
45
+ export declare function resolveServerContainer(requested?: string): Promise<string | null>;
46
+ /**
47
+ * One-shot `docker logs` for a container, newest `tail` lines. `--timestamps`
48
+ * lets us interleave the container's stdout and stderr (captured on separate
49
+ * fds) back into chronological order — RFC3339 prefixes sort lexically.
50
+ */
51
+ export declare function getContainerLogs(name: string, opts?: {
52
+ tail?: number;
53
+ since?: string;
54
+ }): Promise<string[]>;
55
+ /**
56
+ * Follow `docker logs -f` for a container, invoking `onLine` per line from both
57
+ * stdout and stderr. Returns a stop function that kills the child process.
58
+ */
59
+ export declare function streamContainerLogs(name: string, opts: {
60
+ tail?: number;
61
+ }, onLine: (line: string) => void): () => void;
@@ -1,4 +1,4 @@
1
- import { execFile } from "node:child_process";
1
+ import { execFile, spawn } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
3
  const exec = promisify(execFile);
4
4
  export async function killContainer(containerName) {
@@ -99,4 +99,89 @@ export async function listRunningContainers() {
99
99
  return [];
100
100
  }
101
101
  }
102
+ /**
103
+ * Every `lastlight-*` container (the agent plus the egress sidecars,
104
+ * otel-collector, dozzle, and any live sandboxes) — running or stopped. Used
105
+ * by the server-logs endpoints so an operator can read the harness/docker logs
106
+ * over the admin API instead of SSHing to the host.
107
+ */
108
+ export async function listServerContainers() {
109
+ try {
110
+ const { stdout } = await exec("docker", [
111
+ "ps", "-a",
112
+ "--filter", "name=lastlight-",
113
+ "--format", "{{json .}}",
114
+ ]);
115
+ if (!stdout.trim())
116
+ return [];
117
+ return stdout.trim().split("\n").map((line) => {
118
+ const c = JSON.parse(line);
119
+ const name = c.Names ?? c.Name ?? "";
120
+ return {
121
+ name,
122
+ service: name.replace(/^lastlight-/, "").replace(/-\d+$/, ""),
123
+ status: c.Status ?? "",
124
+ image: c.Image ?? "",
125
+ };
126
+ });
127
+ }
128
+ catch {
129
+ return [];
130
+ }
131
+ }
132
+ /**
133
+ * Resolve a requested container (by full name OR short service label) to a real
134
+ * `lastlight-*` container name, validated against the live list. Returns null
135
+ * if nothing matches — callers reject the request, so an arbitrary container
136
+ * name can never reach `docker logs`. With no request, defaults to the agent.
137
+ */
138
+ export async function resolveServerContainer(requested) {
139
+ const containers = await listServerContainers();
140
+ if (requested) {
141
+ const hit = containers.find((c) => c.name === requested || c.service === requested);
142
+ return hit?.name ?? null;
143
+ }
144
+ const agent = containers.find((c) => c.service === "agent" || c.name.includes("-agent-"));
145
+ return agent?.name ?? containers[0]?.name ?? null;
146
+ }
147
+ /**
148
+ * One-shot `docker logs` for a container, newest `tail` lines. `--timestamps`
149
+ * lets us interleave the container's stdout and stderr (captured on separate
150
+ * fds) back into chronological order — RFC3339 prefixes sort lexically.
151
+ */
152
+ export async function getContainerLogs(name, opts = {}) {
153
+ const args = ["logs", "--timestamps", "--tail", String(opts.tail ?? 200)];
154
+ if (opts.since)
155
+ args.push("--since", opts.since);
156
+ args.push(name);
157
+ const { stdout, stderr } = await exec("docker", args, { maxBuffer: 32 * 1024 * 1024 });
158
+ const lines = [
159
+ ...(stdout ? stdout.split("\n") : []),
160
+ ...(stderr ? stderr.split("\n") : []),
161
+ ].filter((l) => l.length > 0);
162
+ lines.sort((a, b) => a.slice(0, 30).localeCompare(b.slice(0, 30)));
163
+ return lines;
164
+ }
165
+ /**
166
+ * Follow `docker logs -f` for a container, invoking `onLine` per line from both
167
+ * stdout and stderr. Returns a stop function that kills the child process.
168
+ */
169
+ export function streamContainerLogs(name, opts, onLine) {
170
+ const child = spawn("docker", [
171
+ "logs", "-f", "--timestamps", "--tail", String(opts.tail ?? 200), name,
172
+ ]);
173
+ const handle = (buf) => {
174
+ for (const line of buf.toString().split("\n"))
175
+ if (line)
176
+ onLine(line);
177
+ };
178
+ child.stdout?.on("data", handle);
179
+ child.stderr?.on("data", handle);
180
+ return () => {
181
+ try {
182
+ child.kill("SIGKILL");
183
+ }
184
+ catch { /* already dead */ }
185
+ };
186
+ }
102
187
  //# sourceMappingURL=docker.js.map