lastlight 0.1.8 → 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 +423 -437
  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 +31 -12
  272. package/dist/setup.js +516 -174
  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 +19 -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
@@ -1,534 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
- import { z } from "zod";
6
- import { execSync } from "child_process";
7
- import { GitHubAppAuth } from "./auth.js";
8
- import { GitHubClient } from "./github.js";
9
-
10
- // ── Config from environment ─────────────────────────────────────────
11
-
12
- const appId = process.env.GITHUB_APP_ID;
13
- const privateKeyPath = process.env.GITHUB_APP_PRIVATE_KEY_PATH;
14
- const installationId = process.env.GITHUB_APP_INSTALLATION_ID;
15
- const staticToken = process.env.GITHUB_TOKEN;
16
-
17
- const hasAppCreds = Boolean(appId && privateKeyPath && installationId);
18
-
19
- if (!staticToken && !hasAppCreds) {
20
- console.error(
21
- "Required auth env vars: either GITHUB_TOKEN or all of GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY_PATH, GITHUB_APP_INSTALLATION_ID"
22
- );
23
- process.exit(1);
24
- }
25
-
26
- // Prefer GitHub App credentials when both are present. Static-token mode is
27
- // the fallback for low-trust sandboxes that intentionally clear the App env
28
- // vars (see executor.ts: GITHUB_APP_ID="" + ALLOW_APP_PEM=0). This ordering
29
- // stops a stale host-side GITHUB_TOKEN PAT from silently downgrading the
30
- // agent's auth — which surfaced as a 403 "Resource not accessible by
31
- // personal access token" when the chat skill tried to create an issue.
32
- const auth = hasAppCreds
33
- ? new GitHubAppAuth({ appId, privateKeyPath, installationId })
34
- : {
35
- async getToken() {
36
- return staticToken;
37
- },
38
- get expiresAt() {
39
- return null;
40
- },
41
- };
42
- const gh = new GitHubClient(auth);
43
-
44
- // ── MCP Server ──────────────────────────────────────────────────────
45
-
46
- const server = new McpServer({
47
- name: "github-app",
48
- version: "1.0.0",
49
- });
50
-
51
- // Helper to run a tool handler and return JSON result
52
- function jsonResult(data) {
53
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
54
- }
55
-
56
- async function run(fn) {
57
- try {
58
- const result = await fn();
59
- return jsonResult(result);
60
- } catch (e) {
61
- const status = e.status || e.response?.status;
62
- const isTransient = [408, 429, 500, 502, 503, 504].includes(status);
63
- return jsonResult({
64
- error: e.message,
65
- status: status || null,
66
- transient: isTransient,
67
- hint: isTransient
68
- ? "This is a transient error. The request was retried automatically but still failed. Wait and try again."
69
- : status === 401
70
- ? "Authentication failed. Call refresh_git_auth to get a fresh token."
71
- : null,
72
- });
73
- }
74
- }
75
-
76
- // ── Git Auth Tools ──────────────────────────────────────────────────
77
-
78
- server.tool(
79
- "clone_repo",
80
- "Clone a repository with GitHub App authentication. Sets up credential helper and bot identity automatically. git push/pull/fetch will just work after cloning.",
81
- {
82
- owner: z.string().describe("Repository owner"),
83
- repo: z.string().describe("Repository name"),
84
- branch: z.string().optional().describe("Branch to checkout (default: repo default branch)"),
85
- path: z.string().optional().describe("Local path to clone into (default: repo name)"),
86
- },
87
- async ({ owner, repo, branch, path: clonePath }) => {
88
- try {
89
- const token = await auth.getToken();
90
- const dest = clonePath || repo;
91
- const url = `https://x-access-token:${token}@github.com/${owner}/${repo}.git`;
92
-
93
- const branchArgs = branch ? ["--branch", branch] : [];
94
- execSync(["git", "clone", ...branchArgs, url, dest].join(" "), {
95
- stdio: "pipe",
96
- timeout: 120_000,
97
- });
98
-
99
- // Configure credential helper so push/pull get fresh tokens
100
- const credHelper = `!f() { echo "username=x-access-token"; echo "password=${token}"; }; f`;
101
- execSync(`git -C ${dest} config credential.helper '${credHelper}'`, { stdio: "pipe" });
102
-
103
- // Set bot identity for commits
104
- execSync(`git -C ${dest} config user.name "last-light[bot]"`, { stdio: "pipe" });
105
- execSync(
106
- `git -C ${dest} config user.email "last-light[bot]@users.noreply.github.com"`,
107
- { stdio: "pipe" }
108
- );
109
-
110
- return jsonResult({
111
- cloned: `${owner}/${repo}`,
112
- path: dest,
113
- branch: branch || "(default)",
114
- expires_at: auth.expiresAt?.toISOString(),
115
- });
116
- } catch (e) {
117
- return jsonResult({ error: e.message, stderr: e.stderr?.toString() });
118
- }
119
- }
120
- );
121
-
122
- server.tool(
123
- "refresh_git_auth",
124
- "Refresh the GitHub App token for an existing git clone. Call this if git push/pull fails with auth errors. Updates the credential helper with a fresh token.",
125
- {
126
- path: z.string().describe("Path to the git repository"),
127
- },
128
- async ({ path: repoPath }) => {
129
- try {
130
- const token = await auth.getToken();
131
- const credHelper = `!f() { echo "username=x-access-token"; echo "password=${token}"; }; f`;
132
- execSync(`git -C ${repoPath} config credential.helper '${credHelper}'`, { stdio: "pipe" });
133
- return jsonResult({
134
- refreshed: true,
135
- path: repoPath,
136
- expires_at: auth.expiresAt?.toISOString(),
137
- });
138
- } catch (e) {
139
- return jsonResult({ error: e.message });
140
- }
141
- }
142
- );
143
-
144
- // DEPRECATED: Use clone_repo + refresh_git_auth instead.
145
- // Kept for backward compatibility with Hermes-based workflows.
146
- server.tool(
147
- "setup_git_auth",
148
- "[DEPRECATED — use clone_repo instead] Refresh the GitHub App token and write it to the credential file for Hermes sandbox sync.",
149
- { owner: z.string().describe("Repository owner"), repo: z.string().describe("Repository name") },
150
- async ({ owner, repo }) => {
151
- try {
152
- const token = await auth.getToken();
153
- const fs = await import("fs");
154
- const nodePath = await import("path");
155
-
156
- const hermesHome = process.env.HERMES_HOME || (process.env.HOME + "/.hermes");
157
- const tokenPath = nodePath.join(hermesHome, ".gh-token");
158
- fs.writeFileSync(tokenPath, token, { mode: 0o600 });
159
-
160
- return jsonResult({
161
- deprecated: "Use clone_repo instead — it handles auth, clone, and identity in one step.",
162
- expires_at: auth.expiresAt?.toISOString(),
163
- token_file: tokenPath,
164
- configure_git: `git config --global include.path ${hermesHome}/.gitconfig-bot`,
165
- clone_with: `git clone https://github.com/${owner}/${repo}.git`,
166
- });
167
- } catch (e) {
168
- return jsonResult({ error: e.message });
169
- }
170
- }
171
- );
172
-
173
- // ── Repository Tools ────────────────────────────────────────────────
174
-
175
- server.tool(
176
- "get_repository",
177
- "Get repository metadata",
178
- { owner: z.string(), repo: z.string() },
179
- async ({ owner, repo }) => run(() => gh.getRepository(owner, repo))
180
- );
181
-
182
- server.tool(
183
- "get_file_contents",
184
- "Get contents of a file or directory from a repository",
185
- {
186
- owner: z.string(),
187
- repo: z.string(),
188
- path: z.string(),
189
- branch: z.string().optional(),
190
- },
191
- async ({ owner, repo, path, branch }) =>
192
- run(() => gh.getFileContents(owner, repo, path, branch))
193
- );
194
-
195
- server.tool(
196
- "create_or_update_file",
197
- "Create or update a single file in a repository",
198
- {
199
- owner: z.string(),
200
- repo: z.string(),
201
- path: z.string(),
202
- content: z.string().describe("File content"),
203
- message: z.string().describe("Commit message"),
204
- branch: z.string().optional(),
205
- sha: z.string().optional().describe("SHA of file being replaced (for updates)"),
206
- },
207
- async ({ owner, repo, path, content, message, branch, sha }) =>
208
- run(() => gh.createOrUpdateFile(owner, repo, path, content, message, branch, sha))
209
- );
210
-
211
- server.tool(
212
- "push_files",
213
- "Push multiple files in a single commit",
214
- {
215
- owner: z.string(),
216
- repo: z.string(),
217
- branch: z.string(),
218
- files: z.array(z.object({ path: z.string(), content: z.string() })),
219
- message: z.string(),
220
- },
221
- async ({ owner, repo, branch, files, message }) =>
222
- run(() => gh.pushFiles(owner, repo, branch, files, message))
223
- );
224
-
225
- server.tool(
226
- "list_branches",
227
- "List branches in a repository",
228
- {
229
- owner: z.string(),
230
- repo: z.string(),
231
- page: z.number().optional(),
232
- per_page: z.number().optional(),
233
- },
234
- async ({ owner, repo, page, per_page }) =>
235
- run(() => gh.listBranches(owner, repo, page, per_page))
236
- );
237
-
238
- server.tool(
239
- "create_branch",
240
- "Create a new branch from an existing branch",
241
- {
242
- owner: z.string(),
243
- repo: z.string(),
244
- branch: z.string().describe("New branch name"),
245
- from_branch: z.string().describe("Source branch"),
246
- },
247
- async ({ owner, repo, branch, from_branch }) =>
248
- run(() => gh.createBranch(owner, repo, branch, from_branch))
249
- );
250
-
251
- // ── Issue Tools ─────────────────────────────────────────────────────
252
-
253
- server.tool(
254
- "list_issues",
255
- "List open issues in a repository",
256
- {
257
- owner: z.string(),
258
- repo: z.string(),
259
- state: z.enum(["open", "closed", "all"]).optional(),
260
- labels: z.string().optional().describe("Comma-separated label names"),
261
- sort: z.enum(["created", "updated", "comments"]).optional(),
262
- direction: z.enum(["asc", "desc"]).optional(),
263
- page: z.number().optional(),
264
- per_page: z.number().optional(),
265
- },
266
- async ({ owner, repo, ...opts }) => run(() => gh.listIssues(owner, repo, opts))
267
- );
268
-
269
- server.tool(
270
- "get_issue",
271
- "Get a specific issue by number",
272
- { owner: z.string(), repo: z.string(), issue_number: z.number() },
273
- async ({ owner, repo, issue_number }) => run(() => gh.getIssue(owner, repo, issue_number))
274
- );
275
-
276
- server.tool(
277
- "create_issue",
278
- "Create a new issue",
279
- {
280
- owner: z.string(),
281
- repo: z.string(),
282
- title: z.string(),
283
- body: z.string().optional(),
284
- labels: z.array(z.string()).optional(),
285
- assignees: z.array(z.string()).optional(),
286
- milestone: z.number().optional(),
287
- },
288
- async ({ owner, repo, title, body, ...opts }) =>
289
- run(() => gh.createIssue(owner, repo, title, body, opts))
290
- );
291
-
292
- server.tool(
293
- "update_issue",
294
- "Update an existing issue (title, body, state, labels, assignees)",
295
- {
296
- owner: z.string(),
297
- repo: z.string(),
298
- issue_number: z.number(),
299
- title: z.string().optional(),
300
- body: z.string().optional(),
301
- state: z.enum(["open", "closed"]).optional(),
302
- labels: z.array(z.string()).optional(),
303
- assignees: z.array(z.string()).optional(),
304
- },
305
- async ({ owner, repo, issue_number, ...updates }) =>
306
- run(() => gh.updateIssue(owner, repo, issue_number, updates))
307
- );
308
-
309
- server.tool(
310
- "add_issue_comment",
311
- "Add a comment to an issue or pull request",
312
- {
313
- owner: z.string(),
314
- repo: z.string(),
315
- issue_number: z.number(),
316
- body: z.string(),
317
- },
318
- async ({ owner, repo, issue_number, body }) =>
319
- run(() => gh.addIssueComment(owner, repo, issue_number, body))
320
- );
321
-
322
- server.tool(
323
- "list_issue_comments",
324
- "List comments on an issue",
325
- {
326
- owner: z.string(),
327
- repo: z.string(),
328
- issue_number: z.number(),
329
- page: z.number().optional(),
330
- per_page: z.number().optional(),
331
- },
332
- async ({ owner, repo, issue_number, ...opts }) =>
333
- run(() => gh.listIssueComments(owner, repo, issue_number, opts))
334
- );
335
-
336
- server.tool(
337
- "add_labels",
338
- "Add labels to an issue or PR",
339
- {
340
- owner: z.string(),
341
- repo: z.string(),
342
- issue_number: z.number(),
343
- labels: z.array(z.string()),
344
- },
345
- async ({ owner, repo, issue_number, labels }) =>
346
- run(() => gh.addLabels(owner, repo, issue_number, labels))
347
- );
348
-
349
- server.tool(
350
- "remove_label",
351
- "Remove a label from an issue or PR",
352
- {
353
- owner: z.string(),
354
- repo: z.string(),
355
- issue_number: z.number(),
356
- name: z.string(),
357
- },
358
- async ({ owner, repo, issue_number, name }) =>
359
- run(() => gh.removeLabel(owner, repo, issue_number, name))
360
- );
361
-
362
- server.tool(
363
- "list_labels",
364
- "List all labels in a repository",
365
- { owner: z.string(), repo: z.string() },
366
- async ({ owner, repo }) => run(() => gh.listLabels(owner, repo))
367
- );
368
-
369
- server.tool(
370
- "create_label",
371
- "Create a new label in a repository",
372
- {
373
- owner: z.string(),
374
- repo: z.string(),
375
- name: z.string(),
376
- color: z.string().describe("Hex color without #, e.g. 'ff0000'"),
377
- description: z.string().optional(),
378
- },
379
- async ({ owner, repo, name, color, description }) =>
380
- run(() => gh.createLabel(owner, repo, name, color, description))
381
- );
382
-
383
- // ── Pull Request Tools ──────────────────────────────────────────────
384
-
385
- server.tool(
386
- "list_pull_requests",
387
- "List pull requests in a repository",
388
- {
389
- owner: z.string(),
390
- repo: z.string(),
391
- state: z.enum(["open", "closed", "all"]).optional(),
392
- sort: z.enum(["created", "updated", "popularity", "long-running"]).optional(),
393
- direction: z.enum(["asc", "desc"]).optional(),
394
- head: z.string().optional().describe("Filter by head branch (user:branch)"),
395
- base: z.string().optional().describe("Filter by base branch"),
396
- page: z.number().optional(),
397
- per_page: z.number().optional(),
398
- },
399
- async ({ owner, repo, ...opts }) => run(() => gh.listPullRequests(owner, repo, opts))
400
- );
401
-
402
- server.tool(
403
- "get_pull_request",
404
- "Get a specific pull request by number",
405
- { owner: z.string(), repo: z.string(), pull_number: z.number() },
406
- async ({ owner, repo, pull_number }) => run(() => gh.getPullRequest(owner, repo, pull_number))
407
- );
408
-
409
- server.tool(
410
- "create_pull_request",
411
- "Create a new pull request",
412
- {
413
- owner: z.string(),
414
- repo: z.string(),
415
- title: z.string(),
416
- body: z.string().optional(),
417
- head: z.string().describe("Branch with changes"),
418
- base: z.string().describe("Branch to merge into"),
419
- },
420
- async ({ owner, repo, title, body, head, base }) =>
421
- run(() => gh.createPullRequest(owner, repo, title, body, head, base))
422
- );
423
-
424
- server.tool(
425
- "list_pull_request_files",
426
- "List files changed in a pull request",
427
- { owner: z.string(), repo: z.string(), pull_number: z.number() },
428
- async ({ owner, repo, pull_number }) =>
429
- run(() => gh.listPullRequestFiles(owner, repo, pull_number))
430
- );
431
-
432
- server.tool(
433
- "get_pull_request_diff",
434
- "Get the diff of a pull request",
435
- { owner: z.string(), repo: z.string(), pull_number: z.number() },
436
- async ({ owner, repo, pull_number }) =>
437
- run(() => gh.getPullRequestDiff(owner, repo, pull_number))
438
- );
439
-
440
- server.tool(
441
- "create_pull_request_review",
442
- "Create a review on a pull request",
443
- {
444
- owner: z.string(),
445
- repo: z.string(),
446
- pull_number: z.number(),
447
- body: z.string().describe("Review summary"),
448
- event: z.enum(["APPROVE", "REQUEST_CHANGES", "COMMENT"]),
449
- comments: z
450
- .array(
451
- z.object({
452
- path: z.string(),
453
- position: z.number().optional(),
454
- line: z.number().optional(),
455
- body: z.string(),
456
- })
457
- )
458
- .optional()
459
- .describe("Inline review comments"),
460
- },
461
- async ({ owner, repo, pull_number, body, event, comments }) =>
462
- run(() => gh.createPullRequestReview(owner, repo, pull_number, body, event, comments || []))
463
- );
464
-
465
- server.tool(
466
- "merge_pull_request",
467
- "Merge a pull request",
468
- {
469
- owner: z.string(),
470
- repo: z.string(),
471
- pull_number: z.number(),
472
- commit_title: z.string().optional(),
473
- commit_message: z.string().optional(),
474
- merge_method: z.enum(["merge", "squash", "rebase"]).optional(),
475
- },
476
- async ({ owner, repo, pull_number, ...opts }) =>
477
- run(() => gh.mergePullRequest(owner, repo, pull_number, opts))
478
- );
479
-
480
- // ── Commit Tools ────────────────────────────────────────────────────
481
-
482
- server.tool(
483
- "list_commits",
484
- "List commits on a repository or branch",
485
- {
486
- owner: z.string(),
487
- repo: z.string(),
488
- sha: z.string().optional().describe("Branch name or commit SHA"),
489
- path: z.string().optional().describe("Only commits touching this path"),
490
- page: z.number().optional(),
491
- per_page: z.number().optional(),
492
- },
493
- async ({ owner, repo, ...opts }) => run(() => gh.listCommits(owner, repo, opts))
494
- );
495
-
496
- // ── Search Tools ────────────────────────────────────────────────────
497
-
498
- server.tool(
499
- "search_repositories",
500
- "Search for GitHub repositories",
501
- {
502
- query: z.string(),
503
- page: z.number().optional(),
504
- per_page: z.number().optional(),
505
- },
506
- async ({ query, page, per_page }) => run(() => gh.searchRepositories(query, page, per_page))
507
- );
508
-
509
- server.tool(
510
- "search_issues",
511
- "Search issues and pull requests across repositories",
512
- {
513
- query: z.string().describe("GitHub search query (e.g. 'repo:owner/name is:open label:bug')"),
514
- page: z.number().optional(),
515
- per_page: z.number().optional(),
516
- },
517
- async ({ query, page, per_page }) => run(() => gh.searchIssues(query, page, per_page))
518
- );
519
-
520
- server.tool(
521
- "search_code",
522
- "Search code across repositories",
523
- {
524
- query: z.string().describe("GitHub code search query"),
525
- page: z.number().optional(),
526
- per_page: z.number().optional(),
527
- },
528
- async ({ query, page, per_page }) => run(() => gh.searchCode(query, page, per_page))
529
- );
530
-
531
- // ── Start ───────────────────────────────────────────────────────────
532
-
533
- const transport = new StdioServerTransport();
534
- await server.connect(transport);
@@ -1,180 +0,0 @@
1
- ---
2
- name: webhook-subscriptions
3
- description: Create and manage webhook subscriptions for event-driven agent activation. Use when the user wants external services to trigger agent runs automatically.
4
- version: 1.0.0
5
- metadata:
6
- hermes:
7
- tags: [webhook, events, automation, integrations]
8
- ---
9
-
10
- # Webhook Subscriptions
11
-
12
- Create dynamic webhook subscriptions so external services (GitHub, GitLab, Stripe, CI/CD, IoT sensors, monitoring tools) can trigger Hermes agent runs by POSTing events to a URL.
13
-
14
- ## Setup (Required First)
15
-
16
- The webhook platform must be enabled before subscriptions can be created. Check with:
17
- ```bash
18
- hermes webhook list
19
- ```
20
-
21
- If it says "Webhook platform is not enabled", set it up:
22
-
23
- ### Option 1: Setup wizard
24
- ```bash
25
- hermes gateway setup
26
- ```
27
- Follow the prompts to enable webhooks, set the port, and set a global HMAC secret.
28
-
29
- ### Option 2: Manual config
30
- Add to `~/.hermes/config.yaml`:
31
- ```yaml
32
- platforms:
33
- webhook:
34
- enabled: true
35
- extra:
36
- host: "0.0.0.0"
37
- port: 8644
38
- secret: "generate-a-strong-secret-here"
39
- ```
40
-
41
- ### Option 3: Environment variables
42
- Add to `~/.hermes/.env`:
43
- ```bash
44
- WEBHOOK_ENABLED=true
45
- WEBHOOK_PORT=8644
46
- WEBHOOK_SECRET=generate-a-strong-secret-here
47
- ```
48
-
49
- After configuration, start (or restart) the gateway:
50
- ```bash
51
- hermes gateway run
52
- # Or if using systemd:
53
- systemctl --user restart hermes-gateway
54
- ```
55
-
56
- Verify it's running:
57
- ```bash
58
- curl http://localhost:8644/health
59
- ```
60
-
61
- ## Commands
62
-
63
- All management is via the `hermes webhook` CLI command:
64
-
65
- ### Create a subscription
66
- ```bash
67
- hermes webhook subscribe <name> \
68
- --prompt "Prompt template with {payload.fields}" \
69
- --events "event1,event2" \
70
- --description "What this does" \
71
- --skills "skill1,skill2" \
72
- --deliver telegram \
73
- --deliver-chat-id "12345" \
74
- --secret "optional-custom-secret"
75
- ```
76
-
77
- Returns the webhook URL and HMAC secret. The user configures their service to POST to that URL.
78
-
79
- ### List subscriptions
80
- ```bash
81
- hermes webhook list
82
- ```
83
-
84
- ### Remove a subscription
85
- ```bash
86
- hermes webhook remove <name>
87
- ```
88
-
89
- ### Test a subscription
90
- ```bash
91
- hermes webhook test <name>
92
- hermes webhook test <name> --payload '{"key": "value"}'
93
- ```
94
-
95
- ## Prompt Templates
96
-
97
- Prompts support `{dot.notation}` for accessing nested payload fields:
98
-
99
- - `{issue.title}` — GitHub issue title
100
- - `{pull_request.user.login}` — PR author
101
- - `{data.object.amount}` — Stripe payment amount
102
- - `{sensor.temperature}` — IoT sensor reading
103
-
104
- If no prompt is specified, the full JSON payload is dumped into the agent prompt.
105
-
106
- ## Common Patterns
107
-
108
- ### GitHub: new issues
109
- ```bash
110
- hermes webhook subscribe github-issues \
111
- --events "issues" \
112
- --prompt "New GitHub issue #{issue.number}: {issue.title}\n\nAction: {action}\nAuthor: {issue.user.login}\nBody:\n{issue.body}\n\nPlease triage this issue." \
113
- --deliver telegram \
114
- --deliver-chat-id "-100123456789"
115
- ```
116
-
117
- Then in GitHub repo Settings → Webhooks → Add webhook:
118
- - Payload URL: the returned webhook_url
119
- - Content type: application/json
120
- - Secret: the returned secret
121
- - Events: "Issues"
122
-
123
- ### GitHub: PR reviews
124
- ```bash
125
- hermes webhook subscribe github-prs \
126
- --events "pull_request" \
127
- --prompt "PR #{pull_request.number} {action}: {pull_request.title}\nBy: {pull_request.user.login}\nBranch: {pull_request.head.ref}\n\n{pull_request.body}" \
128
- --skills "github-code-review" \
129
- --deliver github_comment
130
- ```
131
-
132
- ### Stripe: payment events
133
- ```bash
134
- hermes webhook subscribe stripe-payments \
135
- --events "payment_intent.succeeded,payment_intent.payment_failed" \
136
- --prompt "Payment {data.object.status}: {data.object.amount} cents from {data.object.receipt_email}" \
137
- --deliver telegram \
138
- --deliver-chat-id "-100123456789"
139
- ```
140
-
141
- ### CI/CD: build notifications
142
- ```bash
143
- hermes webhook subscribe ci-builds \
144
- --events "pipeline" \
145
- --prompt "Build {object_attributes.status} on {project.name} branch {object_attributes.ref}\nCommit: {commit.message}" \
146
- --deliver discord \
147
- --deliver-chat-id "1234567890"
148
- ```
149
-
150
- ### Generic monitoring alert
151
- ```bash
152
- hermes webhook subscribe alerts \
153
- --prompt "Alert: {alert.name}\nSeverity: {alert.severity}\nMessage: {alert.message}\n\nPlease investigate and suggest remediation." \
154
- --deliver origin
155
- ```
156
-
157
- ## Security
158
-
159
- - Each subscription gets an auto-generated HMAC-SHA256 secret (or provide your own with `--secret`)
160
- - The webhook adapter validates signatures on every incoming POST
161
- - Static routes from config.yaml cannot be overwritten by dynamic subscriptions
162
- - Subscriptions persist to `~/.hermes/webhook_subscriptions.json`
163
-
164
- ## How It Works
165
-
166
- 1. `hermes webhook subscribe` writes to `~/.hermes/webhook_subscriptions.json`
167
- 2. The webhook adapter hot-reloads this file on each incoming request (mtime-gated, negligible overhead)
168
- 3. When a POST arrives matching a route, the adapter formats the prompt and triggers an agent run
169
- 4. The agent's response is delivered to the configured target (Telegram, Discord, GitHub comment, etc.)
170
-
171
- ## Troubleshooting
172
-
173
- If webhooks aren't working:
174
-
175
- 1. **Is the gateway running?** Check with `systemctl --user status hermes-gateway` or `ps aux | grep gateway`
176
- 2. **Is the webhook server listening?** `curl http://localhost:8644/health` should return `{"status": "ok"}`
177
- 3. **Check gateway logs:** `grep webhook ~/.hermes/logs/gateway.log | tail -20`
178
- 4. **Signature mismatch?** Verify the secret in your service matches the one from `hermes webhook list`. GitHub sends `X-Hub-Signature-256`, GitLab sends `X-Gitlab-Token`.
179
- 5. **Firewall/NAT?** The webhook URL must be reachable from the service. For local development, use a tunnel (ngrok, cloudflared).
180
- 6. **Wrong event type?** Check `--events` filter matches what the service sends. Use `hermes webhook test <name>` to verify the route works.