lastlight 0.16.0 → 0.16.2

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 (385) hide show
  1. package/README.md +71 -692
  2. package/dist/cli-config.js.map +1 -0
  3. package/dist/cli-format.js.map +1 -0
  4. package/dist/{cli/cli-server.d.ts → cli-server.d.ts} +39 -1
  5. package/dist/{cli/cli-server.js → cli-server.js} +105 -5
  6. package/dist/cli-server.js.map +1 -0
  7. package/dist/cli-timeline.js.map +1 -0
  8. package/dist/{cli/cli.js → cli.js} +9 -7
  9. package/dist/cli.js.map +1 -0
  10. package/dist/{cli/fork-cli.d.ts → fork-cli.d.ts} +3 -3
  11. package/dist/{cli/fork-cli.js → fork-cli.js} +28 -27
  12. package/dist/fork-cli.js.map +1 -0
  13. package/dist/{cli/oauth-cli.js → oauth-cli.js} +1 -1
  14. package/dist/oauth-cli.js.map +1 -0
  15. package/dist/{cli/setup.js → setup.js} +10 -4
  16. package/dist/setup.js.map +1 -0
  17. package/dist/{cli/skills-install.d.ts → skills-install.d.ts} +6 -0
  18. package/dist/{cli/skills-install.js → skills-install.js} +6 -2
  19. package/dist/skills-install.js.map +1 -0
  20. package/package.json +20 -65
  21. package/plugins/lastlight/.claude-plugin/plugin.json +1 -1
  22. package/agent-context/rules.md +0 -80
  23. package/agent-context/security.md +0 -69
  24. package/agent-context/soul.md +0 -21
  25. package/config/default.yaml +0 -119
  26. package/deploy/.env.production.example +0 -100
  27. package/deploy/entrypoint.sh +0 -82
  28. package/deploy/native/README.md +0 -160
  29. package/deploy/native/install.sh +0 -110
  30. package/deploy/native/lastlight.env.example +0 -95
  31. package/deploy/native/lastlight.service +0 -50
  32. package/deploy/sandbox-entrypoint.sh +0 -93
  33. package/dist/admin/auth.d.ts +0 -51
  34. package/dist/admin/auth.js +0 -121
  35. package/dist/admin/auth.js.map +0 -1
  36. package/dist/admin/chat-session-reader.d.ts +0 -39
  37. package/dist/admin/chat-session-reader.js +0 -84
  38. package/dist/admin/chat-session-reader.js.map +0 -1
  39. package/dist/admin/docker.d.ts +0 -61
  40. package/dist/admin/docker.js +0 -187
  41. package/dist/admin/docker.js.map +0 -1
  42. package/dist/admin/index.d.ts +0 -9
  43. package/dist/admin/index.js +0 -59
  44. package/dist/admin/index.js.map +0 -1
  45. package/dist/admin/routes.d.ts +0 -81
  46. package/dist/admin/routes.js +0 -1381
  47. package/dist/admin/routes.js.map +0 -1
  48. package/dist/admin/sessions.d.ts +0 -89
  49. package/dist/admin/sessions.js +0 -204
  50. package/dist/admin/sessions.js.map +0 -1
  51. package/dist/admin/tail.d.ts +0 -12
  52. package/dist/admin/tail.js +0 -145
  53. package/dist/admin/tail.js.map +0 -1
  54. package/dist/admin/version.d.ts +0 -22
  55. package/dist/admin/version.js +0 -92
  56. package/dist/admin/version.js.map +0 -1
  57. package/dist/cli/cli-config.js.map +0 -1
  58. package/dist/cli/cli-format.js.map +0 -1
  59. package/dist/cli/cli-server.js.map +0 -1
  60. package/dist/cli/cli-timeline.js.map +0 -1
  61. package/dist/cli/cli.js.map +0 -1
  62. package/dist/cli/fork-cli.js.map +0 -1
  63. package/dist/cli/oauth-cli.js.map +0 -1
  64. package/dist/cli/setup.js.map +0 -1
  65. package/dist/cli/skills-install.js.map +0 -1
  66. package/dist/config/config-resolve.d.ts +0 -28
  67. package/dist/config/config-resolve.js +0 -47
  68. package/dist/config/config-resolve.js.map +0 -1
  69. package/dist/config/config.d.ts +0 -157
  70. package/dist/config/config.js +0 -581
  71. package/dist/config/config.js.map +0 -1
  72. package/dist/config/core-pin.d.ts +0 -16
  73. package/dist/config/core-pin.js +0 -85
  74. package/dist/config/core-pin.js.map +0 -1
  75. package/dist/config/overlay-assets.d.ts +0 -20
  76. package/dist/config/overlay-assets.js +0 -114
  77. package/dist/config/overlay-assets.js.map +0 -1
  78. package/dist/config/overlay-bootstrap.d.ts +0 -44
  79. package/dist/config/overlay-bootstrap.js +0 -304
  80. package/dist/config/overlay-bootstrap.js.map +0 -1
  81. package/dist/connectors/github-webhook.d.ts +0 -45
  82. package/dist/connectors/github-webhook.js +0 -321
  83. package/dist/connectors/github-webhook.js.map +0 -1
  84. package/dist/connectors/index.d.ts +0 -18
  85. package/dist/connectors/index.js +0 -41
  86. package/dist/connectors/index.js.map +0 -1
  87. package/dist/connectors/messaging/base.d.ts +0 -42
  88. package/dist/connectors/messaging/base.js +0 -139
  89. package/dist/connectors/messaging/base.js.map +0 -1
  90. package/dist/connectors/messaging/delivery.d.ts +0 -14
  91. package/dist/connectors/messaging/delivery.js +0 -38
  92. package/dist/connectors/messaging/delivery.js.map +0 -1
  93. package/dist/connectors/messaging/index.d.ts +0 -4
  94. package/dist/connectors/messaging/index.js +0 -4
  95. package/dist/connectors/messaging/index.js.map +0 -1
  96. package/dist/connectors/messaging/session-manager.d.ts +0 -53
  97. package/dist/connectors/messaging/session-manager.js +0 -255
  98. package/dist/connectors/messaging/session-manager.js.map +0 -1
  99. package/dist/connectors/messaging/types.d.ts +0 -58
  100. package/dist/connectors/messaging/types.js +0 -7
  101. package/dist/connectors/messaging/types.js.map +0 -1
  102. package/dist/connectors/slack/connector.d.ts +0 -142
  103. package/dist/connectors/slack/connector.js +0 -494
  104. package/dist/connectors/slack/connector.js.map +0 -1
  105. package/dist/connectors/slack/index.d.ts +0 -2
  106. package/dist/connectors/slack/index.js +0 -3
  107. package/dist/connectors/slack/index.js.map +0 -1
  108. package/dist/connectors/slack/mrkdwn.d.ts +0 -19
  109. package/dist/connectors/slack/mrkdwn.js +0 -240
  110. package/dist/connectors/slack/mrkdwn.js.map +0 -1
  111. package/dist/connectors/types.d.ts +0 -61
  112. package/dist/connectors/types.js +0 -2
  113. package/dist/connectors/types.js.map +0 -1
  114. package/dist/cron/fanout.d.ts +0 -33
  115. package/dist/cron/fanout.js +0 -55
  116. package/dist/cron/fanout.js.map +0 -1
  117. package/dist/cron/jobs.d.ts +0 -18
  118. package/dist/cron/jobs.js +0 -37
  119. package/dist/cron/jobs.js.map +0 -1
  120. package/dist/cron/scheduler.d.ts +0 -45
  121. package/dist/cron/scheduler.js +0 -105
  122. package/dist/cron/scheduler.js.map +0 -1
  123. package/dist/engine/agent-executor.d.ts +0 -34
  124. package/dist/engine/agent-executor.js +0 -246
  125. package/dist/engine/agent-executor.js.map +0 -1
  126. package/dist/engine/chat/chat-runner.d.ts +0 -132
  127. package/dist/engine/chat/chat-runner.js +0 -424
  128. package/dist/engine/chat/chat-runner.js.map +0 -1
  129. package/dist/engine/chat/chat-skills.d.ts +0 -45
  130. package/dist/engine/chat/chat-skills.js +0 -184
  131. package/dist/engine/chat/chat-skills.js.map +0 -1
  132. package/dist/engine/chat/chat.d.ts +0 -54
  133. package/dist/engine/chat/chat.js +0 -316
  134. package/dist/engine/chat/chat.js.map +0 -1
  135. package/dist/engine/chat/message-batcher.d.ts +0 -32
  136. package/dist/engine/chat/message-batcher.js +0 -109
  137. package/dist/engine/chat/message-batcher.js.map +0 -1
  138. package/dist/engine/dispatcher.d.ts +0 -73
  139. package/dist/engine/dispatcher.js +0 -663
  140. package/dist/engine/dispatcher.js.map +0 -1
  141. package/dist/engine/event-shim.d.ts +0 -117
  142. package/dist/engine/event-shim.js +0 -435
  143. package/dist/engine/event-shim.js.map +0 -1
  144. package/dist/engine/executors/orchestrator.d.ts +0 -81
  145. package/dist/engine/executors/orchestrator.js +0 -365
  146. package/dist/engine/executors/orchestrator.js.map +0 -1
  147. package/dist/engine/executors/shared.d.ts +0 -189
  148. package/dist/engine/executors/shared.js +0 -616
  149. package/dist/engine/executors/shared.js.map +0 -1
  150. package/dist/engine/github/git-auth.d.ts +0 -62
  151. package/dist/engine/github/git-auth.js +0 -161
  152. package/dist/engine/github/git-auth.js.map +0 -1
  153. package/dist/engine/github/github-app-client.d.ts +0 -23
  154. package/dist/engine/github/github-app-client.js +0 -33
  155. package/dist/engine/github/github-app-client.js.map +0 -1
  156. package/dist/engine/github/github-tools.d.ts +0 -18
  157. package/dist/engine/github/github-tools.js +0 -263
  158. package/dist/engine/github/github-tools.js.map +0 -1
  159. package/dist/engine/github/github.d.ts +0 -1193
  160. package/dist/engine/github/github.js +0 -357
  161. package/dist/engine/github/github.js.map +0 -1
  162. package/dist/engine/github/profiles.d.ts +0 -279
  163. package/dist/engine/github/profiles.js +0 -42
  164. package/dist/engine/github/profiles.js.map +0 -1
  165. package/dist/engine/github/review-poster.d.ts +0 -98
  166. package/dist/engine/github/review-poster.js +0 -177
  167. package/dist/engine/github/review-poster.js.map +0 -1
  168. package/dist/engine/llm.d.ts +0 -79
  169. package/dist/engine/llm.js +0 -269
  170. package/dist/engine/llm.js.map +0 -1
  171. package/dist/engine/oauth.d.ts +0 -43
  172. package/dist/engine/oauth.js +0 -103
  173. package/dist/engine/oauth.js.map +0 -1
  174. package/dist/engine/router.d.ts +0 -29
  175. package/dist/engine/router.js +0 -680
  176. package/dist/engine/router.js.map +0 -1
  177. package/dist/engine/screen/classifier.d.ts +0 -93
  178. package/dist/engine/screen/classifier.js +0 -215
  179. package/dist/engine/screen/classifier.js.map +0 -1
  180. package/dist/engine/screen/screen.d.ts +0 -41
  181. package/dist/engine/screen/screen.js +0 -93
  182. package/dist/engine/screen/screen.js.map +0 -1
  183. package/dist/evals-api.d.ts +0 -24
  184. package/dist/evals-api.js +0 -22
  185. package/dist/evals-api.js.map +0 -1
  186. package/dist/index.d.ts +0 -1
  187. package/dist/index.js +0 -940
  188. package/dist/index.js.map +0 -1
  189. package/dist/managed-repos.d.ts +0 -30
  190. package/dist/managed-repos.js +0 -72
  191. package/dist/managed-repos.js.map +0 -1
  192. package/dist/notify/blocks.d.ts +0 -23
  193. package/dist/notify/blocks.js +0 -118
  194. package/dist/notify/blocks.js.map +0 -1
  195. package/dist/notify/index.d.ts +0 -17
  196. package/dist/notify/index.js +0 -7
  197. package/dist/notify/index.js.map +0 -1
  198. package/dist/notify/model.d.ts +0 -57
  199. package/dist/notify/model.js +0 -89
  200. package/dist/notify/model.js.map +0 -1
  201. package/dist/notify/notifier.d.ts +0 -18
  202. package/dist/notify/notifier.js +0 -100
  203. package/dist/notify/notifier.js.map +0 -1
  204. package/dist/notify/render.d.ts +0 -21
  205. package/dist/notify/render.js +0 -59
  206. package/dist/notify/render.js.map +0 -1
  207. package/dist/notify/transports/github.d.ts +0 -26
  208. package/dist/notify/transports/github.js +0 -27
  209. package/dist/notify/transports/github.js.map +0 -1
  210. package/dist/notify/transports/slack.d.ts +0 -27
  211. package/dist/notify/transports/slack.js +0 -37
  212. package/dist/notify/transports/slack.js.map +0 -1
  213. package/dist/notify/types.d.ts +0 -119
  214. package/dist/notify/types.js +0 -16
  215. package/dist/notify/types.js.map +0 -1
  216. package/dist/providers.d.ts +0 -125
  217. package/dist/providers.js +0 -279
  218. package/dist/providers.js.map +0 -1
  219. package/dist/sandbox/docker.d.ts +0 -180
  220. package/dist/sandbox/docker.js +0 -517
  221. package/dist/sandbox/docker.js.map +0 -1
  222. package/dist/sandbox/egress-allowlist.d.ts +0 -74
  223. package/dist/sandbox/egress-allowlist.js +0 -164
  224. package/dist/sandbox/egress-allowlist.js.map +0 -1
  225. package/dist/sandbox/egress-firewall-config.d.ts +0 -127
  226. package/dist/sandbox/egress-firewall-config.js +0 -434
  227. package/dist/sandbox/egress-firewall-config.js.map +0 -1
  228. package/dist/sandbox/images.d.ts +0 -23
  229. package/dist/sandbox/images.js +0 -55
  230. package/dist/sandbox/images.js.map +0 -1
  231. package/dist/sandbox/index.d.ts +0 -112
  232. package/dist/sandbox/index.js +0 -332
  233. package/dist/sandbox/index.js.map +0 -1
  234. package/dist/sandbox/sandbox.d.ts +0 -214
  235. package/dist/sandbox/sandbox.js +0 -453
  236. package/dist/sandbox/sandbox.js.map +0 -1
  237. package/dist/sandbox/smol.d.ts +0 -162
  238. package/dist/sandbox/smol.js +0 -485
  239. package/dist/sandbox/smol.js.map +0 -1
  240. package/dist/session-log.d.ts +0 -63
  241. package/dist/session-log.js +0 -290
  242. package/dist/session-log.js.map +0 -1
  243. package/dist/state/approval-store.d.ts +0 -88
  244. package/dist/state/approval-store.js +0 -149
  245. package/dist/state/approval-store.js.map +0 -1
  246. package/dist/state/build-assets.d.ts +0 -50
  247. package/dist/state/build-assets.js +0 -154
  248. package/dist/state/build-assets.js.map +0 -1
  249. package/dist/state/db.d.ts +0 -81
  250. package/dist/state/db.js +0 -155
  251. package/dist/state/db.js.map +0 -1
  252. package/dist/state/execution-store.d.ts +0 -257
  253. package/dist/state/execution-store.js +0 -527
  254. package/dist/state/execution-store.js.map +0 -1
  255. package/dist/state/migrate.d.ts +0 -15
  256. package/dist/state/migrate.js +0 -175
  257. package/dist/state/migrate.js.map +0 -1
  258. package/dist/state/workflow-run-store.d.ts +0 -216
  259. package/dist/state/workflow-run-store.js +0 -403
  260. package/dist/state/workflow-run-store.js.map +0 -1
  261. package/dist/telemetry/index.d.ts +0 -38
  262. package/dist/telemetry/index.js +0 -253
  263. package/dist/telemetry/index.js.map +0 -1
  264. package/dist/telemetry/pi-events.d.ts +0 -12
  265. package/dist/telemetry/pi-events.js +0 -134
  266. package/dist/telemetry/pi-events.js.map +0 -1
  267. package/dist/workflows/dag.d.ts +0 -37
  268. package/dist/workflows/dag.js +0 -118
  269. package/dist/workflows/dag.js.map +0 -1
  270. package/dist/workflows/loader.d.ts +0 -53
  271. package/dist/workflows/loader.js +0 -421
  272. package/dist/workflows/loader.js.map +0 -1
  273. package/dist/workflows/loop-eval.d.ts +0 -28
  274. package/dist/workflows/loop-eval.js +0 -74
  275. package/dist/workflows/loop-eval.js.map +0 -1
  276. package/dist/workflows/phase-executor.d.ts +0 -222
  277. package/dist/workflows/phase-executor.js +0 -1153
  278. package/dist/workflows/phase-executor.js.map +0 -1
  279. package/dist/workflows/phase-ref.d.ts +0 -50
  280. package/dist/workflows/phase-ref.js +0 -91
  281. package/dist/workflows/phase-ref.js.map +0 -1
  282. package/dist/workflows/resume.d.ts +0 -58
  283. package/dist/workflows/resume.js +0 -313
  284. package/dist/workflows/resume.js.map +0 -1
  285. package/dist/workflows/runner.d.ts +0 -63
  286. package/dist/workflows/runner.js +0 -381
  287. package/dist/workflows/runner.js.map +0 -1
  288. package/dist/workflows/schema.d.ts +0 -344
  289. package/dist/workflows/schema.js +0 -460
  290. package/dist/workflows/schema.js.map +0 -1
  291. package/dist/workflows/simple.d.ts +0 -90
  292. package/dist/workflows/simple.js +0 -393
  293. package/dist/workflows/simple.js.map +0 -1
  294. package/dist/workflows/target-policy.d.ts +0 -74
  295. package/dist/workflows/target-policy.js +0 -80
  296. package/dist/workflows/target-policy.js.map +0 -1
  297. package/dist/workflows/templates.d.ts +0 -88
  298. package/dist/workflows/templates.js +0 -127
  299. package/dist/workflows/templates.js.map +0 -1
  300. package/dist/workflows/triggers.d.ts +0 -21
  301. package/dist/workflows/triggers.js +0 -45
  302. package/dist/workflows/triggers.js.map +0 -1
  303. package/dist/workflows/verdict.d.ts +0 -19
  304. package/dist/workflows/verdict.js +0 -30
  305. package/dist/workflows/verdict.js.map +0 -1
  306. package/dist/worktree/manager.d.ts +0 -43
  307. package/dist/worktree/manager.js +0 -127
  308. package/dist/worktree/manager.js.map +0 -1
  309. package/docker-compose.yml +0 -274
  310. package/sandbox.Dockerfile +0 -68
  311. package/skills/README.md +0 -42
  312. package/skills/browser-qa/SKILL.md +0 -208
  313. package/skills/browser-qa/scripts/agent-browser.mjs +0 -531
  314. package/skills/building/SKILL.md +0 -95
  315. package/skills/chat/SKILL.md +0 -36
  316. package/skills/code-review/SKILL.md +0 -82
  317. package/skills/debug-production/SKILL.md +0 -108
  318. package/skills/demo/SKILL.md +0 -228
  319. package/skills/demo/scripts/compose-demo.sh +0 -243
  320. package/skills/issue-answer/SKILL.md +0 -91
  321. package/skills/issue-comment/SKILL.md +0 -49
  322. package/skills/issue-triage/SKILL.md +0 -149
  323. package/skills/issue-triage/references/AGENT-BRIEF.md +0 -65
  324. package/skills/pr-comment/SKILL.md +0 -64
  325. package/skills/pr-review/SKILL.md +0 -148
  326. package/skills/pr-review/references/findings-schema.md +0 -89
  327. package/skills/qa-test/SKILL.md +0 -97
  328. package/skills/repo-health/SKILL.md +0 -67
  329. package/skills/security-feedback/SKILL.md +0 -173
  330. package/skills/security-feedback/references/templates.md +0 -77
  331. package/skills/security-review/SKILL.md +0 -215
  332. package/skills/security-review/references/issue-format.md +0 -302
  333. package/skills/verify/SKILL.md +0 -118
  334. package/workflows/answer.yaml +0 -44
  335. package/workflows/build.yaml +0 -129
  336. package/workflows/cron-health.yaml +0 -6
  337. package/workflows/cron-review.yaml +0 -8
  338. package/workflows/cron-security.yaml +0 -6
  339. package/workflows/cron-triage.yaml +0 -8
  340. package/workflows/demo.yaml +0 -62
  341. package/workflows/examples/bash-smoke.yaml +0 -41
  342. package/workflows/examples/parallel-review.yaml +0 -36
  343. package/workflows/examples/tdd-loop.yaml +0 -17
  344. package/workflows/explore.yaml +0 -80
  345. package/workflows/issue-comment.yaml +0 -15
  346. package/workflows/issue-triage.yaml +0 -22
  347. package/workflows/pr-comment.yaml +0 -16
  348. package/workflows/pr-fix.yaml +0 -17
  349. package/workflows/pr-review.yaml +0 -50
  350. package/workflows/prompts/answer.md +0 -68
  351. package/workflows/prompts/architect.md +0 -44
  352. package/workflows/prompts/classifier.md +0 -60
  353. package/workflows/prompts/classify-adds-info.md +0 -17
  354. package/workflows/prompts/demo.md +0 -125
  355. package/workflows/prompts/executor.md +0 -42
  356. package/workflows/prompts/explore-ask.md +0 -99
  357. package/workflows/prompts/explore-publish.md +0 -31
  358. package/workflows/prompts/explore-read.md +0 -120
  359. package/workflows/prompts/explore-synthesize.md +0 -88
  360. package/workflows/prompts/fix.md +0 -18
  361. package/workflows/prompts/guardrails.md +0 -96
  362. package/workflows/prompts/pr-fix.md +0 -26
  363. package/workflows/prompts/pr.md +0 -39
  364. package/workflows/prompts/qa-browser.md +0 -95
  365. package/workflows/prompts/qa-synth.md +0 -44
  366. package/workflows/prompts/qa-test.md +0 -60
  367. package/workflows/prompts/re-reviewer.md +0 -33
  368. package/workflows/prompts/reviewer.md +0 -60
  369. package/workflows/prompts/verify-browser.md +0 -93
  370. package/workflows/prompts/verify-synth.md +0 -44
  371. package/workflows/prompts/verify.md +0 -63
  372. package/workflows/qa-test.yaml +0 -94
  373. package/workflows/repo-health.yaml +0 -15
  374. package/workflows/security-feedback.yaml +0 -25
  375. package/workflows/security-review.yaml +0 -37
  376. package/workflows/verify.yaml +0 -93
  377. /package/dist/{cli/cli-config.d.ts → cli-config.d.ts} +0 -0
  378. /package/dist/{cli/cli-config.js → cli-config.js} +0 -0
  379. /package/dist/{cli/cli-format.d.ts → cli-format.d.ts} +0 -0
  380. /package/dist/{cli/cli-format.js → cli-format.js} +0 -0
  381. /package/dist/{cli/cli-timeline.d.ts → cli-timeline.d.ts} +0 -0
  382. /package/dist/{cli/cli-timeline.js → cli-timeline.js} +0 -0
  383. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
  384. /package/dist/{cli/oauth-cli.d.ts → oauth-cli.d.ts} +0 -0
  385. /package/dist/{cli/setup.d.ts → setup.d.ts} +0 -0
@@ -1,100 +0,0 @@
1
- # ── Last Light — Production Environment ──────────────────────────
2
- # Copy this file to instance/secrets/.env and fill in your values, where
3
- # instance/ is your private deployment overlay (a separate repo cloned next to
4
- # docker-compose.yml). The whole instance/ folder is mounted read-only into the
5
- # container at /app/instance; the entrypoint reads secrets from
6
- # /app/instance/secrets, and both the agent and caddy services read this file
7
- # via env_file. No repo-root .env is needed.
8
- #
9
- # Overlay config + assets (config.yaml + agent-context/ + workflows/ + skills/)
10
- # are read at startup — edit and `lastlight server restart agent` to apply, no
11
- # rebuild. (Removing a var here needs a recreate: `lastlight server start agent`.)
12
- LASTLIGHT_OVERLAY_DIR=/app/instance
13
-
14
- # =================================================================
15
- # GITHUB APP (required)
16
- # =================================================================
17
- # Create a GitHub App: https://docs.github.com/en/apps/creating-github-apps
18
- # Permissions: Issues (R/W), Pull Requests (R/W), Contents (R/W), Metadata (R).
19
- # Subscribe to issue, issue_comment, pull_request, and pull_request_review events.
20
- # Drop the App private key at instance/secrets/app.pem (the entrypoint symlinks
21
- # it to /app/app.pem; GITHUB_APP_PRIVATE_KEY_PATH is resolved relative to /app).
22
-
23
- GITHUB_APP_ID=
24
- GITHUB_APP_PRIVATE_KEY_PATH=./app.pem
25
- GITHUB_APP_INSTALLATION_ID=
26
-
27
- # =================================================================
28
- # WEBHOOK (required)
29
- # =================================================================
30
- # Must match the webhook secret configured in your GitHub App settings.
31
-
32
- WEBHOOK_SECRET=change-me-to-a-random-string
33
-
34
- # =================================================================
35
- # MODEL + LLM PROVIDER (required — pick one provider key)
36
- # =================================================================
37
- # Default model for sandbox + chat. Any provider/model agentic-pi supports:
38
- # anthropic/…, openai/…, openrouter/<vendor>/<model>, or any pi-ai provider
39
- # (google/…, mistral/…, groq/…, cerebras/…, xai/…, huggingface/…, moonshotai/…,
40
- # nvidia/…, fireworks/…, together/…, deepseek/…, zai/…, kimi-coding/…,
41
- # minimax/…). See src/providers.ts for the registered set.
42
- LASTLIGHT_MODEL=anthropic/claude-sonnet-4-6
43
-
44
- # Set whichever key matches LASTLIGHT_MODEL (set more than one if per-task
45
- # overrides in config.yaml route phases to different providers).
46
- # ANTHROPIC_API_KEY=sk-ant-...
47
- # OPENAI_API_KEY=sk-proj-...
48
- # OPENROUTER_API_KEY=sk-or-...
49
- # GEMINI_API_KEY=AIza... MISTRAL_API_KEY=... GROQ_API_KEY=gsk_...
50
- # CEREBRAS_API_KEY=... XAI_API_KEY=... HF_TOKEN=hf_...
51
- # MOONSHOT_API_KEY=... NVIDIA_API_KEY=... FIREWORKS_API_KEY=...
52
- # TOGETHER_API_KEY=... DEEPSEEK_API_KEY=... ZAI_API_KEY=...
53
- # KIMI_API_KEY=... MINIMAX_API_KEY=...
54
-
55
- # =================================================================
56
- # DOMAIN (for Caddy TLS)
57
- # =================================================================
58
- # Public hostname for automatic Let's Encrypt TLS. Leave "localhost" for local
59
- # dev (HTTP only). The webhook URL is https://<DOMAIN>/webhook.
60
-
61
- DOMAIN=localhost
62
-
63
- # =================================================================
64
- # ADMIN DASHBOARD
65
- # =================================================================
66
- # ADMIN_SECRET signs session tokens (required for login). ADMIN_PASSWORD enables
67
- # password login; auth is also satisfied by a configured OAuth provider below.
68
-
69
- ADMIN_SECRET=change-me-to-a-random-string
70
- # ADMIN_PASSWORD=
71
-
72
- # =================================================================
73
- # OPTIONAL: SLACK
74
- # =================================================================
75
- # Enables the messaging connector + chat skill (and the chat server).
76
- # SLACK_BOT_TOKEN=xoxb-...
77
- # SLACK_APP_TOKEN=xapp-...
78
- # SLACK_DELIVERY_CHANNEL= # channel id for cron reports
79
- # SLACK_ALLOWED_USERS= # comma-separated user ids
80
- #
81
- # "Login with Slack" on the dashboard (OIDC):
82
- # SLACK_OAUTH_CLIENT_ID=
83
- # SLACK_OAUTH_CLIENT_SECRET=
84
- # SLACK_OAUTH_REDIRECT_URI=https://<DOMAIN>/admin/api/auth/slack/callback
85
- # SLACK_ALLOWED_WORKSPACE= # restrict login to one team_id / domain
86
-
87
- # =================================================================
88
- # OPTIONAL: WEB SEARCH (explore workflow only)
89
- # =================================================================
90
- # Set any one to enable agentic-pi's web_search / web_fetch tools for phases
91
- # that opt in (Tavily > Exa > Brave). Other workflows ignore these keys.
92
- # TAVILY_API_KEY=tvly-...
93
- # EXA_API_KEY=...
94
- # BRAVE_SEARCH_API_KEY=BSA...
95
-
96
- # =================================================================
97
- # OPTIONAL: RUNTIME
98
- # =================================================================
99
- # PORT=8644 # webhook listener / admin port
100
- # STATE_DIR=./data # persistent state (mounted as a volume)
@@ -1,82 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Last Light Docker entrypoint
3
- # Links secrets, ensures state dirs, then starts the harness.
4
- set -euo pipefail
5
-
6
- # Secrets live in the consolidated deployment folder (instance/secrets). Fall
7
- # back to the legacy standalone secrets/ mount for pre-migration deployments.
8
- SECRETS="/app/instance/secrets"
9
- [ -d "$SECRETS" ] || SECRETS="/app/secrets"
10
- APP_DIR="/app"
11
- STATE_DIR="${STATE_DIR:-/app/data}"
12
-
13
- # Materialize secrets into the writable /app layer, owned by `lastlight` (mode
14
- # 600). We COPY rather than symlink: the source lives on a read-only mount owned
15
- # by whatever uid created it on the host (often 1000), while the harness runs as
16
- # `lastlight` (uid-pinned 10001) via gosu below. A symlink would leave the
17
- # unreadable 600 source in place and the harness would EACCES on it. root (this
18
- # entrypoint, pre-gosu) bypasses the source perms to read+copy; the chown then
19
- # hands the copy to lastlight. Same pattern as the PEM→state-volume copy below.
20
- # rm -f first so a stale symlink from an older image isn't written through.
21
- for f in .env; do
22
- if [ -f "$SECRETS/$f" ]; then
23
- rm -f "$APP_DIR/$f"
24
- cp "$SECRETS/$f" "$APP_DIR/$f"
25
- chown lastlight:lastlight "$APP_DIR/$f"
26
- chmod 600 "$APP_DIR/$f"
27
- echo "Copied $f from secrets volume"
28
- fi
29
- done
30
-
31
- # GitHub App private key(s) — same copy+chown so the in-process Octokit (which
32
- # also runs as lastlight) can read them.
33
- for pem in "$SECRETS"/*.pem; do
34
- if [ -f "$pem" ]; then
35
- dest="$APP_DIR/$(basename "$pem")"
36
- rm -f "$dest"
37
- cp "$pem" "$dest"
38
- chown lastlight:lastlight "$dest"
39
- chmod 600 "$dest"
40
- echo "Copied $(basename "$pem") from secrets volume"
41
- fi
42
- done
43
-
44
- # Ensure state directory structure exists and is owned by lastlight.
45
- # agent-sessions/ is where agentic-pi's event shim writes JSONL envelopes
46
- # the dashboard reads (path is set by LASTLIGHT_SESSIONS_DIR).
47
- mkdir -p "$STATE_DIR"/{logs,sandboxes,secrets,agent-sessions}
48
- chown -R lastlight:lastlight "$STATE_DIR"
49
-
50
- # Copy PEM to the data volume so sandbox containers can access it via shared
51
- # volume (LASTLIGHT_SANDBOX=docker fallback path only — gondolin doesn't go
52
- # through this). Owner is `lastlight` so the host harness (which exec's via
53
- # gosu lastlight below) can read it for in-process GitHub API calls.
54
- # Sandbox-entrypoint runs as root before switching to `agent`, so it can
55
- # still read this 600 file and materialize an agent-readable copy when
56
- # ALLOW_APP_PEM=1.
57
- for pem in "$SECRETS"/*.pem; do
58
- if [ -f "$pem" ]; then
59
- cp "$pem" "$STATE_DIR/secrets/app.pem"
60
- chown lastlight:lastlight "$STATE_DIR/secrets/app.pem"
61
- chmod 600 "$STATE_DIR/secrets/app.pem"
62
- echo "Copied PEM to data volume for sandbox access"
63
- break
64
- fi
65
- done
66
-
67
- # Source .env if available
68
- if [ -f "$APP_DIR/.env" ]; then
69
- set -a
70
- # shellcheck disable=SC1091
71
- source "$APP_DIR/.env"
72
- set +a
73
- fi
74
-
75
- # Fix Docker socket permissions — host GID may differ from container docker group
76
- if [ -S /var/run/docker.sock ]; then
77
- chmod 666 /var/run/docker.sock
78
- fi
79
-
80
- echo "Starting Last Light (state: $STATE_DIR)..."
81
- # Drop to non-root before exec'ing the harness.
82
- exec gosu lastlight "$@"
@@ -1,160 +0,0 @@
1
- # Native deploy (systemd + gondolin)
2
-
3
- Production deploy for `lastlight` as a systemd service on a KVM-capable
4
- Linux host. Replaces the Docker compose deploy; the Dockerfiles in the
5
- repo root are kept only for local prod-like smoke testing.
6
-
7
- ## Why native
8
-
9
- `agentic-pi`'s gondolin sandbox needs `/dev/kvm`. Running lastlight inside
10
- a container loses or complicates KVM access (Docker-in-Docker, nested
11
- virt, capability juggling). On a bare-metal Linux box you get
12
- near-native VM performance with no extra moving parts.
13
-
14
- See `agentic-pi/SPIKE-gondolin.md` for the full analysis.
15
-
16
- ## First-time install
17
-
18
- On the prod host as root:
19
-
20
- ```bash
21
- # 1. Clone the repo to the canonical path.
22
- git clone https://github.com/nearform/lastlight.git /opt/lastlight
23
- cd /opt/lastlight
24
-
25
- # 2. (Optional) Drop the GitHub App PEM in place before the install runs,
26
- # so install.sh locks it down. Otherwise place it later and re-run.
27
- install -m 0600 -o root /path/to/your-app.pem /etc/lastlight/app.pem
28
-
29
- # 3. Provision system + install systemd unit.
30
- sudo bash deploy/native/install.sh
31
-
32
- # 4. install.sh scaffolds /etc/lastlight/lastlight.env from the example
33
- # and refuses to (re)start the service while any CHANGE_ME placeholder
34
- # remains. Edit it:
35
- sudo $EDITOR /etc/lastlight/lastlight.env
36
-
37
- # 5. Re-run install.sh to start the service.
38
- sudo bash deploy/native/install.sh
39
- ```
40
-
41
- ## Re-deploying a code change
42
-
43
- ```bash
44
- cd /opt/lastlight
45
- sudo -u lastlight git pull
46
- sudo bash deploy/native/install.sh # rebuilds + restarts the service
47
- ```
48
-
49
- The existing `/home/lastlight/deploy.sh` on the prod host should be
50
- replaced with the two lines above (or wrap them in a script).
51
-
52
- ## What's where
53
-
54
- | Path | Purpose |
55
- | --- | --- |
56
- | `/opt/lastlight` | Source checkout. `node dist/index.js` runs from here. |
57
- | `/etc/lastlight/lastlight.env` | systemd EnvironmentFile (mode 0640). Holds all secrets. |
58
- | `/etc/lastlight/app.pem` | GitHub App private key (mode 0640). Optional but typical. |
59
- | `/var/lib/lastlight/` | Persistent state — SQLite DB, session JSONLs, gondolin image cache. |
60
- | `/var/lib/lastlight/lastlight.db` | Workflow runs, executions, messaging sessions. |
61
- | `/var/lib/lastlight/agent-sessions/` | Dashboard's JSONL envelope store. |
62
- | `/var/lib/lastlight/.cache/agentic-pi/images/` | Downloaded gondolin guest images (~89 MB each). |
63
- | `/var/log/lastlight/` | LogsDirectory if anything writes to it. |
64
- | `/etc/systemd/system/lastlight.service` | The unit file (installed by install.sh from `deploy/native/lastlight.service`). |
65
-
66
- ## Operations
67
-
68
- ```bash
69
- # Status / logs
70
- systemctl status lastlight
71
- journalctl -u lastlight -f # live tail
72
- journalctl -u lastlight --since '10 min ago' # recent
73
-
74
- # Restart (e.g. after an env edit that doesn't need a rebuild)
75
- sudo systemctl restart lastlight
76
-
77
- # Stop / disable
78
- sudo systemctl stop lastlight
79
- sudo systemctl disable lastlight
80
- ```
81
-
82
- ## TLS / reverse proxy
83
-
84
- The harness binds `127.0.0.1:8644` by default (PORT in the env file).
85
- Front it with Caddy or nginx for TLS.
86
-
87
- Minimal Caddy setup:
88
-
89
- ```bash
90
- sudo apt-get install -y caddy
91
- sudo tee /etc/caddy/Caddyfile <<'EOF'
92
- your-domain.example.com {
93
- reverse_proxy 127.0.0.1:8644
94
- }
95
- EOF
96
- sudo systemctl reload caddy
97
- ```
98
-
99
- ## Migrating from the Docker compose deploy
100
-
101
- On the old (Docker compose) box:
102
-
103
- ```bash
104
- # Snapshot the persistent volume.
105
- docker run --rm -v lastlight_agent-data:/data -v /tmp:/backup busybox \
106
- tar czf /backup/lastlight-data.tgz -C /data .
107
- scp /tmp/lastlight-data.tgz root@new-host:/tmp/
108
- docker compose down
109
- ```
110
-
111
- On the new (native) host, after running install.sh and editing the env file:
112
-
113
- ```bash
114
- sudo systemctl stop lastlight
115
- sudo tar xzf /tmp/lastlight-data.tgz -C /var/lib/lastlight \
116
- lastlight.db lastlight.db-shm lastlight.db-wal \
117
- agent-sessions secrets || true
118
- # The old volume used these directory names that the new code doesn't read.
119
- # Safe to skip restoring them: opencode-home/, opencode-serve/, sandboxes/,
120
- # sandbox-data/, sessions/, claude-home/.
121
- sudo chown -R lastlight:lastlight /var/lib/lastlight
122
- sudo systemctl start lastlight
123
- ```
124
-
125
- The DB schema is unchanged across the migration, so workflow_runs +
126
- executions history carry over.
127
-
128
- ## Rollback
129
-
130
- If the new service doesn't come up cleanly:
131
-
132
- ```bash
133
- sudo systemctl stop lastlight
134
- sudo systemctl disable lastlight
135
- # Restore the docker stack on the same host (or fail over to the old host)
136
- docker compose up -d
137
- ```
138
-
139
- State at `/var/lib/lastlight/` and the docker `agent-data` volume are
140
- independent — neither rollback step touches the other.
141
-
142
- ## Verification
143
-
144
- After the service is up:
145
-
146
- ```bash
147
- # 1. It started cleanly.
148
- systemctl status lastlight # → active (running)
149
-
150
- # 2. KVM is reachable from the service's user context.
151
- sudo -u lastlight ls -l /dev/kvm
152
-
153
- # 3. The harness is listening.
154
- curl -sS http://127.0.0.1:8644/admin/ | head -5
155
-
156
- # 4. (Optional) Trigger a real workflow via a PR comment and watch:
157
- journalctl -u lastlight -f
158
- # Then look in the dashboard for the executions row + a JSONL under
159
- # /var/lib/lastlight/agent-sessions/projects/<slug>/
160
- ```
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Idempotent provision + (re)deploy of lastlight as a systemd service on a
3
- # KVM-capable Linux host. Run as root from the repo root:
4
- #
5
- # sudo bash deploy/native/install.sh
6
- #
7
- # On first run: installs system deps, creates the lastlight user, scaffolds
8
- # /etc/lastlight/lastlight.env from the example, installs and starts the
9
- # systemd unit. On subsequent runs: re-installs the deps that changed,
10
- # rebuilds, restarts the service.
11
-
12
- set -euo pipefail
13
-
14
- REPO_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
15
- SERVICE_NAME=lastlight
16
- LASTLIGHT_USER=lastlight
17
- LASTLIGHT_HOME=/var/lib/lastlight
18
- ENV_DIR=/etc/lastlight
19
- ENV_FILE="${ENV_DIR}/lastlight.env"
20
- PEM_FILE="${ENV_DIR}/app.pem"
21
-
22
- if [ "$(id -u)" -ne 0 ]; then
23
- echo "install.sh must run as root (try: sudo $0)" >&2
24
- exit 1
25
- fi
26
-
27
- # ── 1. KVM check — gondolin silently hangs without it ──────────────────────
28
- if [ ! -e /dev/kvm ]; then
29
- echo "ERROR: /dev/kvm not present on this host." >&2
30
- echo " gondolin (lastlight's default sandbox) requires KVM. The host must" >&2
31
- echo " be bare-metal Linux or a VM with nested virtualization enabled." >&2
32
- echo " See agentic-pi/SPIKE-gondolin.md for the full constraint." >&2
33
- exit 1
34
- fi
35
-
36
- # ── 2. System dependencies (Debian/Ubuntu) ─────────────────────────────────
37
- export DEBIAN_FRONTEND=noninteractive
38
- apt-get update
39
- apt-get install -y --no-install-recommends \
40
- curl ca-certificates git \
41
- qemu-system-x86 qemu-utils \
42
- python3 build-essential
43
- # Use NodeSource for a current Node 22 LTS (Debian's nodejs is too old).
44
- if ! command -v node >/dev/null 2>&1 || ! node -e 'process.exit(process.versions.node.split(".")[0] >= 20 ? 0 : 1)'; then
45
- curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
46
- apt-get install -y --no-install-recommends nodejs
47
- fi
48
-
49
- # ── 3. User + group ────────────────────────────────────────────────────────
50
- if ! id "$LASTLIGHT_USER" >/dev/null 2>&1; then
51
- useradd --system --create-home --home-dir "$LASTLIGHT_HOME" \
52
- --shell /usr/sbin/nologin "$LASTLIGHT_USER"
53
- fi
54
- # `kvm` group exists once qemu is installed; gate the membership add to
55
- # avoid a usermod warning on hosts where it doesn't.
56
- if getent group kvm >/dev/null 2>&1; then
57
- usermod -aG kvm "$LASTLIGHT_USER"
58
- fi
59
-
60
- # ── 4. Repo install + build (as the lastlight user) ────────────────────────
61
- chown -R "$LASTLIGHT_USER:$LASTLIGHT_USER" "$REPO_DIR"
62
- sudo -u "$LASTLIGHT_USER" -H bash -c "cd '$REPO_DIR' && npm ci --no-audit --no-fund"
63
- sudo -u "$LASTLIGHT_USER" -H bash -c "cd '$REPO_DIR' && npm run build && npm run build:dashboard"
64
- # Prune dev deps to shrink the on-disk footprint of the deployed checkout.
65
- sudo -u "$LASTLIGHT_USER" -H bash -c "cd '$REPO_DIR' && npm prune --omit=dev"
66
-
67
- # ── 5. Env file scaffold (don't overwrite an existing config) ──────────────
68
- mkdir -p "$ENV_DIR"
69
- chmod 0750 "$ENV_DIR"
70
- chgrp "$LASTLIGHT_USER" "$ENV_DIR"
71
- if [ ! -f "$ENV_FILE" ]; then
72
- install -m 0640 -o root -g "$LASTLIGHT_USER" \
73
- "$REPO_DIR/deploy/native/lastlight.env.example" "$ENV_FILE"
74
- echo "" >&2
75
- echo " NOTE: $ENV_FILE was just created from the example template." >&2
76
- echo " Edit it to fill in your GitHub App, model API keys, Slack tokens, etc." >&2
77
- echo " Then re-run this script to start the service." >&2
78
- echo "" >&2
79
- fi
80
-
81
- # ── 6. App PEM — referenced by GITHUB_APP_PRIVATE_KEY_PATH in the env file ─
82
- # If you placed the PEM at /etc/lastlight/app.pem before running install.sh,
83
- # this section locks down its permissions; otherwise it's a no-op.
84
- if [ -f "$PEM_FILE" ]; then
85
- chown root:"$LASTLIGHT_USER" "$PEM_FILE"
86
- chmod 0640 "$PEM_FILE"
87
- fi
88
-
89
- # ── 7. systemd unit ────────────────────────────────────────────────────────
90
- install -m 0644 \
91
- "$REPO_DIR/deploy/native/lastlight.service" \
92
- "/etc/systemd/system/${SERVICE_NAME}.service"
93
- systemctl daemon-reload
94
-
95
- # ── 8. Enable + start ──────────────────────────────────────────────────────
96
- systemctl enable "${SERVICE_NAME}"
97
- # Only start/restart if the env file looks configured (the example has the
98
- # string CHANGE_ME everywhere a value is required).
99
- if grep -q '^[A-Z].*=CHANGE_ME' "$ENV_FILE"; then
100
- echo " $ENV_FILE still has CHANGE_ME placeholders — not (re)starting the service." >&2
101
- echo " Fill in the values and re-run install.sh." >&2
102
- exit 0
103
- fi
104
- systemctl restart "${SERVICE_NAME}"
105
-
106
- # Brief status read-out so the operator sees if it started cleanly.
107
- sleep 2
108
- systemctl status "${SERVICE_NAME}" --no-pager -l | head -20 || true
109
- echo ""
110
- echo " Live logs: journalctl -u ${SERVICE_NAME} -f"
@@ -1,95 +0,0 @@
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
@@ -1,50 +0,0 @@
1
- [Unit]
2
- Description=Last Light — GitHub repository maintenance agent
3
- Documentation=https://github.com/nearform/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