pi-harness-runtime 1.1.397 → 1.1.402

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 (624) hide show
  1. package/AGENTS.md +44 -2
  2. package/CHANGELOG.md +21 -0
  3. package/RULES.md +28 -0
  4. package/harness/agent-handoff.ts +2 -3
  5. package/harness/autonomous-review.ts +1 -1
  6. package/harness/blackboard.ts +2 -3
  7. package/harness/context-compact-orchestrator.ts +1 -1
  8. package/harness/context-window-manager.ts +2 -2
  9. package/harness/e2e/playwright-runner.ts +6 -4
  10. package/harness/herdr-agents.ts +1 -1
  11. package/harness/job-state-machine.ts +1 -1
  12. package/harness/langchain/daemon.ts +3 -3
  13. package/harness/langchain/graph.ts +2 -2
  14. package/harness/langchain/ping-pong-middleware.ts +2 -2
  15. package/harness/loop-code-agent.ts +6 -4
  16. package/harness/loop-controller.ts +1 -1
  17. package/harness/loop-review-agent.ts +1 -1
  18. package/harness/loop-types.ts +1 -1
  19. package/harness/master-planner.ts +1 -1
  20. package/harness/notification-events.ts +6 -6
  21. package/harness/project-detector/detector.ts +1 -2
  22. package/harness/repair-engine.ts +2 -4
  23. package/harness/service-diagnostics.ts +1 -1
  24. package/harness/skill-sync.ts +3 -3
  25. package/index.ts +276 -55
  26. package/mirror.ts +1 -1
  27. package/package.json +5 -3
  28. package/packages/a2a-adapter/dist/discovery.d.ts.map +1 -1
  29. package/packages/a2a-adapter/dist/discovery.js +0 -1
  30. package/packages/a2a-adapter/dist/discovery.js.map +1 -1
  31. package/packages/a2a-adapter/package.json +1 -1
  32. package/packages/a2a-adapter/src/discovery.ts +0 -1
  33. package/packages/agent-policy/package.json +1 -1
  34. package/packages/architecture-generator/package.json +1 -1
  35. package/packages/auth/dist/index.d.ts +9 -0
  36. package/packages/auth/dist/index.d.ts.map +1 -0
  37. package/packages/auth/dist/index.js +9 -0
  38. package/packages/auth/dist/index.js.map +1 -0
  39. package/packages/auth/package.json +1 -1
  40. package/packages/auth/src/index.ts +9 -0
  41. package/packages/autonomous-refactor/package.json +1 -1
  42. package/packages/autonomous-runtime/package.json +1 -1
  43. package/packages/cache-strategy/package.json +1 -1
  44. package/packages/capability-registry/package.json +1 -1
  45. package/packages/checkpoint/package.json +1 -1
  46. package/packages/cli-plugin-sdk/package.json +1 -1
  47. package/packages/clipboard/package.json +1 -1
  48. package/packages/clipboard-plugin/package.json +1 -1
  49. package/packages/code-generation/package.json +1 -1
  50. package/packages/code-review/package.json +1 -1
  51. package/packages/codex-adapter/package.json +1 -1
  52. package/packages/codex-watcher/package.json +1 -1
  53. package/packages/config-capture/dist/index.d.ts +52 -0
  54. package/packages/config-capture/dist/index.d.ts.map +1 -0
  55. package/packages/config-capture/dist/index.js +261 -0
  56. package/packages/config-capture/dist/index.js.map +1 -0
  57. package/packages/config-capture/package.json +1 -1
  58. package/packages/connection-runtime/package.json +1 -1
  59. package/packages/context-compiler/package.json +1 -1
  60. package/packages/context-discovery/package.json +1 -1
  61. package/packages/context-manager/package.json +1 -1
  62. package/packages/contracts/package.json +1 -1
  63. package/packages/cookie-sanitizer/package.json +1 -1
  64. package/packages/cost-optimizer/package.json +1 -1
  65. package/packages/dependency-analyzer/package.json +1 -1
  66. package/packages/django-plugin/package.json +1 -1
  67. package/packages/doc-generator/package.json +1 -1
  68. package/packages/durable-review/package.json +1 -1
  69. package/packages/e2e-tester/package.json +1 -1
  70. package/packages/evaluation-engine/package.json +1 -1
  71. package/packages/evaluation-runner/package.json +1 -1
  72. package/packages/event-bus/package.json +1 -1
  73. package/packages/event-sink/package.json +1 -1
  74. package/packages/event-store/package.json +1 -1
  75. package/packages/experience-replay/package.json +1 -1
  76. package/packages/feedback-collector/package.json +1 -1
  77. package/packages/file-copy-helper/dist/extension.d.ts +15 -0
  78. package/packages/file-copy-helper/dist/extension.d.ts.map +1 -0
  79. package/packages/file-copy-helper/dist/extension.debug.d.ts +15 -0
  80. package/packages/file-copy-helper/dist/extension.debug.d.ts.map +1 -0
  81. package/packages/file-copy-helper/dist/extension.debug.js +215 -0
  82. package/packages/file-copy-helper/dist/extension.debug.js.map +1 -0
  83. package/packages/file-copy-helper/dist/extension.js +222 -0
  84. package/packages/file-copy-helper/dist/extension.js.map +1 -0
  85. package/packages/file-copy-helper/dist/index.d.ts +3 -0
  86. package/packages/file-copy-helper/dist/index.d.ts.map +1 -0
  87. package/packages/file-copy-helper/dist/index.js +3 -0
  88. package/packages/file-copy-helper/dist/index.js.map +1 -0
  89. package/packages/file-copy-helper/dist/intent-detector.d.ts +21 -0
  90. package/packages/file-copy-helper/dist/intent-detector.d.ts.map +1 -0
  91. package/packages/file-copy-helper/dist/intent-detector.js +348 -0
  92. package/packages/file-copy-helper/dist/intent-detector.js.map +1 -0
  93. package/packages/file-copy-helper/package.json +1 -1
  94. package/packages/framework-detector/package.json +1 -1
  95. package/packages/framework-plugin-sdk/package.json +1 -1
  96. package/packages/frappe-plugin/package.json +1 -1
  97. package/packages/generic-web-plugin/package.json +1 -1
  98. package/packages/health-monitor/package.json +1 -1
  99. package/packages/intent-analyzer/package.json +1 -1
  100. package/packages/jev-judge/dist/auto-continue.d.ts +161 -2
  101. package/packages/jev-judge/dist/auto-continue.d.ts.map +1 -1
  102. package/packages/jev-judge/dist/auto-continue.js +267 -22
  103. package/packages/jev-judge/dist/auto-continue.js.map +1 -1
  104. package/packages/jev-judge/dist/index.d.ts +2 -0
  105. package/packages/jev-judge/dist/index.d.ts.map +1 -1
  106. package/packages/jev-judge/dist/index.js +2 -0
  107. package/packages/jev-judge/dist/index.js.map +1 -1
  108. package/packages/jev-judge/dist/question-risk.d.ts +50 -0
  109. package/packages/jev-judge/dist/question-risk.d.ts.map +1 -0
  110. package/packages/jev-judge/dist/question-risk.js +100 -0
  111. package/packages/jev-judge/dist/question-risk.js.map +1 -0
  112. package/packages/jev-judge/package.json +1 -1
  113. package/packages/jev-judge/src/auto-continue.ts +426 -29
  114. package/packages/jev-judge/src/index.ts +4 -0
  115. package/packages/jev-judge/src/question-risk.ts +151 -0
  116. package/packages/jev-judge/tests/auto-continue-context.test.ts +221 -0
  117. package/packages/jev-judge/tests/outcome-application.test.ts +132 -0
  118. package/packages/jev-judge/tests/question-risk.test.ts +116 -0
  119. package/packages/knowledge-graph/package.json +1 -1
  120. package/packages/knowledge-retrieval/package.json +1 -1
  121. package/packages/laravel-plugin/package.json +1 -1
  122. package/packages/learning-engine/package.json +1 -1
  123. package/packages/logging/README.md +36 -3
  124. package/packages/logging/dist/config.d.ts +7 -0
  125. package/packages/logging/dist/config.d.ts.map +1 -1
  126. package/packages/logging/dist/config.js +14 -0
  127. package/packages/logging/dist/config.js.map +1 -1
  128. package/packages/logging/dist/incidents/schema.d.ts +111 -0
  129. package/packages/logging/dist/incidents/schema.d.ts.map +1 -0
  130. package/packages/logging/dist/incidents/schema.js +0 -0
  131. package/packages/logging/dist/incidents/schema.js.map +1 -0
  132. package/packages/logging/dist/index.d.ts +2 -0
  133. package/packages/logging/dist/index.d.ts.map +1 -1
  134. package/packages/logging/dist/index.js +2 -0
  135. package/packages/logging/dist/index.js.map +1 -1
  136. package/packages/logging/dist/server/http.d.ts +4 -3
  137. package/packages/logging/dist/server/http.d.ts.map +1 -1
  138. package/packages/logging/dist/server/http.js +35 -3
  139. package/packages/logging/dist/server/http.js.map +1 -1
  140. package/packages/logging/dist/server/incident-qdrant.d.ts +83 -0
  141. package/packages/logging/dist/server/incident-qdrant.d.ts.map +1 -0
  142. package/packages/logging/dist/server/incident-qdrant.js +129 -0
  143. package/packages/logging/dist/server/incident-qdrant.js.map +1 -0
  144. package/packages/logging/dist/server/incident-store.d.ts +76 -0
  145. package/packages/logging/dist/server/incident-store.d.ts.map +1 -0
  146. package/packages/logging/dist/server/incident-store.js +157 -0
  147. package/packages/logging/dist/server/incident-store.js.map +1 -0
  148. package/packages/logging/dist/server/index.d.ts +4 -0
  149. package/packages/logging/dist/server/index.d.ts.map +1 -1
  150. package/packages/logging/dist/server/index.js +2 -0
  151. package/packages/logging/dist/server/index.js.map +1 -1
  152. package/packages/logging/dist/server/service.d.ts +33 -0
  153. package/packages/logging/dist/server/service.d.ts.map +1 -1
  154. package/packages/logging/dist/server/service.js +63 -0
  155. package/packages/logging/dist/server/service.js.map +1 -1
  156. package/packages/logging/dist/shipper.d.ts +74 -3
  157. package/packages/logging/dist/shipper.d.ts.map +1 -1
  158. package/packages/logging/dist/shipper.js +88 -5
  159. package/packages/logging/dist/shipper.js.map +1 -1
  160. package/packages/logging/dist/singleton.d.ts.map +1 -1
  161. package/packages/logging/dist/singleton.js +1 -0
  162. package/packages/logging/dist/singleton.js.map +1 -1
  163. package/packages/logging/package.json +1 -1
  164. package/packages/logging/src/config.ts +22 -0
  165. package/packages/logging/src/incidents/schema.ts +0 -0
  166. package/packages/logging/src/index.ts +17 -0
  167. package/packages/logging/src/server/http.ts +42 -3
  168. package/packages/logging/src/server/incident-qdrant.ts +177 -0
  169. package/packages/logging/src/server/incident-store.ts +192 -0
  170. package/packages/logging/src/server/index.ts +21 -0
  171. package/packages/logging/src/server/service.ts +79 -0
  172. package/packages/logging/src/shipper.ts +120 -5
  173. package/packages/logging/src/singleton.ts +1 -0
  174. package/packages/logging/test/fanout.test.ts +186 -0
  175. package/packages/logging/test/incidents.test.ts +404 -0
  176. package/packages/mcp-adapter/package.json +1 -1
  177. package/packages/memory-engine/package.json +1 -1
  178. package/packages/milestone-manager/package.json +1 -1
  179. package/packages/model-registry/package.json +1 -1
  180. package/packages/nextjs-plugin/package.json +1 -1
  181. package/packages/notification/dist/adapters/detail-format.d.ts +42 -0
  182. package/packages/notification/dist/adapters/detail-format.d.ts.map +1 -0
  183. package/packages/notification/dist/adapters/detail-format.js +94 -0
  184. package/packages/notification/dist/adapters/detail-format.js.map +1 -0
  185. package/packages/notification/dist/adapters/email-adapter.d.ts.map +1 -1
  186. package/packages/notification/dist/adapters/email-adapter.js +3 -2
  187. package/packages/notification/dist/adapters/email-adapter.js.map +1 -1
  188. package/packages/notification/dist/adapters/line-adapter.d.ts +33 -0
  189. package/packages/notification/dist/adapters/line-adapter.d.ts.map +1 -1
  190. package/packages/notification/dist/adapters/line-adapter.js +87 -9
  191. package/packages/notification/dist/adapters/line-adapter.js.map +1 -1
  192. package/packages/notification/dist/adapters/ntfy-adapter.d.ts.map +1 -1
  193. package/packages/notification/dist/adapters/ntfy-adapter.js +3 -2
  194. package/packages/notification/dist/adapters/ntfy-adapter.js.map +1 -1
  195. package/packages/notification/dist/adapters/telegram-adapter.d.ts +14 -0
  196. package/packages/notification/dist/adapters/telegram-adapter.d.ts.map +1 -1
  197. package/packages/notification/dist/adapters/telegram-adapter.js +89 -69
  198. package/packages/notification/dist/adapters/telegram-adapter.js.map +1 -1
  199. package/packages/notification/dist/notification-center.d.ts.map +1 -1
  200. package/packages/notification/dist/notification-center.js +60 -7
  201. package/packages/notification/dist/notification-center.js.map +1 -1
  202. package/packages/notification/dist/pending-question.d.ts +69 -2
  203. package/packages/notification/dist/pending-question.d.ts.map +1 -1
  204. package/packages/notification/dist/pending-question.js +88 -2
  205. package/packages/notification/dist/pending-question.js.map +1 -1
  206. package/packages/notification/dist/types.d.ts +21 -0
  207. package/packages/notification/dist/types.d.ts.map +1 -1
  208. package/packages/notification/package.json +1 -1
  209. package/packages/notification/src/adapters/detail-format.ts +114 -0
  210. package/packages/notification/src/adapters/email-adapter.ts +3 -2
  211. package/packages/notification/src/adapters/line-adapter.ts +97 -9
  212. package/packages/notification/src/adapters/ntfy-adapter.ts +3 -2
  213. package/packages/notification/src/adapters/telegram-adapter.ts +98 -76
  214. package/packages/notification/src/notification-center.ts +66 -8
  215. package/packages/notification/src/pending-question.ts +160 -8
  216. package/packages/notification/src/types.ts +21 -0
  217. package/packages/notification/test/approval-payload.test.ts +269 -0
  218. package/packages/notification/test/detail-format.test.ts +106 -0
  219. package/packages/notification/test/pending-question-lifecycle.test.ts +195 -0
  220. package/packages/observability/package.json +1 -1
  221. package/packages/okf-indexer/dist/index.d.ts +9 -0
  222. package/packages/okf-indexer/dist/index.d.ts.map +1 -0
  223. package/packages/okf-indexer/dist/index.js +9 -0
  224. package/packages/okf-indexer/dist/index.js.map +1 -0
  225. package/packages/okf-indexer/package.json +1 -1
  226. package/packages/okf-indexer/src/index.ts +9 -0
  227. package/packages/paperclip-integration/package.json +1 -1
  228. package/packages/performance-optimizer/package.json +1 -1
  229. package/packages/permission-mode/package.json +1 -1
  230. package/packages/privilege-broker/package.json +1 -1
  231. package/packages/project-analyzer/package.json +1 -1
  232. package/packages/project-bootstrap/package.json +1 -1
  233. package/packages/projection-engine/package.json +1 -1
  234. package/packages/prompt-compiler/package.json +1 -1
  235. package/packages/prompt-versioning/package.json +1 -1
  236. package/packages/provider-adapter-sdk/package.json +1 -1
  237. package/packages/provider-router/dist/provider-router.d.ts.map +1 -1
  238. package/packages/provider-router/dist/types.d.ts +2 -2
  239. package/packages/provider-router/dist/types.d.ts.map +1 -1
  240. package/packages/provider-router/dist/types.js +1 -1
  241. package/packages/provider-router/package.json +1 -1
  242. package/packages/provider-router/src/types.ts +2 -2
  243. package/packages/provider-selector/package.json +1 -1
  244. package/packages/providers/package.json +1 -1
  245. package/packages/qdrant-skills/package.json +1 -1
  246. package/packages/quota-manager/package.json +1 -1
  247. package/packages/rate-limiter/package.json +1 -1
  248. package/packages/react-vite-plugin/package.json +1 -1
  249. package/packages/relay/package.json +1 -1
  250. package/packages/release-manager/package.json +1 -1
  251. package/packages/requirement-compiler/package.json +1 -1
  252. package/packages/runtime/package.json +1 -1
  253. package/packages/scheduler/dist/index.d.ts +9 -0
  254. package/packages/scheduler/dist/index.d.ts.map +1 -0
  255. package/packages/scheduler/dist/index.js +9 -0
  256. package/packages/scheduler/dist/index.js.map +1 -0
  257. package/packages/scheduler/dist/scheduler.d.ts +17 -0
  258. package/packages/scheduler/dist/scheduler.d.ts.map +1 -0
  259. package/packages/scheduler/dist/scheduler.js +41 -0
  260. package/packages/scheduler/dist/scheduler.js.map +1 -0
  261. package/packages/scheduler/package.json +1 -1
  262. package/packages/scheduler/src/index.ts +9 -0
  263. package/packages/scheduler-adapter/package.json +1 -1
  264. package/packages/session/package.json +1 -1
  265. package/packages/session-api/package.json +1 -1
  266. package/packages/session-export/package.json +1 -1
  267. package/packages/shared-context/dist/index.d.ts +7 -0
  268. package/packages/shared-context/dist/index.d.ts.map +1 -0
  269. package/packages/shared-context/dist/index.js +7 -0
  270. package/packages/shared-context/dist/index.js.map +1 -0
  271. package/packages/shared-context/dist/shared-context.d.ts +12 -0
  272. package/packages/shared-context/dist/shared-context.d.ts.map +1 -0
  273. package/packages/shared-context/dist/shared-context.js +39 -0
  274. package/packages/shared-context/dist/shared-context.js.map +1 -0
  275. package/packages/shared-context/package.json +1 -1
  276. package/packages/skill-mcp-client/dist/client.d.ts +56 -0
  277. package/packages/skill-mcp-client/dist/client.d.ts.map +1 -0
  278. package/packages/skill-mcp-client/dist/client.js +101 -0
  279. package/packages/skill-mcp-client/dist/client.js.map +1 -0
  280. package/packages/skill-mcp-client/dist/errors.d.ts +44 -0
  281. package/packages/skill-mcp-client/dist/errors.d.ts.map +1 -0
  282. package/packages/skill-mcp-client/dist/errors.js +68 -0
  283. package/packages/skill-mcp-client/dist/errors.js.map +1 -0
  284. package/packages/skill-mcp-client/dist/index.d.ts +9 -0
  285. package/packages/skill-mcp-client/dist/index.d.ts.map +1 -0
  286. package/packages/skill-mcp-client/dist/index.js +9 -0
  287. package/packages/skill-mcp-client/dist/index.js.map +1 -0
  288. package/packages/skill-mcp-client/dist/types.d.ts +106 -0
  289. package/packages/skill-mcp-client/dist/types.d.ts.map +1 -0
  290. package/packages/skill-mcp-client/dist/types.js +14 -0
  291. package/packages/skill-mcp-client/dist/types.js.map +1 -0
  292. package/packages/skill-mcp-client/package.json +1 -1
  293. package/packages/skill-registry/package.json +1 -1
  294. package/packages/skills/package.json +1 -5
  295. package/packages/sprint-planner/package.json +1 -1
  296. package/packages/subscription-engine/package.json +1 -1
  297. package/packages/task-compiler/package.json +1 -1
  298. package/packages/telegram/package.json +1 -1
  299. package/packages/telegram/src/agent-messages.d.ts +28 -0
  300. package/packages/telegram/src/agent-messages.js +90 -0
  301. package/packages/telegram/src/bindings.d.ts +296 -0
  302. package/packages/telegram/src/bindings.js +1086 -0
  303. package/packages/telegram/src/bus.d.ts +759 -0
  304. package/packages/telegram/src/bus.js +2732 -0
  305. package/packages/telegram/src/commands.d.ts +761 -0
  306. package/packages/telegram/src/commands.js +2622 -0
  307. package/packages/telegram/src/config.d.ts +222 -0
  308. package/packages/telegram/src/config.js +844 -0
  309. package/packages/telegram/src/delivery.d.ts +161 -0
  310. package/packages/telegram/src/delivery.js +550 -0
  311. package/packages/telegram/src/extension.d.ts +7 -0
  312. package/packages/telegram/src/extension.js +2444 -0
  313. package/packages/telegram/src/inbound.d.ts +94 -0
  314. package/packages/telegram/src/inbound.js +478 -0
  315. package/packages/telegram/src/index.d.ts +6 -0
  316. package/packages/telegram/src/index.js +6 -0
  317. package/packages/telegram/src/keyboard.d.ts +21 -0
  318. package/packages/telegram/src/keyboard.js +37 -0
  319. package/packages/telegram/src/lifecycle.d.ts +210 -0
  320. package/packages/telegram/src/lifecycle.js +538 -0
  321. package/packages/telegram/src/pi.d.ts +76 -0
  322. package/packages/telegram/src/pi.js +130 -0
  323. package/packages/telegram/src/polling.d.ts +332 -0
  324. package/packages/telegram/src/polling.js +1219 -0
  325. package/packages/telegram/src/replies.d.ts +210 -0
  326. package/packages/telegram/src/replies.js +752 -0
  327. package/packages/telegram/src/routing.d.ts +388 -0
  328. package/packages/telegram/src/routing.js +7886 -0
  329. package/packages/telegram/src/runtime.d.ts +159 -0
  330. package/packages/telegram/src/runtime.js +351 -0
  331. package/packages/telegram/src/telegram-api.d.ts +564 -0
  332. package/packages/telegram/src/telegram-api.js +1332 -0
  333. package/packages/telegram/src/turns.d.ts +108 -0
  334. package/packages/telegram/src/turns.js +482 -0
  335. package/packages/telegram/src/updates.d.ts +1545 -0
  336. package/packages/telegram/src/updates.js +6420 -0
  337. package/packages/tencentdb-memory/package.json +1 -1
  338. package/packages/tencentdb-sync/package.json +1 -1
  339. package/packages/test-data-generator/package.json +1 -1
  340. package/packages/test-generator/package.json +1 -1
  341. package/packages/todo-bd-sync/dist/detector.d.ts +54 -0
  342. package/packages/todo-bd-sync/dist/detector.d.ts.map +1 -0
  343. package/packages/todo-bd-sync/dist/detector.js +132 -0
  344. package/packages/todo-bd-sync/dist/detector.js.map +1 -0
  345. package/packages/todo-bd-sync/dist/extension.d.ts +30 -0
  346. package/packages/todo-bd-sync/dist/extension.d.ts.map +1 -0
  347. package/packages/todo-bd-sync/dist/extension.js +35 -0
  348. package/packages/todo-bd-sync/dist/extension.js.map +1 -0
  349. package/packages/todo-bd-sync/dist/index.d.ts +87 -0
  350. package/packages/todo-bd-sync/dist/index.d.ts.map +1 -0
  351. package/packages/todo-bd-sync/dist/index.js +296 -0
  352. package/packages/todo-bd-sync/dist/index.js.map +1 -0
  353. package/packages/todo-bd-sync/dist/sync.d.ts +72 -0
  354. package/packages/todo-bd-sync/dist/sync.d.ts.map +1 -0
  355. package/packages/todo-bd-sync/dist/sync.js +290 -0
  356. package/packages/todo-bd-sync/dist/sync.js.map +1 -0
  357. package/packages/todo-bd-sync/dist/task-analyzer.d.ts +49 -0
  358. package/packages/todo-bd-sync/dist/task-analyzer.d.ts.map +1 -0
  359. package/packages/todo-bd-sync/dist/task-analyzer.js +240 -0
  360. package/packages/todo-bd-sync/dist/task-analyzer.js.map +1 -0
  361. package/packages/todo-bd-sync/dist/todo-reminder.d.ts +126 -0
  362. package/packages/todo-bd-sync/dist/todo-reminder.d.ts.map +1 -0
  363. package/packages/todo-bd-sync/dist/todo-reminder.js +329 -0
  364. package/packages/todo-bd-sync/dist/todo-reminder.js.map +1 -0
  365. package/packages/todo-bd-sync/dist/types.d.ts +65 -0
  366. package/packages/todo-bd-sync/dist/types.d.ts.map +1 -0
  367. package/packages/todo-bd-sync/dist/types.js +67 -0
  368. package/packages/todo-bd-sync/dist/types.js.map +1 -0
  369. package/packages/todo-bd-sync/package.json +1 -1
  370. package/packages/token-estimation/dist/index.d.ts +94 -0
  371. package/packages/token-estimation/dist/index.d.ts.map +1 -0
  372. package/packages/token-estimation/dist/index.js +115 -0
  373. package/packages/token-estimation/dist/index.js.map +1 -0
  374. package/packages/token-estimation/package.json +1 -1
  375. package/packages/token-optimizer/package.json +1 -1
  376. package/packages/trajectory/package.json +1 -1
  377. package/packages/tui/package.json +1 -1
  378. package/packages/types/dist/ai-providers.d.ts +36 -0
  379. package/packages/types/dist/ai-providers.d.ts.map +1 -0
  380. package/packages/types/dist/ai-providers.js +66 -0
  381. package/packages/types/dist/ai-providers.js.map +1 -0
  382. package/packages/types/dist/index.d.ts +12 -0
  383. package/packages/types/dist/index.d.ts.map +1 -0
  384. package/packages/types/dist/index.js +12 -0
  385. package/packages/types/dist/index.js.map +1 -0
  386. package/packages/types/package.json +5 -5
  387. package/packages/types/src/index.ts +12 -0
  388. package/packages/voice-api/package.json +1 -1
  389. package/packages/webmcp-tester/package.json +1 -1
  390. package/packages/wiki/package.json +1 -1
  391. package/packages/workflow-events/package.json +1 -1
  392. package/packages/workspace-scanner/package.json +1 -1
  393. package/packages/worktree/package.json +1 -1
  394. package/packages/worktree/worktree.ts +1 -1
  395. package/packages/write-review/package.json +1 -1
  396. package/renderer.ts +1 -1
  397. package/scripts/build-packages.ts +162 -0
  398. package/scripts/relay-client.ts +2 -2
  399. package/scripts/typecheck-packages.mjs +3 -3
  400. package/scripts/unified-webhook-server.ts +22 -10
  401. package/scripts/verify-package-contents.ts +345 -0
  402. package/scripts/ws-server.ts +1 -1
  403. package/tracker.ts +1 -1
  404. package/harness/browser-scrapers/base-browser-scraper.d.ts +0 -91
  405. package/harness/browser-scrapers/chrome-profile-manager.d.ts +0 -80
  406. package/harness/browser-scrapers/codex-browser-scraper.d.ts +0 -60
  407. package/harness/browser-scrapers/index.d.ts +0 -29
  408. package/harness/browser-scrapers/zai-browser-scraper.d.ts +0 -79
  409. package/harness/e2e/browser-scrapers/base-browser-scraper.d.ts +0 -92
  410. package/harness/e2e/browser-scrapers/chrome-profile-manager.d.ts +0 -81
  411. package/harness/e2e/browser-scrapers/codex-browser-scraper.d.ts +0 -61
  412. package/harness/e2e/browser-scrapers/index.d.ts +0 -30
  413. package/harness/e2e/browser-scrapers/zai-browser-scraper.d.ts +0 -80
  414. package/harness/langchain/agents.d.ts +0 -143
  415. package/harness/langchain/agents.test.d.ts +0 -2
  416. package/harness/langchain/checkpointer.d.ts +0 -48
  417. package/harness/langchain/checkpointer.test.d.ts +0 -8
  418. package/harness/langchain/cron-cli.d.ts +0 -12
  419. package/harness/langchain/daemon.d.ts +0 -161
  420. package/harness/langchain/daemon.test.d.ts +0 -11
  421. package/harness/langchain/file-tools.d.ts +0 -97
  422. package/harness/langchain/graph.d.ts +0 -706
  423. package/harness/langchain/model-router.d.ts +0 -63
  424. package/harness/langchain/model-router.test.d.ts +0 -2
  425. package/harness/langchain/models.d.ts +0 -72
  426. package/harness/langchain/ping-pong-middleware.d.ts +0 -28
  427. package/harness/langchain/ping-pong-middleware.test.d.ts +0 -2
  428. package/harness/langchain/run.d.ts +0 -15
  429. package/harness/langchain/scoreboard.test.d.ts +0 -13
  430. package/harness/langchain/status-line.d.ts +0 -91
  431. package/harness/langchain/status-line.test.d.ts +0 -8
  432. package/harness/langchain/surge.d.ts +0 -111
  433. package/harness/langchain/surge.test.d.ts +0 -10
  434. package/harness/langchain/widget.d.ts +0 -105
  435. package/harness/langchain/widget.test.d.ts +0 -8
  436. package/packages/autonomous-runtime/dist/worker.d.ts +0 -63
  437. package/packages/autonomous-runtime/dist/worker.js +0 -133
  438. package/packages/capability-registry/src/types.d.ts +0 -47
  439. package/packages/clipboard/dist/clipboard.d.ts +0 -11
  440. package/packages/clipboard/dist/clipboard.js +0 -40
  441. package/packages/clipboard/dist/index.d.ts +0 -2
  442. package/packages/clipboard/dist/index.js +0 -2
  443. package/packages/clipboard/dist/types.d.ts +0 -13
  444. package/packages/clipboard/dist/types.js +0 -5
  445. package/packages/context-discovery/dist/discover.d.ts +0 -3
  446. package/packages/context-discovery/dist/discover.js +0 -42
  447. package/packages/context-discovery/dist/discovery.d.ts +0 -28
  448. package/packages/context-discovery/dist/discovery.js +0 -21
  449. package/packages/context-discovery/dist/index.d.ts +0 -3
  450. package/packages/context-discovery/dist/index.js +0 -2
  451. package/packages/context-discovery/dist/types.d.ts +0 -16
  452. package/packages/context-discovery/dist/types.js +0 -2
  453. package/packages/event-bus/dist/bus.d.ts +0 -15
  454. package/packages/event-bus/dist/bus.js +0 -90
  455. package/packages/event-bus/dist/index.d.ts +0 -4
  456. package/packages/event-bus/dist/index.js +0 -3
  457. package/packages/event-bus/dist/test/bus.test.js +0 -52
  458. package/packages/event-bus/dist/types.d.ts +0 -27
  459. package/packages/event-bus/dist/types.js +0 -10
  460. package/packages/event-store/dist/index.d.ts +0 -3
  461. package/packages/event-store/dist/index.js +0 -2
  462. package/packages/event-store/dist/store.d.ts +0 -15
  463. package/packages/event-store/dist/store.js +0 -131
  464. package/packages/event-store/dist/test/store.test.js +0 -57
  465. package/packages/event-store/dist/types.d.ts +0 -48
  466. package/packages/event-store/dist/types.js +0 -5
  467. package/packages/event-store/src/types.d.ts +0 -48
  468. package/packages/file-copy-helper/dist/src/extension.js +0 -186
  469. package/packages/model-registry/src/types.d.ts +0 -63
  470. package/packages/notification/dist/src/adapters/email-adapter.d.ts +0 -17
  471. package/packages/notification/dist/src/adapters/email-adapter.d.ts.map +0 -1
  472. package/packages/notification/dist/src/adapters/email-adapter.js +0 -89
  473. package/packages/notification/dist/src/adapters/email-adapter.js.map +0 -1
  474. package/packages/notification/dist/src/adapters/line-adapter.d.ts +0 -17
  475. package/packages/notification/dist/src/adapters/line-adapter.d.ts.map +0 -1
  476. package/packages/notification/dist/src/adapters/line-adapter.js +0 -99
  477. package/packages/notification/dist/src/adapters/line-adapter.js.map +0 -1
  478. package/packages/notification/dist/src/adapters/ntfy-adapter.d.ts +0 -17
  479. package/packages/notification/dist/src/adapters/ntfy-adapter.d.ts.map +0 -1
  480. package/packages/notification/dist/src/adapters/ntfy-adapter.js +0 -84
  481. package/packages/notification/dist/src/adapters/ntfy-adapter.js.map +0 -1
  482. package/packages/notification/dist/src/adapters/telegram-adapter.d.ts +0 -56
  483. package/packages/notification/dist/src/adapters/telegram-adapter.d.ts.map +0 -1
  484. package/packages/notification/dist/src/adapters/telegram-adapter.js +0 -251
  485. package/packages/notification/dist/src/adapters/telegram-adapter.js.map +0 -1
  486. package/packages/notification/dist/src/adapters/webhook-adapter.d.ts +0 -15
  487. package/packages/notification/dist/src/adapters/webhook-adapter.d.ts.map +0 -1
  488. package/packages/notification/dist/src/adapters/webhook-adapter.js +0 -64
  489. package/packages/notification/dist/src/adapters/webhook-adapter.js.map +0 -1
  490. package/packages/notification/dist/src/base-adapter.d.ts +0 -36
  491. package/packages/notification/dist/src/base-adapter.d.ts.map +0 -1
  492. package/packages/notification/dist/src/base-adapter.js +0 -39
  493. package/packages/notification/dist/src/base-adapter.js.map +0 -1
  494. package/packages/notification/dist/src/index.d.ts +0 -12
  495. package/packages/notification/dist/src/index.d.ts.map +0 -1
  496. package/packages/notification/dist/src/index.js +0 -12
  497. package/packages/notification/dist/src/index.js.map +0 -1
  498. package/packages/notification/dist/src/notification-center.d.ts +0 -89
  499. package/packages/notification/dist/src/notification-center.d.ts.map +0 -1
  500. package/packages/notification/dist/src/notification-center.js +0 -356
  501. package/packages/notification/dist/src/notification-center.js.map +0 -1
  502. package/packages/notification/dist/src/notification-policy.d.ts +0 -66
  503. package/packages/notification/dist/src/notification-policy.d.ts.map +0 -1
  504. package/packages/notification/dist/src/notification-policy.js +0 -153
  505. package/packages/notification/dist/src/notification-policy.js.map +0 -1
  506. package/packages/notification/dist/src/telegram-webhook-handler.d.ts +0 -86
  507. package/packages/notification/dist/src/telegram-webhook-handler.d.ts.map +0 -1
  508. package/packages/notification/dist/src/telegram-webhook-handler.js +0 -149
  509. package/packages/notification/dist/src/telegram-webhook-handler.js.map +0 -1
  510. package/packages/notification/dist/src/types.d.ts +0 -106
  511. package/packages/notification/dist/src/types.d.ts.map +0 -1
  512. package/packages/notification/dist/src/types.js +0 -7
  513. package/packages/notification/dist/src/types.js.map +0 -1
  514. package/packages/projection-engine/dist/engine.d.ts +0 -61
  515. package/packages/projection-engine/dist/engine.js +0 -76
  516. package/packages/projection-engine/dist/index.d.ts +0 -2
  517. package/packages/projection-engine/dist/index.js +0 -2
  518. package/packages/projection-engine/dist/project.d.ts +0 -3
  519. package/packages/projection-engine/dist/project.js +0 -24
  520. package/packages/projection-engine/dist/types.d.ts +0 -55
  521. package/packages/projection-engine/dist/types.js +0 -5
  522. package/packages/projection-engine/src/types.d.ts +0 -55
  523. package/packages/provider-adapter-sdk/dist/src/builder.d.ts +0 -140
  524. package/packages/provider-adapter-sdk/dist/src/builder.d.ts.map +0 -1
  525. package/packages/provider-adapter-sdk/dist/src/builder.js +0 -332
  526. package/packages/provider-adapter-sdk/dist/src/builder.js.map +0 -1
  527. package/packages/provider-adapter-sdk/dist/src/errors.d.ts +0 -71
  528. package/packages/provider-adapter-sdk/dist/src/errors.d.ts.map +0 -1
  529. package/packages/provider-adapter-sdk/dist/src/errors.js +0 -111
  530. package/packages/provider-adapter-sdk/dist/src/errors.js.map +0 -1
  531. package/packages/provider-adapter-sdk/dist/src/index.d.ts +0 -15
  532. package/packages/provider-adapter-sdk/dist/src/index.d.ts.map +0 -1
  533. package/packages/provider-adapter-sdk/dist/src/index.js +0 -19
  534. package/packages/provider-adapter-sdk/dist/src/index.js.map +0 -1
  535. package/packages/provider-adapter-sdk/dist/src/registry.d.ts +0 -108
  536. package/packages/provider-adapter-sdk/dist/src/registry.d.ts.map +0 -1
  537. package/packages/provider-adapter-sdk/dist/src/registry.js +0 -301
  538. package/packages/provider-adapter-sdk/dist/src/registry.js.map +0 -1
  539. package/packages/provider-adapter-sdk/dist/src/tester.d.ts +0 -71
  540. package/packages/provider-adapter-sdk/dist/src/tester.d.ts.map +0 -1
  541. package/packages/provider-adapter-sdk/dist/src/tester.js +0 -392
  542. package/packages/provider-adapter-sdk/dist/src/tester.js.map +0 -1
  543. package/packages/provider-adapter-sdk/dist/src/types.d.ts +0 -182
  544. package/packages/provider-adapter-sdk/dist/src/types.d.ts.map +0 -1
  545. package/packages/provider-adapter-sdk/dist/src/types.js +0 -11
  546. package/packages/provider-adapter-sdk/dist/src/types.js.map +0 -1
  547. package/packages/provider-router/dist/capability-registry/src/types.d.ts +0 -47
  548. package/packages/provider-router/dist/capability-registry/src/types.d.ts.map +0 -1
  549. package/packages/provider-router/dist/capability-registry/src/types.js +0 -10
  550. package/packages/provider-router/dist/capability-registry/src/types.js.map +0 -1
  551. package/packages/provider-router/dist/provider-router/src/index.d.ts +0 -23
  552. package/packages/provider-router/dist/provider-router/src/index.d.ts.map +0 -1
  553. package/packages/provider-router/dist/provider-router/src/index.js +0 -25
  554. package/packages/provider-router/dist/provider-router/src/index.js.map +0 -1
  555. package/packages/provider-router/dist/provider-router/src/policy.d.ts +0 -10
  556. package/packages/provider-router/dist/provider-router/src/policy.d.ts.map +0 -1
  557. package/packages/provider-router/dist/provider-router/src/policy.js +0 -45
  558. package/packages/provider-router/dist/provider-router/src/policy.js.map +0 -1
  559. package/packages/provider-router/dist/provider-router/src/provider-router.d.ts +0 -56
  560. package/packages/provider-router/dist/provider-router/src/provider-router.d.ts.map +0 -1
  561. package/packages/provider-router/dist/provider-router/src/provider-router.js +0 -222
  562. package/packages/provider-router/dist/provider-router/src/provider-router.js.map +0 -1
  563. package/packages/provider-router/dist/provider-router/src/strategies.d.ts +0 -19
  564. package/packages/provider-router/dist/provider-router/src/strategies.d.ts.map +0 -1
  565. package/packages/provider-router/dist/provider-router/src/strategies.js +0 -110
  566. package/packages/provider-router/dist/provider-router/src/strategies.js.map +0 -1
  567. package/packages/provider-router/dist/provider-router/src/types.d.ts +0 -91
  568. package/packages/provider-router/dist/provider-router/src/types.d.ts.map +0 -1
  569. package/packages/provider-router/dist/provider-router/src/types.js +0 -10
  570. package/packages/provider-router/dist/provider-router/src/types.js.map +0 -1
  571. package/packages/provider-router/dist/src/index.d.ts +0 -23
  572. package/packages/provider-router/dist/src/index.d.ts.map +0 -1
  573. package/packages/provider-router/dist/src/index.js +0 -25
  574. package/packages/provider-router/dist/src/index.js.map +0 -1
  575. package/packages/provider-router/dist/src/policy.d.ts +0 -10
  576. package/packages/provider-router/dist/src/policy.d.ts.map +0 -1
  577. package/packages/provider-router/dist/src/policy.js +0 -45
  578. package/packages/provider-router/dist/src/policy.js.map +0 -1
  579. package/packages/provider-router/dist/src/provider-router.d.ts +0 -56
  580. package/packages/provider-router/dist/src/provider-router.d.ts.map +0 -1
  581. package/packages/provider-router/dist/src/provider-router.js +0 -222
  582. package/packages/provider-router/dist/src/provider-router.js.map +0 -1
  583. package/packages/provider-router/dist/src/strategies.d.ts +0 -19
  584. package/packages/provider-router/dist/src/strategies.d.ts.map +0 -1
  585. package/packages/provider-router/dist/src/strategies.js +0 -110
  586. package/packages/provider-router/dist/src/strategies.js.map +0 -1
  587. package/packages/provider-router/dist/src/types.d.ts +0 -91
  588. package/packages/provider-router/dist/src/types.d.ts.map +0 -1
  589. package/packages/provider-router/dist/src/types.js +0 -10
  590. package/packages/provider-router/dist/src/types.js.map +0 -1
  591. package/packages/provider-router/dist/types/src/runtime-types.d.ts +0 -412
  592. package/packages/provider-router/dist/types/src/runtime-types.d.ts.map +0 -1
  593. package/packages/provider-router/dist/types/src/runtime-types.js +0 -2
  594. package/packages/provider-router/dist/types/src/runtime-types.js.map +0 -1
  595. package/packages/session-api/dist/api.d.ts +0 -83
  596. package/packages/session-api/dist/api.js +0 -35
  597. package/packages/session-api/dist/index.d.ts +0 -2
  598. package/packages/session-api/dist/index.js +0 -2
  599. package/packages/session-api/dist/types.d.ts +0 -22
  600. package/packages/session-api/dist/types.js +0 -5
  601. package/packages/session-export/dist/exporter.d.ts +0 -28
  602. package/packages/session-export/dist/exporter.js +0 -38
  603. package/packages/session-export/dist/index.d.ts +0 -2
  604. package/packages/session-export/dist/index.js +0 -2
  605. package/packages/session-export/dist/types.d.ts +0 -20
  606. package/packages/session-export/dist/types.js +0 -5
  607. package/packages/subscription-engine/dist/engine.d.ts +0 -13
  608. package/packages/subscription-engine/dist/engine.js +0 -40
  609. package/packages/subscription-engine/dist/index.d.ts +0 -2
  610. package/packages/subscription-engine/dist/index.js +0 -2
  611. package/packages/subscription-engine/dist/subscriptions.d.ts +0 -19
  612. package/packages/subscription-engine/dist/subscriptions.js +0 -32
  613. package/packages/subscription-engine/dist/types.d.ts +0 -24
  614. package/packages/subscription-engine/dist/types.js +0 -5
  615. package/packages/trajectory/test/store.test.d.ts +0 -2
  616. package/packages/workflow-events/dist/events.d.ts +0 -38
  617. package/packages/workflow-events/dist/events.js +0 -46
  618. package/packages/workflow-events/dist/index.d.ts +0 -2
  619. package/packages/workflow-events/dist/index.js +0 -2
  620. package/packages/workflow-events/dist/pipeline.d.ts +0 -21
  621. package/packages/workflow-events/dist/pipeline.js +0 -27
  622. package/packages/workflow-events/dist/types.d.ts +0 -110
  623. package/packages/workflow-events/dist/types.js +0 -5
  624. package/packages/workflow-events/src/types.d.ts +0 -110
@@ -12,7 +12,7 @@
12
12
  import { logError, logWarn } from "./file-logger.js";
13
13
  import { existsSync, mkdirSync } from "fs";
14
14
  import { join } from "path";
15
- import { DatabaseSync } from "node:sqlite";
15
+ import { createRequire } from "node:module";
16
16
 
17
17
  import type {
18
18
  InlineKeyboardButton,
@@ -32,6 +32,23 @@ import { NtfyAdapter } from "./adapters/ntfy-adapter.js";
32
32
  import { EmailAdapter } from "./adapters/email-adapter.js";
33
33
  import { WebhookAdapter } from "./adapters/webhook-adapter.js";
34
34
 
35
+ /**
36
+ * Load the SQLite binding lazily.
37
+ *
38
+ * `node:sqlite` does not exist in every runtime (Bun 1.3 has no
39
+ * `node:sqlite`), and a static import makes the whole module unloadable
40
+ * there. The persisted channel settings are an optimisation: without the
41
+ * database the center still works with the configured defaults.
42
+ */
43
+ function loadDatabaseSync(): typeof import("node:sqlite").DatabaseSync | null {
44
+ try {
45
+ const require = createRequire(import.meta.url);
46
+ return require("node:sqlite").DatabaseSync;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
35
52
  /**
36
53
  * Pending approval request
37
54
  */
@@ -48,7 +65,7 @@ export class NotificationCenter {
48
65
  private adapters: Map<string, ChannelAdapter> = new Map();
49
66
  private channelEnabled: Map<string, boolean> = new Map();
50
67
  private redactPatterns: RegExp[];
51
- private db: DatabaseSync | null = null;
68
+ private db: import("node:sqlite").DatabaseSync | null = null;
52
69
  /** Pending approval requests keyed by jobId */
53
70
  private pendingApprovals: Map<string, PendingApproval> = new Map();
54
71
 
@@ -69,6 +86,15 @@ export class NotificationCenter {
69
86
  */
70
87
  private initDatabase(): void {
71
88
  try {
89
+ const DatabaseSync = loadDatabaseSync();
90
+ if (!DatabaseSync) {
91
+ logWarn(
92
+ "[NotificationCenter]",
93
+ "node:sqlite is unavailable - the channel settings are not persisted",
94
+ );
95
+ return;
96
+ }
97
+
72
98
  const dbPath = NotificationCenter.getDatabasePath();
73
99
  this.db = new DatabaseSync(dbPath);
74
100
 
@@ -203,6 +229,14 @@ export class NotificationCenter {
203
229
  const adapter = this.createAdapter(config);
204
230
  if (adapter && adapter.isConfigured()) {
205
231
  this.adapters.set(config.id, adapter);
232
+ // A registered channel without a persisted state is enabled
233
+ // unless its configuration says otherwise. Without this the
234
+ // channel is registered but silently skipped by notify(),
235
+ // which happens whenever the settings database is
236
+ // unavailable (no `node:sqlite` in the runtime).
237
+ if (!this.channelEnabled.has(config.id)) {
238
+ this.channelEnabled.set(config.id, config.enabled !== false);
239
+ }
206
240
  return true;
207
241
  }
208
242
  } catch (error) {
@@ -515,14 +549,21 @@ export class NotificationCenter {
515
549
  const approveLabel = options?.approveLabel ?? "Yes";
516
550
  const rejectLabel = options?.rejectLabel ?? "No";
517
551
 
552
+ // The canonical request ID is the approval correlation key. The
553
+ // presentation `jobId` may carry a prefix ("waiting-user-q-123") and
554
+ // must not be used for the correlation: a callback that carries the
555
+ // prefixed value can never match the pending question, so the click
556
+ // is reported as stale and the approval is lost.
557
+ const target = context.questionId ?? context.jobId;
558
+
518
559
  // Build buttons
519
560
  const buttons: InlineKeyboardButton[] = [
520
- { text: `\u2705 ${approveLabel}`, callbackData: buildCallbackData(CallbackActions.APPROVE, context.jobId) },
521
- { text: `\u274C ${rejectLabel}`, callbackData: buildCallbackData(CallbackActions.REJECT, context.jobId) },
561
+ { text: `\u2705 ${approveLabel}`, callbackData: buildCallbackData(CallbackActions.APPROVE, target) },
562
+ { text: `\u274C ${rejectLabel}`, callbackData: buildCallbackData(CallbackActions.REJECT, target) },
522
563
  ];
523
564
 
524
565
  // Track this pending approval so callback can resolve it
525
- this.trackPendingApproval(context.jobId, event, context);
566
+ this.trackPendingApproval(target, event, context);
526
567
 
527
568
  // Send to each channel with buttons (respecting enabled state)
528
569
  const results: NotificationResult[] = [];
@@ -547,16 +588,23 @@ export class NotificationCenter {
547
588
  results.push({ success: false, channel: id, error: String(error) });
548
589
  }
549
590
  } else if (adapter instanceof LineAdapter) {
550
- // LINE: Send approval request with text fallback directing user to answer via Telegram or Pi
591
+ // LINE: the same question and the same canonical request ID
592
+ // as Telegram, with the same Yes/No actions. The postback
593
+ // data uses the shared callback format, so the webhook
594
+ // forwards it into the same runtime resolver.
551
595
  try {
552
596
  const linePayload: NotificationPayload = {
553
597
  jobId: context.jobId,
554
598
  timestamp: new Date().toISOString(),
555
599
  event,
556
600
  title: "Approval Required",
557
- message: (context.requirement || "A decision is needed.") + "\n\nReply via Telegram or type answer in Pi.",
601
+ message: context.requirement || "A decision is needed.",
602
+ ...(context.questionId && { questionId: context.questionId }),
558
603
  details: {
559
604
  jobId: context.jobId,
605
+ ...(context.questionId && { questionId: context.questionId }),
606
+ ...(context.questionKind && { questionKind: context.questionKind }),
607
+ _actionButtons: buttons,
560
608
  ...options?.additionalDetails,
561
609
  },
562
610
  };
@@ -712,12 +760,17 @@ export class NotificationCenter {
712
760
  timestamp: new Date().toISOString(),
713
761
  title,
714
762
  message,
763
+ ...(context.questionId && { questionId: context.questionId }),
715
764
  details: {
716
765
  jobId: context.jobId,
717
766
  requirement: context.requirement,
718
767
  ...(context.taskId && { taskId: context.taskId }),
719
768
  ...(context.taskTitle && { taskTitle: context.taskTitle }),
720
769
  ...(context.error && { error: context.error }),
770
+ ...(context.reason && { reason: context.reason }),
771
+ ...(context.trigger && { trigger: context.trigger }),
772
+ ...(context.questionId && { questionId: context.questionId }),
773
+ ...(context.questionKind && { questionKind: context.questionKind }),
721
774
  // Pass inline keyboard options to Telegram adapter
722
775
  ...(options?.enableInlineKeyboard && { _enableInlineKeyboard: true }),
723
776
  ...(options?.actionButtons && { _actionButtons: options.actionButtons }),
@@ -733,6 +786,11 @@ export class NotificationCenter {
733
786
  const req = context.requirement ?? "";
734
787
  const requirement =
735
788
  req.length > 50 ? req.slice(0, 50) + "..." : req;
789
+ // The question the agent asks has to reach the user in full. A
790
+ // truncated question is not a question the user can answer, so the
791
+ // approval events keep the complete text and let the adapter split
792
+ // it for the platform.
793
+ const fullRequirement = req;
736
794
 
737
795
  const map: Record<NotificationEvent, { title: string; message: string }> = {
738
796
  JobStarted: {
@@ -781,7 +839,7 @@ export class NotificationCenter {
781
839
  },
782
840
  WaitingForUserInput: {
783
841
  title: "Your Input Needed",
784
- message: `Agent needs your input: "${requirement}"${context.error ? ` (${context.error})` : ""}`,
842
+ message: `Agent needs your input: "${fullRequirement}"${context.error ? ` (${context.error})` : ""}`,
785
843
  },
786
844
  AssistantResponse: {
787
845
  title: "Assistant",
@@ -19,13 +19,31 @@ export type QuestionKind =
19
19
  /**
20
20
  * Question states
21
21
  */
22
- export type QuestionState =
22
+ export type QuestionState =
23
23
  | "pending" // Waiting for response
24
24
  | "evaluating" // Jev is evaluating
25
25
  | "resolved" // User answered
26
26
  | "cancelled" // Cancelled (e.g., session switch)
27
27
  | "expired"; // Timed out
28
28
 
29
+ /**
30
+ * The typed outcome of a Jev evaluation.
31
+ *
32
+ * It is deliberately not the same shape as a human answer: an autonomous
33
+ * decision is never reported as a user "yes".
34
+ */
35
+ export type JevOutcome =
36
+ | "approve"
37
+ | "reject"
38
+ | "wait"
39
+ | "proceed_with_caution";
40
+
41
+ /** Who resolved the question. */
42
+ export type ResolutionSource = "user" | "jev" | "timeout";
43
+
44
+ /** The channel a human answer came from. */
45
+ export type ResolutionChannel = "telegram" | "line" | "pi";
46
+
29
47
  /**
30
48
  * Channel delivery states
31
49
  */
@@ -51,6 +69,16 @@ export interface PendingQuestion {
51
69
  questionText: string;
52
70
  /** Question kind */
53
71
  kind: QuestionKind;
72
+ /** Does the proposed action need an explicit human authorization? */
73
+ requiresExplicitAuthorization?: boolean;
74
+ /** Can the proposed action destroy or damage something? */
75
+ destructive?: boolean;
76
+ /** Can the proposed action be undone? */
77
+ reversible?: boolean;
78
+ /** Does the proposed action reach the outside world? */
79
+ external?: boolean;
80
+ /** The signals the risk facts were derived from. */
81
+ riskSignals?: string[];
54
82
  /** Current state */
55
83
  state: QuestionState;
56
84
  /** When created */
@@ -62,7 +90,13 @@ export interface PendingQuestion {
62
90
  /** Resolution: "yes", "no", "clarification", or undefined */
63
91
  resolution?: "yes" | "no" | "clarification";
64
92
  /** Who resolved it */
65
- resolvedBy?: "user" | "jev" | "timeout";
93
+ resolvedBy?: ResolutionSource;
94
+ /** The channel a human answer came from. Unset for a Jev resolution. */
95
+ resolvedChannel?: ResolutionChannel;
96
+ /** The Jev outcome, when the decision was autonomous. */
97
+ jevOutcome?: JevOutcome;
98
+ /** The short reason of the Jev decision. */
99
+ jevReason?: string;
66
100
  /** Channel delivery states */
67
101
  deliveryState: {
68
102
  telegram?: ChannelDeliveryState;
@@ -413,6 +447,14 @@ export class PendingQuestionController {
413
447
  workspacePath: string;
414
448
  jobId?: string;
415
449
  kind: QuestionKind;
450
+ /** The deterministic risk facts of the proposed action. */
451
+ risk?: {
452
+ requiresExplicitAuthorization?: boolean;
453
+ destructive?: boolean;
454
+ reversible?: boolean;
455
+ external?: boolean;
456
+ signals?: string[];
457
+ };
416
458
  }): PendingQuestion {
417
459
  const requestId = this.generateRequestId();
418
460
 
@@ -423,6 +465,11 @@ export class PendingQuestionController {
423
465
  jobId: params.jobId,
424
466
  questionText: params.text,
425
467
  kind: params.kind,
468
+ requiresExplicitAuthorization: params.risk?.requiresExplicitAuthorization,
469
+ destructive: params.risk?.destructive,
470
+ reversible: params.risk?.reversible,
471
+ external: params.risk?.external,
472
+ riskSignals: params.risk?.signals,
426
473
  state: "pending",
427
474
  createdAt: new Date(),
428
475
  dueAt: new Date(Date.now() + this.config.evaluationDelayMs),
@@ -482,9 +529,11 @@ export class PendingQuestionController {
482
529
  */
483
530
  resolve(params: {
484
531
  resolution: "yes" | "no" | "clarification";
485
- by: "user" | "jev" | "timeout";
532
+ by: ResolutionSource;
486
533
  /** Optional requestId to validate (first-answer-wins) */
487
534
  requestId?: string;
535
+ /** The channel a human answer came from. */
536
+ channel?: ResolutionChannel;
488
537
  }): boolean {
489
538
  if (!this.currentQuestion) {
490
539
  logWarn("[PendingQuestion]", "No question to resolve - no pending question");
@@ -504,22 +553,125 @@ export class PendingQuestionController {
504
553
  `Question already resolved as ${this.currentQuestion.resolution} - duplicate callback ignored`);
505
554
  return false;
506
555
  }
507
-
556
+
508
557
  this.currentQuestion.state = "resolved";
509
558
  this.currentQuestion.resolution = params.resolution;
510
559
  this.currentQuestion.resolvedBy = params.by;
511
560
  this.currentQuestion.resolvedAt = new Date();
512
-
561
+ if (params.by === "user" && params.channel) {
562
+ this.currentQuestion.resolvedChannel = params.channel;
563
+ }
564
+
513
565
  logWarn("[PendingQuestion]", `Resolved question ${this.currentQuestion.requestId}: ${params.resolution} by ${params.by}`);
514
-
515
- // Notify callback
516
- if (this.userAnswerCallback) {
566
+
567
+ // Notify callback. A Jev resolution is NOT a user answer: it must never
568
+ // be dispatched as a synthetic "yes" into the conversation.
569
+ if (params.by === "jev") {
570
+ if (this.jevDecisionCallback) {
571
+ this.jevDecisionCallback(this.currentQuestion, {
572
+ action: "continue",
573
+ reason: "resolved by jev",
574
+ eligible: true,
575
+ });
576
+ }
577
+ } else if (this.userAnswerCallback) {
517
578
  this.userAnswerCallback(this.currentQuestion, params.resolution);
518
579
  }
519
580
 
520
581
  return true;
521
582
  }
522
583
 
584
+ /**
585
+ * Resolve a question with an autonomous Jev decision.
586
+ *
587
+ * The question is closed with `resolvedBy: "jev"`, the outcome is recorded
588
+ * and the Jev callback is notified. No user answer is dispatched: nobody
589
+ * clicked anything.
590
+ *
591
+ * @returns true if the question was closed, false when it was stale or
592
+ * already answered by a human.
593
+ */
594
+ resolveByJev(
595
+ requestId: string,
596
+ outcome: JevOutcome,
597
+ reason?: string,
598
+ ): boolean {
599
+ if (!this.currentQuestion) {
600
+ logWarn("[PendingQuestion]", "No question to resolve - no pending question");
601
+ return false;
602
+ }
603
+
604
+ if (this.currentQuestion.requestId !== requestId) {
605
+ logWarn("[PendingQuestion]",
606
+ `Jev resolution for an unknown request: ${requestId} (current=${this.currentQuestion.requestId})`);
607
+ return false;
608
+ }
609
+
610
+ if (this.currentQuestion.state === "resolved") {
611
+ logWarn("[PendingQuestion]",
612
+ `Question already resolved as ${this.currentQuestion.resolution} - jev decision ignored`);
613
+ return false;
614
+ }
615
+
616
+ this.currentQuestion.state = "resolved";
617
+ this.currentQuestion.resolvedBy = "jev";
618
+ this.currentQuestion.jevOutcome = outcome;
619
+ this.currentQuestion.jevReason = reason;
620
+ this.currentQuestion.resolvedAt = new Date();
621
+
622
+ logWarn("[PendingQuestion]",
623
+ `Closed question ${this.currentQuestion.requestId} with jev outcome ${outcome}`);
624
+
625
+ if (this.jevDecisionCallback) {
626
+ this.jevDecisionCallback(this.currentQuestion, {
627
+ action: outcome === "reject" ? "stop" : outcome === "wait" ? "wait" : "continue",
628
+ reason: reason ?? `jev:${outcome}`,
629
+ eligible: true,
630
+ metadata: { outcome },
631
+ });
632
+ }
633
+
634
+ return true;
635
+ }
636
+
637
+ /**
638
+ * Apply an approval action from a channel to the current question.
639
+ *
640
+ * The action names are the shared callback actions, so Telegram and LINE
641
+ * use the same values and the same resolver. A stale request ID, a
642
+ * duplicate click or a wrong session leaves the running wait untouched.
643
+ */
644
+ applyApproval(
645
+ action: string,
646
+ requestId: string,
647
+ channel: ResolutionChannel,
648
+ ): { applied: boolean; resolution?: "yes" | "no"; reason?: string } {
649
+ if (action !== "approve" && action !== "reject") {
650
+ return { applied: false, reason: `unknown action '${action}'` };
651
+ }
652
+
653
+ const resolution = action === "approve" ? "yes" : "no";
654
+ const applied = this.resolve({ resolution, by: "user", requestId, channel });
655
+
656
+ return applied
657
+ ? { applied: true, resolution }
658
+ : { applied: false, resolution, reason: "stale or duplicate request ID" };
659
+ }
660
+
661
+ /**
662
+ * Is the request ID still actionable?
663
+ *
664
+ * A button of a closed question is stale: it must not resolve another
665
+ * question and it must not clear a running wait.
666
+ */
667
+ isActionable(requestId: string): boolean {
668
+ if (!this.currentQuestion) return false;
669
+ return (
670
+ this.currentQuestion.requestId === requestId &&
671
+ (this.currentQuestion.state === "pending" || this.currentQuestion.state === "evaluating")
672
+ );
673
+ }
674
+
523
675
  /**
524
676
  * Cancel the current question (e.g., on session switch)
525
677
  */
@@ -37,6 +37,8 @@ export interface NotificationPayload {
37
37
  // Inline keyboard buttons for Telegram
38
38
  enableInlineKeyboard?: boolean;
39
39
  actionButtons?: InlineKeyboardButton[];
40
+ /** The canonical pending-question request ID (the approval correlation key). */
41
+ questionId?: string;
40
42
  }
41
43
 
42
44
  export interface NotificationConfig {
@@ -148,5 +150,24 @@ export interface NotificationContext {
148
150
  requirement: string;
149
151
  taskId?: string;
150
152
  taskTitle?: string;
153
+ /** A real failure. Only error events render this under an "Error:" label. */
151
154
  error?: string;
155
+ /** Why the event happened (a resume trigger, a quota detail, a review reason). */
156
+ reason?: string;
157
+ /**
158
+ * Why the work resumed ("post-compact", "provider-overload"). A trigger is
159
+ * not a failure: it renders as "Trigger: ..." in a human wording, never
160
+ * under an "Error:" label.
161
+ */
162
+ trigger?: string;
163
+ /**
164
+ * The canonical pending-question request ID.
165
+ *
166
+ * It is the approval correlation key: the callback data of every Yes/No
167
+ * action points at it. The presentation `jobId` may carry a prefix and
168
+ * must not be used for the correlation.
169
+ */
170
+ questionId?: string;
171
+ /** The kind of the pending question (approval, clarification, ...). */
172
+ questionKind?: string;
152
173
  }
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Approval payload tests.
3
+ *
4
+ * The question has to reach the user complete, and the Yes/No actions have
5
+ * to point at the canonical request ID - on Telegram and on LINE. A button
6
+ * that carries a prefixed job ID can never match the pending question, so
7
+ * every click is reported as stale and the approval is lost.
8
+ */
9
+
10
+ import { describe, it, expect, beforeEach, afterEach } from "bun:test";
11
+ import { NotificationCenter } from "../src/notification-center.js";
12
+ import { PendingQuestionController } from "../src/pending-question.js";
13
+ import { parseCallbackData } from "../src/telegram-webhook-handler.js";
14
+ import type { NotificationConfig } from "../src/types.js";
15
+
16
+ const LONG_QUESTION =
17
+ "Want me to implement the persistence layer with the SQLite schema, the migration runner and the rollback path, and then wire it into the harness? ";
18
+
19
+ interface CapturedRequest {
20
+ url: string;
21
+ body: Record<string, any>;
22
+ }
23
+
24
+ let captured: CapturedRequest[] = [];
25
+ let originalFetch: typeof globalThis.fetch;
26
+
27
+ function createCenter(): NotificationCenter {
28
+ const config: NotificationConfig = {
29
+ channels: [
30
+ {
31
+ id: "telegram",
32
+ type: "telegram",
33
+ enabled: true,
34
+ config: {
35
+ botToken: "test-bot-token",
36
+ chatId: "12345",
37
+ enableInlineKeyboard: true,
38
+ },
39
+ },
40
+ {
41
+ id: "line",
42
+ type: "line",
43
+ enabled: true,
44
+ config: { channelAccessToken: "test-line-token", userId: "U-test" },
45
+ },
46
+ ],
47
+ };
48
+ return new NotificationCenter(config);
49
+ }
50
+
51
+ function telegramRequests(): CapturedRequest[] {
52
+ return captured.filter((r) => r.url.includes("api.telegram.org"));
53
+ }
54
+
55
+ function lineRequests(): CapturedRequest[] {
56
+ return captured.filter((r) => r.url.includes("api.line.me"));
57
+ }
58
+
59
+ beforeEach(() => {
60
+ captured = [];
61
+ originalFetch = globalThis.fetch;
62
+ globalThis.fetch = (async (input: any, init?: any) => {
63
+ const url = typeof input === "string" ? input : (input?.url ?? "");
64
+ let body: any = {};
65
+ try {
66
+ body = JSON.parse(init?.body ?? "{}");
67
+ } catch {
68
+ body = {};
69
+ }
70
+ captured.push({ url, body });
71
+
72
+ // The content filter asks Jev. Without a configured key the answer
73
+ // does not matter, and a failure keeps the test offline.
74
+ if (url.includes("typesafe.ai")) {
75
+ return new Response("unauthorized", { status: 401 });
76
+ }
77
+ return new Response(JSON.stringify({ ok: true, result: {} }), {
78
+ status: 200,
79
+ headers: { "Content-Type": "application/json" },
80
+ });
81
+ }) as typeof globalThis.fetch;
82
+ });
83
+
84
+ afterEach(() => {
85
+ globalThis.fetch = originalFetch;
86
+ });
87
+
88
+ describe("approval payload", () => {
89
+ it("sends the complete question to Telegram without truncating it", async () => {
90
+ const center = createCenter();
91
+ const question = LONG_QUESTION.repeat(3);
92
+
93
+ await center.notifyWithApproval("WaitingForUserInput", {
94
+ jobId: "q-long",
95
+ questionId: "q-long",
96
+ requirement: question,
97
+ });
98
+
99
+ const text = telegramRequests()
100
+ .map((r) => String(r.body.text ?? ""))
101
+ .join("\n");
102
+
103
+ expect(text).toContain(question.trim());
104
+ // The shared 50 character summary must not be used for a question.
105
+ expect(text).not.toContain("...");
106
+ });
107
+
108
+ it("sends the complete question to LINE", async () => {
109
+ const center = createCenter();
110
+ const question = LONG_QUESTION.repeat(3);
111
+
112
+ await center.notifyWithApproval("WaitingForUserInput", {
113
+ jobId: "q-long",
114
+ questionId: "q-long",
115
+ requirement: question,
116
+ });
117
+
118
+ const line = lineRequests()[0];
119
+ const messages = line?.body?.messages ?? [];
120
+ const textMessage = messages.find((m: any) => m.type === "text");
121
+
122
+ expect(textMessage).toBeDefined();
123
+ expect(String(textMessage.text)).toContain(question.trim());
124
+ });
125
+
126
+ it("puts the canonical request ID into the Telegram callback data", async () => {
127
+ const center = createCenter();
128
+
129
+ await center.notifyWithApproval("WaitingForUserInput", {
130
+ jobId: "waiting-user-q-123",
131
+ questionId: "q-123",
132
+ requirement: "Want me to continue?",
133
+ });
134
+
135
+ const telegram = telegramRequests()[0];
136
+ const keyboard = telegram?.body?.reply_markup;
137
+ expect(keyboard).toBeDefined();
138
+
139
+ const approve = keyboard.inline_keyboard[0][0];
140
+ const reject = keyboard.inline_keyboard[0][1];
141
+
142
+ const parsedApprove = parseCallbackData(approve.callback_data);
143
+ const parsedReject = parseCallbackData(reject.callback_data);
144
+
145
+ expect(parsedApprove.action).toBe("approve");
146
+ expect(parsedReject.action).toBe("reject");
147
+ // The canonical ID, not the prefixed presentation job ID.
148
+ expect(parsedApprove.targetId).toBe("q-123");
149
+ expect(parsedReject.targetId).toBe("q-123");
150
+ });
151
+
152
+ it("resolves the matching pending question from the real callback data", async () => {
153
+ const center = createCenter();
154
+ const controller = new PendingQuestionController();
155
+ const question = controller.createQuestion({
156
+ text: "Want me to continue?",
157
+ sessionId: "session-1",
158
+ workspacePath: "/tmp",
159
+ kind: "approval",
160
+ });
161
+
162
+ await center.notifyWithApproval("WaitingForUserInput", {
163
+ jobId: `waiting-user-${question.requestId}`,
164
+ questionId: question.requestId,
165
+ requirement: "Want me to continue?",
166
+ });
167
+
168
+ const telegram = telegramRequests()[0];
169
+ const callbackData = telegram.body.reply_markup.inline_keyboard[0][0]
170
+ .callback_data as string;
171
+ const parsed = parseCallbackData(callbackData);
172
+
173
+ const applied = controller.applyApproval(
174
+ parsed.action,
175
+ parsed.targetId,
176
+ "telegram",
177
+ );
178
+
179
+ expect(applied.applied).toBe(true);
180
+ expect(applied.resolution).toBe("yes");
181
+ expect(controller.getResolution()).toBe("yes");
182
+ expect(controller.getCurrentQuestion()?.resolvedBy).toBe("user");
183
+ expect(controller.getCurrentQuestion()?.resolvedChannel).toBe("telegram");
184
+ });
185
+
186
+ it("uses the same canonical ID for the LINE postback actions", async () => {
187
+ const center = createCenter();
188
+
189
+ await center.notifyWithApproval("WaitingForUserInput", {
190
+ jobId: "waiting-user-q-123",
191
+ questionId: "q-123",
192
+ requirement: "Want me to continue?",
193
+ });
194
+
195
+ const line = lineRequests()[0];
196
+ const messages = line?.body?.messages ?? [];
197
+ const template = messages.find((m: any) => m.type === "template");
198
+ expect(template).toBeDefined();
199
+
200
+ const actions = template.template.actions;
201
+ expect(actions).toHaveLength(2);
202
+ expect(actions[0].type).toBe("postback");
203
+ expect(actions[1].type).toBe("postback");
204
+
205
+ const approve = parseCallbackData(actions[0].data);
206
+ const reject = parseCallbackData(actions[1].data);
207
+
208
+ expect(approve.action).toBe("approve");
209
+ expect(reject.action).toBe("reject");
210
+ expect(approve.targetId).toBe("q-123");
211
+ expect(reject.targetId).toBe("q-123");
212
+ });
213
+
214
+ it("routes the LINE postback into the same resolver as Telegram", async () => {
215
+ const center = createCenter();
216
+ const controller = new PendingQuestionController();
217
+ const question = controller.createQuestion({
218
+ text: "Want me to continue?",
219
+ sessionId: "session-1",
220
+ workspacePath: "/tmp",
221
+ kind: "approval",
222
+ });
223
+
224
+ await center.notifyWithApproval("WaitingForUserInput", {
225
+ jobId: `waiting-user-${question.requestId}`,
226
+ questionId: question.requestId,
227
+ requirement: "Want me to continue?",
228
+ });
229
+
230
+ const line = lineRequests()[0];
231
+ const messages = line?.body?.messages ?? [];
232
+ const template = messages.find((m: any) => m.type === "template");
233
+ const parsed = parseCallbackData(template.template.actions[0].data);
234
+
235
+ const applied = controller.applyApproval(
236
+ parsed.action,
237
+ parsed.targetId,
238
+ "line",
239
+ );
240
+
241
+ expect(applied.applied).toBe(true);
242
+ expect(controller.getResolution()).toBe("yes");
243
+ expect(controller.getCurrentQuestion()?.resolvedChannel).toBe("line");
244
+ });
245
+
246
+ it("attaches the keyboard only to the final chunk of a long question", async () => {
247
+ const center = createCenter();
248
+ const question = `${LONG_QUESTION.repeat(30)}Want me to continue?`;
249
+
250
+ await center.notifyWithApproval("WaitingForUserInput", {
251
+ jobId: "q-chunked",
252
+ questionId: "q-chunked",
253
+ requirement: question,
254
+ });
255
+
256
+ const requests = telegramRequests();
257
+ expect(requests.length).toBeGreaterThan(1);
258
+
259
+ const withKeyboard = requests.filter((r) => r.body?.reply_markup);
260
+ expect(withKeyboard).toHaveLength(1);
261
+ // The actionable message is the last one.
262
+ expect(withKeyboard[0]).toBe(requests[requests.length - 1]);
263
+
264
+ // The question stays understandable across the chunks.
265
+ const allText = requests.map((r) => String(r.body.text ?? "")).join("");
266
+ expect(allText).toContain("Want me to continue?");
267
+ expect(allText).toContain("[Part 1/");
268
+ });
269
+ });