@fastagent-sh/fastagent 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/README.md +9 -12
  2. package/dist/agent.d.ts +24 -37
  3. package/dist/agent.js +7 -15
  4. package/dist/atomic-write.d.ts +13 -17
  5. package/dist/atomic-write.js +18 -29
  6. package/dist/bind.d.ts +12 -22
  7. package/dist/bind.js +18 -27
  8. package/dist/channel.d.ts +11 -33
  9. package/dist/channels/agentcore-limits.d.ts +2 -13
  10. package/dist/channels/agentcore-limits.js +2 -13
  11. package/dist/channels/agentcore-protocol.d.ts +67 -58
  12. package/dist/channels/agentcore-protocol.js +23 -15
  13. package/dist/channels/agentcore-service.d.ts +19 -33
  14. package/dist/channels/agentcore-service.js +176 -59
  15. package/dist/channels/agentcore.d.ts +39 -33
  16. package/dist/channels/agentcore.js +90 -224
  17. package/dist/channels/body.d.ts +15 -2
  18. package/dist/channels/body.js +24 -2
  19. package/dist/channels/busy.d.ts +1 -21
  20. package/dist/channels/busy.js +2 -39
  21. package/dist/channels/control.d.ts +17 -62
  22. package/dist/channels/control.js +74 -182
  23. package/dist/channels/define-channel.d.ts +39 -0
  24. package/dist/channels/define-channel.js +9 -0
  25. package/dist/channels/discover.d.ts +10 -31
  26. package/dist/channels/discover.js +37 -31
  27. package/dist/channels/feishu/bootstrap-token.d.ts +1 -8
  28. package/dist/channels/feishu/bootstrap-token.js +7 -23
  29. package/dist/channels/feishu/card.d.ts +14 -28
  30. package/dist/channels/feishu/card.js +16 -30
  31. package/dist/channels/feishu/cloud.d.ts +1 -5
  32. package/dist/channels/feishu/context-buffer.d.ts +4 -23
  33. package/dist/channels/feishu/context-buffer.js +8 -31
  34. package/dist/channels/feishu/crypto.d.ts +10 -5
  35. package/dist/channels/feishu/crypto.js +12 -19
  36. package/dist/channels/feishu/feishu-api.d.ts +2 -1
  37. package/dist/channels/feishu/feishu-api.js +5 -4
  38. package/dist/channels/feishu/feishu.d.ts +4 -10
  39. package/dist/channels/feishu/feishu.js +113 -227
  40. package/dist/channels/feishu/invoke-turn.d.ts +5 -4
  41. package/dist/channels/feishu/invoke-turn.js +36 -54
  42. package/dist/channels/feishu/model.d.ts +4 -21
  43. package/dist/channels/feishu/model.js +1 -8
  44. package/dist/channels/feishu/normalize.d.ts +2 -10
  45. package/dist/channels/feishu/normalize.js +7 -42
  46. package/dist/channels/feishu/parse.d.ts +9 -29
  47. package/dist/channels/feishu/parse.js +8 -26
  48. package/dist/channels/feishu/preview.d.ts +12 -14
  49. package/dist/channels/feishu/preview.js +108 -207
  50. package/dist/channels/feishu/register-app.d.ts +8 -23
  51. package/dist/channels/feishu/register-app.js +7 -20
  52. package/dist/channels/feishu/register-webhook.d.ts +2 -9
  53. package/dist/channels/feishu/register-webhook.js +9 -33
  54. package/dist/channels/feishu/scaffold/channel.ts +27 -19
  55. package/dist/channels/feishu/scaffold/channel.websocket.ts +31 -0
  56. package/dist/channels/feishu/setup-mode.d.ts +11 -36
  57. package/dist/channels/feishu/setup-mode.js +7 -26
  58. package/dist/channels/feishu/ws-ingress.d.ts +1 -2
  59. package/dist/channels/feishu/ws-ingress.js +6 -8
  60. package/dist/channels/http.d.ts +15 -15
  61. package/dist/channels/http.js +19 -9
  62. package/dist/channels/kit/attachment-path.d.ts +4 -5
  63. package/dist/channels/kit/attachment-path.js +10 -34
  64. package/dist/channels/kit/context-buffer.d.ts +14 -21
  65. package/dist/channels/kit/context-buffer.js +25 -38
  66. package/dist/channels/kit/delivery.d.ts +35 -0
  67. package/dist/channels/kit/delivery.js +129 -0
  68. package/dist/channels/kit/event-stream.d.ts +5 -0
  69. package/dist/channels/kit/event-stream.js +29 -0
  70. package/dist/channels/kit/invoke-turn-kit.d.ts +53 -26
  71. package/dist/channels/kit/invoke-turn-kit.js +89 -32
  72. package/dist/channels/kit/preview-kit.d.ts +18 -72
  73. package/dist/channels/kit/preview-kit.js +22 -88
  74. package/dist/channels/kit/signature.d.ts +3 -9
  75. package/dist/channels/kit/signature.js +3 -9
  76. package/dist/channels/kit/state.d.ts +1 -2
  77. package/dist/channels/kit/state.js +5 -14
  78. package/dist/channels/kit/stop-command.d.ts +1 -2
  79. package/dist/channels/kit/stop-command.js +6 -9
  80. package/dist/channels/kit/tasks.d.ts +1 -1
  81. package/dist/channels/kit/tasks.js +8 -21
  82. package/dist/channels/kit/text.d.ts +2 -16
  83. package/dist/channels/kit/text.js +23 -31
  84. package/dist/channels/kit/thread-participants.d.ts +4 -17
  85. package/dist/channels/kit/thread-participants.js +8 -55
  86. package/dist/channels/kit/transport.d.ts +26 -0
  87. package/dist/channels/kit/transport.js +20 -0
  88. package/dist/channels/kit/turn-queue.d.ts +7 -11
  89. package/dist/channels/kit/turn-queue.js +21 -39
  90. package/dist/channels/kit/turn-runner.d.ts +32 -18
  91. package/dist/channels/kit/turn-runner.js +98 -53
  92. package/dist/channels/kit/turn-store.d.ts +32 -32
  93. package/dist/channels/kit/turn-store.js +45 -88
  94. package/dist/channels/lark/lark.d.ts +1 -5
  95. package/dist/channels/lark/onboard.d.ts +3 -12
  96. package/dist/channels/lark/onboard.js +3 -13
  97. package/dist/channels/lark/scaffold/channel.ts +27 -19
  98. package/dist/channels/lark/scaffold/channel.websocket.ts +31 -0
  99. package/dist/channels/registration.d.ts +9 -35
  100. package/dist/channels/registration.js +6 -37
  101. package/dist/channels/secret.js +2 -5
  102. package/dist/channels/serve.d.ts +47 -44
  103. package/dist/channels/serve.js +165 -101
  104. package/dist/channels/slack/config-api.d.ts +4 -27
  105. package/dist/channels/slack/config-api.js +5 -34
  106. package/dist/channels/slack/context-buffer.d.ts +2 -3
  107. package/dist/channels/slack/context-buffer.js +5 -5
  108. package/dist/channels/slack/invoke-turn.d.ts +3 -1
  109. package/dist/channels/slack/invoke-turn.js +25 -34
  110. package/dist/channels/slack/manifest.js +1 -3
  111. package/dist/channels/slack/model.d.ts +1 -2
  112. package/dist/channels/slack/model.js +1 -1
  113. package/dist/channels/slack/onboard.d.ts +4 -3
  114. package/dist/channels/slack/onboard.js +8 -11
  115. package/dist/channels/slack/onboarding-state.d.ts +3 -5
  116. package/dist/channels/slack/onboarding-state.js +9 -6
  117. package/dist/channels/slack/parse.d.ts +4 -13
  118. package/dist/channels/slack/parse.js +7 -28
  119. package/dist/channels/slack/preview.d.ts +12 -2
  120. package/dist/channels/slack/preview.js +292 -269
  121. package/dist/channels/slack/reaction.d.ts +11 -3
  122. package/dist/channels/slack/reaction.js +19 -8
  123. package/dist/channels/slack/register-webhook.js +4 -7
  124. package/dist/channels/slack/scaffold/channel.ts +20 -13
  125. package/dist/channels/slack/scaffold/slack-send.ts +2 -2
  126. package/dist/channels/slack/setup-server.d.ts +1 -5
  127. package/dist/channels/slack/setup-server.js +1 -5
  128. package/dist/channels/slack/shared-api.d.ts +1 -4
  129. package/dist/channels/slack/shared-api.js +2 -13
  130. package/dist/channels/slack/slack-api.d.ts +2 -1
  131. package/dist/channels/slack/slack-api.js +6 -4
  132. package/dist/channels/slack/slack.d.ts +11 -14
  133. package/dist/channels/slack/slack.js +121 -122
  134. package/dist/channels/sse.d.ts +1 -1
  135. package/dist/channels/sse.js +1 -1
  136. package/dist/channels/telegram/context-buffer.d.ts +7 -22
  137. package/dist/channels/telegram/context-buffer.js +6 -23
  138. package/dist/channels/telegram/invoke-turn.d.ts +7 -7
  139. package/dist/channels/telegram/invoke-turn.js +24 -43
  140. package/dist/channels/telegram/parse.d.ts +24 -51
  141. package/dist/channels/telegram/parse.js +32 -84
  142. package/dist/channels/telegram/preview.d.ts +10 -1
  143. package/dist/channels/telegram/preview.js +79 -100
  144. package/dist/channels/telegram/register-webhook.js +5 -23
  145. package/dist/channels/telegram/scaffold/channel.ts +25 -18
  146. package/dist/channels/telegram/scaffold/telegram-send.ts +6 -4
  147. package/dist/channels/telegram/telegram-api.d.ts +4 -3
  148. package/dist/channels/telegram/telegram-api.js +9 -7
  149. package/dist/channels/telegram/telegram.d.ts +4 -18
  150. package/dist/channels/telegram/telegram.js +38 -94
  151. package/dist/channels/telegram/turn-store.d.ts +11 -14
  152. package/dist/channels/telegram/turn-store.js +8 -6
  153. package/dist/channels/wait-health.d.ts +4 -6
  154. package/dist/channels/wait-health.js +10 -14
  155. package/dist/cli/add-feishu.d.ts +2 -12
  156. package/dist/cli/add-feishu.js +24 -71
  157. package/dist/cli/add-slack.d.ts +5 -3
  158. package/dist/cli/add-slack.js +53 -76
  159. package/dist/cli/auth-view.d.ts +2 -16
  160. package/dist/cli/auth-view.js +2 -16
  161. package/dist/cli/commands/add.js +25 -43
  162. package/dist/cli/commands/chat.d.ts +0 -1
  163. package/dist/cli/commands/chat.js +5 -6
  164. package/dist/cli/commands/deploy/agentcore.js +60 -65
  165. package/dist/cli/commands/deploy/docker.js +50 -23
  166. package/dist/cli/commands/deploy/fly.js +23 -61
  167. package/dist/cli/commands/deploy/railway.js +23 -18
  168. package/dist/cli/commands/deploy/shared.d.ts +38 -57
  169. package/dist/cli/commands/deploy/shared.js +40 -59
  170. package/dist/cli/commands/deploy.d.ts +10 -27
  171. package/dist/cli/commands/deploy.js +38 -60
  172. package/dist/cli/commands/destroy.d.ts +4 -0
  173. package/dist/cli/commands/destroy.js +56 -0
  174. package/dist/cli/commands/dev.d.ts +2 -1
  175. package/dist/cli/commands/dev.js +20 -23
  176. package/dist/cli/commands/info.d.ts +0 -2
  177. package/dist/cli/commands/info.js +83 -49
  178. package/dist/cli/commands/init.d.ts +1 -2
  179. package/dist/cli/commands/init.js +16 -55
  180. package/dist/cli/commands/invoke.d.ts +0 -1
  181. package/dist/cli/commands/invoke.js +5 -7
  182. package/dist/cli/commands/login.d.ts +2 -1
  183. package/dist/cli/commands/login.js +33 -38
  184. package/dist/cli/commands/logs.js +3 -4
  185. package/dist/cli/commands/models.js +1 -5
  186. package/dist/cli/commands/routine-run.d.ts +6 -0
  187. package/dist/cli/commands/routine-run.js +47 -0
  188. package/dist/cli/commands/routine.d.ts +25 -0
  189. package/dist/cli/commands/routine.js +122 -0
  190. package/dist/cli/commands/start.d.ts +31 -3
  191. package/dist/cli/commands/start.js +131 -81
  192. package/dist/cli/commands/tool.js +26 -12
  193. package/dist/cli/fail.d.ts +13 -23
  194. package/dist/cli/fail.js +20 -23
  195. package/dist/cli/invoke-stream.d.ts +1 -8
  196. package/dist/cli/kernel.d.ts +6 -38
  197. package/dist/cli/kernel.js +14 -77
  198. package/dist/cli/models-view.d.ts +1 -9
  199. package/dist/cli/models-view.js +11 -22
  200. package/dist/cli/program.d.ts +5 -6
  201. package/dist/cli/program.js +120 -157
  202. package/dist/cli/serve.d.ts +57 -41
  203. package/dist/cli/serve.js +94 -121
  204. package/dist/cli/shared.d.ts +15 -61
  205. package/dist/cli/shared.js +55 -181
  206. package/dist/cli.js +1 -8
  207. package/dist/collect.d.ts +6 -0
  208. package/dist/collect.js +6 -0
  209. package/dist/core.d.ts +4 -1
  210. package/dist/core.js +9 -7
  211. package/dist/declared-secrets.d.ts +55 -0
  212. package/dist/declared-secrets.js +88 -0
  213. package/dist/deploy/agentcore/aws-cli.d.ts +91 -0
  214. package/dist/deploy/agentcore/aws-cli.js +64 -0
  215. package/dist/deploy/agentcore/destroy.d.ts +51 -0
  216. package/dist/deploy/agentcore/destroy.js +273 -0
  217. package/dist/deploy/agentcore/forwarder.js +28 -79
  218. package/dist/deploy/agentcore/logs.d.ts +2 -18
  219. package/dist/deploy/agentcore/logs.js +27 -51
  220. package/dist/deploy/agentcore/plan.d.ts +85 -105
  221. package/dist/deploy/agentcore/plan.js +152 -314
  222. package/dist/deploy/agentcore/run.d.ts +28 -28
  223. package/dist/deploy/agentcore/run.js +227 -306
  224. package/dist/deploy/agentcore/zip.d.ts +2 -15
  225. package/dist/deploy/agentcore/zip.js +3 -17
  226. package/dist/deploy/build-context.d.ts +21 -0
  227. package/dist/deploy/build-context.js +137 -0
  228. package/dist/deploy/channel-ingress.d.ts +26 -39
  229. package/dist/deploy/channel-ingress.js +57 -28
  230. package/dist/deploy/container.d.ts +20 -34
  231. package/dist/deploy/container.js +49 -100
  232. package/dist/deploy/docker/plan.d.ts +12 -11
  233. package/dist/deploy/docker/plan.js +43 -24
  234. package/dist/deploy/docker/run.d.ts +22 -25
  235. package/dist/deploy/docker/run.js +39 -37
  236. package/dist/deploy/fly/plan.d.ts +15 -44
  237. package/dist/deploy/fly/plan.js +41 -73
  238. package/dist/deploy/fly/run.d.ts +16 -51
  239. package/dist/deploy/fly/run.js +42 -95
  240. package/dist/deploy/hosts.d.ts +24 -3
  241. package/dist/deploy/hosts.js +24 -3
  242. package/dist/deploy/preflight.d.ts +47 -41
  243. package/dist/deploy/preflight.js +282 -383
  244. package/dist/deploy/railway/plan.d.ts +16 -42
  245. package/dist/deploy/railway/plan.js +42 -60
  246. package/dist/deploy/railway/run.d.ts +30 -68
  247. package/dist/deploy/railway/run.js +86 -100
  248. package/dist/deploy/registration-gate.d.ts +6 -13
  249. package/dist/deploy/residency.d.ts +37 -0
  250. package/dist/deploy/residency.js +24 -0
  251. package/dist/deploy/runner.d.ts +10 -9
  252. package/dist/deploy/runner.js +7 -18
  253. package/dist/deploy/secrets.d.ts +40 -41
  254. package/dist/deploy/secrets.js +117 -103
  255. package/dist/deploy/workspace.d.ts +50 -0
  256. package/dist/deploy/workspace.js +197 -0
  257. package/dist/dev-supervisor.d.ts +1 -9
  258. package/dist/dev-supervisor.js +21 -64
  259. package/dist/effect-port.d.ts +50 -0
  260. package/dist/effect-port.js +77 -0
  261. package/dist/engines/pi/agent-session-factory.d.ts +50 -69
  262. package/dist/engines/pi/agent-session-factory.js +249 -146
  263. package/dist/engines/pi/auth.d.ts +15 -11
  264. package/dist/engines/pi/auth.js +96 -99
  265. package/dist/engines/pi/chat.d.ts +1 -5
  266. package/dist/engines/pi/chat.js +2 -14
  267. package/dist/engines/pi/config.d.ts +53 -51
  268. package/dist/engines/pi/config.js +83 -92
  269. package/dist/engines/pi/create.d.ts +60 -75
  270. package/dist/engines/pi/create.js +108 -141
  271. package/dist/engines/pi/definition.d.ts +14 -58
  272. package/dist/engines/pi/definition.js +21 -85
  273. package/dist/engines/pi/invoke-session.d.ts +5 -25
  274. package/dist/engines/pi/invoke-session.js +209 -244
  275. package/dist/engines/pi/login.d.ts +95 -35
  276. package/dist/engines/pi/login.js +259 -107
  277. package/dist/engines/pi/machine.d.ts +31 -0
  278. package/dist/engines/pi/machine.js +106 -0
  279. package/dist/engines/pi/models.d.ts +70 -89
  280. package/dist/engines/pi/models.js +188 -81
  281. package/dist/engines/pi/open.d.ts +65 -53
  282. package/dist/engines/pi/open.js +129 -69
  283. package/dist/engines/pi/report.d.ts +3 -12
  284. package/dist/engines/pi/report.js +2 -16
  285. package/dist/engines/pi/search-tools.d.ts +1 -9
  286. package/dist/engines/pi/search-tools.js +26 -57
  287. package/dist/engines/pi/service.d.ts +2 -16
  288. package/dist/engines/pi/service.js +2 -16
  289. package/dist/engines/pi/session-builder.d.ts +5 -9
  290. package/dist/engines/pi/session-builder.js +44 -82
  291. package/dist/engines/pi/session-control.js +286 -269
  292. package/dist/engines/pi/session-effects.d.ts +14 -0
  293. package/dist/engines/pi/session-effects.js +30 -0
  294. package/dist/engines/pi/session-inheritance.d.ts +9 -18
  295. package/dist/engines/pi/session-inheritance.js +103 -160
  296. package/dist/engines/pi/session-markers.d.ts +31 -30
  297. package/dist/engines/pi/session-markers.js +26 -25
  298. package/dist/engines/pi/session-settings.d.ts +6 -22
  299. package/dist/engines/pi/session-settings.js +10 -21
  300. package/dist/engines/pi/session-store.d.ts +26 -92
  301. package/dist/engines/pi/session-store.js +96 -310
  302. package/dist/engines/pi/tool-context.d.ts +17 -45
  303. package/dist/engines/pi/tool-context.js +7 -26
  304. package/dist/engines/pi/tool.d.ts +45 -36
  305. package/dist/engines/pi/tool.js +43 -57
  306. package/dist/engines/pi/turn-kit.d.ts +14 -52
  307. package/dist/engines/pi/turn-kit.js +18 -67
  308. package/dist/engines/pi/wake-tool.d.ts +2 -10
  309. package/dist/engines/pi/wake-tool.js +7 -27
  310. package/dist/env.d.ts +27 -28
  311. package/dist/env.js +45 -50
  312. package/dist/index.js +0 -2
  313. package/dist/lark.d.ts +1 -2
  314. package/dist/lark.js +1 -2
  315. package/dist/loader.d.ts +14 -55
  316. package/dist/loader.js +24 -43
  317. package/dist/log.d.ts +2 -12
  318. package/dist/log.js +3 -24
  319. package/dist/node.d.ts +2 -15
  320. package/dist/node.js +2 -18
  321. package/dist/observe.d.ts +2 -8
  322. package/dist/open-url.d.ts +1 -1
  323. package/dist/open-url.js +1 -1
  324. package/dist/paths.d.ts +70 -134
  325. package/dist/paths.js +165 -232
  326. package/dist/pi.d.ts +4 -6
  327. package/dist/pi.js +3 -3
  328. package/dist/proxy.d.ts +16 -6
  329. package/dist/proxy.js +52 -16
  330. package/dist/runtime.d.ts +18 -12
  331. package/dist/runtime.js +18 -11
  332. package/dist/scaffold/add-channel.d.ts +14 -31
  333. package/dist/scaffold/add-channel.js +48 -112
  334. package/dist/scaffold/init.d.ts +9 -31
  335. package/dist/scaffold/init.js +45 -138
  336. package/dist/scaffold/templates/env.example +6 -4
  337. package/dist/scaffold/templates/fastagent.config.ts +36 -0
  338. package/dist/scaffold/templates.d.ts +3 -3
  339. package/dist/scaffold/templates.js +5 -8
  340. package/dist/scaffold/vendor-skill.d.ts +2 -5
  341. package/dist/scaffold/vendor-skill.js +19 -29
  342. package/dist/schedule/cron.d.ts +9 -5
  343. package/dist/schedule/cron.js +9 -11
  344. package/dist/schedule/discover.d.ts +12 -12
  345. package/dist/schedule/discover.js +43 -34
  346. package/dist/schedule/routine.d.ts +43 -0
  347. package/dist/schedule/routine.js +32 -0
  348. package/dist/schedule/run.d.ts +55 -0
  349. package/dist/schedule/run.js +146 -0
  350. package/dist/schedule/scheduler.d.ts +44 -55
  351. package/dist/schedule/scheduler.js +291 -265
  352. package/dist/schedule/state.d.ts +105 -10
  353. package/dist/schedule/state.js +293 -19
  354. package/dist/schedule/wake-alarm.d.ts +10 -23
  355. package/dist/schedule/wake-alarm.js +91 -121
  356. package/dist/schedule/wakeups.d.ts +23 -39
  357. package/dist/schedule/wakeups.js +33 -75
  358. package/dist/secrets-gate.d.ts +32 -0
  359. package/dist/secrets-gate.js +33 -0
  360. package/dist/service.d.ts +137 -98
  361. package/dist/service.js +250 -252
  362. package/dist/session-remote.d.ts +33 -44
  363. package/dist/session-remote.js +203 -192
  364. package/dist/session.d.ts +153 -228
  365. package/dist/session.js +33 -55
  366. package/dist/tunnel.d.ts +8 -36
  367. package/dist/tunnel.js +24 -65
  368. package/dist/version.d.ts +2 -2
  369. package/dist/version.js +2 -2
  370. package/package.json +10 -16
  371. package/dist/channels/agentcore-state.d.ts +0 -77
  372. package/dist/channels/agentcore-state.js +0 -276
  373. package/dist/channels/github/github.d.ts +0 -31
  374. package/dist/channels/github/github.js +0 -89
  375. package/dist/channels/github/scaffold/channel.ts +0 -25
  376. package/dist/cli/commands/attach.d.ts +0 -108
  377. package/dist/cli/commands/attach.js +0 -637
  378. package/dist/cli/commands/fire.d.ts +0 -7
  379. package/dist/cli/commands/fire.js +0 -38
  380. package/dist/cli/commands/schedule.d.ts +0 -12
  381. package/dist/cli/commands/schedule.js +0 -87
  382. package/dist/github.d.ts +0 -3
  383. package/dist/github.js +0 -2
  384. package/dist/scaffold/templates/fastagent.config.mjs +0 -23
  385. package/dist/schedule/audit.d.ts +0 -18
  386. package/dist/schedule/audit.js +0 -57
  387. package/dist/schedule/schedule.d.ts +0 -35
  388. package/dist/schedule/schedule.js +0 -23
@@ -1,5 +1,5 @@
1
1
  import { log } from "../../log.js";
2
- import { DEFAULT_BUSY_RETRY, attachedFilesManifest, attributedFileName, backgroundImagesManifest, missingAttachmentsNote, streamTurnWithBusyRetry, } from "../kit/invoke-turn-kit.js";
2
+ import { DEFAULT_BUSY_RETRY, attachedFilesManifest, attributedFileName, backgroundImagesManifest, loadBackground, missingAttachmentsNote, turnStream, } from "../kit/invoke-turn-kit.js";
3
3
  import { BUFFER_ATTACH_MAX } from "../kit/context-buffer.js";
4
4
  import { parseContent } from "./parse.js";
5
5
  import { REFERENT_MAX_CODE_POINTS, truncateCodePointPrefix } from "../kit/text.js";
@@ -41,9 +41,8 @@ function fetchedSenderLabel(sender, appId) {
41
41
  * is what makes the walk bounded by STRUCTURE rather than by a level count someone picked.
42
42
  *
43
43
  * This is pointer resolution, not history. Session memory — what this place already knows — is a
44
- * different track (design/participant-model.md §8): a one-hop version of this walk was removed once
45
- * for trying to be that substitute; it returns doing only the pointer's job, which is also why it
46
- * walks through ANY author's message — the chain is the platform's structure, not a conversation the
44
+ * different track (design/participant-model.md §8), so this walk does only the pointer's job, which is also
45
+ * why it walks through ANY author's message — the chain is the platform's structure, not a conversation the
47
46
  * agent took part in. The repetition this implies (an established session re-reads chain text it may
48
47
  * already hold, each reply turn) is accepted deliberately and bounded: ancestors are CONTEXT, not
49
48
  * the ask, so their text shares ONE further `REFERENT_MAX_CODE_POINTS` budget across the whole chain
@@ -201,40 +200,25 @@ async function resolveTurnInputs(t, attachments) {
201
200
  const mergedFiles = capMerge(chain.files, attachments.buffered.files, primaryFiles);
202
201
  const bufferedImages = mergedImages.kept;
203
202
  const bufferedFiles = mergedFiles.kept;
204
- const backgroundImages = [];
205
- const backgroundFiles = [];
206
- let lost = 0;
207
- const imageResults = await Promise.allSettled(bufferedImages.map(async (ref) => ({ ref, image: await t.api.fetchImage(ref.messageId, ref.key) })));
208
- for (const result of imageResults) {
209
- if (result.status === "fulfilled")
210
- backgroundImages.push(result.value);
211
- else {
212
- lost++;
213
- log.warn(`${t.label} could not load an earlier (buffered) image: ${String(result.reason)}`);
214
- }
215
- }
216
- const fileResults = await Promise.allSettled(bufferedFiles.map(async (ref) => ({
217
- ref,
218
- file: await t.api.fetchFile(ref.messageId, ref.key, ref.name ?? ref.key, t.chatId, t.filesDir),
219
- })));
220
- for (const result of fileResults) {
221
- if (result.status === "fulfilled")
222
- backgroundFiles.push(result.value);
223
- else {
224
- lost++;
225
- log.warn(`${t.label} could not load an earlier (buffered) attachment: ${String(result.reason)}`);
226
- }
227
- }
228
- const missingNote = missingAttachmentsNote(lost + attachments.buffered.skipped + mergedImages.dropped + mergedFiles.dropped);
229
- const backgroundImageManifest = backgroundImagesManifest(imageRefs.length, backgroundImages.map(({ ref }) => ref));
203
+ const backgroundImages = await loadBackground(bufferedImages, (ref) => t.api.fetchImage(ref.messageId, ref.key), {
204
+ label: t.label,
205
+ what: "image",
206
+ });
207
+ const backgroundFiles = await loadBackground(bufferedFiles, (ref) => t.api.fetchFile(ref.messageId, ref.key, ref.name ?? ref.key, t.chatId, t.filesDir), { label: t.label, what: "attachment" });
208
+ const missingNote = missingAttachmentsNote(backgroundImages.lost +
209
+ backgroundFiles.lost +
210
+ attachments.buffered.skipped +
211
+ mergedImages.dropped +
212
+ mergedFiles.dropped);
213
+ const backgroundImageManifest = backgroundImagesManifest(imageRefs.length, backgroundImages.loaded.map(({ ref }) => ref));
230
214
  const allFiles = [
231
215
  ...downloaded,
232
- ...backgroundFiles.map(({ file, ref }) => ({
233
- ...file,
234
- name: attributedFileName(file.name, ref.from, ref.messageId),
216
+ ...backgroundFiles.loaded.map(({ value, ref }) => ({
217
+ ...value,
218
+ name: attributedFileName(value.name, ref.from, ref.messageId),
235
219
  })),
236
220
  ];
237
- const allImages = [...imageRefs, ...backgroundImages.map(({ image }) => image)];
221
+ const allImages = [...imageRefs, ...backgroundImages.loaded.map(({ value }) => value)];
238
222
  return {
239
223
  images: allImages.length ? allImages : undefined,
240
224
  promptSuffix: `${referentBlock}${missingNote}${backgroundImageManifest}${attachedFilesManifest(allFiles)}`,
@@ -242,25 +226,23 @@ async function resolveTurnInputs(t, attachments) {
242
226
  };
243
227
  }
244
228
  /**
245
- * Run one turn: resolve its inputs, then stream agent.invoke with the shared busy-wait
246
- * (invoke-turn-kit — `onCompleted` is the durable-commit point; see streamTurnWithBusyRetry). A
247
- * primary-input failure surfaces as a `failed` event (never a silent drop).
229
+ * Run one turn: resolve its inputs, then ask the agent (invoke-turn-kit — a primary-input failure
230
+ * surfaces as a `failed` event, never a silent drop).
248
231
  */
249
- export async function* invokeFeishuTurn(agent, session, text, transport, attachments, onCompleted, busyRetry = DEFAULT_BUSY_RETRY) {
250
- let resolved;
251
- try {
252
- resolved = await resolveTurnInputs(transport, attachments);
253
- }
254
- catch (e) {
255
- yield { type: "failed", details: `could not load attachment: ${String(e)}`, retryable: true };
256
- return;
257
- }
258
- const prompt = { text: `${text}${resolved.promptSuffix}${REPLY_INSTRUCTION}`, images: resolved.images };
259
- // A thread turn names its lineage: parent place + the message ids that can locate the branch point
260
- // (the referent and its chain — nearest first). The engine reads them ONCE, when the thread's
261
- // session does not exist yet; on every later turn they ride along inertly.
262
- const scope = transport.parentSession === undefined
263
- ? { session }
264
- : { session, parentSession: transport.parentSession, branchHints: resolved.referentIds };
265
- yield* streamTurnWithBusyRetry(agent, scope, prompt, { label: transport.label, onCompleted, busyRetry });
232
+ export function feishuTurnStream(agent, session, text, transport, attachments, busyRetry = DEFAULT_BUSY_RETRY) {
233
+ return turnStream({
234
+ agent,
235
+ label: transport.label,
236
+ busyRetry,
237
+ resolve: () => resolveTurnInputs(transport, attachments),
238
+ turn: (resolved) => ({
239
+ // Lineage is resolved per turn; the engine reads it only when creating a new session.
240
+ scope: (transport.parentSession === undefined
241
+ ? { session }
242
+ : { session, parentSession: transport.parentSession, branchHints: resolved.referentIds }),
243
+ prompt: { text: `${text}${resolved.promptSuffix}${REPLY_INSTRUCTION}`, images: resolved.images },
244
+ }),
245
+ // A resource fetch that failed may simply succeed on the redelivery.
246
+ retryableLoadFailure: () => true,
247
+ });
266
248
  }
@@ -1,12 +1,5 @@
1
- /**
2
- * Canonical Feishu/Lark protocol and normalized-message models.
3
- *
4
- * Raw wire types stay at the webhook/policy boundary: authors' existing `route(event)` callbacks keep
5
- * receiving the platform event unchanged. The narrow normalized shape below owns only what currently
6
- * benefits from normalization: conversation-place identity, decoded content, mention presence, and
7
- * message-scoped resource locators. Do not pre-model unused transport metadata for a future ingress.
8
- */
9
- /** The v2 event envelope header. Feishu and Lark use the same wire shape. */
1
+ /** Canonical Feishu/Lark protocol and normalized-message models. */
2
+ /** The v2 event envelope header. */
10
3
  export interface FeishuEventHeader {
11
4
  event_id?: string;
12
5
  event_type?: string;
@@ -16,7 +9,7 @@ export interface FeishuEventHeader {
16
9
  tenant_key?: string;
17
10
  [k: string]: unknown;
18
11
  }
19
- /** One entry of a message's `mentions` array. `key` is the placeholder carried in text content. */
12
+ /** One entry of a message's `mentions` array. */
20
13
  export interface FeishuMention {
21
14
  key: string;
22
15
  id?: {
@@ -25,11 +18,10 @@ export interface FeishuMention {
25
18
  union_id?: string;
26
19
  };
27
20
  name?: string;
28
- mentioned_type?: string;
29
21
  tenant_key?: string;
30
22
  [k: string]: unknown;
31
23
  }
32
- /** A received `im.message.receive_v1` message. `content` is JSON encoded according to `message_type`. */
24
+ /** A received `im.message.receive_v1` message. */
33
25
  export interface FeishuMessage {
34
26
  message_id: string;
35
27
  root_id?: string;
@@ -42,11 +34,6 @@ export interface FeishuMessage {
42
34
  message_type: string;
43
35
  content: string;
44
36
  mentions?: FeishuMention[];
45
- user_agent?: string;
46
- lark_agent_context?: {
47
- active_chat_id?: string;
48
- [k: string]: unknown;
49
- };
50
37
  [k: string]: unknown;
51
38
  }
52
39
  export interface FeishuSender {
@@ -72,10 +59,6 @@ export interface FeishuRoute {
72
59
  text?: string;
73
60
  }
74
61
  export type FeishuResourceKind = "image" | "file" | "audio" | "video";
75
- /**
76
- * A resource locator. User-sent resources are scoped by BOTH their carrying message id and resource
77
- * key; a bare file_key/image_key is insufficient for the message-resource download API.
78
- */
79
62
  interface FeishuResourceRef {
80
63
  kind: FeishuResourceKind;
81
64
  messageId: string;
@@ -1,9 +1,2 @@
1
- /**
2
- * Canonical Feishu/Lark protocol and normalized-message models.
3
- *
4
- * Raw wire types stay at the webhook/policy boundary: authors' existing `route(event)` callbacks keep
5
- * receiving the platform event unchanged. The narrow normalized shape below owns only what currently
6
- * benefits from normalization: conversation-place identity, decoded content, mention presence, and
7
- * message-scoped resource locators. Do not pre-model unused transport metadata for a future ingress.
8
- */
1
+ /** Canonical Feishu/Lark protocol and normalized-message models. */
9
2
  export {};
@@ -1,8 +1,4 @@
1
- /**
2
- * Pure Feishu/Lark message normalization. The platform sends a stable event shell but encodes the
3
- * actual message body as a JSON string selected by `message_type`; this module is the one decoder and
4
- * converts resource keys into message-scoped locators before the turn engine sees them.
5
- */
1
+ /** Pure Feishu/Lark message normalization. */
6
2
  import type { FeishuMessage, FeishuMessageEvent, FeishuResourceKind, NormalizedFeishuMessage } from "./model.ts";
7
3
  interface DecodedFeishuResource {
8
4
  kind: FeishuResourceKind;
@@ -13,11 +9,7 @@ export interface DecodedFeishuContent {
13
9
  text: string;
14
10
  resources: DecodedFeishuResource[];
15
11
  }
16
- /**
17
- * Decode one JSON-string message body. Unknown or malformed external input degrades to a visible
18
- * marker rather than throwing, preserving the channel's existing fail-visible prompt behavior.
19
- */
12
+ /** Decode one JSON-string message body. */
20
13
  export declare function decodeFeishuContent(message: Pick<FeishuMessage, "message_type" | "content" | "mentions">): DecodedFeishuContent;
21
- /** Normalize one verified message event. Returns null only when its required identity is absent. */
22
14
  export declare function normalizeFeishuMessage(event: FeishuMessageEvent): NormalizedFeishuMessage | null;
23
15
  export {};
@@ -1,18 +1,6 @@
1
1
  /**
2
- * Render one paragraph of tagged nodes to a line, collecting any resource it carries INTO the sink
3
- * the caller supplies — or none, when the caller passes no sink.
4
- *
5
- * Shared by `post` and `interactive` because the platform hands both out in the same shape. Card-only
6
- * shapes are handled here rather than in a second walker: `note` nests its own `elements`, and the
7
- * widget tags (button/select/overflow/date_picker) carry their user-visible label in `text` or
8
- * `placeholder` — a card is read for what it SAYS, so a label is content and an unlabelled control is
9
- * nothing.
10
- *
11
- * The OPTIONAL sink is the whole reason this is a parameter rather than a return value: a card's
12
- * resources are documented as unfetchable (see the card branch), so that caller renders the same
13
- * `[image]` / `[video]` markers into the text while collecting nothing. The markers still tell the
14
- * model what is there; what must not happen is a key entering the turn's PRIMARY inputs, which load
15
- * fail-fast.
2
+ * Render one paragraph of tagged nodes to a line, collecting any resource it carries INTO the sink the caller supplies
3
+ * — or none, when the caller passes no sink.
16
4
  */
17
5
  function renderNodes(nodes, resources) {
18
6
  if (!Array.isArray(nodes))
@@ -70,10 +58,7 @@ function restoreMentions(text, mentions) {
70
58
  }
71
59
  return out;
72
60
  }
73
- /**
74
- * Decode one JSON-string message body. Unknown or malformed external input degrades to a visible
75
- * marker rather than throwing, preserving the channel's existing fail-visible prompt behavior.
76
- */
61
+ /** Decode one JSON-string message body. */
77
62
  export function decodeFeishuContent(message) {
78
63
  const rawType = typeof message.message_type === "string" ? message.message_type : "unknown";
79
64
  let content;
@@ -102,18 +87,7 @@ export function decodeFeishuContent(message) {
102
87
  }
103
88
  return { text: lines.join("\n"), resources };
104
89
  }
105
- // A CARD, as the platform hands it BACK. What we send is an entity reference
106
- // (`{type:"card",data:{card_id}}`, card.ts) whose text lives in cardkit — but a query API renders
107
- // the card down to `title` + `elements` (paragraphs of the same tagged nodes as `post`), so the
108
- // content is readable without a second remote call. This is the message type the agent's OWN
109
- // answers are, so the case that matters is a user following up on one: without this branch a
110
- // reply-referent that is the agent's own card decoded to the bare `[interactive message]` marker
111
- // and the model was told its own answer was unreadable (field-observed).
112
- //
113
- // BOTH spellings on purpose: the platform's own docs disagree with themselves — the field table
114
- // says `interactive` (what the receive EVENT carries) while the message-object example shows
115
- // `"msg_type": "card"`. Matching one would leave the other silently on the default branch, which
116
- // is exactly the symptom this fixes.
90
+ // A CARD, as the platform hands it BACK.
117
91
  case "interactive":
118
92
  case "card": {
119
93
  const lines = [];
@@ -122,21 +96,13 @@ export function decodeFeishuContent(message) {
122
96
  lines.push(title);
123
97
  const paragraphs = Array.isArray(content.elements) ? content.elements : [];
124
98
  for (const paragraph of paragraphs) {
125
- // NO resource sink, deliberately. The platform documents that a card's resources cannot be
126
- // fetched at all: `im/v1/messages/:id/resources/:key` answers 234043 ("Unsupported message
127
- // type") for a card message id, by stated limitation rather than by permission. Collecting a
128
- // key here would hand the turn a PRIMARY input that is guaranteed to fail its fail-fast load
129
- // — turning "the card reads as a marker" (the old behaviour) into "the whole turn errors",
130
- // which is strictly worse than the gap this branch exists to close. The text still renders
131
- // `[image]` / `[video]`, so the model knows what is there and that it does not have it.
132
- //
133
- // Tolerate both shapes: elements as paragraphs (array of arrays) and a flat element list.
99
+ // NO resource sink, deliberately.
134
100
  const line = Array.isArray(paragraph) ? renderNodes(paragraph) : renderNodes([paragraph]);
135
101
  if (line)
136
102
  lines.push(line);
137
103
  }
138
- // An unrenderable card (all controls, no labels) still says something by existing — keep the
139
- // marker rather than returning empty, which reads as "the message was blank".
104
+ // An unrenderable card (all controls, no labels) still says something by existing — keep the marker rather than
105
+ // returning empty, which reads as "the message was blank".
140
106
  return { text: lines.length > 0 ? lines.join("\n") : `[${rawType} message]`, resources };
141
107
  }
142
108
  case "image": {
@@ -176,7 +142,6 @@ export function decodeFeishuContent(message) {
176
142
  return { text: `[${rawType} message]`, resources };
177
143
  }
178
144
  }
179
- /** Normalize one verified message event. Returns null only when its required identity is absent. */
180
145
  export function normalizeFeishuMessage(event) {
181
146
  const message = event.message;
182
147
  if (!message || typeof message.message_id !== "string" || typeof message.chat_id !== "string")
@@ -1,14 +1,8 @@
1
- /**
2
- * Canonical Feishu protocol policy and prompt-envelope helpers — PURE. Raw event types remain public
3
- * for the existing `route(event)` authoring surface; JSON-string content decoding is delegated to the
4
- * normalized-message boundary in normalize.ts so the turn engine and compatibility wrappers share one
5
- * decoder.
6
- */
1
+ /** Canonical Feishu protocol policy and prompt-envelope helpers — PURE. */
7
2
  import type { FeishuCloudKind } from "./cloud.ts";
8
3
  import type { FeishuMention, FeishuMessage, FeishuMessageEvent, FeishuRoute, FeishuSender } from "./model.ts";
9
4
  export type { FeishuMention, FeishuMessage, FeishuMessageEvent, FeishuRoute, FeishuSender };
10
- /** A resource reduced to what a caller needs to fetch and name it — the kind and carrying message id
11
- * that {@link decodeFeishuContent} attaches are supplied by the caller's own context. */
5
+ /** A resource reduced to what a caller needs to fetch and name it. */
12
6
  interface FeishuAttachmentRef {
13
7
  key: string;
14
8
  name?: string;
@@ -19,27 +13,15 @@ export interface ParsedFeishuContent {
19
13
  fileRefs: FeishuAttachmentRef[];
20
14
  }
21
15
  /**
22
- * The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own
23
- * (the prompt envelope, and the quoted parent whose resources are carried by the PARENT message id).
24
- * `decodeFeishuContent` stays canonical: this only reshapes what it returns.
16
+ * The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own (the prompt
17
+ * envelope, and the quoted parent whose resources are carried by the PARENT message id).
25
18
  */
26
19
  export declare function parseContent(message: Pick<FeishuMessage, "message_type" | "content" | "mentions">): ParsedFeishuContent;
27
- /** A stable sender label for attribution. Display names require an additional contacts permission. */
20
+ /** A stable sender label for attribution. */
28
21
  export declare function senderLabel(sender: FeishuSender | undefined): string | undefined;
29
- /** Whichever id flavour the tenant populates. `sender_id` is a union and which members are filled is
30
- * app configuration, not an invariant — callers only ever compare these for distinctness. */
22
+ /** Whichever id flavour the tenant populates. */
31
23
  export declare function senderId(sender: FeishuSender | undefined): string | undefined;
32
- /**
33
- * The place a message lives (the chat, or a thread within it) — the session key (participant model §5),
34
- * and the key thread participation is recorded under, since that record is a claim about this session.
35
- *
36
- * Branded with the channel kind, like Slack's twin, because session ids share ONE namespace across
37
- * every channel in a deployment: without it a `feishu` and a `lark` chat carrying the same platform id
38
- * would answer into the same memory. The length bound is the FILENAME the id becomes (session-store.ts
39
- * `piSessionId` escapes every character outside `[A-Za-z0-9.-]` as `_XX` / `_uXXXX`, so each `:` costs
40
- * three), and the worst case here — brand + a 35-char chat id + a 36-char thread id — encodes to well
41
- * under 100 bytes against the filesystem's 255.
42
- */
24
+ /** The place a message lives (the chat, or a thread within it). */
43
25
  export declare function placeKey(kind: string, message: Pick<FeishuMessage, "chat_id" | "thread_id">): string;
44
26
  /** The canonical Feishu-branded prompt envelope. */
45
27
  export declare function feishuEnvelope(event: FeishuMessageEvent): string;
@@ -48,10 +30,8 @@ export declare function cloudEnvelope(event: FeishuMessageEvent, tag: FeishuClou
48
30
  /** Whether the parsed mention list contains this bot's app-scoped open_id. */
49
31
  export declare function mentionsBot(message: Pick<FeishuMessage, "mentions">, botOpenId: string | undefined): boolean;
50
32
  /**
51
- * Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only
52
- * when THIS bot is structurally mentioned. No bot identity means group routing fails closed. The
53
- * stateful channel wiring may additionally admit unmentioned messages in a thread it takes part in
54
- * (docs/design/participant-model.md §3).
33
+ * Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only when THIS bot is
34
+ * structurally mentioned.
55
35
  */
56
36
  export declare function defaultFeishuRoute(event: FeishuMessageEvent, options?: {
57
37
  botOpenId?: string;
@@ -1,8 +1,7 @@
1
1
  import { decodeFeishuContent } from "./normalize.js";
2
2
  /**
3
- * The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own
4
- * (the prompt envelope, and the quoted parent whose resources are carried by the PARENT message id).
5
- * `decodeFeishuContent` stays canonical: this only reshapes what it returns.
3
+ * The decoder projected onto flat per-kind arrays, for callers that resolve a message on their own (the prompt
4
+ * envelope, and the quoted parent whose resources are carried by the PARENT message id).
6
5
  */
7
6
  export function parseContent(message) {
8
7
  const decoded = decodeFeishuContent(message);
@@ -14,27 +13,16 @@ export function parseContent(message) {
14
13
  .map((resource) => ({ key: resource.key, name: resource.name })),
15
14
  };
16
15
  }
17
- /** A stable sender label for attribution. Display names require an additional contacts permission. */
16
+ /** A stable sender label for attribution. */
18
17
  export function senderLabel(sender) {
19
18
  const id = senderId(sender);
20
19
  return id ? `user ${id}` : undefined;
21
20
  }
22
- /** Whichever id flavour the tenant populates. `sender_id` is a union and which members are filled is
23
- * app configuration, not an invariant — callers only ever compare these for distinctness. */
21
+ /** Whichever id flavour the tenant populates. */
24
22
  export function senderId(sender) {
25
23
  return sender?.sender_id?.open_id ?? sender?.sender_id?.user_id ?? sender?.sender_id?.union_id;
26
24
  }
27
- /**
28
- * The place a message lives (the chat, or a thread within it) — the session key (participant model §5),
29
- * and the key thread participation is recorded under, since that record is a claim about this session.
30
- *
31
- * Branded with the channel kind, like Slack's twin, because session ids share ONE namespace across
32
- * every channel in a deployment: without it a `feishu` and a `lark` chat carrying the same platform id
33
- * would answer into the same memory. The length bound is the FILENAME the id becomes (session-store.ts
34
- * `piSessionId` escapes every character outside `[A-Za-z0-9.-]` as `_XX` / `_uXXXX`, so each `:` costs
35
- * three), and the worst case here — brand + a 35-char chat id + a 36-char thread id — encodes to well
36
- * under 100 bytes against the filesystem's 255.
37
- */
25
+ /** The place a message lives (the chat, or a thread within it). */
38
26
  export function placeKey(kind, message) {
39
27
  const chat = `${kind}:${message.chat_id}`;
40
28
  return message.thread_id ? `${chat}:${message.thread_id}` : chat;
@@ -53,11 +41,7 @@ export function cloudEnvelope(event, tag) {
53
41
  `chat ${message.chat_id} (${message.chat_type})`,
54
42
  message.thread_id ? `topic ${message.thread_id}` : undefined,
55
43
  from ? `from ${from}` : undefined,
56
- // The message's own id is LOAD-BEARING, not decoration: it is the only way this message's id
57
- // enters the session transcript, and session inheritance locates a thread's branch point by
58
- // searching the parent transcript for exactly these ids (scope.branchHints — session-inheritance.ts).
59
- // Remove it and every thread quietly inherits from the room's present instead of the branch
60
- // point. It also lets the model name what it is answering in a busy chat.
44
+ // The message's own id is LOAD-BEARING, not decoration.
61
45
  `msg ${message.message_id}`,
62
46
  ]
63
47
  .filter(Boolean)
@@ -73,10 +57,8 @@ export function mentionsBot(message, botOpenId) {
73
57
  return (message.mentions ?? []).some((mention) => mention.id?.open_id === botOpenId);
74
58
  }
75
59
  /**
76
- * Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only
77
- * when THIS bot is structurally mentioned. No bot identity means group routing fails closed. The
78
- * stateful channel wiring may additionally admit unmentioned messages in a thread it takes part in
79
- * (docs/design/participant-model.md §3).
60
+ * Default EXPLICIT-summon policy: ignore non-user senders, always answer p2p, and answer groups only when THIS bot is
61
+ * structurally mentioned.
80
62
  */
81
63
  export function defaultFeishuRoute(event, options) {
82
64
  const message = event.message;
@@ -1,11 +1,13 @@
1
1
  import type { AgentEvent } from "../../agent.ts";
2
+ import * as Effect from "effect/Effect";
3
+ import type * as Stream from "effect/Stream";
4
+ import { type PortFailure } from "../../effect-port.ts";
2
5
  import { type FeishuApi, type FeishuTarget } from "./feishu-api.ts";
3
6
  import { type ChannelFailure, defaultErrorMessage } from "../kit/preview-kit.ts";
4
7
  /** A terminal failure, as the channel hands it to `onError` — the shared channel shape. */
5
8
  export type FeishuFailure = ChannelFailure;
6
9
  export { defaultErrorMessage };
7
- /** A visible preview mounted into the chat. Exported only for the channel wiring: a queued turn mounts
8
- * one before execution, then hands the exact entity/message to {@link streamFeishuReply} for takeover. */
10
+ /** A visible preview mounted into the chat. */
9
11
  export type MountedFeishuPreview = {
10
12
  kind: "card";
11
13
  cardId: string;
@@ -15,20 +17,16 @@ export type MountedFeishuPreview = {
15
17
  messageId: string;
16
18
  };
17
19
  /**
18
- * Mount one preview message: preferably a streaming card entity (`initial` seeds the process element;
19
- * the answer element starts empty), with a static text message as the visible fallback. Queue feedback
20
- * and ordinary turn startup share this constructor so a queued card has exactly the same shape the
21
- * stream pump expects to take over later.
20
+ * Mount one preview message: preferably a streaming card entity (`initial` seeds the process element; the answer
21
+ * element starts empty), with a static text message as the visible fallback.
22
22
  */
23
23
  export declare function mountFeishuPreview(api: FeishuApi, target: FeishuTarget, initial: string, label?: string): Promise<MountedFeishuPreview>;
24
- /** Settle an already-mounted queue preview without starting an Agent stream (the poison/defer paths).
25
- * Card and text tiers both change in place; only a missing/failed preview sends a fresh message. */
24
+ /**
25
+ * Settle a preview without starting an Agent stream: a queue/poison/defer notice, or a recovered answer whose own
26
+ * preview died with the run that produced it (`undefined` — then it is one fresh message).
27
+ */
26
28
  export declare function settleFeishuPreview(api: FeishuApi, target: FeishuTarget, preview: MountedFeishuPreview | undefined, text: string): Promise<void>;
27
29
  /**
28
- * Consume one turn's event stream into a Feishu-compatible chat, live (see the module header for the preview
29
- * model). Preview updates are best-effort (logged once if they fail); the final write is authoritative
30
- * and surfaces a real failure (bad credentials, etc.). `initialPreview`, when present, is the queued
31
- * turn's already-mounted card/text message: the pump and terminal write mutate that same message rather
32
- * than recalling it and posting another reply.
30
+ * Consume one turn's event stream into a Feishu-compatible chat, live.
33
31
  */
34
- export declare function streamFeishuReply(events: AsyncIterable<AgentEvent>, api: FeishuApi, target: FeishuTarget, formatError: (failed: FeishuFailure) => string | undefined, initialPreview?: MountedFeishuPreview, label?: string): Promise<void>;
32
+ export declare function feishuReply(events: Stream.Stream<AgentEvent, PortFailure>, api: FeishuApi, target: FeishuTarget, formatError: (failed: FeishuFailure) => string | undefined, initialPreview?: MountedFeishuPreview, label?: string, onAnswered?: (answer: string) => void): Effect.Effect<void, PortFailure, import("effect/Scope").Scope>;