lastlight 0.15.0 → 0.16.1

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 (382) 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} +26 -1
  5. package/dist/{cli/cli-server.js → cli-server.js} +40 -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} +4 -3
  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 -100
  103. package/dist/connectors/slack/connector.js +0 -341
  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 -8
  109. package/dist/connectors/slack/mrkdwn.js +0 -123
  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 -923
  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/index.d.ts +0 -15
  193. package/dist/notify/index.js +0 -6
  194. package/dist/notify/index.js.map +0 -1
  195. package/dist/notify/model.d.ts +0 -57
  196. package/dist/notify/model.js +0 -89
  197. package/dist/notify/model.js.map +0 -1
  198. package/dist/notify/notifier.d.ts +0 -17
  199. package/dist/notify/notifier.js +0 -87
  200. package/dist/notify/notifier.js.map +0 -1
  201. package/dist/notify/render.d.ts +0 -21
  202. package/dist/notify/render.js +0 -59
  203. package/dist/notify/render.js.map +0 -1
  204. package/dist/notify/transports/github.d.ts +0 -26
  205. package/dist/notify/transports/github.js +0 -26
  206. package/dist/notify/transports/github.js.map +0 -1
  207. package/dist/notify/transports/slack.d.ts +0 -26
  208. package/dist/notify/transports/slack.js +0 -28
  209. package/dist/notify/transports/slack.js.map +0 -1
  210. package/dist/notify/types.d.ts +0 -95
  211. package/dist/notify/types.js +0 -16
  212. package/dist/notify/types.js.map +0 -1
  213. package/dist/providers.d.ts +0 -125
  214. package/dist/providers.js +0 -279
  215. package/dist/providers.js.map +0 -1
  216. package/dist/sandbox/docker.d.ts +0 -180
  217. package/dist/sandbox/docker.js +0 -517
  218. package/dist/sandbox/docker.js.map +0 -1
  219. package/dist/sandbox/egress-allowlist.d.ts +0 -74
  220. package/dist/sandbox/egress-allowlist.js +0 -164
  221. package/dist/sandbox/egress-allowlist.js.map +0 -1
  222. package/dist/sandbox/egress-firewall-config.d.ts +0 -127
  223. package/dist/sandbox/egress-firewall-config.js +0 -434
  224. package/dist/sandbox/egress-firewall-config.js.map +0 -1
  225. package/dist/sandbox/images.d.ts +0 -23
  226. package/dist/sandbox/images.js +0 -55
  227. package/dist/sandbox/images.js.map +0 -1
  228. package/dist/sandbox/index.d.ts +0 -112
  229. package/dist/sandbox/index.js +0 -332
  230. package/dist/sandbox/index.js.map +0 -1
  231. package/dist/sandbox/sandbox.d.ts +0 -214
  232. package/dist/sandbox/sandbox.js +0 -453
  233. package/dist/sandbox/sandbox.js.map +0 -1
  234. package/dist/sandbox/smol.d.ts +0 -162
  235. package/dist/sandbox/smol.js +0 -485
  236. package/dist/sandbox/smol.js.map +0 -1
  237. package/dist/session-log.d.ts +0 -63
  238. package/dist/session-log.js +0 -290
  239. package/dist/session-log.js.map +0 -1
  240. package/dist/state/approval-store.d.ts +0 -88
  241. package/dist/state/approval-store.js +0 -149
  242. package/dist/state/approval-store.js.map +0 -1
  243. package/dist/state/build-assets.d.ts +0 -50
  244. package/dist/state/build-assets.js +0 -154
  245. package/dist/state/build-assets.js.map +0 -1
  246. package/dist/state/db.d.ts +0 -81
  247. package/dist/state/db.js +0 -155
  248. package/dist/state/db.js.map +0 -1
  249. package/dist/state/execution-store.d.ts +0 -257
  250. package/dist/state/execution-store.js +0 -527
  251. package/dist/state/execution-store.js.map +0 -1
  252. package/dist/state/migrate.d.ts +0 -15
  253. package/dist/state/migrate.js +0 -175
  254. package/dist/state/migrate.js.map +0 -1
  255. package/dist/state/workflow-run-store.d.ts +0 -216
  256. package/dist/state/workflow-run-store.js +0 -403
  257. package/dist/state/workflow-run-store.js.map +0 -1
  258. package/dist/telemetry/index.d.ts +0 -38
  259. package/dist/telemetry/index.js +0 -253
  260. package/dist/telemetry/index.js.map +0 -1
  261. package/dist/telemetry/pi-events.d.ts +0 -12
  262. package/dist/telemetry/pi-events.js +0 -134
  263. package/dist/telemetry/pi-events.js.map +0 -1
  264. package/dist/workflows/dag.d.ts +0 -37
  265. package/dist/workflows/dag.js +0 -118
  266. package/dist/workflows/dag.js.map +0 -1
  267. package/dist/workflows/loader.d.ts +0 -53
  268. package/dist/workflows/loader.js +0 -421
  269. package/dist/workflows/loader.js.map +0 -1
  270. package/dist/workflows/loop-eval.d.ts +0 -28
  271. package/dist/workflows/loop-eval.js +0 -74
  272. package/dist/workflows/loop-eval.js.map +0 -1
  273. package/dist/workflows/phase-executor.d.ts +0 -215
  274. package/dist/workflows/phase-executor.js +0 -1144
  275. package/dist/workflows/phase-executor.js.map +0 -1
  276. package/dist/workflows/phase-ref.d.ts +0 -50
  277. package/dist/workflows/phase-ref.js +0 -91
  278. package/dist/workflows/phase-ref.js.map +0 -1
  279. package/dist/workflows/resume.d.ts +0 -58
  280. package/dist/workflows/resume.js +0 -313
  281. package/dist/workflows/resume.js.map +0 -1
  282. package/dist/workflows/runner.d.ts +0 -63
  283. package/dist/workflows/runner.js +0 -364
  284. package/dist/workflows/runner.js.map +0 -1
  285. package/dist/workflows/schema.d.ts +0 -344
  286. package/dist/workflows/schema.js +0 -460
  287. package/dist/workflows/schema.js.map +0 -1
  288. package/dist/workflows/simple.d.ts +0 -90
  289. package/dist/workflows/simple.js +0 -393
  290. package/dist/workflows/simple.js.map +0 -1
  291. package/dist/workflows/target-policy.d.ts +0 -74
  292. package/dist/workflows/target-policy.js +0 -80
  293. package/dist/workflows/target-policy.js.map +0 -1
  294. package/dist/workflows/templates.d.ts +0 -88
  295. package/dist/workflows/templates.js +0 -127
  296. package/dist/workflows/templates.js.map +0 -1
  297. package/dist/workflows/triggers.d.ts +0 -21
  298. package/dist/workflows/triggers.js +0 -45
  299. package/dist/workflows/triggers.js.map +0 -1
  300. package/dist/workflows/verdict.d.ts +0 -19
  301. package/dist/workflows/verdict.js +0 -30
  302. package/dist/workflows/verdict.js.map +0 -1
  303. package/dist/worktree/manager.d.ts +0 -43
  304. package/dist/worktree/manager.js +0 -127
  305. package/dist/worktree/manager.js.map +0 -1
  306. package/docker-compose.yml +0 -274
  307. package/sandbox.Dockerfile +0 -68
  308. package/skills/README.md +0 -42
  309. package/skills/browser-qa/SKILL.md +0 -208
  310. package/skills/browser-qa/scripts/agent-browser.mjs +0 -531
  311. package/skills/building/SKILL.md +0 -95
  312. package/skills/chat/SKILL.md +0 -36
  313. package/skills/code-review/SKILL.md +0 -82
  314. package/skills/debug-production/SKILL.md +0 -108
  315. package/skills/demo/SKILL.md +0 -228
  316. package/skills/demo/scripts/compose-demo.sh +0 -243
  317. package/skills/issue-answer/SKILL.md +0 -91
  318. package/skills/issue-comment/SKILL.md +0 -49
  319. package/skills/issue-triage/SKILL.md +0 -149
  320. package/skills/issue-triage/references/AGENT-BRIEF.md +0 -65
  321. package/skills/pr-comment/SKILL.md +0 -64
  322. package/skills/pr-review/SKILL.md +0 -148
  323. package/skills/pr-review/references/findings-schema.md +0 -89
  324. package/skills/qa-test/SKILL.md +0 -97
  325. package/skills/repo-health/SKILL.md +0 -67
  326. package/skills/security-feedback/SKILL.md +0 -173
  327. package/skills/security-feedback/references/templates.md +0 -77
  328. package/skills/security-review/SKILL.md +0 -215
  329. package/skills/security-review/references/issue-format.md +0 -302
  330. package/skills/verify/SKILL.md +0 -118
  331. package/workflows/answer.yaml +0 -44
  332. package/workflows/build.yaml +0 -129
  333. package/workflows/cron-health.yaml +0 -6
  334. package/workflows/cron-review.yaml +0 -8
  335. package/workflows/cron-security.yaml +0 -6
  336. package/workflows/cron-triage.yaml +0 -8
  337. package/workflows/demo.yaml +0 -62
  338. package/workflows/examples/bash-smoke.yaml +0 -41
  339. package/workflows/examples/parallel-review.yaml +0 -36
  340. package/workflows/examples/tdd-loop.yaml +0 -17
  341. package/workflows/explore.yaml +0 -80
  342. package/workflows/issue-comment.yaml +0 -15
  343. package/workflows/issue-triage.yaml +0 -22
  344. package/workflows/pr-comment.yaml +0 -16
  345. package/workflows/pr-fix.yaml +0 -17
  346. package/workflows/pr-review.yaml +0 -50
  347. package/workflows/prompts/answer.md +0 -68
  348. package/workflows/prompts/architect.md +0 -44
  349. package/workflows/prompts/classifier.md +0 -60
  350. package/workflows/prompts/classify-adds-info.md +0 -17
  351. package/workflows/prompts/demo.md +0 -125
  352. package/workflows/prompts/executor.md +0 -42
  353. package/workflows/prompts/explore-ask.md +0 -99
  354. package/workflows/prompts/explore-publish.md +0 -31
  355. package/workflows/prompts/explore-read.md +0 -120
  356. package/workflows/prompts/explore-synthesize.md +0 -88
  357. package/workflows/prompts/fix.md +0 -18
  358. package/workflows/prompts/guardrails.md +0 -96
  359. package/workflows/prompts/pr-fix.md +0 -26
  360. package/workflows/prompts/pr.md +0 -39
  361. package/workflows/prompts/qa-browser.md +0 -95
  362. package/workflows/prompts/qa-synth.md +0 -44
  363. package/workflows/prompts/qa-test.md +0 -60
  364. package/workflows/prompts/re-reviewer.md +0 -33
  365. package/workflows/prompts/reviewer.md +0 -60
  366. package/workflows/prompts/verify-browser.md +0 -93
  367. package/workflows/prompts/verify-synth.md +0 -44
  368. package/workflows/prompts/verify.md +0 -63
  369. package/workflows/qa-test.yaml +0 -94
  370. package/workflows/repo-health.yaml +0 -15
  371. package/workflows/security-feedback.yaml +0 -25
  372. package/workflows/security-review.yaml +0 -37
  373. package/workflows/verify.yaml +0 -93
  374. /package/dist/{cli/cli-config.d.ts → cli-config.d.ts} +0 -0
  375. /package/dist/{cli/cli-config.js → cli-config.js} +0 -0
  376. /package/dist/{cli/cli-format.d.ts → cli-format.d.ts} +0 -0
  377. /package/dist/{cli/cli-format.js → cli-format.js} +0 -0
  378. /package/dist/{cli/cli-timeline.d.ts → cli-timeline.d.ts} +0 -0
  379. /package/dist/{cli/cli-timeline.js → cli-timeline.js} +0 -0
  380. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
  381. /package/dist/{cli/oauth-cli.d.ts → oauth-cli.d.ts} +0 -0
  382. /package/dist/{cli/setup.d.ts → setup.d.ts} +0 -0
@@ -1,269 +0,0 @@
1
- /**
2
- * Thin one-shot LLM chat helper used by the prompt-injection screener and the
3
- * intent classifier. Powered by `src/providers.ts` — that registry is the
4
- * single source of truth for which providers this helper can call.
5
- *
6
- * The screener + classifier are deliberately small and explicit. They need a
7
- * cheap/fast model on the SAME provider the user picked (or any registered
8
- * provider whose key is present) so the agent's primary model and the cheap
9
- * helper share one footprint. We support two request families:
10
- *
11
- * `openai-completions` — body `{ model, messages, <maxTokensField> }`,
12
- * response `choices[0].message.content`. Covers
13
- * OpenAI, OpenRouter, Groq, Cerebras, xAI,
14
- * Hugging Face, Moonshot, NVIDIA, Fireworks,
15
- * Together, DeepSeek, Z.AI, and Google/Mistral
16
- * via their OpenAI-compatible endpoints.
17
- * `anthropic-messages` — `system` field + content-block response.
18
- * Covers Anthropic, Kimi for Coding, MiniMax.
19
- *
20
- * Scope: this helper supports the providers listed in `src/providers.ts`.
21
- * Workflow phases themselves are provider-agnostic (whatever pi-ai
22
- * supports); only the screener/classifier path is constrained here.
23
- */
24
- import { PROVIDERS, providerByPrefix } from "../providers.js";
25
- import { getRuntimeConfig } from "../config/config.js";
26
- // ── Resolvers (exported for unit tests) ──────────────────────────────────────
27
- /**
28
- * Resolve a `provider/model` spec (or a bare model id) into a routing
29
- * decision. Prefers an explicit `<prefix>/<model>` over name-inference.
30
- *
31
- * @throws if the prefix is present but not registered — silently
32
- * mis-routing a `xai/grok-4` to OpenAI would bill the wrong account and
33
- * fail at request time with a confusing error, so we surface it early.
34
- */
35
- export function resolveProvider(model) {
36
- const slash = model.indexOf("/");
37
- if (slash > 0) {
38
- const prefix = model.slice(0, slash).toLowerCase();
39
- const tail = model.slice(slash + 1);
40
- const spec = providerByPrefix(prefix);
41
- if (spec) {
42
- return {
43
- provider: spec.prefix,
44
- modelId: tail,
45
- api: spec.api,
46
- };
47
- }
48
- throw new Error(`llm helper: unsupported provider prefix "${prefix}" ` +
49
- `(registered: ${PROVIDERS.map((p) => p.prefix).join(", ")})`);
50
- }
51
- // Bare model id — fall back to inference by name. OpenRouter's nested
52
- // `vendor/model` ids are handled above (its prefix is "openrouter").
53
- if (/^claude/i.test(model)) {
54
- return { provider: "anthropic", modelId: model, api: "anthropic-messages" };
55
- }
56
- if (/^gpt/i.test(model) || /^o\d/.test(model)) {
57
- return { provider: "openai", modelId: model, api: "openai-completions" };
58
- }
59
- // Anything else: assume OpenAI-completions shape against an OpenAI endpoint.
60
- return { provider: "openai", modelId: model, api: "openai-completions" };
61
- }
62
- /**
63
- * Resolve the model id for a tiny one-shot helper call (classifier / screener).
64
- * Precedence for a given `taskType`:
65
- * 1. an explicit per-task entry in the config `models:` map (`models.classifier`,
66
- * `models.screener`) — which already has env `OPENCODE_MODELS` /
67
- * `LASTLIGHT_MODELS` layered on top at config-load, so this covers both
68
- * config.yaml and the env override in one lookup;
69
- * 2. the env `OPENCODE_MODELS` map read directly — a fallback for contexts
70
- * where runtime config isn't loaded (some CLI / test paths);
71
- * 3. the first configured provider in `PROVIDERS` order (registry order:
72
- * Anthropic first, then OpenAI, OpenRouter, then the rest — `src/providers.ts`).
73
- *
74
- * Note: only an EXPLICIT per-task entry counts — never `models.default` — so the
75
- * cheap helpers stay cheap unless a deployment deliberately pins them.
76
- */
77
- export function defaultFastModel(taskType) {
78
- if (taskType) {
79
- const configured = getRuntimeConfig()?.models?.[taskType];
80
- if (configured)
81
- return configured;
82
- const override = readOpencodeModelOverride(taskType);
83
- if (override)
84
- return override;
85
- }
86
- for (const spec of PROVIDERS) {
87
- if (process.env[spec.envKey])
88
- return `${spec.prefix}/${spec.fastModel}`;
89
- }
90
- // No keys set — fall back to the OpenAI default; chat() will then throw a
91
- // clear "OPENAI_API_KEY not set" error at call time.
92
- const openaiSpec = providerByPrefix("openai");
93
- return `${openaiSpec.prefix}/${openaiSpec.fastModel}`;
94
- }
95
- function readOpencodeModelOverride(taskType) {
96
- const raw = process.env.OPENCODE_MODELS;
97
- if (!raw)
98
- return undefined;
99
- try {
100
- const parsed = JSON.parse(raw);
101
- const v = parsed?.[taskType];
102
- return typeof v === "string" ? v : undefined;
103
- }
104
- catch {
105
- return undefined;
106
- }
107
- }
108
- // ── Request builders ────────────────────────────────────────────────────────
109
- function apiKeyFor(spec) {
110
- const apiKey = process.env[spec.envKey];
111
- if (!apiKey)
112
- throw new Error(`${spec.envKey} not set`);
113
- return apiKey;
114
- }
115
- /** Append `/messages` (Anthropic-style) taking baseUrl shape into account. */
116
- function anthropicUrl(spec) {
117
- return spec.baseUrl.endsWith("/v1")
118
- ? `${spec.baseUrl}/messages`
119
- : `${spec.baseUrl}/v1/messages`;
120
- }
121
- /** Append `/chat/completions` (OpenAI-style). */
122
- function openaiUrl(spec) {
123
- return `${spec.baseUrl}/chat/completions`;
124
- }
125
- function buildRequest(spec, modelId, messages, opts, apiKey, signal) {
126
- if (spec.api === "anthropic-messages") {
127
- return buildAnthropicMessages({ spec, modelId, messages, opts, apiKey, signal });
128
- }
129
- return buildOpenaiCompletions({ spec, modelId, messages, opts, apiKey, signal });
130
- }
131
- function buildAnthropicMessages(args) {
132
- const { spec, modelId, messages, opts, apiKey, signal } = args;
133
- const system = messages
134
- .filter((m) => m.role === "system")
135
- .map((m) => m.content)
136
- .join("\n");
137
- return {
138
- url: anthropicUrl(spec),
139
- init: {
140
- method: "POST",
141
- signal,
142
- headers: {
143
- "content-type": "application/json",
144
- "x-api-key": apiKey,
145
- "anthropic-version": "2023-06-01",
146
- },
147
- body: JSON.stringify({
148
- model: modelId,
149
- max_tokens: opts.maxTokens ?? 256,
150
- ...(system ? { system } : {}),
151
- messages: messages
152
- .filter((m) => m.role !== "system")
153
- .map((m) => ({ role: m.role, content: m.content })),
154
- }),
155
- },
156
- };
157
- }
158
- function buildOpenaiCompletions(args) {
159
- const { spec, modelId, messages, opts, apiKey, signal } = args;
160
- // OpenAI's `max_completion_tokens` (newer family) vs. the cross-provider
161
- // `max_tokens`. Almost every OpenAI-completions provider accepts `max_tokens`;
162
- // OpenAI itself prefers `max_completion_tokens` so we surface that as a
163
- // per-provider override in the registry.
164
- const maxField = spec.maxTokensField ?? "max_tokens";
165
- const headers = {
166
- "content-type": "application/json",
167
- authorization: `Bearer ${apiKey}`,
168
- };
169
- if (spec.extraHeaders) {
170
- for (const [k, v] of Object.entries(spec.extraHeaders))
171
- headers[k] = v;
172
- }
173
- return {
174
- url: openaiUrl(spec),
175
- init: {
176
- method: "POST",
177
- signal,
178
- headers,
179
- body: JSON.stringify({
180
- model: modelId,
181
- [maxField]: opts.maxTokens ?? 256,
182
- messages,
183
- }),
184
- },
185
- };
186
- }
187
- // ── Response extractors ─────────────────────────────────────────────────────
188
- function extractAnthropicText(data) {
189
- const content = data.content ?? [];
190
- return content
191
- .filter((block) => block.type === "text" && typeof block.text === "string")
192
- .map((block) => block.text)
193
- .join("");
194
- }
195
- function extractOpenaiText(data) {
196
- return (data.choices?.[0]?.message?.content ??
197
- "");
198
- }
199
- function extractText(spec, data) {
200
- return spec.api === "anthropic-messages" ? extractAnthropicText(data) : extractOpenaiText(data);
201
- }
202
- // ── Public API ───────────────────────────────────────────────────────────────
203
- /**
204
- * Make a provider-agnostic chat call and return the final assistant text.
205
- *
206
- * @throws if the relevant API key isn't set or the upstream returns non-2xx
207
- */
208
- export async function chat(model, messages, opts = {}) {
209
- const { provider, modelId, api } = resolveProvider(model);
210
- const spec = providerByPrefix(provider);
211
- // For bare-id inference where the prefix isn't in the registry (the
212
- // generic "assume OpenAI" fallback), synthesize a pseudo-spec so the
213
- // OpenAI-completions builder still runs.
214
- const resolvedSpec = spec ?? {
215
- prefix: provider,
216
- displayName: provider,
217
- envKey: "OPENAI_API_KEY",
218
- baseUrl: "https://api.openai.com/v1",
219
- api,
220
- host: "openai.com",
221
- fastModel: modelId,
222
- sampleModel: modelId,
223
- };
224
- return withRetry(async (signal) => {
225
- const apiKey = apiKeyFor(resolvedSpec);
226
- const { url, init } = buildRequest(resolvedSpec, modelId, messages, opts, apiKey, signal);
227
- const res = await fetch(url, init);
228
- if (!res.ok) {
229
- const text = await res.text().catch(() => "");
230
- throw new Error(`${resolvedSpec.prefix} api ${res.status}: ${text}`);
231
- }
232
- const data = await res.json();
233
- return extractText(resolvedSpec, data);
234
- }, opts.timeoutMs ?? 30_000);
235
- }
236
- /** Compatibility wrapper for older single-turn call sites. */
237
- export async function callLlm(model, systemPrompt, userPrompt, opts = {}) {
238
- return chat(model, [
239
- { role: "system", content: systemPrompt },
240
- { role: "user", content: userPrompt },
241
- ], opts);
242
- }
243
- /**
244
- * Single retry on transient upstream failures. The screener and classifier
245
- * call this inline on every incoming event, so a single 429/503 from the
246
- * provider would otherwise silently drop the event and break routing.
247
- */
248
- async function withRetry(call, timeoutMs) {
249
- for (let attempt = 0; attempt < 2; attempt++) {
250
- const ctrl = new AbortController();
251
- const timer = setTimeout(() => ctrl.abort(), timeoutMs);
252
- try {
253
- return await call(ctrl.signal);
254
- }
255
- catch (err) {
256
- const msg = err instanceof Error ? err.message : String(err);
257
- const transient = /\b(429|5\d\d)\b/.test(msg);
258
- if (attempt === 1 || !transient)
259
- throw err;
260
- await new Promise((r) => setTimeout(r, 750));
261
- }
262
- finally {
263
- clearTimeout(timer);
264
- }
265
- }
266
- // Unreachable — loop either returns or throws.
267
- throw new Error("chat: retry loop fell through");
268
- }
269
- //# sourceMappingURL=llm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/engine/llm.ts"],"names":[],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- import { getOAuthProvider, getOAuthProviders, type OAuthCredentials } from "@earendil-works/pi-ai/oauth";
2
- /** Stored form — pi-ai's CLI tags each entry with `type: "oauth"`; we match it. */
3
- export type StoredCredentials = OAuthCredentials & {
4
- type?: string;
5
- };
6
- export type AuthMap = Record<string, StoredCredentials>;
7
- /** OAuth providers that CANNOT fall back to an API key — login is mandatory. */
8
- export declare const OAUTH_ONLY_PROVIDERS: ReadonlySet<string>;
9
- /** OAuth provider id backing a model spec, or undefined if it's API-key based. */
10
- export declare function oauthProviderIdForModel(spec: string): string | undefined;
11
- /**
12
- * The env var pi-ai reads inside a sandbox for a provider's OAuth token, when
13
- * one exists. Returns undefined for providers with no env-var route (Codex),
14
- * which therefore cannot authenticate in the agentic-pi sandbox.
15
- */
16
- export declare function oauthEnvVarForProvider(id: string): string | undefined;
17
- /**
18
- * Resolve the credential-store path. Precedence:
19
- * 1. explicit argument (a caller-computed path),
20
- * 2. `LASTLIGHT_AUTH_FILE` (hard override),
21
- * 3. `<stateDir | $STATE_DIR | ./data>/auth.json`.
22
- * The CLI writes here and the harness reads here, so both must agree; passing
23
- * the harness's resolved `stateDir` keeps them aligned even if the process cwd
24
- * differs.
25
- */
26
- export declare function resolveAuthFile(explicit?: string, stateDir?: string): string;
27
- export declare function loadAuthMap(file?: string, stateDir?: string): AuthMap;
28
- export declare function saveAuthMap(map: AuthMap, file?: string, stateDir?: string): void;
29
- export declare function hasOAuthCredentials(id: string, file?: string, stateDir?: string): boolean;
30
- export interface OAuthKeyResult {
31
- apiKey: string;
32
- credentials: OAuthCredentials;
33
- }
34
- /**
35
- * Resolve a usable API key for an OAuth provider from stored credentials,
36
- * refreshing an expired token and persisting the rotated credentials back to
37
- * the store. Returns null when nothing is stored for `id`. Throws only if a
38
- * refresh actually fails (expired refresh token, revoked grant) — callers
39
- * should surface that as "re-run login".
40
- */
41
- export declare function resolveOAuthApiKey(id: string, file?: string, stateDir?: string): Promise<OAuthKeyResult | null>;
42
- /** Re-exported so callers depend on this module, not pi-ai's oauth entry directly. */
43
- export { getOAuthProvider, getOAuthProviders };
@@ -1,103 +0,0 @@
1
- /**
2
- * OAuth credential management for LLM providers that authenticate with a
3
- * subscription login instead of a static API key — ChatGPT Plus/Pro (Codex),
4
- * Claude Pro/Max, and GitHub Copilot.
5
- *
6
- * pi-ai (`@earendil-works/pi-ai/oauth`) owns the actual OAuth flows, token
7
- * refresh, and credential→apiKey conversion; this module is the thin Last
8
- * Light layer on top:
9
- * - a single on-disk credential store (`auth.json`, same JSON shape pi-ai's
10
- * own CLI writes) resolved under `$STATE_DIR` so the CLI (writer) and the
11
- * running harness (reader) agree on one path,
12
- * - `resolveOAuthApiKey()` — refresh-if-expired + persist rotated creds +
13
- * return a usable key, used by the in-process chat path,
14
- * - the model-prefix → provider-id map and the sandbox env-var route so the
15
- * chat and sandbox executors can both find the right credential.
16
- *
17
- * Two consumption seams with different reach:
18
- * - **chat** (in-process pi-ai) — passes `apiKey` in the stream options, so
19
- * ALL three OAuth providers work, Codex included.
20
- * - **sandbox** (agentic-pi) — has no apiKey option; it reads provider creds
21
- * from env only. pi-ai honours `ANTHROPIC_OAUTH_TOKEN` and
22
- * `COPILOT_GITHUB_TOKEN`, but Codex (chatgpt.com backend) has no env route,
23
- * so a Codex model cannot run in the sandbox. See `oauthEnvVarForProvider`.
24
- */
25
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
26
- import { dirname, resolve } from "node:path";
27
- import { getOAuthApiKey, getOAuthProvider, getOAuthProviders, } from "@earendil-works/pi-ai/oauth";
28
- import { OAUTH_PROVIDERS, oauthProviderByModelPrefix, oauthProviderById } from "../providers.js";
29
- /** OAuth providers that CANNOT fall back to an API key — login is mandatory. */
30
- export const OAUTH_ONLY_PROVIDERS = new Set(OAUTH_PROVIDERS.filter((p) => p.oauthOnly).map((p) => p.id));
31
- /** OAuth provider id backing a model spec, or undefined if it's API-key based. */
32
- export function oauthProviderIdForModel(spec) {
33
- const prefix = spec.includes("/") ? spec.slice(0, spec.indexOf("/")) : spec;
34
- return oauthProviderByModelPrefix(prefix)?.id;
35
- }
36
- /**
37
- * The env var pi-ai reads inside a sandbox for a provider's OAuth token, when
38
- * one exists. Returns undefined for providers with no env-var route (Codex),
39
- * which therefore cannot authenticate in the agentic-pi sandbox.
40
- */
41
- export function oauthEnvVarForProvider(id) {
42
- return oauthProviderById(id)?.sandboxEnvVar ?? undefined;
43
- }
44
- /**
45
- * Resolve the credential-store path. Precedence:
46
- * 1. explicit argument (a caller-computed path),
47
- * 2. `LASTLIGHT_AUTH_FILE` (hard override),
48
- * 3. `<stateDir | $STATE_DIR | ./data>/auth.json`.
49
- * The CLI writes here and the harness reads here, so both must agree; passing
50
- * the harness's resolved `stateDir` keeps them aligned even if the process cwd
51
- * differs.
52
- */
53
- export function resolveAuthFile(explicit, stateDir) {
54
- if (explicit)
55
- return resolve(explicit);
56
- if (process.env.LASTLIGHT_AUTH_FILE)
57
- return resolve(process.env.LASTLIGHT_AUTH_FILE);
58
- return resolve(stateDir || process.env.STATE_DIR || "data", "auth.json");
59
- }
60
- export function loadAuthMap(file, stateDir) {
61
- const path = resolveAuthFile(file, stateDir);
62
- if (!existsSync(path))
63
- return {};
64
- try {
65
- const parsed = JSON.parse(readFileSync(path, "utf8"));
66
- return parsed && typeof parsed === "object" ? parsed : {};
67
- }
68
- catch {
69
- return {};
70
- }
71
- }
72
- export function saveAuthMap(map, file, stateDir) {
73
- const path = resolveAuthFile(file, stateDir);
74
- mkdirSync(dirname(path), { recursive: true });
75
- // Mode 0600 — the file holds long-lived refresh tokens.
76
- writeFileSync(path, JSON.stringify(map, null, 2), { mode: 0o600 });
77
- }
78
- export function hasOAuthCredentials(id, file, stateDir) {
79
- return !!loadAuthMap(file, stateDir)[id];
80
- }
81
- /**
82
- * Resolve a usable API key for an OAuth provider from stored credentials,
83
- * refreshing an expired token and persisting the rotated credentials back to
84
- * the store. Returns null when nothing is stored for `id`. Throws only if a
85
- * refresh actually fails (expired refresh token, revoked grant) — callers
86
- * should surface that as "re-run login".
87
- */
88
- export async function resolveOAuthApiKey(id, file, stateDir) {
89
- const map = loadAuthMap(file, stateDir);
90
- if (!map[id])
91
- return null;
92
- const res = await getOAuthApiKey(id, map);
93
- if (!res)
94
- return null;
95
- // Persist the rotated credentials so the next refresh chains from the new
96
- // token rather than re-using a spent one.
97
- map[id] = { type: "oauth", ...res.newCredentials };
98
- saveAuthMap(map, file, stateDir);
99
- return { apiKey: res.apiKey, credentials: res.newCredentials };
100
- }
101
- /** Re-exported so callers depend on this module, not pi-ai's oauth entry directly. */
102
- export { getOAuthProvider, getOAuthProviders };
103
- //# sourceMappingURL=oauth.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/engine/oauth.ts"],"names":[],"mappings":"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"}
@@ -1,29 +0,0 @@
1
- import type { EventEnvelope } from "../connectors/types.js";
2
- import type { StateDb } from "../state/db.js";
3
- /**
4
- * A routing decision — the single term for "what should process this event"
5
- * is `handler`. It names either an in-process handler (chat, status-report,
6
- * approval-response, …) or a workflow (issue-triage, pr-review, build, …);
7
- * the dispatcher decides which. The router itself performs no side effects.
8
- */
9
- export type Route = {
10
- action: "handler";
11
- handler: string;
12
- context: Record<string, unknown>;
13
- } | {
14
- action: "reply";
15
- message: string;
16
- } | {
17
- action: "ignore";
18
- reason: string;
19
- };
20
- /** Optional dependencies the router needs to short-circuit paused runs. */
21
- export interface RouterDeps {
22
- db?: StateDb;
23
- }
24
- /**
25
- * Event routing — deterministic for most events, LLM-classified for comments.
26
- * Maps normalized events to the handler that should process them. Returns a
27
- * decision only; the dispatcher performs the side effects.
28
- */
29
- export declare function routeEvent(envelope: EventEnvelope, deps?: RouterDeps): Promise<Route>;