@0xmaxma/claude-gateway 1.8.14 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (582) hide show
  1. package/README.md +28 -1613
  2. package/config.template.json +7 -1
  3. package/dist/agent/runner.d.ts +377 -0
  4. package/dist/agent/runner.d.ts.map +1 -1
  5. package/dist/agent/runner.js +680 -24
  6. package/dist/agent/runner.js.map +1 -1
  7. package/dist/agent/skill-learning/index.d.ts +6 -4
  8. package/dist/agent/skill-learning/index.d.ts.map +1 -1
  9. package/dist/agent/skill-learning/index.js +3 -3
  10. package/dist/agent/skill-learning/index.js.map +1 -1
  11. package/dist/agent/skill-learning/notifier.d.ts +3 -4
  12. package/dist/agent/skill-learning/notifier.d.ts.map +1 -1
  13. package/dist/agent/skill-learning/notifier.js +15 -13
  14. package/dist/agent/skill-learning/notifier.js.map +1 -1
  15. package/dist/agent/skill-learning/reviewer.d.ts.map +1 -1
  16. package/dist/agent/skill-learning/reviewer.js +3 -1
  17. package/dist/agent/skill-learning/reviewer.js.map +1 -1
  18. package/dist/api/connectors-router.d.ts.map +1 -1
  19. package/dist/api/connectors-router.js +110 -4
  20. package/dist/api/connectors-router.js.map +1 -1
  21. package/dist/api/gateway-router.d.ts +1 -0
  22. package/dist/api/gateway-router.d.ts.map +1 -1
  23. package/dist/api/gateway-router.js +13 -1
  24. package/dist/api/gateway-router.js.map +1 -1
  25. package/dist/api/line-webhook-router.d.ts +2 -2
  26. package/dist/api/line-webhook-router.d.ts.map +1 -1
  27. package/dist/api/line-webhook-router.js +264 -230
  28. package/dist/api/line-webhook-router.js.map +1 -1
  29. package/dist/api/router.d.ts.map +1 -1
  30. package/dist/api/router.js +135 -10
  31. package/dist/api/router.js.map +1 -1
  32. package/dist/api/share-router.d.ts.map +1 -1
  33. package/dist/api/share-router.js +29 -10
  34. package/dist/api/share-router.js.map +1 -1
  35. package/dist/api/slack-client.d.ts +2 -0
  36. package/dist/api/slack-client.d.ts.map +1 -1
  37. package/dist/api/slack-client.js +6 -2
  38. package/dist/api/slack-client.js.map +1 -1
  39. package/dist/api/slack-webhook-router.d.ts +3 -0
  40. package/dist/api/slack-webhook-router.d.ts.map +1 -1
  41. package/dist/api/slack-webhook-router.js +226 -131
  42. package/dist/api/slack-webhook-router.js.map +1 -1
  43. package/dist/api/voice-router.d.ts +21 -0
  44. package/dist/api/voice-router.d.ts.map +1 -0
  45. package/dist/api/voice-router.js +372 -0
  46. package/dist/api/voice-router.js.map +1 -0
  47. package/dist/api/voice-settings-router.d.ts +5 -0
  48. package/dist/api/voice-settings-router.d.ts.map +1 -0
  49. package/dist/api/voice-settings-router.js +318 -0
  50. package/dist/api/voice-settings-router.js.map +1 -0
  51. package/dist/apps/agent-container-migration.d.ts +11 -0
  52. package/dist/apps/agent-container-migration.d.ts.map +1 -0
  53. package/dist/apps/agent-container-migration.js +85 -0
  54. package/dist/apps/agent-container-migration.js.map +1 -0
  55. package/dist/apps/installer.d.ts +1 -1
  56. package/dist/apps/installer.d.ts.map +1 -1
  57. package/dist/apps/installer.js +2 -1
  58. package/dist/apps/installer.js.map +1 -1
  59. package/dist/cli/commands/tasks.d.ts +5 -0
  60. package/dist/cli/commands/tasks.d.ts.map +1 -0
  61. package/dist/cli/commands/tasks.js +92 -0
  62. package/dist/cli/commands/tasks.js.map +1 -0
  63. package/dist/cli/http-client.d.ts +2 -0
  64. package/dist/cli/http-client.d.ts.map +1 -1
  65. package/dist/cli/http-client.js +8 -3
  66. package/dist/cli/http-client.js.map +1 -1
  67. package/dist/cli/index.d.ts.map +1 -1
  68. package/dist/cli/index.js +5 -1
  69. package/dist/cli/index.js.map +1 -1
  70. package/dist/config/config-write-lock.d.ts +2 -0
  71. package/dist/config/config-write-lock.d.ts.map +1 -1
  72. package/dist/config/config-write-lock.js +5 -0
  73. package/dist/config/config-write-lock.js.map +1 -1
  74. package/dist/config/loader.d.ts.map +1 -1
  75. package/dist/config/loader.js +87 -2
  76. package/dist/config/loader.js.map +1 -1
  77. package/dist/config/migrator.d.ts.map +1 -1
  78. package/dist/config/migrator.js +12 -1
  79. package/dist/config/migrator.js.map +1 -1
  80. package/dist/config/watcher.d.ts.map +1 -1
  81. package/dist/config/watcher.js +6 -0
  82. package/dist/config/watcher.js.map +1 -1
  83. package/dist/connectors/resolve.d.ts.map +1 -1
  84. package/dist/connectors/resolve.js +3 -1
  85. package/dist/connectors/resolve.js.map +1 -1
  86. package/dist/connectors/types.d.ts +8 -0
  87. package/dist/connectors/types.d.ts.map +1 -1
  88. package/dist/cron/manager.d.ts.map +1 -1
  89. package/dist/cron/manager.js +21 -2
  90. package/dist/cron/manager.js.map +1 -1
  91. package/dist/discord/receiver.d.ts +2 -1
  92. package/dist/discord/receiver.d.ts.map +1 -1
  93. package/dist/discord/receiver.js +5 -1
  94. package/dist/discord/receiver.js.map +1 -1
  95. package/dist/history/db.d.ts +3 -0
  96. package/dist/history/db.d.ts.map +1 -1
  97. package/dist/history/db.js +21 -1
  98. package/dist/history/db.js.map +1 -1
  99. package/dist/history/types.d.ts +2 -0
  100. package/dist/history/types.d.ts.map +1 -1
  101. package/dist/index.js +48 -9
  102. package/dist/index.js.map +1 -1
  103. package/dist/orchestration/bounded-queue.d.ts +15 -0
  104. package/dist/orchestration/bounded-queue.d.ts.map +1 -0
  105. package/dist/orchestration/bounded-queue.js +58 -0
  106. package/dist/orchestration/bounded-queue.js.map +1 -0
  107. package/dist/orchestration/bridge.d.ts +55 -0
  108. package/dist/orchestration/bridge.d.ts.map +1 -0
  109. package/dist/orchestration/bridge.js +234 -0
  110. package/dist/orchestration/bridge.js.map +1 -0
  111. package/dist/orchestration/browser-routing.d.ts +7 -0
  112. package/dist/orchestration/browser-routing.d.ts.map +1 -0
  113. package/dist/orchestration/browser-routing.js +22 -0
  114. package/dist/orchestration/browser-routing.js.map +1 -0
  115. package/dist/orchestration/capabilities.d.ts +49 -0
  116. package/dist/orchestration/capabilities.d.ts.map +1 -0
  117. package/dist/orchestration/capabilities.js +417 -0
  118. package/dist/orchestration/capabilities.js.map +1 -0
  119. package/dist/orchestration/capacity.d.ts +14 -0
  120. package/dist/orchestration/capacity.d.ts.map +1 -0
  121. package/dist/orchestration/capacity.js +52 -0
  122. package/dist/orchestration/capacity.js.map +1 -0
  123. package/dist/orchestration/channel-activity.d.ts +21 -0
  124. package/dist/orchestration/channel-activity.d.ts.map +1 -0
  125. package/dist/orchestration/channel-activity.js +72 -0
  126. package/dist/orchestration/channel-activity.js.map +1 -0
  127. package/dist/orchestration/channel-controls.d.ts +32 -0
  128. package/dist/orchestration/channel-controls.d.ts.map +1 -0
  129. package/dist/orchestration/channel-controls.js +105 -0
  130. package/dist/orchestration/channel-controls.js.map +1 -0
  131. package/dist/orchestration/channel-input-media.d.ts +11 -0
  132. package/dist/orchestration/channel-input-media.d.ts.map +1 -0
  133. package/dist/orchestration/channel-input-media.js +54 -0
  134. package/dist/orchestration/channel-input-media.js.map +1 -0
  135. package/dist/orchestration/channel-media.d.ts +4 -0
  136. package/dist/orchestration/channel-media.d.ts.map +1 -0
  137. package/dist/orchestration/channel-media.js +70 -0
  138. package/dist/orchestration/channel-media.js.map +1 -0
  139. package/dist/orchestration/channel-speech.d.ts +7 -0
  140. package/dist/orchestration/channel-speech.d.ts.map +1 -0
  141. package/dist/orchestration/channel-speech.js +65 -0
  142. package/dist/orchestration/channel-speech.js.map +1 -0
  143. package/dist/orchestration/cli-skills.d.ts +12 -0
  144. package/dist/orchestration/cli-skills.d.ts.map +1 -0
  145. package/dist/orchestration/cli-skills.js +132 -0
  146. package/dist/orchestration/cli-skills.js.map +1 -0
  147. package/dist/orchestration/config.d.ts +256 -0
  148. package/dist/orchestration/config.d.ts.map +1 -0
  149. package/dist/orchestration/config.js +110 -0
  150. package/dist/orchestration/config.js.map +1 -0
  151. package/dist/orchestration/container.d.ts +21 -0
  152. package/dist/orchestration/container.d.ts.map +1 -0
  153. package/dist/orchestration/container.js +195 -0
  154. package/dist/orchestration/container.js.map +1 -0
  155. package/dist/orchestration/control-delivery.d.ts +5 -0
  156. package/dist/orchestration/control-delivery.d.ts.map +1 -0
  157. package/dist/orchestration/control-delivery.js +50 -0
  158. package/dist/orchestration/control-delivery.js.map +1 -0
  159. package/dist/orchestration/conversation-intake.d.ts +32 -0
  160. package/dist/orchestration/conversation-intake.d.ts.map +1 -0
  161. package/dist/orchestration/conversation-intake.js +92 -0
  162. package/dist/orchestration/conversation-intake.js.map +1 -0
  163. package/dist/orchestration/decisions.d.ts +27 -0
  164. package/dist/orchestration/decisions.d.ts.map +1 -0
  165. package/dist/orchestration/decisions.js +148 -0
  166. package/dist/orchestration/decisions.js.map +1 -0
  167. package/dist/orchestration/delivery.d.ts +30 -0
  168. package/dist/orchestration/delivery.d.ts.map +1 -0
  169. package/dist/orchestration/delivery.js +219 -0
  170. package/dist/orchestration/delivery.js.map +1 -0
  171. package/dist/orchestration/display-stream.d.ts +4 -0
  172. package/dist/orchestration/display-stream.d.ts.map +1 -0
  173. package/dist/orchestration/display-stream.js +77 -0
  174. package/dist/orchestration/display-stream.js.map +1 -0
  175. package/dist/orchestration/events.d.ts +30 -0
  176. package/dist/orchestration/events.d.ts.map +1 -0
  177. package/dist/orchestration/events.js +65 -0
  178. package/dist/orchestration/events.js.map +1 -0
  179. package/dist/orchestration/execution-observation.d.ts +38 -0
  180. package/dist/orchestration/execution-observation.d.ts.map +1 -0
  181. package/dist/orchestration/execution-observation.js +25 -0
  182. package/dist/orchestration/execution-observation.js.map +1 -0
  183. package/dist/orchestration/file-delivery.d.ts +16 -0
  184. package/dist/orchestration/file-delivery.d.ts.map +1 -0
  185. package/dist/orchestration/file-delivery.js +139 -0
  186. package/dist/orchestration/file-delivery.js.map +1 -0
  187. package/dist/orchestration/gateway-config.d.ts +17 -0
  188. package/dist/orchestration/gateway-config.d.ts.map +1 -0
  189. package/dist/orchestration/gateway-config.js +128 -0
  190. package/dist/orchestration/gateway-config.js.map +1 -0
  191. package/dist/orchestration/history.d.ts +13 -0
  192. package/dist/orchestration/history.d.ts.map +1 -0
  193. package/dist/orchestration/history.js +48 -0
  194. package/dist/orchestration/history.js.map +1 -0
  195. package/dist/orchestration/identity.d.ts +6 -0
  196. package/dist/orchestration/identity.d.ts.map +1 -0
  197. package/dist/orchestration/identity.js +13 -0
  198. package/dist/orchestration/identity.js.map +1 -0
  199. package/dist/orchestration/inference-errors.d.ts +3 -0
  200. package/dist/orchestration/inference-errors.d.ts.map +1 -0
  201. package/dist/orchestration/inference-errors.js +16 -0
  202. package/dist/orchestration/inference-errors.js.map +1 -0
  203. package/dist/orchestration/input-images.d.ts +12 -0
  204. package/dist/orchestration/input-images.d.ts.map +1 -0
  205. package/dist/orchestration/input-images.js +66 -0
  206. package/dist/orchestration/input-images.js.map +1 -0
  207. package/dist/orchestration/instance-lock.d.ts +5 -0
  208. package/dist/orchestration/instance-lock.d.ts.map +1 -0
  209. package/dist/orchestration/instance-lock.js +33 -0
  210. package/dist/orchestration/instance-lock.js.map +1 -0
  211. package/dist/orchestration/line-loading.d.ts +21 -0
  212. package/dist/orchestration/line-loading.d.ts.map +1 -0
  213. package/dist/orchestration/line-loading.js +89 -0
  214. package/dist/orchestration/line-loading.js.map +1 -0
  215. package/dist/orchestration/media.d.ts +3 -0
  216. package/dist/orchestration/media.d.ts.map +1 -0
  217. package/dist/orchestration/media.js +46 -0
  218. package/dist/orchestration/media.js.map +1 -0
  219. package/dist/orchestration/migrations/schema.d.ts +3 -0
  220. package/dist/orchestration/migrations/schema.d.ts.map +1 -0
  221. package/dist/orchestration/migrations/schema.js +80 -0
  222. package/dist/orchestration/migrations/schema.js.map +1 -0
  223. package/dist/orchestration/notification-mailbox.d.ts +5 -0
  224. package/dist/orchestration/notification-mailbox.d.ts.map +1 -0
  225. package/dist/orchestration/notification-mailbox.js +29 -0
  226. package/dist/orchestration/notification-mailbox.js.map +1 -0
  227. package/dist/orchestration/process-activity.d.ts +23 -0
  228. package/dist/orchestration/process-activity.d.ts.map +1 -0
  229. package/dist/orchestration/process-activity.js +95 -0
  230. package/dist/orchestration/process-activity.js.map +1 -0
  231. package/dist/orchestration/process-supervisor.d.ts +15 -0
  232. package/dist/orchestration/process-supervisor.d.ts.map +1 -0
  233. package/dist/orchestration/process-supervisor.js +92 -0
  234. package/dist/orchestration/process-supervisor.js.map +1 -0
  235. package/dist/orchestration/process-turn.d.ts +35 -0
  236. package/dist/orchestration/process-turn.d.ts.map +1 -0
  237. package/dist/orchestration/process-turn.js +246 -0
  238. package/dist/orchestration/process-turn.js.map +1 -0
  239. package/dist/orchestration/progress-review.d.ts +28 -0
  240. package/dist/orchestration/progress-review.d.ts.map +1 -0
  241. package/dist/orchestration/progress-review.js +48 -0
  242. package/dist/orchestration/progress-review.js.map +1 -0
  243. package/dist/orchestration/recovery.d.ts +8 -0
  244. package/dist/orchestration/recovery.d.ts.map +1 -0
  245. package/dist/orchestration/recovery.js +35 -0
  246. package/dist/orchestration/recovery.js.map +1 -0
  247. package/dist/orchestration/reply-context.d.ts +7 -0
  248. package/dist/orchestration/reply-context.d.ts.map +1 -0
  249. package/dist/orchestration/reply-context.js +54 -0
  250. package/dist/orchestration/reply-context.js.map +1 -0
  251. package/dist/orchestration/runtime.d.ts +232 -0
  252. package/dist/orchestration/runtime.d.ts.map +1 -0
  253. package/dist/orchestration/runtime.js +962 -0
  254. package/dist/orchestration/runtime.js.map +1 -0
  255. package/dist/orchestration/skills.d.ts +17 -0
  256. package/dist/orchestration/skills.d.ts.map +1 -0
  257. package/dist/orchestration/skills.js +32 -0
  258. package/dist/orchestration/skills.js.map +1 -0
  259. package/dist/orchestration/source-policy.d.ts +6 -0
  260. package/dist/orchestration/source-policy.d.ts.map +1 -0
  261. package/dist/orchestration/source-policy.js +16 -0
  262. package/dist/orchestration/source-policy.js.map +1 -0
  263. package/dist/orchestration/speech.d.ts +24 -0
  264. package/dist/orchestration/speech.d.ts.map +1 -0
  265. package/dist/orchestration/speech.js +61 -0
  266. package/dist/orchestration/speech.js.map +1 -0
  267. package/dist/orchestration/stop-controls.d.ts +30 -0
  268. package/dist/orchestration/stop-controls.d.ts.map +1 -0
  269. package/dist/orchestration/stop-controls.js +79 -0
  270. package/dist/orchestration/stop-controls.js.map +1 -0
  271. package/dist/orchestration/store.d.ts +86 -0
  272. package/dist/orchestration/store.d.ts.map +1 -0
  273. package/dist/orchestration/store.js +275 -0
  274. package/dist/orchestration/store.js.map +1 -0
  275. package/dist/orchestration/task-controls.d.ts +130 -0
  276. package/dist/orchestration/task-controls.d.ts.map +1 -0
  277. package/dist/orchestration/task-controls.js +55 -0
  278. package/dist/orchestration/task-controls.js.map +1 -0
  279. package/dist/orchestration/task-files.d.ts +29 -0
  280. package/dist/orchestration/task-files.d.ts.map +1 -0
  281. package/dist/orchestration/task-files.js +200 -0
  282. package/dist/orchestration/task-files.js.map +1 -0
  283. package/dist/orchestration/task-report.d.ts +7 -0
  284. package/dist/orchestration/task-report.d.ts.map +1 -0
  285. package/dist/orchestration/task-report.js +33 -0
  286. package/dist/orchestration/task-report.js.map +1 -0
  287. package/dist/orchestration/tasks/checkpoint-hook.d.ts +19 -0
  288. package/dist/orchestration/tasks/checkpoint-hook.d.ts.map +1 -0
  289. package/dist/orchestration/tasks/checkpoint-hook.js +49 -0
  290. package/dist/orchestration/tasks/checkpoint-hook.js.map +1 -0
  291. package/dist/orchestration/tasks/cleanup.d.ts +18 -0
  292. package/dist/orchestration/tasks/cleanup.d.ts.map +1 -0
  293. package/dist/orchestration/tasks/cleanup.js +113 -0
  294. package/dist/orchestration/tasks/cleanup.js.map +1 -0
  295. package/dist/orchestration/tasks/driver.d.ts +23 -0
  296. package/dist/orchestration/tasks/driver.d.ts.map +1 -0
  297. package/dist/orchestration/tasks/driver.js +209 -0
  298. package/dist/orchestration/tasks/driver.js.map +1 -0
  299. package/dist/orchestration/tasks/failure.d.ts +5 -0
  300. package/dist/orchestration/tasks/failure.d.ts.map +1 -0
  301. package/dist/orchestration/tasks/failure.js +17 -0
  302. package/dist/orchestration/tasks/failure.js.map +1 -0
  303. package/dist/orchestration/tasks/pool.d.ts +18 -0
  304. package/dist/orchestration/tasks/pool.d.ts.map +1 -0
  305. package/dist/orchestration/tasks/pool.js +73 -0
  306. package/dist/orchestration/tasks/pool.js.map +1 -0
  307. package/dist/orchestration/tasks/scheduler.d.ts +38 -0
  308. package/dist/orchestration/tasks/scheduler.d.ts.map +1 -0
  309. package/dist/orchestration/tasks/scheduler.js +160 -0
  310. package/dist/orchestration/tasks/scheduler.js.map +1 -0
  311. package/dist/orchestration/tasks/service.d.ts +109 -0
  312. package/dist/orchestration/tasks/service.d.ts.map +1 -0
  313. package/dist/orchestration/tasks/service.js +697 -0
  314. package/dist/orchestration/tasks/service.js.map +1 -0
  315. package/dist/orchestration/tasks/shared-workspace.d.ts +25 -0
  316. package/dist/orchestration/tasks/shared-workspace.d.ts.map +1 -0
  317. package/dist/orchestration/tasks/shared-workspace.js +162 -0
  318. package/dist/orchestration/tasks/shared-workspace.js.map +1 -0
  319. package/dist/orchestration/tasks/task-directive.d.ts +6 -0
  320. package/dist/orchestration/tasks/task-directive.d.ts.map +1 -0
  321. package/dist/orchestration/tasks/task-directive.js +41 -0
  322. package/dist/orchestration/tasks/task-directive.js.map +1 -0
  323. package/dist/orchestration/tasks/timing.d.ts +15 -0
  324. package/dist/orchestration/tasks/timing.d.ts.map +1 -0
  325. package/dist/orchestration/tasks/timing.js +48 -0
  326. package/dist/orchestration/tasks/timing.js.map +1 -0
  327. package/dist/orchestration/tasks/tool-repetition.d.ts +3 -0
  328. package/dist/orchestration/tasks/tool-repetition.d.ts.map +1 -0
  329. package/dist/orchestration/tasks/tool-repetition.js +30 -0
  330. package/dist/orchestration/tasks/tool-repetition.js.map +1 -0
  331. package/dist/orchestration/tasks/workspace.d.ts +24 -0
  332. package/dist/orchestration/tasks/workspace.d.ts.map +1 -0
  333. package/dist/orchestration/tasks/workspace.js +147 -0
  334. package/dist/orchestration/tasks/workspace.js.map +1 -0
  335. package/dist/orchestration/telegram-speech.d.ts +17 -0
  336. package/dist/orchestration/telegram-speech.d.ts.map +1 -0
  337. package/dist/orchestration/telegram-speech.js +55 -0
  338. package/dist/orchestration/telegram-speech.js.map +1 -0
  339. package/dist/orchestration/telegram-tool-status.d.ts +23 -0
  340. package/dist/orchestration/telegram-tool-status.d.ts.map +1 -0
  341. package/dist/orchestration/telegram-tool-status.js +207 -0
  342. package/dist/orchestration/telegram-tool-status.js.map +1 -0
  343. package/dist/orchestration/telegram-voices.d.ts +42 -0
  344. package/dist/orchestration/telegram-voices.d.ts.map +1 -0
  345. package/dist/orchestration/telegram-voices.js +70 -0
  346. package/dist/orchestration/telegram-voices.js.map +1 -0
  347. package/dist/orchestration/tool-activity.d.ts +10 -0
  348. package/dist/orchestration/tool-activity.d.ts.map +1 -0
  349. package/dist/orchestration/tool-activity.js +38 -0
  350. package/dist/orchestration/tool-activity.js.map +1 -0
  351. package/dist/orchestration/types.d.ts +177 -0
  352. package/dist/orchestration/types.d.ts.map +1 -0
  353. package/dist/orchestration/types.js +13 -0
  354. package/dist/orchestration/types.js.map +1 -0
  355. package/dist/orchestration/voice-reply-policy.d.ts +8 -0
  356. package/dist/orchestration/voice-reply-policy.d.ts.map +1 -0
  357. package/dist/orchestration/voice-reply-policy.js +46 -0
  358. package/dist/orchestration/voice-reply-policy.js.map +1 -0
  359. package/dist/orchestration/worker-shares.d.ts +8 -0
  360. package/dist/orchestration/worker-shares.d.ts.map +1 -0
  361. package/dist/orchestration/worker-shares.js +59 -0
  362. package/dist/orchestration/worker-shares.js.map +1 -0
  363. package/dist/orchestration/workflow.d.ts +121 -0
  364. package/dist/orchestration/workflow.d.ts.map +1 -0
  365. package/dist/orchestration/workflow.js +69 -0
  366. package/dist/orchestration/workflow.js.map +1 -0
  367. package/dist/session/input-image.d.ts +10 -0
  368. package/dist/session/input-image.d.ts.map +1 -0
  369. package/dist/session/input-image.js +3 -0
  370. package/dist/session/input-image.js.map +1 -0
  371. package/dist/session/process.d.ts +15 -3
  372. package/dist/session/process.d.ts.map +1 -1
  373. package/dist/session/process.js +143 -35
  374. package/dist/session/process.js.map +1 -1
  375. package/dist/session/runtime-profile.d.ts +36 -0
  376. package/dist/session/runtime-profile.d.ts.map +1 -0
  377. package/dist/session/runtime-profile.js +63 -0
  378. package/dist/session/runtime-profile.js.map +1 -0
  379. package/dist/session/store.d.ts.map +1 -1
  380. package/dist/session/store.js +23 -1
  381. package/dist/session/store.js.map +1 -1
  382. package/dist/share/share-store.d.ts +3 -1
  383. package/dist/share/share-store.d.ts.map +1 -1
  384. package/dist/share/share-store.js +13 -2
  385. package/dist/share/share-store.js.map +1 -1
  386. package/dist/shared/line-request-order.d.ts +2 -0
  387. package/dist/shared/line-request-order.d.ts.map +1 -0
  388. package/dist/shared/line-request-order.js +16 -0
  389. package/dist/shared/line-request-order.js.map +1 -0
  390. package/dist/shared/task-elapsed.d.ts +3 -0
  391. package/dist/shared/task-elapsed.d.ts.map +1 -0
  392. package/dist/shared/task-elapsed.js +12 -0
  393. package/dist/shared/task-elapsed.js.map +1 -0
  394. package/dist/shared/task-updated-time.d.ts +3 -0
  395. package/dist/shared/task-updated-time.d.ts.map +1 -0
  396. package/dist/shared/task-updated-time.js +15 -0
  397. package/dist/shared/task-updated-time.js.map +1 -0
  398. package/dist/skills/loader.d.ts +2 -0
  399. package/dist/skills/loader.d.ts.map +1 -1
  400. package/dist/skills/loader.js.map +1 -1
  401. package/dist/telegram/chunks.d.ts +19 -0
  402. package/dist/telegram/chunks.d.ts.map +1 -0
  403. package/dist/telegram/chunks.js +129 -0
  404. package/dist/telegram/chunks.js.map +1 -0
  405. package/dist/telegram/markdown.d.ts.map +1 -1
  406. package/dist/telegram/markdown.js +18 -3
  407. package/dist/telegram/markdown.js.map +1 -1
  408. package/dist/telegram/receiver.d.ts +2 -1
  409. package/dist/telegram/receiver.d.ts.map +1 -1
  410. package/dist/telegram/receiver.js +6 -1
  411. package/dist/telegram/receiver.js.map +1 -1
  412. package/dist/types.d.ts +14 -0
  413. package/dist/types.d.ts.map +1 -1
  414. package/dist/ui/web-ui.d.ts.map +1 -1
  415. package/dist/ui/web-ui.js +31 -5
  416. package/dist/ui/web-ui.js.map +1 -1
  417. package/dist/voice/diagnostics.d.ts +29 -0
  418. package/dist/voice/diagnostics.d.ts.map +1 -0
  419. package/dist/voice/diagnostics.js +37 -0
  420. package/dist/voice/diagnostics.js.map +1 -0
  421. package/dist/voice/errors.d.ts +19 -0
  422. package/dist/voice/errors.d.ts.map +1 -0
  423. package/dist/voice/errors.js +133 -0
  424. package/dist/voice/errors.js.map +1 -0
  425. package/dist/voice/line-audio.d.ts +4 -0
  426. package/dist/voice/line-audio.d.ts.map +1 -0
  427. package/dist/voice/line-audio.js +27 -0
  428. package/dist/voice/line-audio.js.map +1 -0
  429. package/dist/voice/managed-quota.d.ts +5 -0
  430. package/dist/voice/managed-quota.d.ts.map +1 -0
  431. package/dist/voice/managed-quota.js +35 -0
  432. package/dist/voice/managed-quota.js.map +1 -0
  433. package/dist/voice/mp3.d.ts +3 -0
  434. package/dist/voice/mp3.d.ts.map +1 -0
  435. package/dist/voice/mp3.js +30 -0
  436. package/dist/voice/mp3.js.map +1 -0
  437. package/dist/voice/notes.d.ts +9 -0
  438. package/dist/voice/notes.d.ts.map +1 -0
  439. package/dist/voice/notes.js +68 -0
  440. package/dist/voice/notes.js.map +1 -0
  441. package/dist/voice/playback.d.ts +22 -0
  442. package/dist/voice/playback.d.ts.map +1 -0
  443. package/dist/voice/playback.js +52 -0
  444. package/dist/voice/playback.js.map +1 -0
  445. package/dist/voice/preview.d.ts +6 -0
  446. package/dist/voice/preview.d.ts.map +1 -0
  447. package/dist/voice/preview.js +44 -0
  448. package/dist/voice/preview.js.map +1 -0
  449. package/dist/voice/protocol.d.ts +10 -0
  450. package/dist/voice/protocol.d.ts.map +1 -0
  451. package/dist/voice/protocol.js +30 -0
  452. package/dist/voice/protocol.js.map +1 -0
  453. package/dist/voice/providers/cartesia-tts.d.ts +26 -0
  454. package/dist/voice/providers/cartesia-tts.d.ts.map +1 -0
  455. package/dist/voice/providers/cartesia-tts.js +95 -0
  456. package/dist/voice/providers/cartesia-tts.js.map +1 -0
  457. package/dist/voice/providers/deepgram-stt.d.ts +20 -0
  458. package/dist/voice/providers/deepgram-stt.d.ts.map +1 -0
  459. package/dist/voice/providers/deepgram-stt.js +66 -0
  460. package/dist/voice/providers/deepgram-stt.js.map +1 -0
  461. package/dist/voice/providers/elevenlabs-stt.d.ts +20 -0
  462. package/dist/voice/providers/elevenlabs-stt.d.ts.map +1 -0
  463. package/dist/voice/providers/elevenlabs-stt.js +92 -0
  464. package/dist/voice/providers/elevenlabs-stt.js.map +1 -0
  465. package/dist/voice/providers/elevenlabs-tts.d.ts +26 -0
  466. package/dist/voice/providers/elevenlabs-tts.d.ts.map +1 -0
  467. package/dist/voice/providers/elevenlabs-tts.js +82 -0
  468. package/dist/voice/providers/elevenlabs-tts.js.map +1 -0
  469. package/dist/voice/providers/encoded-audio-tts.d.ts +21 -0
  470. package/dist/voice/providers/encoded-audio-tts.d.ts.map +1 -0
  471. package/dist/voice/providers/encoded-audio-tts.js +175 -0
  472. package/dist/voice/providers/encoded-audio-tts.js.map +1 -0
  473. package/dist/voice/providers/fake.d.ts +39 -0
  474. package/dist/voice/providers/fake.d.ts.map +1 -0
  475. package/dist/voice/providers/fake.js +41 -0
  476. package/dist/voice/providers/fake.js.map +1 -0
  477. package/dist/voice/providers/gemini-live-stt.d.ts +21 -0
  478. package/dist/voice/providers/gemini-live-stt.d.ts.map +1 -0
  479. package/dist/voice/providers/gemini-live-stt.js +158 -0
  480. package/dist/voice/providers/gemini-live-stt.js.map +1 -0
  481. package/dist/voice/providers/gemini.d.ts +60 -0
  482. package/dist/voice/providers/gemini.d.ts.map +1 -0
  483. package/dist/voice/providers/gemini.js +124 -0
  484. package/dist/voice/providers/gemini.js.map +1 -0
  485. package/dist/voice/providers/model-ref.d.ts +9 -0
  486. package/dist/voice/providers/model-ref.d.ts.map +1 -0
  487. package/dist/voice/providers/model-ref.js +31 -0
  488. package/dist/voice/providers/model-ref.js.map +1 -0
  489. package/dist/voice/providers/openrouter.d.ts +39 -0
  490. package/dist/voice/providers/openrouter.d.ts.map +1 -0
  491. package/dist/voice/providers/openrouter.js +154 -0
  492. package/dist/voice/providers/openrouter.js.map +1 -0
  493. package/dist/voice/providers/paxalabs-stt.d.ts +12 -0
  494. package/dist/voice/providers/paxalabs-stt.d.ts.map +1 -0
  495. package/dist/voice/providers/paxalabs-stt.js +41 -0
  496. package/dist/voice/providers/paxalabs-stt.js.map +1 -0
  497. package/dist/voice/providers/paxalabs-tts.d.ts +23 -0
  498. package/dist/voice/providers/paxalabs-tts.d.ts.map +1 -0
  499. package/dist/voice/providers/paxalabs-tts.js +80 -0
  500. package/dist/voice/providers/paxalabs-tts.js.map +1 -0
  501. package/dist/voice/providers/recorded-stt.d.ts +34 -0
  502. package/dist/voice/providers/recorded-stt.d.ts.map +1 -0
  503. package/dist/voice/providers/recorded-stt.js +59 -0
  504. package/dist/voice/providers/recorded-stt.js.map +1 -0
  505. package/dist/voice/providers/registry.d.ts +10 -0
  506. package/dist/voice/providers/registry.d.ts.map +1 -0
  507. package/dist/voice/providers/registry.js +77 -0
  508. package/dist/voice/providers/registry.js.map +1 -0
  509. package/dist/voice/providers/socket.d.ts +10 -0
  510. package/dist/voice/providers/socket.d.ts.map +1 -0
  511. package/dist/voice/providers/socket.js +91 -0
  512. package/dist/voice/providers/socket.js.map +1 -0
  513. package/dist/voice/providers/upstream.d.ts +9 -0
  514. package/dist/voice/providers/upstream.d.ts.map +1 -0
  515. package/dist/voice/providers/upstream.js +51 -0
  516. package/dist/voice/providers/upstream.js.map +1 -0
  517. package/dist/voice/providers/voice-catalog.d.ts +17 -0
  518. package/dist/voice/providers/voice-catalog.d.ts.map +1 -0
  519. package/dist/voice/providers/voice-catalog.js +167 -0
  520. package/dist/voice/providers/voice-catalog.js.map +1 -0
  521. package/dist/voice/queue.d.ts +2 -0
  522. package/dist/voice/queue.d.ts.map +1 -0
  523. package/dist/voice/queue.js +6 -0
  524. package/dist/voice/queue.js.map +1 -0
  525. package/dist/voice/session.d.ts +86 -0
  526. package/dist/voice/session.d.ts.map +1 -0
  527. package/dist/voice/session.js +464 -0
  528. package/dist/voice/session.js.map +1 -0
  529. package/dist/voice/turn-manager.d.ts +27 -0
  530. package/dist/voice/turn-manager.d.ts.map +1 -0
  531. package/dist/voice/turn-manager.js +75 -0
  532. package/dist/voice/turn-manager.js.map +1 -0
  533. package/dist/voice/types.d.ts +78 -0
  534. package/dist/voice/types.d.ts.map +1 -0
  535. package/dist/voice/types.js +18 -0
  536. package/dist/voice/types.js.map +1 -0
  537. package/dist/voice/wav.d.ts +2 -0
  538. package/dist/voice/wav.d.ts.map +1 -0
  539. package/dist/voice/wav.js +21 -0
  540. package/dist/voice/wav.js.map +1 -0
  541. package/dist/wechat/ilink-client.d.ts +13 -0
  542. package/dist/wechat/ilink-client.d.ts.map +1 -1
  543. package/dist/wechat/ilink-client.js +19 -0
  544. package/dist/wechat/ilink-client.js.map +1 -1
  545. package/dist/whatsapp/manager.d.ts.map +1 -1
  546. package/dist/whatsapp/manager.js +51 -1
  547. package/dist/whatsapp/manager.js.map +1 -1
  548. package/mcp/capability-catalog.ts +206 -0
  549. package/mcp/modules.ts +56 -0
  550. package/mcp/server.ts +18 -37
  551. package/mcp/tools/browser/module.ts +1 -1
  552. package/mcp/tools/browser/skills/open-browser/SKILL.md +5 -3
  553. package/mcp/tools/discord/commands.ts +17 -1
  554. package/mcp/tools/discord/inbound.ts +11 -0
  555. package/mcp/tools/discord/module.ts +42 -2
  556. package/mcp/tools/discord/receiver-server.ts +10 -0
  557. package/mcp/tools/discord/types.ts +4 -1
  558. package/mcp/tools/image/module.ts +3 -1
  559. package/mcp/tools/receiver-spool.test.ts +28 -0
  560. package/mcp/tools/receiver-spool.ts +56 -0
  561. package/mcp/tools/share-file/module.ts +9 -1
  562. package/mcp/tools/shared/share-client.ts +19 -0
  563. package/mcp/tools/tasks/module.ts +35 -0
  564. package/mcp/tools/telegram/media-group.ts +21 -0
  565. package/mcp/tools/telegram/receiver-server.ts +232 -11
  566. package/mcp/tools/telegram/selection-confirmation.ts +20 -0
  567. package/mcp/tools/telegram/task-browser.ts +117 -0
  568. package/mcp/tools/telegram/task-detail.ts +36 -0
  569. package/mcp/tools/telegram/task-elapsed.ts +1 -0
  570. package/mcp/tools/telegram/typing.ts +6 -116
  571. package/mcp/tools/video/module.ts +1 -1
  572. package/mcp/types.ts +5 -0
  573. package/package.json +2 -1
  574. package/resource/claude_gateway.jpeg +0 -0
  575. package/scripts/orchestration/bench-store.cjs +30 -0
  576. package/scripts/orchestration/inspect.cjs +16 -0
  577. package/scripts/orchestration/probe-profile.cjs +67 -0
  578. package/scripts/orchestration/reconcile.cjs +21 -0
  579. package/scripts/orchestration/smoke-elevenlabs.cjs +90 -0
  580. package/scripts/orchestration/smoke-media.cjs +70 -0
  581. package/scripts/orchestration/smoke-text.cjs +101 -0
  582. package/scripts/orchestration/smoke-vision.cjs +49 -0
@@ -40,6 +40,7 @@ exports.markMediaUnavailable = markMediaUnavailable;
40
40
  exports.parseCliPostback = parseCliPostback;
41
41
  exports.normalizeLinePostback = normalizeLinePostback;
42
42
  exports.createLineWebhookHandler = createLineWebhookHandler;
43
+ const line_request_order_1 = require("../shared/line-request-order");
43
44
  const fs = __importStar(require("fs"));
44
45
  const os = __importStar(require("os"));
45
46
  const path = __importStar(require("path"));
@@ -336,7 +337,7 @@ function pairingMessage(code, kind) {
336
337
  /**
337
338
  * Normalize a LINE webhook event into the gateway's {content, meta} intake shape.
338
339
  * Returns null for anything we don't handle (message types other than text/image/
339
- * file, or a source we can't key a conversation on).
340
+ * file/audio, or a source we can't key a conversation on).
340
341
  *
341
342
  * `resolved` lets the caller pass the source it already resolved for the access
342
343
  * gate, so a single event isn't re-parsed; omitted, it resolves here.
@@ -345,11 +346,11 @@ function normalizeLineEvent(event, resolved) {
345
346
  if (event.type !== 'message')
346
347
  return null;
347
348
  const msg = event.message;
348
- // Text, image, and file are handled. Image/file bytes are fetched separately in
349
+ // Text, image, file and audio are normalized; audio routing is orchestration-only. Image/file bytes are fetched separately in
349
350
  // handlePost (via the LINE blob API) and surfaced to the agent through
350
351
  // meta.image_path — the generic "local path the agent should Read" channel,
351
352
  // which the runner stages into MediaStore regardless of media kind.
352
- if (!msg || (msg.type !== 'text' && msg.type !== 'image' && msg.type !== 'file'))
353
+ if (!msg || (msg.type !== 'text' && msg.type !== 'image' && msg.type !== 'file' && msg.type !== 'audio'))
353
354
  return null;
354
355
  // Accept 1:1 user, group, and room sources. chat_id is the conversation key
355
356
  // (userId / groupId / roomId — the reply/push target); user_id is the human
@@ -368,9 +369,17 @@ function normalizeLineEvent(event, resolved) {
368
369
  ts: new Date(event.timestamp ?? Date.now()).toISOString(),
369
370
  line_chat_type: kind, // 'user' | 'group' | 'room'
370
371
  };
372
+ const quoted = msg.quotedMessageId;
373
+ if (typeof quoted === 'string')
374
+ meta.replied_message_id = quoted;
371
375
  if (msg.type === 'image')
372
376
  meta.media_type = 'image';
373
377
  let content = text;
378
+ if (msg.type === 'audio') {
379
+ meta.media_type = 'audio';
380
+ meta.attachment_kind = 'voice';
381
+ content = '(voice message)';
382
+ }
374
383
  if (msg.type === 'file') {
375
384
  const file = msg;
376
385
  meta.media_type = 'file';
@@ -410,7 +419,7 @@ function normalizeLineEvent(event, resolved) {
410
419
  function markMediaUnavailable(norm, mediaType, reason) {
411
420
  delete norm.meta.image_path;
412
421
  const name = norm.meta.attachment_name;
413
- const label = mediaType === 'image' ? 'image' : name ? `file: ${name}` : 'file';
422
+ const label = mediaType === 'image' ? 'image' : mediaType === 'audio' ? 'audio' : name ? `file: ${name}` : 'file';
414
423
  norm.content = `(${label} — not available: ${reason})`;
415
424
  }
416
425
  /** Parse a `/cli` approve/deny postback payload, or null when it's not ours. */
@@ -509,257 +518,282 @@ function createLineWebhookHandler(agents, logDir, opts = {}) {
509
518
  req.headers.host ||
510
519
  '';
511
520
  persistPublicBase(runner.getAgentConfig().workspace, host, logger);
512
- // Acknowledge immediately; process events after responding.
513
- res.status(200).json({ ok: true });
514
- let events = [];
521
+ // Orchestrated conversations retain durable admission while draining after opt-out.
522
+ const orchestrationConfig = runner.getAgentConfig().orchestration;
523
+ const durableIngress = runner.requiresDurableChannelIngress?.('line') ?? (orchestrationConfig?.enabled && (orchestrationConfig.channels ?? ['api']).includes('line'));
524
+ if (!durableIngress)
525
+ res.status(200).json({ ok: true });
515
526
  try {
516
- events = JSON.parse(buf.toString('utf8')).events ?? [];
517
- }
518
- catch (err) {
519
- logger.warn('LINE webhook: bad JSON', { error: err.message });
520
- return;
521
- }
522
- const token = cfg?.channelAccessToken ?? '';
523
- const client = token
524
- ? new bot_sdk_1.messagingApi.MessagingApiClient({
525
- channelAccessToken: token,
526
- ...(opts.apiBase ? { baseURL: opts.apiBase } : {}),
527
- })
528
- : null;
529
- // Blob/data API lives on a different host (api-data.line.me) than the
530
- // messaging API, so it takes its own base override (used by tests).
531
- const blobClient = token
532
- ? new bot_sdk_1.messagingApi.MessagingApiBlobClient({
533
- channelAccessToken: token,
534
- ...(opts.dataApiBase ? { baseURL: opts.dataApiBase } : {}),
535
- })
536
- : null;
537
- for (const event of events) {
538
- // Postback BEFORE access gate: a tap on our slow-LLM button must reach the
539
- // cache even if the user's allowlist status changed since the button was sent.
540
- // The postback data is opaque (request_id we issued), so bypassing the gate here
541
- // is safe only users who received the button can tap it.
542
- const pb = normalizeLinePostback(event);
543
- if (pb) {
544
- // `/cli` approve/deny — unlock (or reject) a terminal-viewer pairing.
545
- // The pairing binds the requesting user; approveCliPairing checks the
546
- // tapping user (pb.chatId, a LINE-verified id) matches, so bypassing the
547
- // access gate here is safe — same as the slow-LLM postback below.
548
- const cli = parseCliPostback(pb.data);
549
- if (cli) {
550
- const result = runner.approveCliPairing('line', cli.pairingId, pb.chatId, cli.deny);
551
- if (client && pb.replyToken) {
552
- const text = cli.deny
553
- ? 'Denied.'
554
- : result === 'ok'
555
- ? 'Approved return to the browser.'
556
- : 'Could not approve (the link may have expired). Send /cli again.';
557
- await client
558
- .replyMessage({ replyToken: pb.replyToken, messages: [{ type: 'text', text }] })
559
- .catch(() => { });
527
+ let events = [];
528
+ try {
529
+ events = JSON.parse(buf.toString('utf8')).events ?? [];
530
+ }
531
+ catch (err) {
532
+ logger.warn('LINE webhook: bad JSON', { error: err.message });
533
+ return;
534
+ }
535
+ const token = cfg?.channelAccessToken ?? '';
536
+ const client = token
537
+ ? new bot_sdk_1.messagingApi.MessagingApiClient({
538
+ channelAccessToken: token,
539
+ ...(opts.apiBase ? { baseURL: opts.apiBase } : {}),
540
+ })
541
+ : null;
542
+ // Blob/data API lives on a different host (api-data.line.me) than the
543
+ // messaging API, so it takes its own base override (used by tests).
544
+ const blobClient = token
545
+ ? new bot_sdk_1.messagingApi.MessagingApiBlobClient({
546
+ channelAccessToken: token,
547
+ ...(opts.dataApiBase ? { baseURL: opts.dataApiBase } : {}),
548
+ })
549
+ : null;
550
+ for (const event of events) {
551
+ // Postback BEFORE access gate: a tap on our slow-LLM button must reach the
552
+ // cache even if the user's allowlist status changed since the button was sent.
553
+ // The postback data is opaque (request_id we issued), so bypassing the gate here
554
+ // is safe — only users who received the button can tap it.
555
+ const pb = normalizeLinePostback(event);
556
+ if (pb) {
557
+ if (/^orch:[a-f0-9-]{36}$/.test(pb.data)) {
558
+ if (!(0, line_access_1.isResolvedSourceAllowed)(cfg, (0, line_access_1.resolveLineSource)(event.source)))
559
+ continue;
560
+ const forwarded = await fetch(`http://127.0.0.1:${runner.getCallbackPort()}/channel`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: `/orch ${pb.data.slice(5)}`, meta: { source: 'line', chat_id: pb.chatId, user_id: event.source?.userId ?? pb.chatId, reply_token: pb.replyToken } }) });
561
+ if (!forwarded.ok)
562
+ throw Error('Control unavailable');
563
+ continue;
564
+ }
565
+ // `/cli` approve/deny — unlock (or reject) a terminal-viewer pairing.
566
+ // The pairing binds the requesting user; approveCliPairing checks the
567
+ // tapping user (pb.chatId, a LINE-verified id) matches, so bypassing the
568
+ // access gate here is safe — same as the slow-LLM postback below.
569
+ const cli = parseCliPostback(pb.data);
570
+ if (cli) {
571
+ const result = runner.approveCliPairing('line', cli.pairingId, pb.chatId, cli.deny);
572
+ if (client && pb.replyToken) {
573
+ const text = cli.deny
574
+ ? 'Denied.'
575
+ : result === 'ok'
576
+ ? 'Approved — return to the browser.'
577
+ : 'Could not approve (the link may have expired). Send /cli again.';
578
+ await client
579
+ .replyMessage({ replyToken: pb.replyToken, messages: [{ type: 'text', text }] })
580
+ .catch(() => { });
581
+ }
582
+ continue;
583
+ }
584
+ try {
585
+ await runner.handleLinePostback(pb.chatId, pb.replyToken, pb.data);
586
+ }
587
+ catch (err) {
588
+ logger.error('LINE webhook: postback handling failed', {
589
+ error: err.message,
590
+ });
560
591
  }
561
592
  continue;
562
593
  }
563
- try {
564
- await runner.handleLinePostback(pb.chatId, pb.replyToken, pb.data);
565
- }
566
- catch (err) {
567
- logger.error('LINE webhook: postback handling failed', {
568
- error: err.message,
594
+ // Access gate (single choke point — mirrors hermes _dispatch_event):
595
+ // resolve the source once and gate before any message handling.
596
+ // Closed by default for both DMs (dmPolicy/dmAllowlist) and groups/rooms
597
+ // (groupPolicy/groupAllowlist). `'open'` restores answer-to-anyone.
598
+ const resolved = (0, line_access_1.resolveLineSource)(event.source);
599
+ if (!(0, line_access_1.isResolvedSourceAllowed)(cfg, resolved)) {
600
+ logger.debug('LINE webhook: source not allowed', {
601
+ agentId: runner.getAgentConfig().id,
602
+ kind: resolved.kind,
603
+ policy: (resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy) ?? '(closed)',
604
+ conversationId: resolved.conversationId,
569
605
  });
570
- }
571
- continue;
572
- }
573
- // Access gate (single choke point mirrors hermes _dispatch_event):
574
- // resolve the source once and gate before any message handling.
575
- // Closed by default for both DMs (dmPolicy/dmAllowlist) and groups/rooms
576
- // (groupPolicy/groupAllowlist). `'open'` restores answer-to-anyone.
577
- const resolved = (0, line_access_1.resolveLineSource)(event.source);
578
- if (!(0, line_access_1.isResolvedSourceAllowed)(cfg, resolved)) {
579
- logger.debug('LINE webhook: source not allowed', {
580
- agentId: runner.getAgentConfig().id,
581
- kind: resolved.kind,
582
- policy: (resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy) ?? '(closed)',
583
- conversationId: resolved.conversationId,
584
- });
585
- // Remember the knock so an admin can find + add it from the UI without
586
- // grepping logs, and (pairing mode) reply a one-time code the admin can
587
- // visually match before +Add. The id we track is the sender (DM) or the
588
- // conversation (group/room). Names are backfilled best-effort without
589
- // bumping the knock count.
590
- const deniedAgentId = runner.getAgentConfig().id;
591
- const knockId = resolved.kind === 'user' ? resolved.senderId : resolved.conversationId;
592
- if (knockId) {
593
- // Pairing applies only under allowlist/closed-default (open never
594
- // denies; disabled is hard-off) and unless explicitly turned off.
595
- const sourcePolicy = resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy;
596
- const isPairing = cfg?.pairing !== false && sourcePolicy !== 'open' && sourcePolicy !== 'disabled';
597
- const prev = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
598
- const code = prev?.code ?? (isPairing ? (0, pending_senders_1.generatePairingCode)() : undefined);
599
- let wasNew = false;
600
- if (resolved.kind === 'user') {
601
- wasNew = (0, pending_senders_1.recordDeniedSender)('line', deniedAgentId, knockId, undefined, Date.now(), code);
602
- if (client) {
603
- void client
604
- .getProfile(knockId)
605
- .then((p) => {
606
- const e = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
607
- if (e && p?.displayName && !e.displayName)
608
- e.displayName = p.displayName;
609
- })
610
- .catch(() => { });
606
+ // Remember the knock so an admin can find + add it from the UI without
607
+ // grepping logs, and (pairing mode) reply a one-time code the admin can
608
+ // visually match before +Add. The id we track is the sender (DM) or the
609
+ // conversation (group/room). Names are backfilled best-effort without
610
+ // bumping the knock count.
611
+ const deniedAgentId = runner.getAgentConfig().id;
612
+ const knockId = resolved.kind === 'user' ? resolved.senderId : resolved.conversationId;
613
+ if (knockId) {
614
+ // Pairing applies only under allowlist/closed-default (open never
615
+ // denies; disabled is hard-off) and unless explicitly turned off.
616
+ const sourcePolicy = resolved.kind === 'user' ? cfg?.dmPolicy : cfg?.groupPolicy;
617
+ const isPairing = cfg?.pairing !== false && sourcePolicy !== 'open' && sourcePolicy !== 'disabled';
618
+ const prev = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
619
+ const code = prev?.code ?? (isPairing ? (0, pending_senders_1.generatePairingCode)() : undefined);
620
+ let wasNew = false;
621
+ if (resolved.kind === 'user') {
622
+ wasNew = (0, pending_senders_1.recordDeniedSender)('line', deniedAgentId, knockId, undefined, Date.now(), code);
623
+ if (client) {
624
+ void client
625
+ .getProfile(knockId)
626
+ .then((p) => {
627
+ const e = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
628
+ if (e && p?.displayName && !e.displayName)
629
+ e.displayName = p.displayName;
630
+ })
631
+ .catch(() => { });
632
+ }
611
633
  }
612
- }
613
- else if (resolved.kind === 'group') {
614
- wasNew = (0, pending_senders_1.recordDeniedConversation)('line', deniedAgentId, knockId, 'group', undefined, Date.now(), code);
615
- if (client) {
634
+ else if (resolved.kind === 'group') {
635
+ wasNew = (0, pending_senders_1.recordDeniedConversation)('line', deniedAgentId, knockId, 'group', undefined, Date.now(), code);
636
+ if (client) {
637
+ void client
638
+ .getGroupSummary(knockId)
639
+ .then((s) => {
640
+ const e = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
641
+ if (e && s?.groupName && !e.displayName)
642
+ e.displayName = s.groupName;
643
+ })
644
+ .catch(() => { });
645
+ }
646
+ }
647
+ else if (resolved.kind === 'room') {
648
+ wasNew = (0, pending_senders_1.recordDeniedConversation)('line', deniedAgentId, knockId, 'room', undefined, Date.now(), code);
649
+ }
650
+ // Send the pairing code exactly once — on first contact only — via the
651
+ // free reply token (never push; don't spend quota on strangers).
652
+ const replyToken = event.replyToken;
653
+ if (isPairing && wasNew && code && client && typeof replyToken === 'string' && replyToken) {
616
654
  void client
617
- .getGroupSummary(knockId)
618
- .then((s) => {
619
- const e = (0, pending_senders_1.getPendingSender)('line', deniedAgentId, knockId);
620
- if (e && s?.groupName && !e.displayName)
621
- e.displayName = s.groupName;
655
+ .replyMessage({
656
+ replyToken,
657
+ messages: [{ type: 'text', text: pairingMessage(code, resolved.kind) }],
622
658
  })
623
- .catch(() => { });
659
+ .catch((err) => logger.debug('LINE pairing code reply failed', { error: err.message }));
624
660
  }
625
661
  }
626
- else if (resolved.kind === 'room') {
627
- wasNew = (0, pending_senders_1.recordDeniedConversation)('line', deniedAgentId, knockId, 'room', undefined, Date.now(), code);
628
- }
629
- // Send the pairing code exactly once — on first contact only — via the
630
- // free reply token (never push; don't spend quota on strangers).
631
- const replyToken = event.replyToken;
632
- if (isPairing && wasNew && code && client && typeof replyToken === 'string' && replyToken) {
633
- void client
634
- .replyMessage({
635
- replyToken,
636
- messages: [{ type: 'text', text: pairingMessage(code, resolved.kind) }],
637
- })
638
- .catch((err) => logger.debug('LINE pairing code reply failed', { error: err.message }));
662
+ continue;
663
+ }
664
+ // Normalize the event into our /channel intake format.
665
+ const norm = normalizeLineEvent(event, resolved);
666
+ if (!norm)
667
+ continue;
668
+ const userId = norm.meta.chat_id;
669
+ // `/cli` opens the live terminal viewer (DM only). Mint a pairing and reply
670
+ // with an open-link + Approve/Deny buttons instead of forwarding to the
671
+ // agent. Reached only after the access gate above authorized this source.
672
+ if ((norm.content ?? '').trim().toLowerCase() === '/cli') {
673
+ if (norm.meta['line_chat_type'] === 'user' && client) {
674
+ const replyToken = norm.meta['reply_token'] ?? '';
675
+ const pairing = runner.createCliPairing('line', userId);
676
+ if (replyToken) {
677
+ const messages = pairing
678
+ ? [{
679
+ type: 'template',
680
+ altText: 'Live terminal viewer',
681
+ template: {
682
+ type: 'buttons',
683
+ text: `Live terminal viewer\nCode ${pairing.code} — open, confirm the code, then Approve.`,
684
+ actions: [
685
+ { type: 'uri', label: 'Open terminal', uri: pairing.url },
686
+ { type: 'postback', label: `Approve ${pairing.code}`, data: JSON.stringify({ action: 'cli_approve', pairing_id: pairing.pairingId }), displayText: 'Approve terminal viewer' },
687
+ { type: 'postback', label: 'Deny', data: JSON.stringify({ action: 'cli_deny', pairing_id: pairing.pairingId }) },
688
+ ],
689
+ },
690
+ }]
691
+ : [{ type: 'text', text: 'Terminal viewer is not configured. Set gateway.publicUrl in config.json first.' }];
692
+ await client.replyMessage({ replyToken, messages }).catch((err) => {
693
+ logger.debug('LINE /cli reply failed', { error: err.message });
694
+ });
695
+ }
639
696
  }
697
+ continue;
640
698
  }
641
- continue;
642
- }
643
- // Normalize the event into our /channel intake format.
644
- const norm = normalizeLineEvent(event, resolved);
645
- if (!norm)
646
- continue;
647
- const userId = norm.meta.chat_id;
648
- // `/cli` opens the live terminal viewer (DM only). Mint a pairing and reply
649
- // with an open-link + Approve/Deny buttons instead of forwarding to the
650
- // agent. Reached only after the access gate above authorized this source.
651
- if ((norm.content ?? '').trim().toLowerCase() === '/cli') {
652
- if (norm.meta['line_chat_type'] === 'user' && client) {
653
- const replyToken = norm.meta['reply_token'] ?? '';
654
- const pairing = runner.createCliPairing('line', userId);
655
- if (replyToken) {
656
- const messages = pairing
657
- ? [{
658
- type: 'template',
659
- altText: 'Live terminal viewer',
660
- template: {
661
- type: 'buttons',
662
- text: `Live terminal viewer\nCode ${pairing.code} — open, confirm the code, then Approve.`,
663
- actions: [
664
- { type: 'uri', label: 'Open terminal', uri: pairing.url },
665
- { type: 'postback', label: `Approve ${pairing.code}`, data: JSON.stringify({ action: 'cli_approve', pairing_id: pairing.pairingId }), displayText: 'Approve terminal viewer' },
666
- { type: 'postback', label: 'Deny', data: JSON.stringify({ action: 'cli_deny', pairing_id: pairing.pairingId }) },
667
- ],
668
- },
669
- }]
670
- : [{ type: 'text', text: 'Terminal viewer is not configured. Set gateway.publicUrl in config.json first.' }];
671
- await client.replyMessage({ replyToken, messages }).catch((err) => {
672
- logger.debug('LINE /cli reply failed', { error: err.message });
699
+ // Group/room activation gate: unless requireMention is explicitly false,
700
+ // only respond when the bot is @mentioned (native isSelf or its name).
701
+ // DMs (line_chat_type === 'user') always pass. This runs after normalize
702
+ // so unhandled message types are already filtered out.
703
+ //
704
+ // NOTE: LINE attaches `mention` to TEXT messages only, so an image or file
705
+ // posted in a group can never satisfy this gate — such media reaches the
706
+ // agent in DMs, and in groups only when requireMention is false. That is
707
+ // the pre-existing behaviour for images and is left unchanged for files:
708
+ // waiving the gate for media would let any group member push attachments
709
+ // at the agent without ever addressing it.
710
+ if (norm.meta.line_chat_type !== 'user' && cfg?.requireMention !== false) {
711
+ const msg = event.message;
712
+ if (!(0, line_mention_1.wasBotMentioned)(msg)) {
713
+ logger.debug('LINE webhook: group/room message without bot mention, ignoring', {
714
+ agentId: runner.getAgentConfig().id,
715
+ chatType: norm.meta.line_chat_type,
716
+ conversationId: userId,
673
717
  });
718
+ continue;
674
719
  }
675
720
  }
676
- continue;
677
- }
678
- // Group/room activation gate: unless requireMention is explicitly false,
679
- // only respond when the bot is @mentioned (native isSelf or its name).
680
- // DMs (line_chat_type === 'user') always pass. This runs after normalize
681
- // so unhandled message types are already filtered out.
682
- //
683
- // NOTE: LINE attaches `mention` to TEXT messages only, so an image or file
684
- // posted in a group can never satisfy this gate — such media reaches the
685
- // agent in DMs, and in groups only when requireMention is false. That is
686
- // the pre-existing behaviour for images and is left unchanged for files:
687
- // waiving the gate for media would let any group member push attachments
688
- // at the agent without ever addressing it.
689
- if (norm.meta.line_chat_type !== 'user' && cfg?.requireMention !== false) {
690
- const msg = event.message;
691
- if (!(0, line_mention_1.wasBotMentioned)(msg)) {
692
- logger.debug('LINE webhook: group/room message without bot mention, ignoring', {
693
- agentId: runner.getAgentConfig().id,
694
- chatType: norm.meta.line_chat_type,
695
- conversationId: userId,
696
- });
721
+ // Inbound media: fetch the bytes via the blob API and hand the agent an
722
+ // absolute path (meta.image_path). The runner persists it to MediaStore
723
+ // and instructs the agent to Read it, same as Telegram attachments.
724
+ // Images and files share that path; meta.media_type tells them apart.
725
+ const mediaType = norm.meta.media_type;
726
+ if (mediaType === 'audio' && !(runner.getAgentConfig().orchestration?.enabled && (runner.getAgentConfig().orchestration?.channels ?? ['api']).includes('line')))
697
727
  continue;
728
+ // Loading animation (best-effort, 1:1 only — LINE rejects it for
729
+ // groups/rooms, where chat_id is a groupId/roomId).
730
+ if (client && norm.meta.line_chat_type === 'user') {
731
+ await (0, line_request_order_1.orderLineRequest)(runner.getAgentConfig().id, userId, () => client.showLoadingAnimation({ chatId: userId, loadingSeconds: LOADING_SECONDS }))
732
+ .catch((err) => logger.debug('showLoadingAnimation failed', { error: err.message }));
698
733
  }
699
- }
700
- // Inbound media: fetch the bytes via the blob API and hand the agent an
701
- // absolute path (meta.image_path). The runner persists it to MediaStore
702
- // and instructs the agent to Read it, same as Telegram attachments.
703
- // Images and files share that path; meta.media_type tells them apart.
704
- const mediaType = norm.meta.media_type;
705
- if ((mediaType === 'image' || mediaType === 'file') && blobClient && norm.meta.message_id) {
706
- try {
707
- let mediaPath;
708
- if (mediaType === 'image') {
709
- mediaPath = await downloadLineImage(blobClient, norm.meta.message_id);
710
- }
711
- else {
712
- // The extension comes from the RAW event name (safeFileExt sanitises
713
- // it itself) meta.attachment_name is the display label and has
714
- // already had characters stripped, which could corrupt the suffix.
715
- const file = event.message;
716
- mediaPath = await downloadLineFile(blobClient, norm.meta.message_id, file.fileName, file.fileSize);
734
+ if ((mediaType === 'image' || mediaType === 'file' || mediaType === 'audio') && blobClient && norm.meta.message_id) {
735
+ try {
736
+ let mediaPath;
737
+ if (mediaType === 'image') {
738
+ mediaPath = await downloadLineImage(blobClient, norm.meta.message_id);
739
+ }
740
+ else if (mediaType === 'audio') {
741
+ mediaPath = await downloadLineFile(blobClient, norm.meta.message_id, 'voice.m4a');
742
+ }
743
+ else {
744
+ // The extension comes from the RAW event name (safeFileExt sanitises
745
+ // it itself) — meta.attachment_name is the display label and has
746
+ // already had characters stripped, which could corrupt the suffix.
747
+ const file = event.message;
748
+ mediaPath = await downloadLineFile(blobClient, norm.meta.message_id, file.fileName, file.fileSize);
749
+ }
750
+ // A null path means the blob API answered with zero bytes. Both that and
751
+ // a throw leave the agent with no file, so both must say so — see
752
+ // markMediaUnavailable.
753
+ if (mediaPath) {
754
+ norm.meta.image_path = mediaPath;
755
+ // Staging copy under os.tmpdir(): the runner owns it from here and
756
+ // deletes it once MediaStore has its permanent copy. Nothing else
757
+ // sweeps the temp dir, so without this every inbound attachment —
758
+ // up to MediaStore.maxUploadBytes each — stays on disk forever.
759
+ norm.meta.media_ephemeral = '1';
760
+ }
761
+ else
762
+ markMediaUnavailable(norm, mediaType, 'the sender uploaded no content');
717
763
  }
718
- // A null path means the blob API answered with zero bytes. Both that and
719
- // a throw leave the agent with no file, so both must say so — see
720
- // markMediaUnavailable.
721
- if (mediaPath) {
722
- norm.meta.image_path = mediaPath;
723
- // Staging copy under os.tmpdir(): the runner owns it from here and
724
- // deletes it once MediaStore has its permanent copy. Nothing else
725
- // sweeps the temp dir, so without this every inbound attachment —
726
- // up to MediaStore.maxUploadBytes each — stays on disk forever.
727
- norm.meta.media_ephemeral = '1';
764
+ catch (err) {
765
+ logger.warn('LINE webhook: media download failed', {
766
+ mediaType,
767
+ messageId: norm.meta.message_id,
768
+ error: err.message,
769
+ });
770
+ markMediaUnavailable(norm, mediaType, err instanceof MediaTooLargeError
771
+ ? `larger than the ${Math.floor(MAX_MEDIA_BYTES / (1024 * 1024))} MB limit`
772
+ : 'the download failed');
728
773
  }
729
- else
730
- markMediaUnavailable(norm, mediaType, 'the sender uploaded no content');
774
+ }
775
+ // Forward to the agent's existing /channel intake (same path Telegram uses).
776
+ try {
777
+ const forwarded = await fetch(`http://127.0.0.1:${runner.getCallbackPort()}/channel`, {
778
+ method: 'POST',
779
+ headers: { 'Content-Type': 'application/json' },
780
+ body: JSON.stringify(norm),
781
+ });
782
+ if (durableIngress && !forwarded.ok)
783
+ throw new Error('Durable input admission failed');
731
784
  }
732
785
  catch (err) {
733
- logger.warn('LINE webhook: media download failed', {
734
- mediaType,
735
- messageId: norm.meta.message_id,
786
+ if (durableIngress && !res.headersSent)
787
+ res.status(503).json({ error: 'Input admission unavailable' });
788
+ logger.error('LINE webhook: failed to forward to callback', {
736
789
  error: err.message,
737
790
  });
738
- markMediaUnavailable(norm, mediaType, err instanceof MediaTooLargeError
739
- ? `larger than the ${Math.floor(MAX_MEDIA_BYTES / (1024 * 1024))} MB limit`
740
- : 'the download failed');
741
791
  }
742
792
  }
743
- // Loading animation (best-effort, 1:1 only — LINE rejects it for
744
- // groups/rooms, where chat_id is a groupId/roomId).
745
- if (client && norm.meta.line_chat_type === 'user') {
746
- client
747
- .showLoadingAnimation({ chatId: userId, loadingSeconds: LOADING_SECONDS })
748
- .catch((err) => logger.debug('showLoadingAnimation failed', { error: err.message }));
749
- }
750
- // Forward to the agent's existing /channel intake (same path Telegram uses).
751
- try {
752
- await fetch(`http://127.0.0.1:${runner.getCallbackPort()}/channel`, {
753
- method: 'POST',
754
- headers: { 'Content-Type': 'application/json' },
755
- body: JSON.stringify(norm),
756
- });
757
- }
758
- catch (err) {
759
- logger.error('LINE webhook: failed to forward to callback', {
760
- error: err.message,
761
- });
762
- }
793
+ }
794
+ finally {
795
+ if (!res.headersSent)
796
+ res.status(200).json({ ok: true });
763
797
  }
764
798
  };
765
799
  return { verify: handleGet, handlePost };