agent-nuvira 3.3.1 → 3.3.4

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 (466) hide show
  1. package/README.md +18 -13
  2. package/dist/agent-sdk/src/agent.d.ts +2 -0
  3. package/dist/agent-sdk/src/agent.d.ts.map +1 -1
  4. package/dist/agent-sdk/src/define.d.ts +64 -0
  5. package/dist/agent-sdk/src/define.d.ts.map +1 -0
  6. package/dist/agent-sdk/src/define.js +76 -0
  7. package/dist/agent-sdk/src/define.js.map +1 -0
  8. package/dist/agent-sdk/src/index.d.ts +9 -0
  9. package/dist/agent-sdk/src/index.d.ts.map +1 -1
  10. package/dist/agent-sdk/src/index.js +9 -0
  11. package/dist/agent-sdk/src/index.js.map +1 -1
  12. package/dist/agent-sdk/src/scaffold.d.ts +11 -0
  13. package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
  14. package/dist/agent-sdk/src/scaffold.js +16 -6
  15. package/dist/agent-sdk/src/scaffold.js.map +1 -1
  16. package/dist/agents/agents/runner.d.ts +9 -0
  17. package/dist/agents/agents/runner.d.ts.map +1 -1
  18. package/dist/agents/agents/runner.js +34 -12
  19. package/dist/agents/agents/runner.js.map +1 -1
  20. package/dist/agents/agents/writer-tool-calling.d.ts.map +1 -1
  21. package/dist/agents/agents/writer-tool-calling.js +7 -2
  22. package/dist/agents/agents/writer-tool-calling.js.map +1 -1
  23. package/dist/agents/agents/writer.d.ts.map +1 -1
  24. package/dist/agents/agents/writer.js +7 -1
  25. package/dist/agents/agents/writer.js.map +1 -1
  26. package/dist/agents/artifact-verification.d.ts +102 -0
  27. package/dist/agents/artifact-verification.d.ts.map +1 -0
  28. package/dist/agents/artifact-verification.js +216 -0
  29. package/dist/agents/artifact-verification.js.map +1 -0
  30. package/dist/agents/checkpoint-store.d.ts +73 -0
  31. package/dist/agents/checkpoint-store.d.ts.map +1 -1
  32. package/dist/agents/checkpoint-store.js +161 -0
  33. package/dist/agents/checkpoint-store.js.map +1 -1
  34. package/dist/agents/credential-store.d.ts +120 -0
  35. package/dist/agents/credential-store.d.ts.map +1 -1
  36. package/dist/agents/credential-store.js +358 -19
  37. package/dist/agents/credential-store.js.map +1 -1
  38. package/dist/agents/long-form-plan.d.ts.map +1 -1
  39. package/dist/agents/long-form-plan.js +2 -1
  40. package/dist/agents/long-form-plan.js.map +1 -1
  41. package/dist/agents/orchestrator.d.ts +10 -1
  42. package/dist/agents/orchestrator.d.ts.map +1 -1
  43. package/dist/agents/orchestrator.js +239 -79
  44. package/dist/agents/orchestrator.js.map +1 -1
  45. package/dist/agents/phase-engine.d.ts +61 -0
  46. package/dist/agents/phase-engine.d.ts.map +1 -1
  47. package/dist/agents/phase-engine.js +68 -2
  48. package/dist/agents/phase-engine.js.map +1 -1
  49. package/dist/agents/prompt-assembly.d.ts +11 -0
  50. package/dist/agents/prompt-assembly.d.ts.map +1 -1
  51. package/dist/agents/prompt-assembly.js +17 -0
  52. package/dist/agents/prompt-assembly.js.map +1 -1
  53. package/dist/agents/release-preflight.d.ts +121 -0
  54. package/dist/agents/release-preflight.d.ts.map +1 -0
  55. package/dist/agents/release-preflight.js +259 -0
  56. package/dist/agents/release-preflight.js.map +1 -0
  57. package/dist/agents/release-runner.d.ts +157 -0
  58. package/dist/agents/release-runner.d.ts.map +1 -0
  59. package/dist/agents/release-runner.js +719 -0
  60. package/dist/agents/release-runner.js.map +1 -0
  61. package/dist/agents/step-handoff.d.ts +190 -0
  62. package/dist/agents/step-handoff.d.ts.map +1 -0
  63. package/dist/agents/step-handoff.js +443 -0
  64. package/dist/agents/step-handoff.js.map +1 -0
  65. package/dist/cli/agent.d.ts +2 -2
  66. package/dist/cli/agent.js +10 -10
  67. package/dist/cli/benchmark.d.ts.map +1 -1
  68. package/dist/cli/benchmark.js +11 -4
  69. package/dist/cli/benchmark.js.map +1 -1
  70. package/dist/cli/chat.d.ts +94 -0
  71. package/dist/cli/chat.d.ts.map +1 -1
  72. package/dist/cli/chat.js +379 -24
  73. package/dist/cli/chat.js.map +1 -1
  74. package/dist/cli/cli-program.d.ts.map +1 -1
  75. package/dist/cli/cli-program.js +8 -0
  76. package/dist/cli/cli-program.js.map +1 -1
  77. package/dist/cli/config.d.ts.map +1 -1
  78. package/dist/cli/config.js +9 -1
  79. package/dist/cli/config.js.map +1 -1
  80. package/dist/cli/credentials.d.ts +28 -0
  81. package/dist/cli/credentials.d.ts.map +1 -0
  82. package/dist/cli/credentials.js +213 -0
  83. package/dist/cli/credentials.js.map +1 -0
  84. package/dist/cli/doctor.d.ts.map +1 -1
  85. package/dist/cli/doctor.js +3 -2
  86. package/dist/cli/doctor.js.map +1 -1
  87. package/dist/cli/edit.js +2 -2
  88. package/dist/cli/eval.d.ts +17 -0
  89. package/dist/cli/eval.d.ts.map +1 -1
  90. package/dist/cli/eval.js +105 -2
  91. package/dist/cli/eval.js.map +1 -1
  92. package/dist/cli/execute.d.ts +16 -1
  93. package/dist/cli/execute.d.ts.map +1 -1
  94. package/dist/cli/execute.js +192 -22
  95. package/dist/cli/execute.js.map +1 -1
  96. package/dist/cli/failover-runner.d.ts.map +1 -1
  97. package/dist/cli/failover-runner.js +9 -3
  98. package/dist/cli/failover-runner.js.map +1 -1
  99. package/dist/cli/loop-executor.d.ts +55 -0
  100. package/dist/cli/loop-executor.d.ts.map +1 -1
  101. package/dist/cli/loop-executor.js +285 -19
  102. package/dist/cli/loop-executor.js.map +1 -1
  103. package/dist/cli/model.d.ts.map +1 -1
  104. package/dist/cli/model.js +9 -8
  105. package/dist/cli/model.js.map +1 -1
  106. package/dist/cli/models.d.ts +1 -1
  107. package/dist/cli/models.js +4 -4
  108. package/dist/cli/nlu.d.ts.map +1 -1
  109. package/dist/cli/nlu.js +8 -2
  110. package/dist/cli/nlu.js.map +1 -1
  111. package/dist/cli/parity.d.ts +85 -0
  112. package/dist/cli/parity.d.ts.map +1 -0
  113. package/dist/cli/parity.js +506 -0
  114. package/dist/cli/parity.js.map +1 -0
  115. package/dist/cli/plan.d.ts.map +1 -1
  116. package/dist/cli/plan.js +2 -1
  117. package/dist/cli/plan.js.map +1 -1
  118. package/dist/cli/publish.d.ts +22 -0
  119. package/dist/cli/publish.d.ts.map +1 -1
  120. package/dist/cli/publish.js +109 -13
  121. package/dist/cli/publish.js.map +1 -1
  122. package/dist/cli/retrieval.d.ts.map +1 -1
  123. package/dist/cli/retrieval.js +5 -4
  124. package/dist/cli/retrieval.js.map +1 -1
  125. package/dist/cli/sdk.js +4 -4
  126. package/dist/cli/sdk.js.map +1 -1
  127. package/dist/cli/trace.d.ts.map +1 -1
  128. package/dist/cli/trace.js +2 -1
  129. package/dist/cli/trace.js.map +1 -1
  130. package/dist/cli/workflow.js +2 -2
  131. package/dist/cli/workflow.js.map +1 -1
  132. package/dist/config/live-credentials.d.ts +57 -0
  133. package/dist/config/live-credentials.d.ts.map +1 -0
  134. package/dist/config/live-credentials.js +126 -0
  135. package/dist/config/live-credentials.js.map +1 -0
  136. package/dist/config/paths.d.ts +18 -0
  137. package/dist/config/paths.d.ts.map +1 -1
  138. package/dist/config/paths.js +25 -0
  139. package/dist/config/paths.js.map +1 -1
  140. package/dist/config/types.d.ts +44 -0
  141. package/dist/config/types.d.ts.map +1 -1
  142. package/dist/federation/a2a-types.js +1 -1
  143. package/dist/federation/a2a-types.js.map +1 -1
  144. package/dist/findings/verdicts.d.ts +241 -0
  145. package/dist/findings/verdicts.d.ts.map +1 -0
  146. package/dist/findings/verdicts.js +284 -0
  147. package/dist/findings/verdicts.js.map +1 -0
  148. package/dist/gateway/adapters.d.ts +65 -0
  149. package/dist/gateway/adapters.d.ts.map +1 -1
  150. package/dist/gateway/adapters.js +216 -10
  151. package/dist/gateway/adapters.js.map +1 -1
  152. package/dist/gateway/channel-directory.d.ts +31 -0
  153. package/dist/gateway/channel-directory.d.ts.map +1 -1
  154. package/dist/gateway/channel-directory.js +40 -0
  155. package/dist/gateway/channel-directory.js.map +1 -1
  156. package/dist/gateway/gateway-log.d.ts +1 -1
  157. package/dist/gateway/gateway-log.d.ts.map +1 -1
  158. package/dist/gateway/gateway-log.js.map +1 -1
  159. package/dist/gateway/hooks.d.ts +87 -19
  160. package/dist/gateway/hooks.d.ts.map +1 -1
  161. package/dist/gateway/hooks.js +62 -23
  162. package/dist/gateway/hooks.js.map +1 -1
  163. package/dist/gateway/inbound-media.d.ts +147 -0
  164. package/dist/gateway/inbound-media.d.ts.map +1 -0
  165. package/dist/gateway/inbound-media.js +317 -0
  166. package/dist/gateway/inbound-media.js.map +1 -0
  167. package/dist/gateway/inbox.d.ts +8 -1
  168. package/dist/gateway/inbox.d.ts.map +1 -1
  169. package/dist/gateway/inbox.js.map +1 -1
  170. package/dist/gateway/platform-config.d.ts +14 -0
  171. package/dist/gateway/platform-config.d.ts.map +1 -1
  172. package/dist/gateway/platform-config.js +26 -8
  173. package/dist/gateway/platform-config.js.map +1 -1
  174. package/dist/gateway/realtime.d.ts +114 -0
  175. package/dist/gateway/realtime.d.ts.map +1 -0
  176. package/dist/gateway/realtime.js +402 -0
  177. package/dist/gateway/realtime.js.map +1 -0
  178. package/dist/gateway/registry.d.ts +31 -0
  179. package/dist/gateway/registry.d.ts.map +1 -1
  180. package/dist/gateway/registry.js +224 -4
  181. package/dist/gateway/registry.js.map +1 -1
  182. package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
  183. package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
  184. package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
  185. package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
  186. package/dist/gateway/whatsapp/bridge.d.ts +6 -2
  187. package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
  188. package/dist/gateway/whatsapp/bridge.js.map +1 -1
  189. package/dist/index.js +8 -0
  190. package/dist/index.js.map +1 -1
  191. package/dist/inference/factory.d.ts +14 -0
  192. package/dist/inference/factory.d.ts.map +1 -1
  193. package/dist/inference/factory.js +17 -0
  194. package/dist/inference/factory.js.map +1 -1
  195. package/dist/inference/groq-adapter.d.ts +2 -0
  196. package/dist/inference/groq-adapter.d.ts.map +1 -1
  197. package/dist/inference/groq-adapter.js +16 -6
  198. package/dist/inference/groq-adapter.js.map +1 -1
  199. package/dist/inference/model-validator.d.ts +6 -1
  200. package/dist/inference/model-validator.d.ts.map +1 -1
  201. package/dist/inference/model-validator.js +7 -2
  202. package/dist/inference/model-validator.js.map +1 -1
  203. package/dist/inference/route-resolver.d.ts +116 -0
  204. package/dist/inference/route-resolver.d.ts.map +1 -0
  205. package/dist/inference/route-resolver.js +159 -0
  206. package/dist/inference/route-resolver.js.map +1 -0
  207. package/dist/inference/tools.d.ts.map +1 -1
  208. package/dist/inference/tools.js +29 -0
  209. package/dist/inference/tools.js.map +1 -1
  210. package/dist/learning/autonomy-policy.d.ts +18 -0
  211. package/dist/learning/autonomy-policy.d.ts.map +1 -1
  212. package/dist/learning/autonomy-policy.js +35 -0
  213. package/dist/learning/autonomy-policy.js.map +1 -1
  214. package/dist/learning/benchmark.d.ts.map +1 -1
  215. package/dist/learning/benchmark.js +3 -2
  216. package/dist/learning/benchmark.js.map +1 -1
  217. package/dist/learning/continuation.d.ts.map +1 -1
  218. package/dist/learning/continuation.js +2 -1
  219. package/dist/learning/continuation.js.map +1 -1
  220. package/dist/learning/cost-tracker.d.ts.map +1 -1
  221. package/dist/learning/cost-tracker.js +2 -1
  222. package/dist/learning/cost-tracker.js.map +1 -1
  223. package/dist/learning/deferred-task.d.ts.map +1 -1
  224. package/dist/learning/deferred-task.js +13 -4
  225. package/dist/learning/deferred-task.js.map +1 -1
  226. package/dist/learning/eval-framework.d.ts.map +1 -1
  227. package/dist/learning/eval-framework.js +2 -1
  228. package/dist/learning/eval-framework.js.map +1 -1
  229. package/dist/learning/long-form.d.ts.map +1 -1
  230. package/dist/learning/long-form.js +2 -1
  231. package/dist/learning/long-form.js.map +1 -1
  232. package/dist/learning/model-registry.d.ts.map +1 -1
  233. package/dist/learning/model-registry.js +2 -1
  234. package/dist/learning/model-registry.js.map +1 -1
  235. package/dist/learning/reasoning-cache.d.ts.map +1 -1
  236. package/dist/learning/reasoning-cache.js +2 -1
  237. package/dist/learning/reasoning-cache.js.map +1 -1
  238. package/dist/learning/reasoning-trace.d.ts +38 -2
  239. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  240. package/dist/learning/reasoning-trace.js +91 -1
  241. package/dist/learning/reasoning-trace.js.map +1 -1
  242. package/dist/learning/resilient-call.d.ts.map +1 -1
  243. package/dist/learning/resilient-call.js +31 -18
  244. package/dist/learning/resilient-call.js.map +1 -1
  245. package/dist/learning/retrieval.d.ts.map +1 -1
  246. package/dist/learning/retrieval.js +2 -1
  247. package/dist/learning/retrieval.js.map +1 -1
  248. package/dist/learning/seeded-benchmark.d.ts +160 -0
  249. package/dist/learning/seeded-benchmark.d.ts.map +1 -0
  250. package/dist/learning/seeded-benchmark.js +321 -0
  251. package/dist/learning/seeded-benchmark.js.map +1 -0
  252. package/dist/learning/seeded-bugs.d.ts +142 -0
  253. package/dist/learning/seeded-bugs.d.ts.map +1 -0
  254. package/dist/learning/seeded-bugs.js +535 -0
  255. package/dist/learning/seeded-bugs.js.map +1 -0
  256. package/dist/learning/skill-store.d.ts.map +1 -1
  257. package/dist/learning/skill-store.js +30 -9
  258. package/dist/learning/skill-store.js.map +1 -1
  259. package/dist/learning/step-checkpoint.d.ts +127 -0
  260. package/dist/learning/step-checkpoint.d.ts.map +1 -0
  261. package/dist/learning/step-checkpoint.js +244 -0
  262. package/dist/learning/step-checkpoint.js.map +1 -0
  263. package/dist/mcp/catalog.js +2 -3
  264. package/dist/mcp/catalog.js.map +1 -1
  265. package/dist/mcp/manager.d.ts.map +1 -1
  266. package/dist/mcp/manager.js +5 -3
  267. package/dist/mcp/manager.js.map +1 -1
  268. package/dist/nlu/intent-confirm.d.ts +23 -1
  269. package/dist/nlu/intent-confirm.d.ts.map +1 -1
  270. package/dist/nlu/intent-confirm.js +85 -2
  271. package/dist/nlu/intent-confirm.js.map +1 -1
  272. package/dist/nlu/learnings.d.ts +7 -0
  273. package/dist/nlu/learnings.d.ts.map +1 -1
  274. package/dist/nlu/learnings.js +7 -0
  275. package/dist/nlu/learnings.js.map +1 -1
  276. package/dist/observability/debug-log.d.ts +250 -0
  277. package/dist/observability/debug-log.d.ts.map +1 -0
  278. package/dist/observability/debug-log.js +500 -0
  279. package/dist/observability/debug-log.js.map +1 -0
  280. package/dist/observability/event-bus.d.ts.map +1 -1
  281. package/dist/observability/event-bus.js +4 -1
  282. package/dist/observability/event-bus.js.map +1 -1
  283. package/dist/observability/otel.d.ts +278 -0
  284. package/dist/observability/otel.d.ts.map +1 -0
  285. package/dist/observability/otel.js +590 -0
  286. package/dist/observability/otel.js.map +1 -0
  287. package/dist/parity/drivers.d.ts +99 -0
  288. package/dist/parity/drivers.d.ts.map +1 -0
  289. package/dist/parity/drivers.js +1362 -0
  290. package/dist/parity/drivers.js.map +1 -0
  291. package/dist/parity/graph.d.ts +73 -0
  292. package/dist/parity/graph.d.ts.map +1 -0
  293. package/dist/parity/graph.js +162 -0
  294. package/dist/parity/graph.js.map +1 -0
  295. package/dist/parity/matrix.d.ts +105 -0
  296. package/dist/parity/matrix.d.ts.map +1 -0
  297. package/dist/parity/matrix.js +352 -0
  298. package/dist/parity/matrix.js.map +1 -0
  299. package/dist/parity/observation.d.ts +444 -0
  300. package/dist/parity/observation.d.ts.map +1 -0
  301. package/dist/parity/observation.js +333 -0
  302. package/dist/parity/observation.js.map +1 -0
  303. package/dist/parity/scenarios.d.ts +229 -0
  304. package/dist/parity/scenarios.d.ts.map +1 -0
  305. package/dist/parity/scenarios.js +175 -0
  306. package/dist/parity/scenarios.js.map +1 -0
  307. package/dist/parity/surfaces.d.ts +122 -0
  308. package/dist/parity/surfaces.d.ts.map +1 -0
  309. package/dist/parity/surfaces.js +190 -0
  310. package/dist/parity/surfaces.js.map +1 -0
  311. package/dist/runtime/fault-injection.d.ts +173 -0
  312. package/dist/runtime/fault-injection.d.ts.map +1 -0
  313. package/dist/runtime/fault-injection.js +281 -0
  314. package/dist/runtime/fault-injection.js.map +1 -0
  315. package/dist/skills/secret-capture.d.ts.map +1 -1
  316. package/dist/skills/secret-capture.js +9 -4
  317. package/dist/skills/secret-capture.js.map +1 -1
  318. package/dist/tools/child-agent-entry.d.ts +23 -0
  319. package/dist/tools/child-agent-entry.d.ts.map +1 -0
  320. package/dist/tools/child-agent-entry.js +129 -0
  321. package/dist/tools/child-agent-entry.js.map +1 -0
  322. package/dist/tools/child-agent-runtime.d.ts +124 -0
  323. package/dist/tools/child-agent-runtime.d.ts.map +1 -0
  324. package/dist/tools/child-agent-runtime.js +704 -0
  325. package/dist/tools/child-agent-runtime.js.map +1 -0
  326. package/dist/tools/coding-tools.d.ts.map +1 -1
  327. package/dist/tools/coding-tools.js +82 -10
  328. package/dist/tools/coding-tools.js.map +1 -1
  329. package/dist/tools/credentials-tool.d.ts +24 -0
  330. package/dist/tools/credentials-tool.d.ts.map +1 -0
  331. package/dist/tools/credentials-tool.js +125 -0
  332. package/dist/tools/credentials-tool.js.map +1 -0
  333. package/dist/tools/delegation-system.d.ts +31 -0
  334. package/dist/tools/delegation-system.d.ts.map +1 -1
  335. package/dist/tools/delegation-system.js +70 -9
  336. package/dist/tools/delegation-system.js.map +1 -1
  337. package/dist/tools/extract/docx.d.ts +27 -0
  338. package/dist/tools/extract/docx.d.ts.map +1 -0
  339. package/dist/tools/extract/docx.js +48 -0
  340. package/dist/tools/extract/docx.js.map +1 -0
  341. package/dist/tools/extract/html-text.d.ts +27 -0
  342. package/dist/tools/extract/html-text.d.ts.map +1 -0
  343. package/dist/tools/extract/html-text.js +86 -0
  344. package/dist/tools/extract/html-text.js.map +1 -0
  345. package/dist/tools/extract/pdf-ocr.d.ts +58 -0
  346. package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
  347. package/dist/tools/extract/pdf-ocr.js +116 -0
  348. package/dist/tools/extract/pdf-ocr.js.map +1 -0
  349. package/dist/tools/extract/pdf.d.ts +65 -0
  350. package/dist/tools/extract/pdf.d.ts.map +1 -0
  351. package/dist/tools/extract/pdf.js +197 -0
  352. package/dist/tools/extract/pdf.js.map +1 -0
  353. package/dist/tools/extract/pptx.d.ts +32 -0
  354. package/dist/tools/extract/pptx.d.ts.map +1 -0
  355. package/dist/tools/extract/pptx.js +77 -0
  356. package/dist/tools/extract/pptx.js.map +1 -0
  357. package/dist/tools/extract/xlsx.d.ts +47 -0
  358. package/dist/tools/extract/xlsx.d.ts.map +1 -0
  359. package/dist/tools/extract/xlsx.js +111 -0
  360. package/dist/tools/extract/xlsx.js.map +1 -0
  361. package/dist/tools/finding-tool.d.ts +76 -0
  362. package/dist/tools/finding-tool.d.ts.map +1 -0
  363. package/dist/tools/finding-tool.js +125 -0
  364. package/dist/tools/finding-tool.js.map +1 -0
  365. package/dist/tools/git-tool.d.ts +25 -7
  366. package/dist/tools/git-tool.d.ts.map +1 -1
  367. package/dist/tools/git-tool.js +155 -15
  368. package/dist/tools/git-tool.js.map +1 -1
  369. package/dist/tools/loop-project-context.d.ts.map +1 -1
  370. package/dist/tools/loop-project-context.js +16 -0
  371. package/dist/tools/loop-project-context.js.map +1 -1
  372. package/dist/tools/loop-route-feed.d.ts +57 -0
  373. package/dist/tools/loop-route-feed.d.ts.map +1 -0
  374. package/dist/tools/loop-route-feed.js +101 -0
  375. package/dist/tools/loop-route-feed.js.map +1 -0
  376. package/dist/tools/messaging-tools.d.ts +41 -11
  377. package/dist/tools/messaging-tools.d.ts.map +1 -1
  378. package/dist/tools/messaging-tools.js +104 -55
  379. package/dist/tools/messaging-tools.js.map +1 -1
  380. package/dist/tools/neutts-synth.d.ts +27 -3
  381. package/dist/tools/neutts-synth.d.ts.map +1 -1
  382. package/dist/tools/neutts-synth.js +57 -13
  383. package/dist/tools/neutts-synth.js.map +1 -1
  384. package/dist/tools/pipeline-tool.d.ts +43 -1
  385. package/dist/tools/pipeline-tool.d.ts.map +1 -1
  386. package/dist/tools/pipeline-tool.js +21 -4
  387. package/dist/tools/pipeline-tool.js.map +1 -1
  388. package/dist/tools/publish-tool.d.ts.map +1 -1
  389. package/dist/tools/publish-tool.js +76 -10
  390. package/dist/tools/publish-tool.js.map +1 -1
  391. package/dist/tools/read-extract.d.ts +116 -45
  392. package/dist/tools/read-extract.d.ts.map +1 -1
  393. package/dist/tools/read-extract.js +494 -158
  394. package/dist/tools/read-extract.js.map +1 -1
  395. package/dist/tools/registry.d.ts +23 -3
  396. package/dist/tools/registry.d.ts.map +1 -1
  397. package/dist/tools/registry.js +196 -29
  398. package/dist/tools/registry.js.map +1 -1
  399. package/dist/tools/run-terminal.d.ts +9 -0
  400. package/dist/tools/run-terminal.d.ts.map +1 -1
  401. package/dist/tools/run-terminal.js +80 -2
  402. package/dist/tools/run-terminal.js.map +1 -1
  403. package/dist/tools/subagent-refusal.d.ts +15 -0
  404. package/dist/tools/subagent-refusal.d.ts.map +1 -0
  405. package/dist/tools/subagent-refusal.js +18 -0
  406. package/dist/tools/subagent-refusal.js.map +1 -0
  407. package/dist/tools/subagent-spawner.d.ts +122 -0
  408. package/dist/tools/subagent-spawner.d.ts.map +1 -1
  409. package/dist/tools/subagent-spawner.js +249 -28
  410. package/dist/tools/subagent-spawner.js.map +1 -1
  411. package/dist/tools/tool-hooks.d.ts +177 -0
  412. package/dist/tools/tool-hooks.d.ts.map +1 -0
  413. package/dist/tools/tool-hooks.js +427 -0
  414. package/dist/tools/tool-hooks.js.map +1 -0
  415. package/dist/tools/tool-loop.d.ts +94 -5
  416. package/dist/tools/tool-loop.d.ts.map +1 -1
  417. package/dist/tools/tool-loop.js +315 -9
  418. package/dist/tools/tool-loop.js.map +1 -1
  419. package/dist/tools/tool-refusal.d.ts +68 -0
  420. package/dist/tools/tool-refusal.d.ts.map +1 -0
  421. package/dist/tools/tool-refusal.js +78 -0
  422. package/dist/tools/tool-refusal.js.map +1 -0
  423. package/dist/tools/toolsets.d.ts +8 -0
  424. package/dist/tools/toolsets.d.ts.map +1 -1
  425. package/dist/tools/toolsets.js +14 -4
  426. package/dist/tools/toolsets.js.map +1 -1
  427. package/dist/tools/vision-tools.d.ts +88 -83
  428. package/dist/tools/vision-tools.d.ts.map +1 -1
  429. package/dist/tools/vision-tools.js +134 -103
  430. package/dist/tools/vision-tools.js.map +1 -1
  431. package/dist/tools/worktree.d.ts +210 -0
  432. package/dist/tools/worktree.d.ts.map +1 -0
  433. package/dist/tools/worktree.js +374 -0
  434. package/dist/tools/worktree.js.map +1 -0
  435. package/dist/utils/format.d.ts +3 -0
  436. package/dist/utils/format.d.ts.map +1 -0
  437. package/dist/utils/format.js +32 -0
  438. package/dist/utils/format.js.map +1 -0
  439. package/dist/web-dashboard/attachment-extract.d.ts +64 -0
  440. package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
  441. package/dist/web-dashboard/attachment-extract.js +154 -0
  442. package/dist/web-dashboard/attachment-extract.js.map +1 -0
  443. package/dist/web-dashboard/chat-console.d.ts +108 -1
  444. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  445. package/dist/web-dashboard/chat-console.js +36 -0
  446. package/dist/web-dashboard/chat-console.js.map +1 -1
  447. package/dist/web-dashboard/hub-data.d.ts +37 -0
  448. package/dist/web-dashboard/hub-data.d.ts.map +1 -1
  449. package/dist/web-dashboard/hub-data.js +61 -1
  450. package/dist/web-dashboard/hub-data.js.map +1 -1
  451. package/dist/web-dashboard/server.d.ts +14 -0
  452. package/dist/web-dashboard/server.d.ts.map +1 -1
  453. package/dist/web-dashboard/server.js +247 -13
  454. package/dist/web-dashboard/server.js.map +1 -1
  455. package/dist/web-dashboard/src/types.d.ts +196 -48
  456. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  457. package/dist/workflow/registry.js +1 -1
  458. package/dist/workflow/registry.js.map +1 -1
  459. package/package.json +22 -6
  460. package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
  461. package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
  462. package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
  463. package/src/web-dashboard/public/index.html +2 -2
  464. package/dist/tools/child-agent-worker.js +0 -212
  465. package/src/web-dashboard/public/assets/index-CjvoBhlz.js +0 -207
  466. package/src/web-dashboard/public/assets/index-CjvoBhlz.js.map +0 -1
@@ -17,6 +17,8 @@ import { fileURLToPath } from 'node:url';
17
17
  import { homedir } from 'node:os';
18
18
  import { parseRbacUsers } from '../enterprise/rbac.js';
19
19
  import { registerDagHandlers } from '../observability/dag-bridge.js';
20
+ import { debugLogDir, debugLoggingEnabled, debugLogsForSession } from '../observability/debug-log.js';
21
+ import { scrubSecrets } from '../gateway/gateway-log.js';
20
22
  import { resolveBuffConfigDir, resolveBuffConfigPath, resolveNuviraHome } from '../config/paths.js';
21
23
  import { loadEnv } from '../utils/env.js';
22
24
  import { ConfigManager } from '../config/manager.js';
@@ -51,7 +53,7 @@ import { setSkillEnabled } from '../learning/hub-skill-catalog.js';
51
53
  // mock node:fs before importing the server (router's package.json read would
52
54
  // hit the mocked readFileSync).
53
55
  import { createConfiguredAdapters } from '../gateway/adapters.js';
54
- import { ChannelDirectory, PLATFORM_ENV_VARS } from '../gateway/channel-directory.js';
56
+ import { ChannelDirectory, PLATFORM_ENV_VARS, platformConfigVars } from '../gateway/channel-directory.js';
55
57
  import { applyEnvToProcess, configurablePlatforms, platformConfigStatus, platformEnvVarMeta, redactValue, writeEnvFile, } from '../gateway/platform-config.js';
56
58
  // ─── Constants ──────────────────────────────────────────────────────────────
57
59
  const PORT = parseInt(envBuff('DASHBOARD_PORT') || '3030', 10);
@@ -469,6 +471,88 @@ function generateZip(files) {
469
471
  parts.push(new Uint8Array(eocd));
470
472
  return Buffer.concat(parts.map((p) => Buffer.from(p.buffer, p.byteOffset, p.byteLength)));
471
473
  }
474
+ // ─── WS2 (#24) — the attachable support bundle ──────────────────────────────
475
+ /** Cap on the transcript the bundle carries, so one long chat cannot make a 50 MB zip. */
476
+ const MAX_SUPPORT_TRANSCRIPT_CHARS = 400_000;
477
+ /**
478
+ * The front page of a support bundle: what is inside, and — just as important —
479
+ * what is deliberately NOT.
480
+ *
481
+ * Load-bearing rather than decorative. A bundle exists to be pasted into a bug
482
+ * report, often a public one, so it has to say plainly that credentials are
483
+ * redacted and that the logs carry previews instead of payloads. A user who
484
+ * cannot tell what they are about to attach either does not attach it or
485
+ * attaches it and regrets it, and both of those make the artifact useless.
486
+ */
487
+ function renderSupportManifest(opts) {
488
+ const named = (values) => [
489
+ ...new Set(values.filter((v) => typeof v === 'string' && v.length > 0)),
490
+ ];
491
+ const surfaces = named(opts.logs.map((l) => l.header.surface));
492
+ const versions = named(opts.logs.map((l) => l.header.version));
493
+ const backends = [
494
+ ...new Set(opts.logs
495
+ .map((l) => [l.header.provider, l.header.model, l.header.transport].filter(Boolean).join(' / '))
496
+ .filter((b) => b.length > 0)),
497
+ ];
498
+ return [
499
+ 'nuvira support bundle',
500
+ `generated: ${opts.generatedAt.toISOString()}`,
501
+ `session: ${opts.sessionId}`,
502
+ `surface(s): ${surfaces.join(', ') || 'unknown'}`,
503
+ `version(s): ${versions.join(', ') || 'unknown'}`,
504
+ `debug logs: ${opts.logs.length} (oldest first)`,
505
+ ...(backends.length > 0 ? [`backend(s) seen: ${backends.join(' | ')}`] : []),
506
+ ...(opts.turns !== null ? [`conversation turns: ${opts.turns}`] : []),
507
+ '',
508
+ 'contents:',
509
+ ...opts.files.map((f) => ` - ${f}`),
510
+ '',
511
+ 'notes:',
512
+ ' - credentials are redacted, with the same scrubber the gateway log uses',
513
+ ' - a session debug log carries bounded previews and event lines, not full payloads',
514
+ ' - each log names the backend that ACTUALLY served its turn, after any failover',
515
+ ...(opts.turns !== null
516
+ ? [' - conversation.txt is your own chat with the agent, included so the reading is unambiguous']
517
+ : []),
518
+ '',
519
+ ].join('\n');
520
+ }
521
+ /**
522
+ * The conversation as text — the other half of a bug report, and the reason the
523
+ * bundle is worth more than the log alone ("it did not answer" needs the ask).
524
+ *
525
+ * Redacted with the same `scrubSecrets` for the same reason as the logs: a user
526
+ * pasting this into a public issue must not leak a key they happened to type
527
+ * into a prompt three turns earlier. Bounded by characters, and it SAYS when it
528
+ * was cut, so a truncated bundle is never mistaken for the whole story.
529
+ */
530
+ function renderSupportTranscript(sessionId, record, generatedAt) {
531
+ const lines = [
532
+ `Conversation with the dashboard agent (session ${sessionId})`,
533
+ `Exported: ${generatedAt.toISOString()}`,
534
+ `Turns: ${record.turns.length}`,
535
+ '─'.repeat(60),
536
+ '',
537
+ ];
538
+ let used = 0;
539
+ let truncated = false;
540
+ for (const turn of record.turns) {
541
+ const body = scrubSecrets(turn.content);
542
+ if (used + body.length > MAX_SUPPORT_TRANSCRIPT_CHARS) {
543
+ truncated = true;
544
+ break;
545
+ }
546
+ used += body.length;
547
+ lines.push(turn.role === 'user' ? 'You:' : 'Agent:');
548
+ lines.push(body);
549
+ lines.push('');
550
+ }
551
+ if (truncated) {
552
+ lines.push(`[truncated at ${MAX_SUPPORT_TRANSCRIPT_CHARS} characters — the full transcript is in the session store]`);
553
+ }
554
+ return lines.join('\n');
555
+ }
472
556
  let activePipeline = null; // goal/description of current pipeline
473
557
  let activeNodes = [];
474
558
  let activeEdges = [];
@@ -4747,6 +4831,9 @@ function handleRequest(req, res) {
4747
4831
  varName: v.varName,
4748
4832
  set: v.set,
4749
4833
  value: canWrite ? v.value : v.set ? redactValue(v.value) : '',
4834
+ // `prompt` carries the "(optional)" marker for additive transport
4835
+ // modes (platformEnvVarMeta), so the form labels them without the UI
4836
+ // having to know which vars are required.
4750
4837
  prompt: m?.prompt ?? v.varName,
4751
4838
  secret: m?.secret ?? false,
4752
4839
  };
@@ -4780,7 +4867,10 @@ function handleRequest(req, res) {
4780
4867
  }
4781
4868
  const body = await readJsonBody(req);
4782
4869
  const values = (body?.values ?? {});
4783
- const allowed = new Set(PLATFORM_ENV_VARS[platform]);
4870
+ // platformConfigVars, not PLATFORM_ENV_VARS: the form renders every managed
4871
+ // var (including the additional transport modes), so a key it displays must
4872
+ // be writable here — otherwise a value the UI offers is rejected as unknown.
4873
+ const allowed = new Set(platformConfigVars(platform));
4784
4874
  const clean = {};
4785
4875
  for (const [key, value] of Object.entries(values)) {
4786
4876
  if (!allowed.has(key)) {
@@ -4819,7 +4909,7 @@ function handleRequest(req, res) {
4819
4909
  writeJson(res, 400, { ok: false, error: `Platform '${platform}' is not env-configurable.` });
4820
4910
  return;
4821
4911
  }
4822
- const keys = PLATFORM_ENV_VARS[platform];
4912
+ const keys = platformConfigVars(platform);
4823
4913
  writeEnvFile({}, keys);
4824
4914
  applyEnvToProcess({}, keys);
4825
4915
  writeJson(res, 200, { ok: true, removed: keys, status: platformConfigStatus(platform) });
@@ -5448,14 +5538,34 @@ function handleRequest(req, res) {
5448
5538
  : newChatSessionId();
5449
5539
  const provider = typeof body?.provider === 'string' ? body.provider : undefined;
5450
5540
  const model = typeof body?.model === 'string' ? body.model : undefined;
5451
- // P8 — turn attachments (file picker / paste-as-attachment / drag-drop).
5452
- // The GUI reads files client-side and sends the text inline; the server
5453
- // injects them into the SAME answerOnce context as [Attachment: name].
5454
- const rawAttachments = Array.isArray(body?.attachments) ? body.attachments : [];
5455
- const attachments = rawAttachments
5456
- .filter((a) => !!a && typeof a.name === 'string' && typeof a.content === 'string' && a.name.trim().length > 0)
5457
- .map((a) => ({ name: a.name.trim().slice(0, 120), content: a.content.slice(0, 300_000) }))
5458
- .slice(0, 10);
5541
+ // WS5 (#27) — per-turn isolation and resume, from the GUI.
5542
+ //
5543
+ // Read as a strict TRI-state, because the three cases are genuinely
5544
+ // different here: `true` asks for it, `false` declines a deployment-wide
5545
+ // `NUVIRA_ISOLATE`/`NUVIRA_RESUME` for this one turn, and ABSENT (`undefined`)
5546
+ // defers to that environment. Collapsing absent into `false` would make the
5547
+ // GUI's silence outrank the deployment's configuration — the same defect the
5548
+ // CLI's option defaults had.
5549
+ const worktree = body?.worktree === true ? true : body?.worktree === false ? false : undefined;
5550
+ const keepWorktree = body?.keepWorktree === true ? true : body?.keepWorktree === false ? false : undefined;
5551
+ const resume = typeof body?.resume === 'string'
5552
+ ? body.resume
5553
+ : body?.resume === true
5554
+ ? true
5555
+ : body?.resume === false
5556
+ ? false
5557
+ : undefined;
5558
+ // P8 + P2 — turn attachments (file picker / paste-as-attachment / drag-drop).
5559
+ //
5560
+ // The GUI sends TEXT inline. For anything it cannot decode as text (PDF, DOCX,
5561
+ // XLSX, PPTX, images) it sends the BYTES as base64 and the extraction happens
5562
+ // here, through the same `read_extract` the agent uses for a file in the project
5563
+ // folder — so a refusal reaches the turn as a refusal instead of as mojibake.
5564
+ // Previously every file was read with `File.text()` client-side, which is how a
5565
+ // PDF arrived as `%PDF-1.4 …` with nothing indicating extraction had failed
5566
+ // (TOOL_TRUTHFULNESS_TRACKER.md findings #1/#7 and P2).
5567
+ const { hydrateAttachments } = await import('./attachment-extract.js');
5568
+ const attachments = await hydrateAttachments(body?.attachments);
5459
5569
  // P3 — an attached project's bounded snapshot rides into the turn as
5460
5570
  // `[Project context]`, so "assess THIS project" works without the user
5461
5571
  // describing the codebase. Cache misses rebuild automatically.
@@ -5500,7 +5610,16 @@ function handleRequest(req, res) {
5500
5610
  // Mark the failover log BEFORE the turn so a failure can report which
5501
5611
  // models were actually tried (same contract as the gateway).
5502
5612
  const attemptMark = markFailoverAttempts();
5503
- const result = await chatConsole.answer(sessionId, message, { provider, model, projectContext, projectPath, attachments });
5613
+ const result = await chatConsole.answer(sessionId, message, {
5614
+ provider,
5615
+ model,
5616
+ projectContext,
5617
+ projectPath,
5618
+ attachments,
5619
+ ...(worktree === undefined ? {} : { worktree }),
5620
+ ...(keepWorktree === undefined ? {} : { keepWorktree }),
5621
+ ...(resume === undefined ? {} : { resume }),
5622
+ });
5504
5623
  // The response is written below — remove the disconnect listener so a
5505
5624
  // post-completion close can never touch the console again.
5506
5625
  res.off('close', onResClose);
@@ -5521,7 +5640,12 @@ function handleRequest(req, res) {
5521
5640
  // retrying on its own — a manual re-send on top of the queued one would
5522
5641
  // run the same ask twice.
5523
5642
  let retryQueued = false;
5524
- if (result.generationFailed === true) {
5643
+ // WS5 (#27) — a REFUSED turn is failed but not retryable: the turn declined
5644
+ // to run (isolation was asked for and could not be made), and the answer is
5645
+ // the reason, already in `content`. The retry machinery below would replace
5646
+ // that reason with a "keep trying" offer for a request that cannot succeed,
5647
+ // and would queue a background re-run of the very ask that refused.
5648
+ if (result.generationFailed === true && result.refused !== true) {
5525
5649
  const report = chatRetryBroker.onFailure(sessionId, message, attemptMark);
5526
5650
  if (report) {
5527
5651
  content = content.trim() ? `${content}\n\n${report}` : report;
@@ -5542,6 +5666,26 @@ function handleRequest(req, res) {
5542
5666
  followups: result.followups ?? [],
5543
5667
  provider: result.provider ?? null,
5544
5668
  model: result.model ?? null,
5669
+ // WS1 — the findings this turn recorded, with the gate's verdicts, so
5670
+ // a dashboard client reads the same wire form the CLI, the gateway and
5671
+ // the subagent report (the GUI card is a rendering decision; the FACT
5672
+ // travels here rather than being dropped at the HTTP boundary).
5673
+ findings: result.findings ?? [],
5674
+ // WS5 — the isolation this turn ACTUALLY had, as the console reported it
5675
+ // (absent when the turn was not isolated), never re-derived from the flags
5676
+ // this request sent: a client that asked for isolation and got a refusal
5677
+ // must be able to see the difference, and the refusal is the turn's own
5678
+ // content. The diff arrives with it — `diff.payload` is the same
5679
+ // `{files, summary}` shape the `git:diff` event and the diff card already
5680
+ // use, so the GUI renders one card for both.
5681
+ ...(result.worktree ? { worktree: result.worktree } : {}),
5682
+ // WS5 — what a resume replayed. Sent for the same reason: a deployment
5683
+ // that sets `NUVIRA_RESUME` gets resumed turns, and a reader who is never
5684
+ // told cannot tell a replayed turn from a fresh one.
5685
+ ...(result.resume ? { resume: result.resume } : {}),
5686
+ // WS5 — whether the turn declined to run, so the client labels the failure
5687
+ // as the refusal it is instead of offering a Retry that cannot help.
5688
+ refused: result.refused === true,
5545
5689
  generationFailed: result.generationFailed === true,
5546
5690
  retryQueued,
5547
5691
  });
@@ -5650,6 +5794,89 @@ function handleRequest(req, res) {
5650
5794
  })();
5651
5795
  return;
5652
5796
  }
5797
+ // GET /api/chat/:sessionId/support-bundle — the debug logs THIS conversation
5798
+ // wrote, plus the conversation and a manifest, as one downloadable ZIP.
5799
+ //
5800
+ // WS2 (#24) taught every surface to write an attachable log; a log the user
5801
+ // cannot FIND is only half an artifact, and `~/.nuvira/debug-logs/` is exactly
5802
+ // the kind of path nobody goes and greps while filing a bug. So the chat the
5803
+ // user is already looking at becomes the way in.
5804
+ //
5805
+ // Selected by the log's OWN `# session:` header — never by recency, which with
5806
+ // a second tab open is somebody else's conversation. And when there is no log
5807
+ // the endpoint REFUSES rather than handing over a bundle without the one thing
5808
+ // a bug report needs, saying which step is missing instead.
5809
+ const chatBundleMatch = /^\/api\/chat\/([^/]+)\/support-bundle$/.exec(pathname);
5810
+ if (chatBundleMatch && req.method === 'GET') {
5811
+ void (async () => {
5812
+ // The `?token=` fallback as well as the header, for the same reason the
5813
+ // events stream has one: this is a plain GET that a browser or curl can be
5814
+ // handed, so it must not depend on a JS fetch that sets headers.
5815
+ const token = bearerToken(req) ?? new URL(req.url ?? '/', 'http://localhost').searchParams.get('token');
5816
+ const admin = adminSessions.validate(token);
5817
+ if (!admin) {
5818
+ writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
5819
+ return;
5820
+ }
5821
+ if (!roleCan(admin.role, 'routing.operate')) {
5822
+ writeJson(res, 403, { ok: false, error: `Access denied — role '${admin.role}' cannot read a chat session.` });
5823
+ return;
5824
+ }
5825
+ const sessionId = decodeURIComponent(chatBundleMatch[1]);
5826
+ try {
5827
+ const logs = debugLogsForSession(sessionId);
5828
+ if (logs.length === 0) {
5829
+ // Two different nothings with two different fixes, so they are NOT
5830
+ // collapsed into one message that fits neither.
5831
+ const enabled = debugLoggingEnabled();
5832
+ writeJson(res, 200, {
5833
+ ok: false,
5834
+ reason: enabled ? 'no_logs' : 'logging_disabled',
5835
+ error: enabled
5836
+ ? 'No debug log for this conversation yet. Logging is on, so the next turn here writes one — send a message (a log is written when the turn ENDS, not while it runs), then download again.'
5837
+ : `Session debug logging is off in the dashboard process, so there is nothing to attach yet. Set NUVIRA_DEBUG_LOG=1, restart the dashboard, send a message, then download again. Logs land in ${debugLogDir()}.`,
5838
+ });
5839
+ return;
5840
+ }
5841
+ const now = new Date();
5842
+ const record = chatConsole.get(sessionId);
5843
+ const safeId = sessionId.replace(/[^\w.-]/g, '_').slice(0, 48) || 'session';
5844
+ const files = [];
5845
+ for (const log of logs) {
5846
+ // The log's own basename carries its surface and start time, so two
5847
+ // turns of one conversation cannot collide inside the archive.
5848
+ files.push({ name: basename(log.path).replace(/[^\w.-]/g, '_'), content: log.text });
5849
+ }
5850
+ if (record) {
5851
+ files.push({ name: 'conversation.txt', content: renderSupportTranscript(sessionId, record, now) });
5852
+ }
5853
+ files.unshift({
5854
+ name: 'manifest.txt',
5855
+ content: renderSupportManifest({
5856
+ sessionId,
5857
+ logs,
5858
+ files: ['manifest.txt', ...files.map((f) => f.name)],
5859
+ turns: record ? record.turns.length : null,
5860
+ generatedAt: now,
5861
+ }),
5862
+ });
5863
+ const zip = generateZip(files);
5864
+ res.writeHead(200, {
5865
+ 'Content-Type': 'application/zip',
5866
+ 'Content-Disposition': `attachment; filename="nuvira-support-${safeId}.zip"`,
5867
+ 'Content-Length': zip.length,
5868
+ });
5869
+ res.end(zip);
5870
+ }
5871
+ catch (err) {
5872
+ writeJson(res, 500, {
5873
+ ok: false,
5874
+ error: `Support bundle failed: ${err instanceof Error ? err.message : String(err)}`,
5875
+ });
5876
+ }
5877
+ })();
5878
+ return;
5879
+ }
5653
5880
  // GET /api/chat/:sessionId/events — SSE stream of the session's LIVE
5654
5881
  // progress (agent working steps) + status while a turn is in flight. The
5655
5882
  // client subscribes FIRST, then POSTs the message; tool-call lines stream
@@ -5726,6 +5953,13 @@ function handleRequest(req, res) {
5726
5953
  updatedAt: event.updatedAt,
5727
5954
  })}\n\n`);
5728
5955
  }
5956
+ else if (event.kind === 'finding') {
5957
+ // WS1 — a recorded finding: the claim, the outcome, the evidence and
5958
+ // the verdict the GATE computed. Rendered as its own card so a
5959
+ // CONFIRMED verdict and a PLAUSIBLE guess never read the same in the
5960
+ // thread — the whole point of the row.
5961
+ res.write(`event: finding\ndata: ${JSON.stringify({ finding: event.finding })}\n\n`);
5962
+ }
5729
5963
  else if (event.kind === 'status') {
5730
5964
  res.write(`event: status\ndata: ${JSON.stringify({ status: event.status })}\n\n`);
5731
5965
  }