@fased/fased 0.1.45 → 0.1.47

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 (685) hide show
  1. package/dist/acp/client.js +2 -2
  2. package/dist/acp/control-plane/spawn.js +1 -1
  3. package/dist/acp/secret-file.js +2 -2
  4. package/dist/agents/acp-spawn-parent-stream.js +2 -2
  5. package/dist/agents/acp-spawn.js +3 -3
  6. package/dist/agents/agent-scope.js +2 -2
  7. package/dist/agents/apply-patch.js +8 -8
  8. package/dist/agents/auth-profiles/paths.js +2 -2
  9. package/dist/agents/auth-profiles/store.js +2 -2
  10. package/dist/agents/bash-tools.exec-approval-request.js +1 -1
  11. package/dist/agents/bash-tools.exec-host-node.js +1 -1
  12. package/dist/agents/bash-tools.exec-runtime.js +1 -1
  13. package/dist/agents/bash-tools.exec.js +1 -1
  14. package/dist/agents/bash-tools.shared.js +2 -2
  15. package/dist/agents/cli-credentials.js +4 -4
  16. package/dist/agents/defaults.js +1 -1
  17. package/dist/agents/docs-path.js +3 -3
  18. package/dist/agents/embedded-pi-mcp.js +4 -4
  19. package/dist/agents/fased-tools.js +4 -4
  20. package/dist/agents/identity-avatar.js +4 -4
  21. package/dist/agents/identity-file.js +2 -2
  22. package/dist/agents/pi-embedded-runner/compact.js +4 -4
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +5 -5
  24. package/dist/agents/pi-embedded-runner/run/images.js +1 -1
  25. package/dist/agents/pi-embedded-runner/run.js +2 -2
  26. package/dist/agents/pi-embedded-runner/system-prompt.js +1 -1
  27. package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +1 -1
  28. package/dist/agents/pi-embedded-subscribe.handlers.messages.js +1 -1
  29. package/dist/agents/pi-embedded-subscribe.js +2 -2
  30. package/dist/agents/pi-embedded-subscribe.raw-stream.js +3 -3
  31. package/dist/agents/pi-embedded-subscribe.tools.js +1 -1
  32. package/dist/agents/pi-extensions/compaction-safeguard.js +3 -3
  33. package/dist/agents/pi-model-discovery.js +6 -6
  34. package/dist/agents/pi-project-settings.js +3 -3
  35. package/dist/agents/pi-tools.js +2 -2
  36. package/dist/agents/pi-tools.read.js +1 -1
  37. package/dist/agents/sandbox/browser.js +2 -2
  38. package/dist/agents/sandbox/context.js +2 -2
  39. package/dist/agents/sandbox/docker.js +1 -1
  40. package/dist/agents/sandbox/fs-bridge.js +2 -2
  41. package/dist/agents/sandbox/manage.js +2 -2
  42. package/dist/agents/sandbox/prune.js +2 -2
  43. package/dist/agents/session-dirs.js +4 -4
  44. package/dist/agents/session-write-lock.js +13 -13
  45. package/dist/agents/shell-utils.js +5 -5
  46. package/dist/agents/skills/bundled-dir.js +4 -4
  47. package/dist/agents/skills/local-loader.js +6 -6
  48. package/dist/agents/skills/plugin-skills.js +2 -2
  49. package/dist/agents/skills/workspace.js +13 -13
  50. package/dist/agents/skills-install-download.js +7 -7
  51. package/dist/agents/skills-install-plan.js +2 -2
  52. package/dist/agents/skills-install.js +2 -2
  53. package/dist/agents/skills-status.js +2 -2
  54. package/dist/agents/subagent-announce-output.js +3 -3
  55. package/dist/agents/subagent-announce.js +6 -6
  56. package/dist/agents/subagent-announce.runtime.js +1 -1
  57. package/dist/agents/subagent-depth.js +2 -2
  58. package/dist/agents/subagent-registry.js +3 -3
  59. package/dist/agents/subagent-spawn.js +2 -2
  60. package/dist/agents/system-prompt-params.js +3 -3
  61. package/dist/agents/tool-images.js +1 -1
  62. package/dist/agents/tools/canvas-tool.js +2 -2
  63. package/dist/agents/tools/cron-tool.js +1 -1
  64. package/dist/agents/tools/diff-view-tool.js +1 -1
  65. package/dist/agents/tools/discord-actions-messaging.js +1 -1
  66. package/dist/agents/tools/gateway-tool.js +1 -1
  67. package/dist/agents/tools/gateway.js +1 -1
  68. package/dist/agents/tools/marketplace-offer-draft-tool.js +3 -3
  69. package/dist/agents/tools/message-tool.js +5 -5
  70. package/dist/agents/tools/mining-tool.js +1 -1
  71. package/dist/agents/tools/nodes-tool.js +1 -1
  72. package/dist/agents/tools/session-status-tool.js +3 -3
  73. package/dist/agents/tools/sessions-history-tool.js +1 -1
  74. package/dist/agents/tools/sessions-list-tool.js +1 -1
  75. package/dist/agents/tools/sessions-send-tool.a2a.js +1 -1
  76. package/dist/agents/tools/sessions-send-tool.js +1 -1
  77. package/dist/agents/tools/slack-actions.js +1 -1
  78. package/dist/agents/tools/subagents-tool.js +3 -3
  79. package/dist/agents/tools/telegram-actions.js +1 -1
  80. package/dist/agents/tools/tts-tool.js +1 -1
  81. package/dist/agents/tools/wallet-action-tool.js +4 -4
  82. package/dist/agents/tools/wallet-tool.js +7 -7
  83. package/dist/agents/tools/web-fetch.js +1 -1
  84. package/dist/agents/workspace.js +22 -22
  85. package/dist/auto-reply/chunk.js +1 -1
  86. package/dist/auto-reply/envelope.js +1 -1
  87. package/dist/auto-reply/reply/abort.js +2 -2
  88. package/dist/auto-reply/reply/agent-runner-execution.js +4 -4
  89. package/dist/auto-reply/reply/agent-runner-memory.js +2 -2
  90. package/dist/auto-reply/reply/agent-runner-payloads.js +1 -1
  91. package/dist/auto-reply/reply/agent-runner.js +8 -8
  92. package/dist/auto-reply/reply/bash-command.js +1 -1
  93. package/dist/auto-reply/reply/commands-acp/diagnostics.js +1 -1
  94. package/dist/auto-reply/reply/commands-acp/lifecycle.js +2 -2
  95. package/dist/auto-reply/reply/commands-acp/shared.js +1 -1
  96. package/dist/auto-reply/reply/commands-compact.js +2 -2
  97. package/dist/auto-reply/reply/commands-control.js +1 -1
  98. package/dist/auto-reply/reply/commands-export-session.js +7 -7
  99. package/dist/auto-reply/reply/commands-models.js +1 -1
  100. package/dist/auto-reply/reply/commands-session-abort.js +2 -2
  101. package/dist/auto-reply/reply/commands-status.js +2 -2
  102. package/dist/auto-reply/reply/commands-subagents/action-focus.js +1 -1
  103. package/dist/auto-reply/reply/commands-subagents/action-kill.js +2 -2
  104. package/dist/auto-reply/reply/commands-subagents/action-send.js +1 -1
  105. package/dist/auto-reply/reply/commands-subagents/shared.js +1 -1
  106. package/dist/auto-reply/reply/dispatch-acp.js +5 -5
  107. package/dist/auto-reply/reply/dispatch-from-config.js +2 -2
  108. package/dist/auto-reply/reply/followup-runner.js +4 -4
  109. package/dist/auto-reply/reply/get-reply-directives.js +2 -2
  110. package/dist/auto-reply/reply/get-reply-inline-actions.js +2 -2
  111. package/dist/auto-reply/reply/get-reply-run.js +4 -4
  112. package/dist/auto-reply/reply/model-selection.js +2 -2
  113. package/dist/auto-reply/reply/post-compaction-audit.js +3 -3
  114. package/dist/auto-reply/reply/post-compaction-context.js +3 -3
  115. package/dist/auto-reply/reply/queue/cleanup.js +1 -1
  116. package/dist/auto-reply/reply/reply-delivery.js +1 -1
  117. package/dist/auto-reply/reply/reply-directives.js +1 -1
  118. package/dist/auto-reply/reply/route-reply.js +1 -1
  119. package/dist/auto-reply/reply/session-reset-model.js +1 -1
  120. package/dist/auto-reply/reply/session-updates.js +1 -1
  121. package/dist/auto-reply/reply/session.js +3 -3
  122. package/dist/auto-reply/reply/streaming-directives.js +1 -1
  123. package/dist/auto-reply/reply.js +1 -1
  124. package/dist/auto-reply/skill-commands.js +3 -3
  125. package/dist/auto-reply/status.js +9 -9
  126. package/dist/brand.js +1 -1
  127. package/dist/browser/chrome.executables.js +3 -3
  128. package/dist/browser/chrome.js +3 -3
  129. package/dist/browser/chrome.profile-decoration.js +6 -6
  130. package/dist/browser/profiles-service.js +2 -2
  131. package/dist/browser/server-context.js +2 -2
  132. package/dist/browser/trash.js +4 -4
  133. package/dist/build-info.json +3 -3
  134. package/dist/bundled/session-memory/handler.js +1 -1
  135. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  136. package/dist/canvas-host/a2ui.js +1 -1
  137. package/dist/canvas-host/server.js +5 -5
  138. package/dist/capabilities/catalog.js +3 -3
  139. package/dist/channel-web.js +1 -1
  140. package/dist/channels/plugins/actions/signal.js +1 -1
  141. package/dist/channels/plugins/actions/telegram.js +2 -2
  142. package/dist/channels/plugins/catalog.js +3 -3
  143. package/dist/channels/plugins/onboarding/discord.js +1 -1
  144. package/dist/channels/plugins/onboarding/imessage.js +1 -1
  145. package/dist/cli/browser-cli-extension.js +7 -7
  146. package/dist/cli/command-format.js +2 -2
  147. package/dist/cli/components-cli.js +1 -1
  148. package/dist/cli/cron-cli/register.cron-simple.js +2 -2
  149. package/dist/cli/cron-cli/shared.js +1 -1
  150. package/dist/cli/daemon-cli/install.js +2 -2
  151. package/dist/cli/daemon-cli/status.gather.js +1 -1
  152. package/dist/cli/daemon-cli/status.print.js +1 -1
  153. package/dist/cli/directory-cli.js +1 -1
  154. package/dist/cli/dns-cli.js +9 -9
  155. package/dist/cli/exec-approvals-cli.js +2 -2
  156. package/dist/cli/federation-cli.js +3 -3
  157. package/dist/cli/gateway-cli/dev.js +5 -5
  158. package/dist/cli/gateway-cli/register.js +3 -3
  159. package/dist/cli/gateway-cli/run.js +3 -3
  160. package/dist/cli/hooks-cli.js +6 -6
  161. package/dist/cli/memory-cli.js +7 -7
  162. package/dist/cli/node-cli/daemon.js +1 -1
  163. package/dist/cli/nodes-cli/register.status.js +1 -1
  164. package/dist/cli/nodes-cli/rpc.js +1 -1
  165. package/dist/cli/nodes-media-utils.js +2 -2
  166. package/dist/cli/plugins-cli.js +3 -3
  167. package/dist/cli/program/message/helpers.js +1 -1
  168. package/dist/cli/program/register.agent.js +1 -1
  169. package/dist/cli/program/register.status-health-sessions.js +1 -1
  170. package/dist/cli/program/register.wallet.js +1 -1
  171. package/dist/cli/run-main.js +1 -1
  172. package/dist/cli/secrets-cli.js +3 -3
  173. package/dist/cli/tui-cli.js +1 -1
  174. package/dist/cli/update-cli/status.js +1 -1
  175. package/dist/cli/update-cli/update-command.js +3 -3
  176. package/dist/cli/windows-argv.js +2 -2
  177. package/dist/commands/agent/attempt.js +1 -1
  178. package/dist/commands/agent/delivery.js +2 -2
  179. package/dist/commands/agent.js +9 -9
  180. package/dist/commands/agents.commands.add.js +1 -1
  181. package/dist/commands/agents.commands.delete.js +1 -1
  182. package/dist/commands/channels/add.js +2 -2
  183. package/dist/commands/channels/list.js +2 -2
  184. package/dist/commands/channels/status.js +1 -1
  185. package/dist/commands/configure.daemon.js +1 -1
  186. package/dist/commands/configure.wizard.js +1 -1
  187. package/dist/commands/dashboard-link.js +3 -3
  188. package/dist/commands/dashboard.js +2 -2
  189. package/dist/commands/docs.js +1 -1
  190. package/dist/commands/doctor-config-flow.js +2 -2
  191. package/dist/commands/doctor-format.js +1 -1
  192. package/dist/commands/doctor-gateway-daemon-flow.js +5 -5
  193. package/dist/commands/doctor-gateway-services.js +2 -2
  194. package/dist/commands/doctor-install.js +5 -5
  195. package/dist/commands/doctor-memory-search.js +2 -2
  196. package/dist/commands/doctor-platform-notes.js +2 -2
  197. package/dist/commands/doctor-sandbox.js +2 -2
  198. package/dist/commands/doctor-security.js +1 -1
  199. package/dist/commands/doctor-state-integrity.js +23 -23
  200. package/dist/commands/doctor-workspace.js +3 -3
  201. package/dist/commands/doctor.js +4 -4
  202. package/dist/commands/gateway-status.js +2 -2
  203. package/dist/commands/hosted-dashboard-probe.js +2 -2
  204. package/dist/commands/managed-up.js +2 -2
  205. package/dist/commands/message.js +1 -1
  206. package/dist/commands/models/list.probe.js +3 -3
  207. package/dist/commands/models/list.status-command.js +3 -3
  208. package/dist/commands/onboard-auth.credentials.js +3 -3
  209. package/dist/commands/onboard-channels.js +1 -1
  210. package/dist/commands/onboard-helpers.js +1 -1
  211. package/dist/commands/onboard-non-interactive/local/daemon-install.js +2 -2
  212. package/dist/commands/onboard-non-interactive/local.js +1 -1
  213. package/dist/commands/onboard-skills.js +1 -1
  214. package/dist/commands/onboarding/plugin-install.js +3 -3
  215. package/dist/commands/openai-model-default.js +1 -1
  216. package/dist/commands/sessions-cleanup.js +2 -2
  217. package/dist/commands/signal-install.js +6 -6
  218. package/dist/commands/status-all/channels.js +3 -3
  219. package/dist/commands/status-all/diagnosis.js +1 -1
  220. package/dist/commands/status-all/format.js +1 -1
  221. package/dist/commands/status-all.js +8 -8
  222. package/dist/commands/status.command.js +4 -4
  223. package/dist/commands/status.gateway-probe.js +1 -1
  224. package/dist/commands/status.scan.js +3 -3
  225. package/dist/commands/status.summary.js +1 -1
  226. package/dist/commands/wallet.js +51 -50
  227. package/dist/config/cache-utils.js +2 -2
  228. package/dist/config/includes.js +5 -5
  229. package/dist/config/io.js +2 -2
  230. package/dist/config/paths.js +3 -3
  231. package/dist/config/sat-runtime-ids.js +3 -3
  232. package/dist/config/sessions/disk-budget.js +6 -6
  233. package/dist/config/sessions/paths.js +2 -2
  234. package/dist/config/sessions/store.js +17 -17
  235. package/dist/config/sessions/transcript.js +4 -4
  236. package/dist/config/talk.js +2 -2
  237. package/dist/control-ui/assets/{app-JBrTSsNu.js → app-CHqTx3P_.js} +4 -4
  238. package/dist/control-ui/assets/chat-model-ref-BbrdMKjQ.js +2 -0
  239. package/dist/control-ui/assets/{index-H-2DWAnH.js → index-CFHfNlLv.js} +3 -3
  240. package/dist/control-ui/assets/{providers-C9hLw4o6.js → providers-DqFL6WrJ.js} +2 -2
  241. package/dist/control-ui/index.html +1 -1
  242. package/dist/cron/isolated-agent/delivery-dispatch.js +2 -2
  243. package/dist/cron/isolated-agent/delivery-target.js +1 -1
  244. package/dist/cron/isolated-agent/run.js +5 -5
  245. package/dist/cron/service/store.js +2 -2
  246. package/dist/cron/store.js +6 -6
  247. package/dist/daemon/service-audit.js +2 -2
  248. package/dist/daemon/systemd-system.js +10 -10
  249. package/dist/discord/monitor/agent-components.js +9 -9
  250. package/dist/discord/monitor/gateway-plugin.js +1 -1
  251. package/dist/discord/monitor/listeners.js +2 -2
  252. package/dist/discord/monitor/message-handler.js +1 -1
  253. package/dist/discord/monitor/message-handler.preflight.js +8 -8
  254. package/dist/discord/monitor/message-handler.process.js +5 -5
  255. package/dist/discord/monitor/native-command.js +9 -9
  256. package/dist/discord/monitor/provider.js +2 -2
  257. package/dist/discord/monitor/reply-delivery.js +1 -1
  258. package/dist/discord/monitor/thread-bindings.state.js +2 -2
  259. package/dist/discord/send.outbound.js +1 -1
  260. package/dist/discord/voice/command.js +1 -1
  261. package/dist/extensionAPI.js +1 -1
  262. package/dist/extensions/sat-mining/src/rpc-read.js +7 -3
  263. package/dist/extensions/sat-mining/src/sat-bond-layout.js +9 -9
  264. package/dist/extensions/sat-mining/src/solana-submit.js +2 -2
  265. package/dist/federation/auto-connect.js +1 -1
  266. package/dist/federation/marketplace-capability-adapter.js +1 -1
  267. package/dist/federation/marketplace-delivery.js +1 -1
  268. package/dist/federation/marketplace-direct-payment.js +1 -1
  269. package/dist/federation/marketplace-escrow.js +2 -2
  270. package/dist/federation/settlement-evidence.js +1 -1
  271. package/dist/gateway/a2a-http.js +1 -1
  272. package/dist/gateway/call.js +2 -2
  273. package/dist/gateway/client.js +3 -3
  274. package/dist/gateway/control-ui-boot-check.js +7 -7
  275. package/dist/gateway/control-ui-login.js +7 -7
  276. package/dist/gateway/control-ui.js +10 -10
  277. package/dist/gateway/federation-http.js +3 -3
  278. package/dist/gateway/federation-marketplace.js +1 -1
  279. package/dist/gateway/hooks-mapping.js +4 -4
  280. package/dist/gateway/hooks.js +1 -1
  281. package/dist/gateway/openai-http.js +1 -1
  282. package/dist/gateway/openresponses-http.js +1 -1
  283. package/dist/gateway/server/health-state.js +1 -1
  284. package/dist/gateway/server/hooks.js +2 -2
  285. package/dist/gateway/server/ws-connection/message-handler.js +6 -6
  286. package/dist/gateway/server-channels.js +1 -1
  287. package/dist/gateway/server-cron.js +3 -3
  288. package/dist/gateway/server-discovery.js +2 -2
  289. package/dist/gateway/server-http.js +17 -17
  290. package/dist/gateway/server-methods/agent.js +4 -4
  291. package/dist/gateway/server-methods/agents.js +1 -1
  292. package/dist/gateway/server-methods/channels.js +1 -1
  293. package/dist/gateway/server-methods/chat.js +6 -6
  294. package/dist/gateway/server-methods/commands.js +1 -1
  295. package/dist/gateway/server-methods/devices.js +1 -1
  296. package/dist/gateway/server-methods/doctor.js +2 -2
  297. package/dist/gateway/server-methods/hooks.js +1 -1
  298. package/dist/gateway/server-methods/models.js +1 -1
  299. package/dist/gateway/server-methods/nodes.js +2 -2
  300. package/dist/gateway/server-methods/send.js +4 -4
  301. package/dist/gateway/server-methods/services.js +1 -1
  302. package/dist/gateway/server-methods/sessions.js +12 -12
  303. package/dist/gateway/server-methods/skills.js +2 -2
  304. package/dist/gateway/server-methods/system.js +1 -1
  305. package/dist/gateway/server-methods/tts.js +2 -2
  306. package/dist/gateway/server-methods/usage.js +2 -2
  307. package/dist/gateway/server-node-events.js +5 -5
  308. package/dist/gateway/server-reload-handlers.js +3 -3
  309. package/dist/gateway/server-restart-sentinel.js +3 -3
  310. package/dist/gateway/server.impl.js +19 -19
  311. package/dist/gateway/session-compaction-checkpoints.js +4 -4
  312. package/dist/gateway/session-utils.fs.js +24 -24
  313. package/dist/gateway/session-utils.js +6 -6
  314. package/dist/gateway/sessions-patch.js +2 -2
  315. package/dist/gateway/tools-invoke-http.js +2 -2
  316. package/dist/hooks/bundled-dir.js +4 -4
  317. package/dist/hooks/gmail-setup-utils.js +6 -6
  318. package/dist/hooks/import-url.js +2 -2
  319. package/dist/hooks/loader.js +5 -5
  320. package/dist/hooks/workspace.js +7 -7
  321. package/dist/imessage/monitor/deliver.js +1 -1
  322. package/dist/imessage/monitor/inbound-processing.js +4 -4
  323. package/dist/imessage/monitor/monitor-provider.js +2 -2
  324. package/dist/imessage/send.js +2 -2
  325. package/dist/index.js +1 -1
  326. package/dist/infra/archive.js +17 -17
  327. package/dist/infra/boundary-file-read.js +2 -2
  328. package/dist/infra/boundary-path.js +15 -15
  329. package/dist/infra/brew.js +2 -2
  330. package/dist/infra/control-ui-assets.js +14 -14
  331. package/dist/infra/device-auth-store.js +8 -8
  332. package/dist/infra/device-identity.js +8 -8
  333. package/dist/infra/dotenv.js +2 -2
  334. package/dist/infra/exec-approvals.js +9 -9
  335. package/dist/infra/exec-command-resolution.js +4 -4
  336. package/dist/infra/exec-safe-bin-trust.js +2 -2
  337. package/dist/infra/fased-root.js +5 -5
  338. package/dist/infra/fs-safe.js +14 -14
  339. package/dist/infra/gateway-lock.js +11 -11
  340. package/dist/infra/git-commit.js +5 -5
  341. package/dist/infra/git-root.js +4 -4
  342. package/dist/infra/heartbeat-runner.js +8 -8
  343. package/dist/infra/hosted-runtime-artifact.js +3 -3
  344. package/dist/infra/is-main.js +2 -2
  345. package/dist/infra/json-file.js +7 -7
  346. package/dist/infra/outbound/channel-resolution.js +1 -1
  347. package/dist/infra/outbound/deliver.js +3 -3
  348. package/dist/infra/outbound/delivery-queue.js +16 -16
  349. package/dist/infra/outbound/message-action-params.js +2 -2
  350. package/dist/infra/outbound/message-action-runner.js +4 -4
  351. package/dist/infra/outbound/message.js +3 -3
  352. package/dist/infra/outbound/outbound-session.js +1 -1
  353. package/dist/infra/outbound/payloads.js +1 -1
  354. package/dist/infra/path-env.js +3 -3
  355. package/dist/infra/ports-lsof.js +4 -4
  356. package/dist/infra/provider-usage.auth.js +3 -3
  357. package/dist/infra/safe-open-sync.js +2 -2
  358. package/dist/infra/session-cost-usage.js +9 -9
  359. package/dist/infra/session-maintenance-warning.js +1 -1
  360. package/dist/infra/shell-env.js +2 -2
  361. package/dist/infra/skills-remote.js +1 -1
  362. package/dist/infra/state-migrations.fs.js +6 -6
  363. package/dist/infra/state-migrations.js +23 -23
  364. package/dist/infra/tmp-fased-dir.js +6 -6
  365. package/dist/infra/update-runner.js +1 -1
  366. package/dist/infra/widearea-dns.js +3 -3
  367. package/dist/infra/wsl.js +2 -2
  368. package/dist/light-update-status.js +11 -11
  369. package/dist/line/accounts.js +2 -2
  370. package/dist/line/bot-handlers.js +2 -2
  371. package/dist/line/bot-message-context.js +2 -2
  372. package/dist/line/download.js +3 -3
  373. package/dist/line/monitor.js +3 -3
  374. package/dist/line/webhook-node.js +1 -1
  375. package/dist/llm-slug-generator.js +1 -1
  376. package/dist/logging/config.js +3 -3
  377. package/dist/logging/logger.js +7 -7
  378. package/dist/managed/federation.js +3 -3
  379. package/dist/managed/tunnel.js +3 -3
  380. package/dist/media/fetch.js +1 -1
  381. package/dist/media/input-files.js +2 -2
  382. package/dist/media/store.js +14 -14
  383. package/dist/media-understanding/attachments.js +4 -4
  384. package/dist/media-understanding/providers/google/inline-data.js +1 -1
  385. package/dist/media-understanding/providers/shared.js +1 -1
  386. package/dist/media-understanding/runner.js +3 -3
  387. package/dist/memory/embeddings.js +2 -2
  388. package/dist/memory/internal.js +10 -10
  389. package/dist/memory/manager-sync-ops.js +7 -7
  390. package/dist/memory/repair-executor.js +17 -17
  391. package/dist/node-host/invoke-system-run-plan.js +8 -8
  392. package/dist/node-host/invoke.js +2 -2
  393. package/dist/node-host/runner.js +5 -5
  394. package/dist/pairing/pairing-store.js +3 -3
  395. package/dist/plugin-sdk/{accounts-Bz_2QZSt.js → accounts-DzLdrOVC.js} +1 -1
  396. package/dist/plugin-sdk/{actions-CysoQjk1.js → actions-PhofTgnO.js} +4 -4
  397. package/dist/plugin-sdk/{active-listener-C5ALSs7Y.js → active-listener-C8a74qPO.js} +1 -1
  398. package/dist/plugin-sdk/{allow-list-yqasgPpz.js → allow-list-BYeKk0Sy.js} +2 -2
  399. package/dist/plugin-sdk/{audio-preflight-CKgOmu0p.js → audio-preflight-CARAVcz-.js} +51 -49
  400. package/dist/plugin-sdk/{audit-BFnu5TVB.js → audit-ByK45Q1d.js} +1 -1
  401. package/dist/plugin-sdk/{channel-access-BiWxa3LR.js → channel-access-BEin0yA4.js} +1 -1
  402. package/dist/plugin-sdk/{channel-access-configure-gJvqbbXB.js → channel-access-configure-Di_DoR-Q.js} +1 -1
  403. package/dist/plugin-sdk/{channel-adapters.discord-g8Do3f5N.js → channel-adapters.discord-IOZP8Cv5.js} +1 -1
  404. package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
  405. package/dist/plugin-sdk/channel-plugin-common.js +8 -8
  406. package/dist/plugin-sdk/{chunk-CuJIMshx.js → chunk-CwN3c1Fq.js} +1 -1
  407. package/dist/plugin-sdk/{chunk-items-CNyHcNiG.js → chunk-items-DH7ooQBZ.js} +1 -1
  408. package/dist/plugin-sdk/command-status.js +51 -49
  409. package/dist/plugin-sdk/{commands-registry-DwQIFJmL.js → commands-registry-Bea-V_lR.js} +2 -2
  410. package/dist/plugin-sdk/{common-C90EHP1w.js → common-BJPuBxmx.js} +1 -1
  411. package/dist/plugin-sdk/{config-DKNrb8oT.js → config-BxOWD3gF.js} +61 -6
  412. package/dist/plugin-sdk/{pi-embedded-runner-XtyJMQqg.js → config-schema-ChJcPn7x.js} +4818 -445
  413. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  414. package/dist/plugin-sdk/device-pair.js +3 -3
  415. package/dist/plugin-sdk/{device-pairing-J1IH1jFl.js → device-pairing-D2Yq-_U6.js} +1 -1
  416. package/dist/plugin-sdk/{diagnostic-C16gioN6.js → diagnostic-Dfn1iERm.js} +4 -4
  417. package/dist/plugin-sdk/{directory-live-DK_83362.js → directory-live-ClwN5KKq.js} +1 -1
  418. package/dist/plugin-sdk/{directory-live-G7AN8y8N.js → directory-live-DatqU-eS.js} +1 -1
  419. package/dist/plugin-sdk/discord.d.ts +4 -4
  420. package/dist/plugin-sdk/discord.js +36 -37
  421. package/dist/plugin-sdk/{draft-stream-controls-DGYBMJYc.js → draft-stream-controls-D4Tb_iS_.js} +1 -1
  422. package/dist/plugin-sdk/{fetch-RV7QDF43.js → fetch-Cu-ahkie.js} +2 -2
  423. package/dist/plugin-sdk/{fetch-guard-CxXvFYq5.js → fetch-guard-BuYrl6q2.js} +3 -3
  424. package/dist/plugin-sdk/{filesystem-manager-CeSmCA_A.js → filesystem-manager-B9DDPgfU.js} +2 -2
  425. package/dist/plugin-sdk/{fs-safe-DztQeyQe.js → fs-safe-BG-VzVkL.js} +1 -1
  426. package/dist/plugin-sdk/{guilds-n7MMnX1c.js → guilds-BeT3iHHJ.js} +1 -1
  427. package/dist/plugin-sdk/{handle-action-DkfMckah.js → handle-action-Bk-L2J84.js} +29 -29
  428. package/dist/plugin-sdk/{helpers-C1pcZJsv.js → helpers-0E444CR0.js} +74 -2
  429. package/dist/plugin-sdk/{image-ops-BSQmb-17.js → image-ops-BYc-Ol7C.js} +1 -1
  430. package/dist/plugin-sdk/index.d.ts +20 -16
  431. package/dist/plugin-sdk/index.js +63 -4294
  432. package/dist/plugin-sdk/{internal-CC6TMTtc.js → internal-qo16nNU1.js} +1 -1
  433. package/dist/plugin-sdk/json-store.js +6 -6
  434. package/dist/plugin-sdk/{login-YbYyMkkE.js → login-B_At7IVI.js} +3 -3
  435. package/dist/plugin-sdk/{login-qr-DvJw8_2g.js → login-qr-BlSQ8QJF.js} +6 -6
  436. package/dist/plugin-sdk/{manager-DQ1dH8OM.js → manager-VNI6sxbG.js} +11 -11
  437. package/dist/plugin-sdk/{markdown-tables-DrB-IM8r.js → markdown-tables-CpNefu6e.js} +1 -1
  438. package/dist/plugin-sdk/{media-D8pWjqEt.js → media-QBCmvhBQ.js} +4 -4
  439. package/dist/plugin-sdk/{monitor-dqvs6ijC.js → monitor-BhHlerHI.js} +59 -57
  440. package/dist/plugin-sdk/{monitor-B8dLCpFA.js → monitor-C9UczH5N.js} +67 -67
  441. package/dist/plugin-sdk/{openresponses-http-S64mJyy8.js → openresponses-http-CtuFHD5w.js} +51 -49
  442. package/dist/plugin-sdk/{optional-runtime-dependency-Bt_3Yigu.js → optional-runtime-dependency-BaVO1F3i.js} +1 -1
  443. package/dist/plugin-sdk/{outbound-B5ukMdUv.js → outbound-CWrcAWpE.js} +9 -9
  444. package/dist/plugin-sdk/{outbound-attachment-C9oadpUP.js → outbound-attachment-Dhi2Q-_f.js} +2 -2
  445. package/dist/plugin-sdk/{pairing-message-DfIyssV_.d.ts → pairing-message-6XVXW554.d.ts} +1 -1
  446. package/dist/plugin-sdk/{pairing-message-B787pcJI.js → pairing-message-D01_6FkJ.js} +1 -1
  447. package/dist/plugin-sdk/{pairing-store-BdOcH_GA.js → pairing-store-DADXOv-J.js} +2 -2
  448. package/dist/plugin-sdk/{pi-model-discovery-DQdXL_-F.js → pi-model-discovery-D9-CQFS2.js} +1 -1
  449. package/dist/plugin-sdk/{pi-model-discovery-runtime-IwiWDCQ3.js → pi-model-discovery-runtime-DhNNXQgq.js} +5 -5
  450. package/dist/plugin-sdk/{probe-CJ6lN-jD.js → probe-Cyb-DGA3.js} +3 -3
  451. package/dist/plugin-sdk/{probe-CvXWxzag.js → probe-D8JAILir.js} +2 -2
  452. package/dist/plugin-sdk/{probe-DO4M1Qd1.js → probe-Dlk0Jxpw.js} +2 -2
  453. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
  454. package/dist/plugin-sdk/{pw-ai-BFHYmEIx.js → pw-ai-CQG7vp-Y.js} +11 -11
  455. package/dist/plugin-sdk/{qmd-manager-D2LMB27z.js → qmd-manager-DCUE21Kj.js} +5 -5
  456. package/dist/plugin-sdk/{query-expansion-BM7lmqaP.js → query-expansion-Zr9qQixm.js} +3 -3
  457. package/dist/plugin-sdk/{redact-sensitive-url-B0RJQqO7.js → redact-sensitive-url-dPvnFFsK.js} +1 -0
  458. package/dist/plugin-sdk/{replies-BPFt4O-j.js → replies-C_FeIOF4.js} +4 -4
  459. package/dist/plugin-sdk/{resolve-channels-sscr14hU.js → resolve-channels-ChWKWtA9.js} +2 -2
  460. package/dist/plugin-sdk/{probe-DbhD54Aw.js → resolve-channels-zEnvugag.js} +4 -3
  461. package/dist/plugin-sdk/{resolve-outbound-target-BP_JscKT.js → resolve-outbound-target-DD8edEdz.js} +2 -2
  462. package/dist/plugin-sdk/{resolve-route-wp5xq4Ws.js → resolve-route-BPkfG5Pg.js} +1 -1
  463. package/dist/plugin-sdk/{resolve-users-C1sjzEsV.js → resolve-users-BTvjQuui.js} +1 -1
  464. package/dist/plugin-sdk/{resolve-users-B63RqPIO.js → resolve-users-CTzoruIZ.js} +2 -2
  465. package/dist/plugin-sdk/{retry-policy-BTH89onl.js → retry-policy-C0YsRX_6.js} +2 -2
  466. package/dist/plugin-sdk/{runtime-BUpqjZNM.js → runtime-CyTWeylK.js} +5 -5
  467. package/dist/plugin-sdk/{runtime-dependency-B5Fut2tT.js → runtime-dependency-D6tYtvtU.js} +5 -5
  468. package/dist/plugin-sdk/{sandbox-paths-fc-HFGJr.js → sandbox-paths-lj7_EVuA.js} +1 -1
  469. package/dist/plugin-sdk/sat-runtime.d.ts +2 -2
  470. package/dist/plugin-sdk/sat-runtime.js +14 -14
  471. package/dist/plugin-sdk/{send-CRI83FPV.js → send-BedQ8ekw.js} +14 -14
  472. package/dist/plugin-sdk/{send-DUp9GIX8.js → send-BtFuV6zU.js} +9 -9
  473. package/dist/plugin-sdk/{send-DWB5HFdb.js → send-CNxLDNQ9.js} +9 -9
  474. package/dist/plugin-sdk/{send-DGUAXb2b.js → send-FcEJfLTd.js} +6 -6
  475. package/dist/plugin-sdk/{send-zn5KBXIN.js → send-Qckp3h4k.js} +10 -10
  476. package/dist/plugin-sdk/{session-BLyxz03u.js → session-C3Ul4abD.js} +4 -4
  477. package/dist/plugin-sdk/{skill-commands-DCnCOVR_.js → skill-commands-C2CnUTPX.js} +4 -4
  478. package/dist/plugin-sdk/{slack-actions-Dwy-8Zg7.js → slack-actions-CLyEd8FK.js} +25 -25
  479. package/dist/plugin-sdk/{slack-DcXn5HVj.js → slack-bSeSOI9d.js} +72 -71
  480. package/dist/plugin-sdk/slack.d.ts +4 -4
  481. package/dist/plugin-sdk/slack.js +17 -18
  482. package/dist/plugin-sdk/{ssrf-D_4q0mKh.js → ssrf-BZG8Ztod.js} +1 -1
  483. package/dist/plugin-sdk/{sticker-cache-C3YATyKD.js → sticker-cache-DBnS3hHh.js} +4 -4
  484. package/dist/plugin-sdk/{tables-DX84FwPB.js → tables-L5mXZ5y_.js} +2 -2
  485. package/dist/plugin-sdk/{targets-BgSHco9b.js → targets-eG595pY0.js} +2 -2
  486. package/dist/plugin-sdk/{telegram-actions-Dd_iEzYH.js → telegram-actions-D0Kyqy_e.js} +56 -54
  487. package/dist/plugin-sdk/telegram.d.ts +4 -4
  488. package/dist/plugin-sdk/telegram.js +15 -16
  489. package/dist/plugin-sdk/{thread-bindings.lifecycle-DjpMLjhY.js → thread-bindings.lifecycle-C_5BEWmL.js} +3 -3
  490. package/dist/plugin-sdk/{thread-bindings.state-DYYR9qeT.js → thread-bindings.state-DRZAbcUu.js} +4 -4
  491. package/dist/plugin-sdk/{tmp-fased-dir-Bcp1DTSV.d.ts → tmp-fased-dir-BpMLNd4L.d.ts} +1 -1
  492. package/dist/plugin-sdk/{types-BTkcYtOt.d.ts → types-0CsXVmg8.d.ts} +2 -2
  493. package/dist/plugin-sdk/{types-CMoLtViq.d.ts → types-DMLEeE52.d.ts} +1 -1
  494. package/dist/plugin-sdk/{wallet-status-D9UVH6k9.js → wallet-status-2yrXvqSS.js} +7 -7
  495. package/dist/plugin-sdk/{web-BgTy1WeG.js → web-CSRe4zy2.js} +60 -58
  496. package/dist/plugin-sdk/{whatsapp-actions-DISRDbu1.js → whatsapp-actions-CkLkpg8M.js} +23 -23
  497. package/dist/plugin-sdk/{whatsapp-heartbeat-KM3lYpt-.js → whatsapp-heartbeat-DuAE9_88.js} +3 -3
  498. package/dist/plugin-sdk/whatsapp.d.ts +9 -9
  499. package/dist/plugin-sdk/whatsapp.js +18 -19
  500. package/dist/plugin-sdk/{ws-CxmRDbD9.js → ws-CocpWGhl.js} +1 -1
  501. package/dist/plugin-sdk/{wsl-Cw-xOsqF.js → wsl-CXVwPntb.js} +3 -3
  502. package/dist/plugin-sdk/{zod-schema.providers-core-CIzCjXH9.d.ts → zod-schema.providers-core-FaYR6KdD.d.ts} +61 -61
  503. package/dist/plugins/bundled-dir.js +3 -3
  504. package/dist/plugins/config-state.js +1 -0
  505. package/dist/plugins/discovery.js +11 -11
  506. package/dist/plugins/loader.js +13 -13
  507. package/dist/plugins/manifest-registry.js +2 -2
  508. package/dist/plugins/manifest.js +4 -4
  509. package/dist/plugins/path-safety.js +3 -3
  510. package/dist/plugins/providers.js +1 -1
  511. package/dist/plugins/runtime/index.js +12 -12
  512. package/dist/plugins/status-cache.js +9 -9
  513. package/dist/plugins/status.js +1 -1
  514. package/dist/plugins/tools.js +1 -1
  515. package/dist/plugins/update.js +3 -3
  516. package/dist/plugins/web-search-install-catalog.js +3 -3
  517. package/dist/plugins/web-search-providers.runtime.js +1 -1
  518. package/dist/process/command-queue.js +1 -1
  519. package/dist/providers/refresh.js +2 -2
  520. package/dist/providers/registry.js +53 -2
  521. package/dist/secrets/apply.js +16 -16
  522. package/dist/secrets/audit.js +11 -11
  523. package/dist/secrets/shared.js +9 -9
  524. package/dist/security/audit-channel.js +1 -1
  525. package/dist/security/audit-extra.async.js +3 -3
  526. package/dist/security/audit-extra.sync.js +2 -2
  527. package/dist/security/audit.js +4 -4
  528. package/dist/security/dm-policy-shared.js +1 -1
  529. package/dist/security/scan-paths.js +2 -2
  530. package/dist/shared/config-eval.js +2 -2
  531. package/dist/shared/model-thinking.js +4 -1
  532. package/dist/shared/net/redact-sensitive-url.js +1 -0
  533. package/dist/shared/pid-alive.js +2 -2
  534. package/dist/signal/client.js +1 -1
  535. package/dist/signal/index.js +1 -1
  536. package/dist/signal/monitor/access-policy.js +1 -1
  537. package/dist/signal/monitor/event-handler.js +6 -6
  538. package/dist/signal/monitor.js +4 -4
  539. package/dist/signal/send.js +3 -3
  540. package/dist/slack/monitor/auth.js +1 -1
  541. package/dist/slack/monitor/context.js +1 -1
  542. package/dist/slack/monitor/dm-auth.js +1 -1
  543. package/dist/slack/monitor/message-handler/prepare.js +4 -4
  544. package/dist/slack/monitor/provider.js +3 -3
  545. package/dist/slack/monitor/replies.js +1 -1
  546. package/dist/slack/monitor/slash.js +1 -1
  547. package/dist/slack/send.js +1 -1
  548. package/dist/tasks/standing-orders.js +5 -5
  549. package/dist/tasks/task-flow-registry.js +5 -5
  550. package/dist/tasks/task-registry.js +5 -5
  551. package/dist/tasks/workflow-definitions.js +6 -6
  552. package/dist/telegram/bot/helpers.js +2 -2
  553. package/dist/telegram/bot-handlers.js +6 -6
  554. package/dist/telegram/bot-message-context.js +6 -6
  555. package/dist/telegram/bot-message-dispatch.js +2 -2
  556. package/dist/telegram/bot-native-commands.js +4 -4
  557. package/dist/telegram/bot.js +1 -1
  558. package/dist/telegram/dm-access.js +1 -1
  559. package/dist/telegram/group-access.js +1 -1
  560. package/dist/telegram/monitor.js +2 -2
  561. package/dist/telegram/send.js +2 -2
  562. package/dist/telegram/token.js +5 -5
  563. package/dist/telegram/webhook.js +1 -1
  564. package/dist/tts/tts-core.js +1 -1
  565. package/dist/utils.js +5 -5
  566. package/dist/video-generation/dashscope-compatible.js +1 -1
  567. package/dist/wallet/local-socket-signer-broker.js +18 -18
  568. package/dist/wallet/providers/embedded-keystore-adapter.js +6 -6
  569. package/dist/wallet/providers/local-socket-signer-adapter.js +5 -5
  570. package/dist/wallet/wallet-approval-auth.js +5 -5
  571. package/dist/wallet/wallet-audit-log.js +5 -5
  572. package/dist/wallet/wallet-canary.js +1 -1
  573. package/dist/wallet/wallet-custody.js +25 -25
  574. package/dist/wallet/wallet-inbound-events.js +7 -7
  575. package/dist/wallet/wallet-observability.js +5 -5
  576. package/dist/wallet/wallet-policy.js +11 -11
  577. package/dist/wallet/wallet-provider-registry.js +7 -7
  578. package/dist/wallet/wallet-provider-resolver.js +1 -1
  579. package/dist/wallet/wallet-runtime-config.js +3 -3
  580. package/dist/wallet/wallet-secrets-store.js +22 -22
  581. package/dist/wallet/wallet-send-approvals.js +10 -10
  582. package/dist/wallet/wallet-settlement-links.js +5 -5
  583. package/dist/wallet/wallet-status.js +2 -2
  584. package/dist/web/accounts.js +3 -3
  585. package/dist/web/auth-store.js +18 -18
  586. package/dist/web/auto-reply/deliver-reply.js +2 -2
  587. package/dist/web/auto-reply/heartbeat-runner.js +3 -3
  588. package/dist/web/auto-reply/monitor/group-gating.js +1 -1
  589. package/dist/web/auto-reply/monitor/process-message.js +4 -4
  590. package/dist/web/auto-reply/monitor.js +4 -4
  591. package/dist/web/inbound/access-control.js +3 -3
  592. package/dist/web/inbound/monitor.js +2 -2
  593. package/dist/web/media.js +2 -2
  594. package/dist/web/outbound.js +3 -3
  595. package/dist/web/session.js +4 -4
  596. package/dist/wizard/host-security-capability.js +2 -2
  597. package/dist/wizard/onboarding.federation.js +1 -1
  598. package/dist/wizard/onboarding.finalize.js +7 -7
  599. package/dist/wizard/onboarding.host-security.js +7 -7
  600. package/dist/wizard/onboarding.js +8 -8
  601. package/dist/wizard/onboarding.wallet.js +45 -45
  602. package/extensions/acpx/package.json +1 -1
  603. package/extensions/bluebubbles/package.json +1 -1
  604. package/extensions/copilot-proxy/package.json +1 -1
  605. package/extensions/diagnostics-otel/package.json +1 -1
  606. package/extensions/fased-federation/package.json +1 -1
  607. package/extensions/google-gemini-cli-auth/package.json +1 -1
  608. package/extensions/imessage/package.json +1 -1
  609. package/extensions/irc/package.json +1 -1
  610. package/extensions/line/package.json +1 -1
  611. package/extensions/llm-task/package.json +1 -1
  612. package/extensions/lobster/package.json +1 -1
  613. package/extensions/matrix/CHANGELOG.md +12 -0
  614. package/extensions/matrix/package.json +1 -1
  615. package/extensions/mattermost/package.json +1 -1
  616. package/extensions/memory-core/package.json +2 -2
  617. package/extensions/memory-lancedb/package.json +1 -1
  618. package/extensions/minimax-portal-auth/package.json +1 -1
  619. package/extensions/msteams/CHANGELOG.md +12 -0
  620. package/extensions/msteams/package.json +1 -1
  621. package/extensions/nextcloud-talk/package.json +1 -1
  622. package/extensions/nostr/CHANGELOG.md +12 -0
  623. package/extensions/nostr/package.json +1 -1
  624. package/extensions/open-prose/package.json +1 -1
  625. package/extensions/sat-mining/index.ts +13 -1
  626. package/extensions/sat-mining/package.json +1 -1
  627. package/extensions/sat-mining/src/epoch-service.ts +16 -0
  628. package/extensions/sat-mining/src/round-watcher.ts +21 -0
  629. package/extensions/sat-mining/src/rpc-read.ts +9 -2
  630. package/extensions/sat-mining/src/runtime.ts +5 -1
  631. package/extensions/signal/package.json +1 -1
  632. package/extensions/synology-chat/package.json +1 -1
  633. package/extensions/tlon/package.json +1 -1
  634. package/extensions/twitch/CHANGELOG.md +12 -0
  635. package/extensions/twitch/package.json +1 -1
  636. package/extensions/voice-call/CHANGELOG.md +12 -0
  637. package/extensions/voice-call/package.json +1 -1
  638. package/extensions/zalo/CHANGELOG.md +12 -0
  639. package/extensions/zalo/package.json +1 -1
  640. package/extensions/zalouser/CHANGELOG.md +12 -0
  641. package/extensions/zalouser/package.json +1 -1
  642. package/package.json +1 -1
  643. package/dist/control-ui/assets/chat-model-ref-DV2P__mw.js +0 -2
  644. package/dist/plugin-sdk/links-D5ecKoG9.js +0 -74
  645. package/dist/plugin-sdk/media-payload-DpYEcV-X.js +0 -18
  646. package/dist/plugin-sdk/resolve-channels-B-dUtZYa.js +0 -4
  647. package/dist/plugin-sdk/resolve-utils-DrvLA82C.js +0 -136
  648. /package/dist/plugin-sdk/{blocks-input-DdQwSVtP.js → blocks-input-Dcitfh7h.js} +0 -0
  649. /package/dist/plugin-sdk/{channel-activity-B7MIaDei.js → channel-activity-Cg1xRoc2.js} +0 -0
  650. /package/dist/plugin-sdk/{channel-core-CMPoGCik.js → channel-core-BOkyXXLa.js} +0 -0
  651. /package/dist/plugin-sdk/{client-BTUzO_8g.js → client-D2N7hqVu.js} +0 -0
  652. /package/dist/plugin-sdk/{command-poll-backoff-CBq0jVRw.js → command-poll-backoff-NAePk3eL.js} +0 -0
  653. /package/dist/plugin-sdk/{date-time-Bbp5JvNw.js → date-time-CE3Uer3C.js} +0 -0
  654. /package/dist/plugin-sdk/{diagnostic-session-state-B-9PL5r7.js → diagnostic-session-state-HO94DMou.js} +0 -0
  655. /package/dist/plugin-sdk/{draft-stream-loop-DZ1OAyye.js → draft-stream-loop-CKyHn8IX.js} +0 -0
  656. /package/dist/plugin-sdk/{fetch-headers-DvXyXtoI.js → fetch-headers-my7hgV2G.js} +0 -0
  657. /package/dist/plugin-sdk/{fetch-timeout-jOIu9Xud.js → fetch-timeout-l_6RdoMw.js} +0 -0
  658. /package/dist/plugin-sdk/{gateway-registry-C-MTEdvG.js → gateway-registry-DFsoY6C0.js} +0 -0
  659. /package/dist/plugin-sdk/{github-copilot-token-Dgug856m.js → github-copilot-token-CUK__1s1.js} +0 -0
  660. /package/dist/plugin-sdk/{inbound-context-BNCTzgjG.js → inbound-context-BFnIdcqI.js} +0 -0
  661. /package/dist/plugin-sdk/{ip-BkeyFRJr.js → ip-C70a-YlD.js} +0 -0
  662. /package/dist/plugin-sdk/{memory-search-DHSeU4pJ.js → memory-search-C3C0bD2H.js} +0 -0
  663. /package/dist/plugin-sdk/{pairing-token-HQpaqod5.js → pairing-token-N_6Jbt1L.js} +0 -0
  664. /package/dist/plugin-sdk/{path-alias-guards-BlIJ0AmG.js → path-alias-guards-Dg3gU-MA.js} +0 -0
  665. /package/dist/plugin-sdk/{paths-B88DQEK8.js → paths-CTZ2RS_E.js} +0 -0
  666. /package/dist/plugin-sdk/{polls-Dy1NsYKT.js → polls-DQrR-qT3.js} +0 -0
  667. /package/dist/plugin-sdk/{proxy-R5TjOIFS.js → proxy-7xs_rsnV.js} +0 -0
  668. /package/dist/plugin-sdk/{qmd-scope-C9tRnohc.js → qmd-scope-D1sSG_Rx.js} +0 -0
  669. /package/dist/plugin-sdk/{redact-CwCz68Mi.js → redact-Bm8vu_ju.js} +0 -0
  670. /package/dist/plugin-sdk/{redact-identifier-CDvAeiFm.js → redact-identifier-Q3tkvxhm.js} +0 -0
  671. /package/dist/plugin-sdk/{render-K7NwXvVu.js → render-Bwu_WxwA.js} +0 -0
  672. /package/dist/plugin-sdk/{reply-prefix-CbPHNXlm.js → reply-prefix-Bqzm6DC1.js} +0 -0
  673. /package/dist/plugin-sdk/{reply-reference-CWEIswqw.js → reply-reference-BkbK_DWT.js} +0 -0
  674. /package/dist/plugin-sdk/{retry-DycQ4ymF.js → retry-DstNBhDW.js} +0 -0
  675. /package/dist/plugin-sdk/{run-with-concurrency-CLARJMM7.js → run-with-concurrency-BsDJWzgM.js} +0 -0
  676. /package/dist/plugin-sdk/{secure-random-C2EhANj2.js → secure-random-Bl-AVLVb.js} +0 -0
  677. /package/dist/plugin-sdk/{shared-V35XNAbz.js → shared-clhhbWN3.js} +0 -0
  678. /package/dist/plugin-sdk/{tailscale-status-BGBRraZW.js → tailscale-status-ClsquRGs.js} +0 -0
  679. /package/dist/plugin-sdk/{target-errors-C0yNDbGS.js → target-errors-C_SVKoEv.js} +0 -0
  680. /package/dist/plugin-sdk/{targets-CuTZl1mO.js → targets-BDvvnlph.js} +0 -0
  681. /package/dist/plugin-sdk/{tokens-Do_JU4Rh.js → tokens-BvtlOzVP.js} +0 -0
  682. /package/dist/plugin-sdk/{tool-loop-detection-P5u2k0_f.js → tool-loop-detection-CWphm1k_.js} +0 -0
  683. /package/dist/plugin-sdk/{transcript-events-NZiMKWBK.js → transcript-events-BJQWUdmU.js} +0 -0
  684. /package/dist/plugin-sdk/{ui-KGr1WRXC.js → ui-e020ouhJ.js} +0 -0
  685. /package/dist/plugin-sdk/{with-timeout-Dl513q34.js → with-timeout-BYrRAYFV.js} +0 -0
@@ -1,4298 +1,67 @@
1
- import { $n as resolveEffectiveAllowFromLists, A as clearHistoryEntriesIfEnabled, Cn as readJsonBodyWithLimit, Dn as resolveChannelMediaMaxBytes, E as DEFAULT_GROUP_HISTORY_LIMIT, F as removeAckReactionAfterReply, Fn as processLineMessage, Gn as createDedupeCache, Gt as stringEnum, Hn as DEFAULT_HEARTBEAT_EVERY, I as shouldAckReaction, In as stripMarkdown, Jn as withTempDownloadPath, L as shouldAckReactionForWhatsApp, Ln as createReceiptCard, M as recordPendingHistoryEntry, N as recordPendingHistoryEntryIfEnabled, O as buildPendingHistoryContextFromMap, On as runFederationAutoConnectOnce, P as recordInboundSession, Pn as hasMarkdownToConvert, Qn as resolveDmGroupAccessWithLists, Rn as attachFooterText, S as detectBinary, Sn as isRequestBodyLimitError, Tn as requestBodyErrorToText, Tt as peekSystemEvents, Un as resolveHeartbeatPrompt, Vn as DEFAULT_HEARTBEAT_ACK_MAX_CHARS, W as formatInboundFromLabel, Wn as waitForAbortSignal, Wt as optionalStringEnum, Xn as readStoreAllowFromForDmPolicy, Yn as DM_GROUP_ACCESS_REASON, Zn as resolveDmGroupAccessWithCommandGate, _ as resolveDefaultLineAccountId, _t as getPluginToolMeta, ar as BLUEBUBBLES_ACTION_NAMES, at as createFasedAgentCodingTools, b as logInboundDrop, bn as RequestBodyLimitError, c as loadModelCatalog, cn as registerAcpRuntimeBackend, d as issuePairingChallenge, dn as AcpRuntimeError, en as resolveToolDisplay, f as createTypingCallbacks, g as normalizeAccountId$1, gt as getChannelAgentToolMeta, h as listLineAccountIds, ir as BLUEBUBBLES_ACTIONS, j as evictOldHistoryKeys, k as clearHistoryEntries, kn as startFederationAutoConnect, ln as unregisterAcpRuntimeBackend, m as resolveMentionGatingWithBypass, nr as assertOkOrThrowHttpError, o as resolveStrictAgenticRuntimeMode, on as getAcpSessionManager, or as BLUEBUBBLES_GROUP_ACTIONS, ot as resolveEffectiveToolPolicy, p as resolveMentionGating, qn as extractToolSend, rr as registerPluginHttpRoute, sn as getAcpRuntimeBackend, sr as CHANNEL_MESSAGE_ACTION_NAMES, t as runEmbeddedPiAgent, tr as resolveControlCommandGate, u as deriveModelMetadata, un as resolveRuntimeOptionsFromMeta, v as resolveLineAccount, vn as DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, vt as buildChannelSummary, wn as readRequestBodyWithLimit, x as logTypingFailure, xn as installRequestBodyLimitGuard, y as logAckFailure, yn as DEFAULT_WEBHOOK_MAX_BODY_BYTES } from "./pi-embedded-runner-XtyJMQqg.js";
2
- import { Bt as resolveBlueBubblesGroupRequireMention, Ft as trimMessagingTarget, Gn as getPluginCommandSpecs, Gt as resolveGoogleChatGroupToolPolicy, Kn as listPluginCommands, Kt as resolveIMessageGroupRequireMention, Ln as logMutatingAdminRpcAudit, Nn as getChatChannelMeta, Pt as looksLikeHandleOrPhoneTarget, Rn as consumeMutatingAdminRpcBudget, Rt as looksLikeSignalTargetId, Vn as authorizeOperatorScopesForMethod, Vt as resolveBlueBubblesGroupToolPolicy, Wt as resolveGoogleChatGroupRequireMention, Xn as normalizePluginHttpPath, at as resolveMainSessionKey, c as listAgentsForGateway, ct as listChannelPlugins, dn as resolveDefaultSignalAccountId, et as resolveFreshSessionTotalTokens, f as resolveContextTokensForModel, fn as resolveSignalAccount, hn as resolveIMessageAccount, mn as resolveDefaultIMessageAccountId, pn as listIMessageAccountIds, qt as resolveIMessageGroupToolPolicy, s as classifySessionKey, t as getActivePluginRegistry, u as resolveSessionModelRef, un as listSignalAccountIds, x as loadSessionStore, yn as resolveToolsBySender, zt as normalizeSignalMessagingTarget } from "./runtime-BUpqjZNM.js";
3
- import { n as stripAnsi, t as createSubsystemLogger } from "./subsystem-DBPNbQDQ.js";
1
+ import { $ as clearHistoryEntriesIfEnabled, $n as createInfoCard, $r as extractDashscopeVideoUrls, Ar as resolveSenderCommandAuthorization, B as normalizeAccountId$1, Bn as resolveChannelMediaMaxBytes, Br as getRealtimeVoiceProvider, C as resolveEffectiveToolInventory, Cn as unregisterAcpRuntimeBackend, Cr as sendMediaWithLeadingCaption, D as runEmbeddedPiAgent, Dr as buildAgentMediaPayload, E as ACPX_PUSH_TEST_WRAPPER_ID, Er as fetchWithBearerAuthScopeFallback, F as issuePairingChallenge, Fn as isRequestBodyLimitError, Fr as resolveEffectiveAllowFromLists, G as logTypingFailure, Gr as listRealtimeTranscriptionProviders, H as resolveLineAccount, Hn as startFederationAutoConnect, Hr as normalizeRealtimeVoiceProviderId, I as createTypingCallbacks, In as readJsonBodyWithLimit, Jn as processLineMessage, Jr as DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, Kr as normalizeRealtimeTranscriptionProviderId, L as resolveMentionGating, Ln as readRequestBodyWithLimit, Lr as resolveControlCommandGate, Mn as DEFAULT_WEBHOOK_MAX_BODY_BYTES, Mr as readStoreAllowFromForDmPolicy, Nn as RequestBodyLimitError, Nr as resolveDmGroupAccessWithCommandGate, Or as chunkTextForOutbound, Pn as installRequestBodyLimitGuard, Pr as resolveDmGroupAccessWithLists, Q as clearHistoryEntries, Qn as createImageCard, Qr as downloadDashscopeGeneratedVideos, R as resolveMentionGatingWithBypass, Rn as requestBodyErrorToText, Rr as evaluateSenderGroupAccess, S as getPublicGatewayIdentity, Sn as registerAcpRuntimeBackend, Sr as resolveOutboundMediaUrls, T as ACPX_PUSH_TEST_METHOD, Tr as createScopedPairingAccess, U as logAckFailure, Ur as canonicalizeRealtimeTranscriptionProviderId, V as resolveDefaultLineAccountId, Vn as runFederationAutoConnectOnce, Vr as listRealtimeVoiceProviders, W as logInboundDrop, Wr as getRealtimeTranscriptionProvider, Xn as createReceiptCard, Xr as buildDashscopeVideoGenerationInput, Y as DEFAULT_GROUP_HISTORY_LIMIT, Yn as stripMarkdown, Yr as DEFAULT_VIDEO_RESOLUTION_TO_SIZE, Z as buildPendingHistoryContextFromMap, Zn as createActionCard, Zr as buildDashscopeVideoGenerationParameters, _ as getGatewayUpdateStatus, _r as buildHostnameAllowlistPolicyFromSuffixAllowlist, a as normalizeIMessageMessagingTarget, ai as BLUEBUBBLES_ACTIONS, ar as createPersistentDedupe, at as shouldAckReaction, b as getStatusSummary, br as createNormalizedOutboundDeliverer, ci as CHANNEL_MESSAGE_ACTION_NAMES, cn as stringEnum, cr as registerWebhookTarget, d as mergeAllowlist, dr as resolveSingleWebhookTargetAsync, ei as pollDashscopeVideoTaskUntilComplete, er as createListCard, et as evictOldHistoryKeys, fr as resolveWebhookTargets, g as buildCommandsListResult, gr as withTempDownloadPath, h as getAcpStatusSnapshot, hr as extractToolSend, i as looksLikeIMessageTargetId, ii as resolveAllowlistMatchSimple, ir as createLoggerBackedRuntime, it as removeAckReactionAfterReply, jn as DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, jr as DM_GROUP_ACCESS_REASON, kr as resolveChannelAccountConfigBasePath, lr as rejectNonPostWebhookRequest, m as pushHandlers, mr as resolveWebhookPath, n as collectBlueBubblesStatusIssues, ni as registerPluginHttpRoute, nt as recordPendingHistoryEntryIfEnabled, o as imessageOnboardingAdapter, oi as BLUEBUBBLES_ACTION_NAMES, or as createDedupeCache, ot as shouldAckReactionForWhatsApp, p as summarizeMapping, pr as normalizeWebhookPath, pt as formatInboundFromLabel, qn as hasMarkdownToConvert, qr as DEFAULT_VIDEO_GENERATION_DURATION_SECONDS, r as signalOnboardingAdapter, ri as formatAllowlistMatchMeta, rr as waitForAbortSignal, rt as recordInboundSession, s as buildMediaPayload, si as BLUEBUBBLES_GROUP_ACTIONS, sn as optionalStringEnum, t as LineConfigSchema, ti as resolveVideoGenerationReferenceUrls, tt as recordPendingHistoryEntry, ur as resolveSingleWebhookTarget, v as buildModelCatalogStatus, vr as isHttpsUrlAllowedByHostnameSuffixAllowlist, w as executeAcpxPushTestRequest, wn as AcpRuntimeError, wr as buildOauthProviderAuthResult, x as isDangerousNameMatchingEnabled, xr as formatTextWithAttachmentLinks, y as loadGatewayModelCatalog, yr as normalizeHostnameSuffixAllowlist, z as listLineAccountIds, zr as canonicalizeRealtimeVoiceProviderId } from "./config-schema-ChJcPn7x.js";
2
+ import { Bt as resolveBlueBubblesGroupRequireMention, Gt as resolveGoogleChatGroupToolPolicy, Kt as resolveIMessageGroupRequireMention, Nn as getChatChannelMeta, Rt as looksLikeSignalTargetId, Vt as resolveBlueBubblesGroupToolPolicy, Wt as resolveGoogleChatGroupRequireMention, Xn as normalizePluginHttpPath, dn as resolveDefaultSignalAccountId, fn as resolveSignalAccount, hn as resolveIMessageAccount, mn as resolveDefaultIMessageAccountId, pn as listIMessageAccountIds, qt as resolveIMessageGroupToolPolicy, un as listSignalAccountIds, yn as resolveToolsBySender, zt as normalizeSignalMessagingTarget } from "./runtime-CyTWeylK.js";
3
+ import { n as stripAnsi } from "./subsystem-DBPNbQDQ.js";
4
4
  import { g as registerLogTransport, w as resolvePreferredFasedAgentTmpDir } from "./globals-B_jjtAje.js";
5
- import { s as resolveStateDir } from "./paths-BEmvSyOV.js";
6
- import { c as isRecord, d as normalizeE164, g as safeParseJson, n as clamp, o as escapeRegExp, t as CONFIG_DIR, y as sleep } from "./utils-CYk9EKoq.js";
7
- import { A as GroupPolicySchema, Cr as formatCliCommand, D as BlockStreamingCoalesceSchema, E as ToolPolicySchema, F as TtsConfigSchema, Fn as withFileLock, H as parseDurationMs, I as TtsModeSchema, Jt as resolveConfiguredModelRef, L as TtsProviderSchema, M as MarkdownTableModeSchema, N as ReplyRuntimeConfigSchemaShape, O as DmConfigSchema, P as TtsAutoSchema, Pn as acquireFileLock, R as normalizeAllowFrom, Tr as isTruthyEnvValue, ar as DEFAULT_MODEL, d as GoogleChatConfigSchema, f as IMessageConfigSchema, fr as formatErrorMessage, hr as extractArchive, i as readConfigFileSnapshot, ir as DEFAULT_CONTEXT_TOKENS, j as MarkdownConfigSchema, k as DmPolicySchema, m as SignalConfigSchema, n as loadConfig, or as DEFAULT_PROVIDER, p as MSTeamsConfigSchema, sr as VERSION, z as requireOpenAllowFrom, zn as normalizeProviderId } from "./config-DKNrb8oT.js";
8
- import { E as resolveFasedAgentPackageRoot, a as resolveAgentDir, i as resolveAgentConfig, l as resolveAgentWorkspaceDir, p as resolveSessionAgentId, r as listAgentIds, u as resolveDefaultAgentId } from "./agent-scope-BbgPlhtw.js";
9
- import { S as parseAgentSessionKey, f as DEFAULT_ACCOUNT_ID, p as normalizeAccountId, s as normalizeAgentId, u as resolveThreadSessionKeys } from "./session-key-HSJ2KQTc.js";
5
+ import "./paths-BEmvSyOV.js";
6
+ import { d as normalizeE164, g as safeParseJson, n as clamp, o as escapeRegExp, y as sleep } from "./utils-CYk9EKoq.js";
7
+ import { A as GroupPolicySchema, D as BlockStreamingCoalesceSchema, E as ToolPolicySchema, F as TtsConfigSchema, Fn as withFileLock, I as TtsModeSchema, L as TtsProviderSchema, M as MarkdownTableModeSchema, N as ReplyRuntimeConfigSchemaShape, O as DmConfigSchema, P as TtsAutoSchema, Pn as acquireFileLock, R as normalizeAllowFrom, Tr as isTruthyEnvValue, d as GoogleChatConfigSchema, f as IMessageConfigSchema, fr as formatErrorMessage, j as MarkdownConfigSchema, k as DmPolicySchema, m as SignalConfigSchema, p as MSTeamsConfigSchema, z as requireOpenAllowFrom } from "./config-BxOWD3gF.js";
8
+ import { r as listAgentIds, u as resolveDefaultAgentId } from "./agent-scope-BbgPlhtw.js";
9
+ import { f as DEFAULT_ACCOUNT_ID, p as normalizeAccountId, u as resolveThreadSessionKeys } from "./session-key-HSJ2KQTc.js";
10
10
  import "./accounts-RHZyaB73.js";
11
11
  import "./accounts-CuqIKU8X.js";
12
12
  import "./logger-BbFvCoKk.js";
13
- import { t as runCommandWithTimeout } from "./exec-DQ8j4Fm3.js";
14
- import "./accounts-Bz_2QZSt.js";
15
- import { C as resolveNestedAllowlistDecision, S as resolveChannelEntryMatchWithFallback, b as normalizeChannelSlug, x as resolveChannelEntryMatch, y as buildChannelKeyCandidates } from "./allow-list-yqasgPpz.js";
16
- import { c as formatAllowlistMatchMeta, i as mergeAllowlist, l as resolveAllowlistMatchSimple, o as summarizeMapping, s as isDangerousNameMatchingEnabled } from "./resolve-utils-DrvLA82C.js";
17
- import { n as redactSensitiveText, t as getDefaultRedactPatterns } from "./redact-CwCz68Mi.js";
18
- import "./github-copilot-token-Dgug856m.js";
19
- import "./retry-DycQ4ymF.js";
20
- import { l as resolveStorePath } from "./paths-B88DQEK8.js";
21
- import { a as deleteAccountFromConfigSection, c as formatPairingApproveHint, l as resolveChannelDefaultAccountId, n as applyAccountNameToChannelSection, o as setAccountEnabledInConfigSection, r as migrateBaseNameToDefaultAccount, s as buildChannelConfigSchema, t as PAIRING_APPROVED_MESSAGE, u as emptyPluginConfigSchema } from "./pairing-message-B787pcJI.js";
22
- import { n as fetchWithTimeout } from "./fetch-timeout-jOIu9Xud.js";
23
- import { t as normalizeRequestInitHeadersForFetch } from "./fetch-headers-DvXyXtoI.js";
24
- import "./ip-BkeyFRJr.js";
25
- import { a as isBlockedHostnameOrIp, i as isBlockedHostname, o as isPrivateIpAddress, t as SsrFBlockedError } from "./ssrf-D_4q0mKh.js";
26
- import { t as fetchWithSsrFGuard } from "./fetch-guard-CxXvFYq5.js";
27
- import { t as redactSensitiveUrl } from "./redact-sensitive-url-B0RJQqO7.js";
28
- import { c as normalizeIMessageHandle, d as parseChatTargetPrefixesOrThrow, f as resolveServicePrefixedAllowTarget, g as isNormalizedSenderAllowed, h as isAllowedParsedChatSender, m as formatAllowFromLowercase, p as resolveServicePrefixedTarget, u as parseChatAllowTargetPrefixes } from "./send-DGUAXb2b.js";
29
- import { a as resolveOpenProviderRuntimeGroupPolicy, i as resolveDefaultGroupPolicy, n as GROUP_POLICY_BLOCKED_LABEL, o as warnMissingProviderGroupPolicyFallbackOnce, r as resolveAllowlistProviderRuntimeGroupPolicy, t as formatDocsLink } from "./links-D5ecKoG9.js";
30
- import { D as formatLocationText, O as toLocationContext, n as isWSLEnv, r as isWSLSync, t as isWSL2Sync } from "./wsl-Cw-xOsqF.js";
31
- import { o as readJsonFileWithFallback, s as writeJsonFileAtomically } from "./pairing-store-BdOcH_GA.js";
32
- import { p as chunkTextByBreakResolver } from "./chunk-CuJIMshx.js";
33
- import { n as resolveGatewayBindUrl, r as runPluginCommandWithTimeout, t as resolveTailnetHostWithRunner } from "./tailscale-status-BGBRraZW.js";
34
- import { a as resolveAckReaction, n as createReplyPrefixOptions, t as createReplyPrefixContext } from "./reply-prefix-CbPHNXlm.js";
35
- import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-Do_JU4Rh.js";
36
- import { i as rejectDevicePairing, r as listDevicePairing, t as approveDevicePairing } from "./device-pairing-J1IH1jFl.js";
37
- import { o as createAsyncLock, s as readJsonFile } from "./pairing-token-HQpaqod5.js";
38
- import { h as onDiagnosticEvent, m as isDiagnosticsEnabled, p as emitDiagnosticEvent } from "./diagnostic-C16gioN6.js";
39
- import "./diagnostic-session-state-B-9PL5r7.js";
40
- import "./optional-runtime-dependency-Bt_3Yigu.js";
41
- import { c as detectMime, l as extensionForMime, u as getFileExtension } from "./image-ops-BSQmb-17.js";
42
- import { At as resolveModel, C as resolveFederationHandle, S as resolveFederationBaseUrl, St as errorShape, b as normalizeHandle, bt as validatePushTestParams, gt as publicKeyRawBase64UrlFromPem, ht as loadOrCreateDeviceIdentity, x as resolveAgentPublicOrigin, xt as ErrorCodes, y as DEFAULT_FEDERATION_BASE_URL, yt as formatValidationErrors } from "./wallet-status-D9UVH6k9.js";
43
- import "./pi-model-discovery-DQdXL_-F.js";
44
- import "./runtime-dependency-B5Fut2tT.js";
45
- import { t as rawDataToString } from "./ws-CxmRDbD9.js";
46
- import "./path-alias-guards-BlIJ0AmG.js";
47
- import "./fs-safe-DztQeyQe.js";
48
- import "./markdown-tables-DrB-IM8r.js";
49
- import { n as loadWebMedia } from "./media-D8pWjqEt.js";
50
- import "./send-DWB5HFdb.js";
51
- import { r as extractOriginalFilename } from "./outbound-attachment-C9oadpUP.js";
52
- import "./fetch-RV7QDF43.js";
53
- import { U as listAcpSessionEntries } from "./thread-bindings.state-DYYR9qeT.js";
54
- import "./memory-search-DHSeU4pJ.js";
55
- import "./manager-DQ1dH8OM.js";
56
- import "./query-expansion-BM7lmqaP.js";
57
- import { a as jsonResult, c as readReactionParams, d as readStringParam, n as createActionGate, s as readNumberParam } from "./common-C90EHP1w.js";
58
- import { m as resolveNativeCommandName, o as listChatCommandsForConfig } from "./commands-registry-DwQIFJmL.js";
59
- import { n as listSkillCommandsForAgents } from "./skill-commands-DCnCOVR_.js";
60
- import "./directory-live-G7AN8y8N.js";
61
- import "./targets-BgSHco9b.js";
62
- import "./sandbox-paths-fc-HFGJr.js";
63
- import { n as missingTargetError } from "./target-errors-C0yNDbGS.js";
64
- import "./resolve-route-wp5xq4Ws.js";
65
- import "./render-K7NwXvVu.js";
66
- import "./tables-DX84FwPB.js";
67
- import { C as buildBaseChannelStatusSummary, E as createDefaultChannelRuntimeState, S as buildBaseAccountStatusSnapshot, T as collectStatusIssuesFromLastError, b as setOnboardingChannelEnabled, c as parseOnboardingEntriesAllowingWildcard, f as promptParsedAllowFromForScopedChannel, h as resolveAccountIdForConfigure, l as patchChannelConfigForAccount, r as mergeAllowFromEntries, t as addWildcardAllowFrom, u as promptAccountId, v as setChannelDmPolicyWithAllowFrom, w as buildTokenChannelStatusSummary } from "./helpers-C1pcZJsv.js";
68
- import { t as buildMediaPayload } from "./media-payload-DpYEcV-X.js";
69
- import { t as promptChannelAccessConfig } from "./channel-access-BiWxa3LR.js";
70
- import { n as asString, r as collectIssuesForEnabledAccounts } from "./shared-V35XNAbz.js";
71
- import path from "node:path";
72
- import chalk from "chalk";
73
- import fs, { createWriteStream, existsSync } from "node:fs";
74
- import os from "node:os";
75
- import JSON5 from "json5";
76
- import { format } from "node:util";
77
- import fs$1 from "node:fs/promises";
78
- import { spawn } from "node:child_process";
79
- import { createHash, createPrivateKey, randomUUID, sign } from "node:crypto";
80
- import { pipeline } from "node:stream/promises";
81
- import { z } from "zod";
82
- import { request } from "node:https";
83
- import { WebSocket as WebSocket$1 } from "ws";
84
- import http2 from "node:http2";
85
-
86
- //#region src/video-generation/dashscope-compatible.ts
87
- const DEFAULT_VIDEO_GENERATION_DURATION_SECONDS = 5;
88
- const DEFAULT_VIDEO_GENERATION_TIMEOUT_MS = 12e4;
89
- const DEFAULT_VIDEO_RESOLUTION_TO_SIZE = {
90
- "480P": "832*480",
91
- "720P": "1280*720",
92
- "1080P": "1920*1080"
93
- };
94
- const DEFAULT_VIDEO_GENERATION_POLL_INTERVAL_MS = 2500;
95
- const DEFAULT_VIDEO_GENERATION_MAX_POLL_ATTEMPTS = 120;
96
- function buildDashscopeVideoGenerationInput(params) {
97
- if ([...params.req.inputImages ?? [], ...params.req.inputVideos ?? []].some((asset) => !asset.url?.trim() && asset.buffer)) throw new Error(`${params.providerLabel} video generation currently requires remote http(s) URLs for reference images/videos.`);
98
- const input = { prompt: params.req.prompt };
99
- const referenceUrls = resolveVideoGenerationReferenceUrls(params.req.inputImages, params.req.inputVideos);
100
- if (referenceUrls.length === 1 && (params.req.inputImages?.length ?? 0) === 1 && !params.req.inputVideos?.length) input.img_url = referenceUrls[0];
101
- else if (referenceUrls.length > 0) input.reference_urls = referenceUrls;
102
- return input;
103
- }
104
- function resolveVideoGenerationReferenceUrls(inputImages, inputVideos) {
105
- return [...inputImages ?? [], ...inputVideos ?? []].map((asset) => asset.url?.trim()).filter((value) => Boolean(value));
106
- }
107
- function buildDashscopeVideoGenerationParameters(req, resolutionToSize = DEFAULT_VIDEO_RESOLUTION_TO_SIZE) {
108
- const parameters = {};
109
- const size = req.size?.trim() || (req.resolution ? resolutionToSize[req.resolution] : void 0);
110
- if (size) parameters.size = size;
111
- if (req.aspectRatio?.trim()) parameters.aspect_ratio = req.aspectRatio.trim();
112
- if (typeof req.durationSeconds === "number" && Number.isFinite(req.durationSeconds)) parameters.duration = Math.max(1, Math.round(req.durationSeconds));
113
- if (typeof req.audio === "boolean") parameters.enable_audio = req.audio;
114
- if (typeof req.watermark === "boolean") parameters.watermark = req.watermark;
115
- return Object.keys(parameters).length > 0 ? parameters : void 0;
116
- }
117
- function extractDashscopeVideoUrls(payload) {
118
- const urls = [...payload.output?.results?.map((entry) => entry.video_url).filter(Boolean) ?? [], payload.output?.video_url].filter((value) => typeof value === "string" && value.trim().length > 0);
119
- return [...new Set(urls)];
120
- }
121
- async function pollDashscopeVideoTaskUntilComplete(params) {
122
- for (let attempt = 0; attempt < DEFAULT_VIDEO_GENERATION_MAX_POLL_ATTEMPTS; attempt += 1) {
123
- const response = await fetchWithTimeout(`${params.baseUrl}/api/v1/tasks/${params.taskId}`, {
124
- method: "GET",
125
- headers: params.headers
126
- }, params.timeoutMs ?? params.defaultTimeoutMs ?? DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, params.fetchFn);
127
- await assertOkOrThrowHttpError(response, `${params.providerLabel} video-generation task poll failed`);
128
- const payload = await response.json();
129
- const status = payload.output?.task_status?.trim().toUpperCase();
130
- if (status === "SUCCEEDED") return payload;
131
- if (status === "FAILED" || status === "CANCELED") throw new Error(payload.output?.message?.trim() || payload.message?.trim() || `${params.providerLabel} video generation task ${params.taskId} ${status.toLowerCase()}`);
132
- await new Promise((resolve) => setTimeout(resolve, DEFAULT_VIDEO_GENERATION_POLL_INTERVAL_MS));
133
- }
134
- throw new Error(`${params.providerLabel} video generation task ${params.taskId} did not finish in time`);
135
- }
136
- async function downloadDashscopeGeneratedVideos(params) {
137
- const videos = [];
138
- for (const [index, url] of params.urls.entries()) {
139
- const response = await fetchWithTimeout(url, { method: "GET" }, params.timeoutMs ?? params.defaultTimeoutMs ?? DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, params.fetchFn);
140
- await assertOkOrThrowHttpError(response, `${params.providerLabel} generated video download failed`);
141
- const arrayBuffer = await response.arrayBuffer();
142
- videos.push({
143
- buffer: Buffer.from(arrayBuffer),
144
- mimeType: response.headers.get("content-type")?.trim() || "video/mp4",
145
- fileName: `video-${index + 1}.mp4`,
146
- metadata: { sourceUrl: redactSensitiveUrl(url) }
147
- });
148
- }
149
- return videos;
150
- }
151
-
152
- //#endregion
153
- //#region src/plugins/capability-provider-runtime.ts
154
- function resolvePluginCapabilityProviders(params) {
155
- return (getActivePluginRegistry()?.[params.key] ?? []).map((entry) => entry.provider);
156
- }
157
-
158
- //#endregion
159
- //#region src/realtime-transcription/provider-registry.ts
160
- function trimToUndefined$1(value) {
161
- const trimmed = value?.trim().toLowerCase();
162
- return trimmed ? trimmed : void 0;
163
- }
164
- function normalizeRealtimeTranscriptionProviderId(providerId) {
165
- return trimToUndefined$1(providerId);
166
- }
167
- function resolveRealtimeTranscriptionProviderEntries(_cfg) {
168
- return resolvePluginCapabilityProviders({ key: "realtimeTranscriptionProviders" });
169
- }
170
- function buildProviderMaps$1(_cfg) {
171
- const canonical = /* @__PURE__ */ new Map();
172
- const aliases = /* @__PURE__ */ new Map();
173
- const register = (provider) => {
174
- const id = normalizeRealtimeTranscriptionProviderId(provider.id);
175
- if (!id) return;
176
- canonical.set(id, provider);
177
- aliases.set(id, provider);
178
- for (const alias of provider.aliases ?? []) {
179
- const normalizedAlias = normalizeRealtimeTranscriptionProviderId(alias);
180
- if (normalizedAlias) aliases.set(normalizedAlias, provider);
181
- }
182
- };
183
- for (const provider of resolveRealtimeTranscriptionProviderEntries(_cfg)) register(provider);
184
- return {
185
- canonical,
186
- aliases
187
- };
188
- }
189
- function listRealtimeTranscriptionProviders(cfg) {
190
- return [...buildProviderMaps$1(cfg).canonical.values()];
191
- }
192
- function getRealtimeTranscriptionProvider(providerId, cfg) {
193
- const normalized = normalizeRealtimeTranscriptionProviderId(providerId);
194
- if (!normalized) return;
195
- return buildProviderMaps$1(cfg).aliases.get(normalized);
196
- }
197
- function canonicalizeRealtimeTranscriptionProviderId(providerId, cfg) {
198
- const normalized = normalizeRealtimeTranscriptionProviderId(providerId);
199
- if (!normalized) return;
200
- return getRealtimeTranscriptionProvider(normalized, cfg)?.id ?? normalized;
201
- }
202
-
203
- //#endregion
204
- //#region src/realtime-voice/provider-registry.ts
205
- function trimToUndefined(value) {
206
- const trimmed = value?.trim().toLowerCase();
207
- return trimmed ? trimmed : void 0;
208
- }
209
- function normalizeRealtimeVoiceProviderId(providerId) {
210
- return trimToUndefined(providerId);
211
- }
212
- function resolveRealtimeVoiceProviderEntries(_cfg) {
213
- return resolvePluginCapabilityProviders({ key: "realtimeVoiceProviders" });
214
- }
215
- function buildProviderMaps(_cfg) {
216
- const canonical = /* @__PURE__ */ new Map();
217
- const aliases = /* @__PURE__ */ new Map();
218
- const register = (provider) => {
219
- const id = normalizeRealtimeVoiceProviderId(provider.id);
220
- if (!id) return;
221
- canonical.set(id, provider);
222
- aliases.set(id, provider);
223
- for (const alias of provider.aliases ?? []) {
224
- const normalizedAlias = normalizeRealtimeVoiceProviderId(alias);
225
- if (normalizedAlias) aliases.set(normalizedAlias, provider);
226
- }
227
- };
228
- for (const provider of resolveRealtimeVoiceProviderEntries(_cfg)) register(provider);
229
- return {
230
- canonical,
231
- aliases
232
- };
233
- }
234
- function listRealtimeVoiceProviders(cfg) {
235
- return [...buildProviderMaps(cfg).canonical.values()];
236
- }
237
- function getRealtimeVoiceProvider(providerId, cfg) {
238
- const normalized = normalizeRealtimeVoiceProviderId(providerId);
239
- if (!normalized) return;
240
- return buildProviderMaps(cfg).aliases.get(normalized);
241
- }
242
- function canonicalizeRealtimeVoiceProviderId(providerId, cfg) {
243
- const normalized = normalizeRealtimeVoiceProviderId(providerId);
244
- if (!normalized) return;
245
- return getRealtimeVoiceProvider(normalized, cfg)?.id ?? normalized;
246
- }
247
-
248
- //#endregion
249
- //#region src/plugin-sdk/group-access.ts
250
- function evaluateSenderGroupAccess(params) {
251
- const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
252
- providerConfigPresent: params.providerConfigPresent,
253
- groupPolicy: params.configuredGroupPolicy,
254
- defaultGroupPolicy: params.defaultGroupPolicy
255
- });
256
- if (groupPolicy === "disabled") return {
257
- allowed: false,
258
- groupPolicy,
259
- providerMissingFallbackApplied,
260
- reason: "disabled"
261
- };
262
- if (groupPolicy === "allowlist") {
263
- if (params.groupAllowFrom.length === 0) return {
264
- allowed: false,
265
- groupPolicy,
266
- providerMissingFallbackApplied,
267
- reason: "empty_allowlist"
268
- };
269
- if (!params.isSenderAllowed(params.senderId, params.groupAllowFrom)) return {
270
- allowed: false,
271
- groupPolicy,
272
- providerMissingFallbackApplied,
273
- reason: "sender_not_allowlisted"
274
- };
275
- }
276
- return {
277
- allowed: true,
278
- groupPolicy,
279
- providerMissingFallbackApplied,
280
- reason: "allowed"
281
- };
282
- }
283
-
284
- //#endregion
285
- //#region src/plugin-sdk/command-auth.ts
286
- async function resolveSenderCommandAuthorization(params) {
287
- const shouldComputeAuth = params.shouldComputeCommandAuthorized(params.rawBody, params.cfg);
288
- const storeAllowFrom = !params.isGroup && params.dmPolicy !== "allowlist" && (params.dmPolicy !== "open" || shouldComputeAuth) ? await params.readAllowFromStore().catch(() => []) : [];
289
- const access = resolveDmGroupAccessWithLists({
290
- isGroup: params.isGroup,
291
- dmPolicy: params.dmPolicy,
292
- groupPolicy: "allowlist",
293
- allowFrom: params.configuredAllowFrom,
294
- groupAllowFrom: params.configuredGroupAllowFrom ?? [],
295
- storeAllowFrom,
296
- isSenderAllowed: (allowFrom) => params.isSenderAllowed(params.senderId, allowFrom)
297
- });
298
- const effectiveAllowFrom = access.effectiveAllowFrom;
299
- const effectiveGroupAllowFrom = access.effectiveGroupAllowFrom;
300
- const useAccessGroups = params.cfg.commands?.useAccessGroups !== false;
301
- const senderAllowedForCommands = params.isSenderAllowed(params.senderId, params.isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom);
302
- const ownerAllowedForCommands = params.isSenderAllowed(params.senderId, effectiveAllowFrom);
303
- const groupAllowedForCommands = params.isSenderAllowed(params.senderId, effectiveGroupAllowFrom);
304
- return {
305
- shouldComputeAuth,
306
- effectiveAllowFrom,
307
- effectiveGroupAllowFrom,
308
- senderAllowedForCommands,
309
- commandAuthorized: shouldComputeAuth ? params.resolveCommandAuthorizedFromAuthorizers({
310
- useAccessGroups,
311
- authorizers: [{
312
- configured: effectiveAllowFrom.length > 0,
313
- allowed: ownerAllowedForCommands
314
- }, {
315
- configured: effectiveGroupAllowFrom.length > 0,
316
- allowed: groupAllowedForCommands
317
- }]
318
- }) : void 0
319
- };
320
- }
321
-
322
- //#endregion
323
- //#region src/plugin-sdk/config-paths.ts
324
- function resolveChannelAccountConfigBasePath(params) {
325
- const accounts = (params.cfg.channels?.[params.channelKey])?.accounts;
326
- return Boolean(accounts?.[params.accountId]) ? `channels.${params.channelKey}.accounts.${params.accountId}.` : `channels.${params.channelKey}.`;
327
- }
328
-
329
- //#endregion
330
- //#region src/plugin-sdk/text-chunking.ts
331
- function chunkTextForOutbound(text, limit) {
332
- return chunkTextByBreakResolver(text, limit, (window) => {
333
- const lastNewline = window.lastIndexOf("\n");
334
- const lastSpace = window.lastIndexOf(" ");
335
- return lastNewline > 0 ? lastNewline : lastSpace;
336
- });
337
- }
338
-
339
- //#endregion
340
- //#region src/plugin-sdk/agent-media-payload.ts
341
- function buildAgentMediaPayload(mediaList) {
342
- const first = mediaList[0];
343
- const mediaPaths = mediaList.map((media) => media.path);
344
- const mediaTypes = mediaList.map((media) => media.contentType).filter(Boolean);
345
- return {
346
- MediaPath: first?.path,
347
- MediaType: first?.contentType ?? void 0,
348
- MediaUrl: first?.path,
349
- MediaPaths: mediaPaths.length > 0 ? mediaPaths : void 0,
350
- MediaUrls: mediaPaths.length > 0 ? mediaPaths : void 0,
351
- MediaTypes: mediaTypes.length > 0 ? mediaTypes : void 0
352
- };
353
- }
354
-
355
- //#endregion
356
- //#region src/plugin-sdk/fetch-auth.ts
357
- function isAuthFailureStatus(status) {
358
- return status === 401 || status === 403;
359
- }
360
- async function fetchWithBearerAuthScopeFallback(params) {
361
- const fetchFn = params.fetchFn ?? fetch;
362
- let parsedUrl;
363
- try {
364
- parsedUrl = new URL(params.url);
365
- } catch {
366
- throw new Error(`Invalid URL: ${params.url}`);
367
- }
368
- if (params.requireHttps === true && parsedUrl.protocol !== "https:") throw new Error(`URL must use HTTPS: ${params.url}`);
369
- const requestInit = normalizeRequestInitHeadersForFetch(params.requestInit);
370
- const fetchOnce = (headers) => fetchFn(params.url, {
371
- ...requestInit,
372
- ...headers ? { headers } : {}
373
- });
374
- const firstAttempt = await fetchOnce();
375
- if (firstAttempt.ok) return firstAttempt;
376
- if (!params.tokenProvider) return firstAttempt;
377
- const shouldRetry = params.shouldRetry ?? ((response) => isAuthFailureStatus(response.status));
378
- if (!shouldRetry(firstAttempt)) return firstAttempt;
379
- if (params.shouldAttachAuth && !params.shouldAttachAuth(params.url)) return firstAttempt;
380
- for (const scope of params.scopes) try {
381
- const token = await params.tokenProvider.getAccessToken(scope);
382
- const authHeaders = new Headers(requestInit?.headers);
383
- authHeaders.set("Authorization", `Bearer ${token}`);
384
- const authAttempt = await fetchOnce(authHeaders);
385
- if (authAttempt.ok) return authAttempt;
386
- if (!shouldRetry(authAttempt)) continue;
387
- } catch {}
388
- return firstAttempt;
389
- }
390
-
391
- //#endregion
392
- //#region src/plugin-sdk/pairing-access.ts
393
- function createScopedPairingAccess(params) {
394
- const resolvedAccountId = normalizeAccountId(params.accountId);
395
- return {
396
- accountId: resolvedAccountId,
397
- readAllowFromStore: () => params.core.channel.pairing.readAllowFromStore({
398
- channel: params.channel,
399
- accountId: resolvedAccountId
400
- }),
401
- readStoreForDmPolicy: (provider, accountId) => params.core.channel.pairing.readAllowFromStore({
402
- channel: provider,
403
- accountId: normalizeAccountId(accountId)
404
- }),
405
- upsertPairingRequest: (input) => params.core.channel.pairing.upsertPairingRequest({
406
- channel: params.channel,
407
- accountId: resolvedAccountId,
408
- ...input
409
- })
410
- };
411
- }
412
-
413
- //#endregion
414
- //#region src/plugin-sdk/provider-auth-result.ts
415
- function buildOauthProviderAuthResult(params) {
416
- const email = params.email ?? void 0;
417
- return {
418
- profiles: [{
419
- profileId: `${params.profilePrefix ?? params.providerId}:${email ?? "default"}`,
420
- credential: {
421
- type: "oauth",
422
- provider: params.providerId,
423
- access: params.access,
424
- ...params.refresh ? { refresh: params.refresh } : {},
425
- ...Number.isFinite(params.expires) ? { expires: params.expires } : {},
426
- ...email ? { email } : {},
427
- ...params.credentialExtra
428
- }
429
- }],
430
- configPatch: params.configPatch ?? { agents: { defaults: { models: { [params.defaultModel]: {} } } } },
431
- defaultModel: params.defaultModel,
432
- notes: params.notes
433
- };
434
- }
435
-
436
- //#endregion
437
- //#region src/plugin-sdk/reply-payload.ts
438
- function normalizeOutboundReplyPayload(payload) {
439
- return {
440
- text: typeof payload.text === "string" ? payload.text : void 0,
441
- mediaUrls: Array.isArray(payload.mediaUrls) ? payload.mediaUrls.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0,
442
- mediaUrl: typeof payload.mediaUrl === "string" ? payload.mediaUrl : void 0,
443
- replyToId: typeof payload.replyToId === "string" ? payload.replyToId : void 0
444
- };
445
- }
446
- function createNormalizedOutboundDeliverer(handler) {
447
- return async (payload) => {
448
- await handler(payload && typeof payload === "object" ? normalizeOutboundReplyPayload(payload) : {});
449
- };
450
- }
451
- function resolveOutboundMediaUrls(payload) {
452
- if (payload.mediaUrls?.length) return payload.mediaUrls;
453
- if (payload.mediaUrl) return [payload.mediaUrl];
454
- return [];
455
- }
456
- function formatTextWithAttachmentLinks(text, mediaUrls) {
457
- const trimmedText = text?.trim() ?? "";
458
- if (!trimmedText && mediaUrls.length === 0) return "";
459
- const mediaBlock = mediaUrls.length ? mediaUrls.map((url) => `Attachment: ${url}`).join("\n") : "";
460
- if (!trimmedText) return mediaBlock;
461
- if (!mediaBlock) return trimmedText;
462
- return `${trimmedText}\n\n${mediaBlock}`;
463
- }
464
- async function sendMediaWithLeadingCaption(params) {
465
- if (params.mediaUrls.length === 0) return false;
466
- let first = true;
467
- for (const mediaUrl of params.mediaUrls) {
468
- const caption = first ? params.caption : void 0;
469
- first = false;
470
- try {
471
- await params.send({
472
- mediaUrl,
473
- caption
474
- });
475
- } catch (error) {
476
- if (params.onError) {
477
- params.onError(error, mediaUrl);
478
- continue;
479
- }
480
- throw error;
481
- }
482
- }
483
- return true;
484
- }
485
-
486
- //#endregion
487
- //#region src/plugin-sdk/ssrf-policy.ts
488
- function normalizeHostnameSuffix(value) {
489
- const trimmed = value.trim().toLowerCase();
490
- if (!trimmed) return "";
491
- if (trimmed === "*" || trimmed === "*.") return "*";
492
- return trimmed.replace(/^\*\.?/, "").replace(/^\.+/, "").replace(/\.+$/, "");
493
- }
494
- function isHostnameAllowedBySuffixAllowlist(hostname, allowlist) {
495
- if (allowlist.includes("*")) return true;
496
- const normalized = hostname.toLowerCase();
497
- return allowlist.some((entry) => normalized === entry || normalized.endsWith(`.${entry}`));
498
- }
499
- function normalizeHostnameSuffixAllowlist(input, defaults) {
500
- const source = input && input.length > 0 ? input : defaults;
501
- if (!source || source.length === 0) return [];
502
- const normalized = source.map(normalizeHostnameSuffix).filter(Boolean);
503
- if (normalized.includes("*")) return ["*"];
504
- return Array.from(new Set(normalized));
505
- }
506
- function isHttpsUrlAllowedByHostnameSuffixAllowlist(url, allowlist) {
507
- try {
508
- const parsed = new URL(url);
509
- if (parsed.protocol !== "https:") return false;
510
- return isHostnameAllowedBySuffixAllowlist(parsed.hostname, allowlist);
511
- } catch {
512
- return false;
513
- }
514
- }
515
- /**
516
- * Converts suffix-style host allowlists (for example "example.com") into SSRF
517
- * hostname allowlist patterns used by the shared fetch guard.
518
- *
519
- * Suffix semantics:
520
- * - "example.com" allows "example.com" and "*.example.com"
521
- * - "*" disables hostname allowlist restrictions
522
- */
523
- function buildHostnameAllowlistPolicyFromSuffixAllowlist(allowHosts) {
524
- const normalizedAllowHosts = normalizeHostnameSuffixAllowlist(allowHosts);
525
- if (normalizedAllowHosts.length === 0) return;
526
- const patterns = /* @__PURE__ */ new Set();
527
- for (const normalized of normalizedAllowHosts) {
528
- if (normalized === "*") return;
529
- patterns.add(normalized);
530
- patterns.add(`*.${normalized}`);
531
- }
532
- if (patterns.size === 0) return;
533
- return { hostnameAllowlist: Array.from(patterns) };
534
- }
535
-
536
- //#endregion
537
- //#region src/plugin-sdk/webhook-path.ts
538
- function normalizeWebhookPath(raw) {
539
- const trimmed = raw.trim();
540
- if (!trimmed) return "/";
541
- const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
542
- if (withSlash.length > 1 && withSlash.endsWith("/")) return withSlash.slice(0, -1);
543
- return withSlash;
544
- }
545
- function resolveWebhookPath(params) {
546
- const trimmedPath = params.webhookPath?.trim();
547
- if (trimmedPath) return normalizeWebhookPath(trimmedPath);
548
- if (params.webhookUrl?.trim()) try {
549
- return normalizeWebhookPath(new URL(params.webhookUrl).pathname || "/");
550
- } catch {
551
- return null;
552
- }
553
- return params.defaultPath ?? null;
554
- }
555
-
556
- //#endregion
557
- //#region src/plugin-sdk/webhook-targets.ts
558
- function registerWebhookTarget(targetsByPath, target) {
559
- const key = normalizeWebhookPath(target.path);
560
- const normalizedTarget = {
561
- ...target,
562
- path: key
563
- };
564
- const existing = targetsByPath.get(key) ?? [];
565
- targetsByPath.set(key, [...existing, normalizedTarget]);
566
- const unregister = () => {
567
- const updated = (targetsByPath.get(key) ?? []).filter((entry) => entry !== normalizedTarget);
568
- if (updated.length > 0) {
569
- targetsByPath.set(key, updated);
570
- return;
571
- }
572
- targetsByPath.delete(key);
573
- };
574
- return {
575
- target: normalizedTarget,
576
- unregister
577
- };
578
- }
579
- function resolveWebhookTargets(req, targetsByPath) {
580
- const path = normalizeWebhookPath(new URL(req.url ?? "/", "http://localhost").pathname);
581
- const targets = targetsByPath.get(path);
582
- if (!targets || targets.length === 0) return null;
583
- return {
584
- path,
585
- targets
586
- };
587
- }
588
- function resolveSingleWebhookTarget(targets, isMatch) {
589
- let matched;
590
- for (const target of targets) {
591
- if (!isMatch(target)) continue;
592
- if (matched) return { kind: "ambiguous" };
593
- matched = target;
594
- }
595
- if (!matched) return { kind: "none" };
596
- return {
597
- kind: "single",
598
- target: matched
599
- };
600
- }
601
- async function resolveSingleWebhookTargetAsync(targets, isMatch) {
602
- let matched;
603
- for (const target of targets) {
604
- if (!await isMatch(target)) continue;
605
- if (matched) return { kind: "ambiguous" };
606
- matched = target;
607
- }
608
- if (!matched) return { kind: "none" };
609
- return {
610
- kind: "single",
611
- target: matched
612
- };
613
- }
614
- function rejectNonPostWebhookRequest(req, res) {
615
- if (req.method === "POST") return false;
616
- res.statusCode = 405;
617
- res.setHeader("Allow", "POST");
618
- res.end("Method Not Allowed");
619
- return true;
620
- }
621
-
622
- //#endregion
623
- //#region src/plugin-sdk/persistent-dedupe.ts
624
- const DEFAULT_LOCK_OPTIONS = {
625
- retries: {
626
- retries: 6,
627
- factor: 1.35,
628
- minTimeout: 8,
629
- maxTimeout: 180,
630
- randomize: true
631
- },
632
- stale: 6e4
633
- };
634
- function mergeLockOptions(overrides) {
635
- return {
636
- stale: overrides?.stale ?? DEFAULT_LOCK_OPTIONS.stale,
637
- retries: {
638
- retries: overrides?.retries?.retries ?? DEFAULT_LOCK_OPTIONS.retries.retries,
639
- factor: overrides?.retries?.factor ?? DEFAULT_LOCK_OPTIONS.retries.factor,
640
- minTimeout: overrides?.retries?.minTimeout ?? DEFAULT_LOCK_OPTIONS.retries.minTimeout,
641
- maxTimeout: overrides?.retries?.maxTimeout ?? DEFAULT_LOCK_OPTIONS.retries.maxTimeout,
642
- randomize: overrides?.retries?.randomize ?? DEFAULT_LOCK_OPTIONS.retries.randomize
643
- }
644
- };
645
- }
646
- function sanitizeData(value) {
647
- if (!value || typeof value !== "object") return {};
648
- const out = {};
649
- for (const [key, ts] of Object.entries(value)) if (typeof ts === "number" && Number.isFinite(ts) && ts > 0) out[key] = ts;
650
- return out;
651
- }
652
- function pruneData(data, now, ttlMs, maxEntries) {
653
- if (ttlMs > 0) {
654
- for (const [key, ts] of Object.entries(data)) if (now - ts >= ttlMs) delete data[key];
655
- }
656
- const keys = Object.keys(data);
657
- if (keys.length <= maxEntries) return;
658
- keys.toSorted((a, b) => data[a] - data[b]).slice(0, keys.length - maxEntries).forEach((key) => {
659
- delete data[key];
660
- });
661
- }
662
- function createPersistentDedupe(options) {
663
- const ttlMs = Math.max(0, Math.floor(options.ttlMs));
664
- const memoryMaxSize = Math.max(0, Math.floor(options.memoryMaxSize));
665
- const fileMaxEntries = Math.max(1, Math.floor(options.fileMaxEntries));
666
- const lockOptions = mergeLockOptions(options.lockOptions);
667
- const memory = createDedupeCache({
668
- ttlMs,
669
- maxSize: memoryMaxSize
670
- });
671
- const inflight = /* @__PURE__ */ new Map();
672
- async function checkAndRecordInner(key, namespace, scopedKey, now, onDiskError) {
673
- if (memory.check(scopedKey, now)) return false;
674
- const path = options.resolveFilePath(namespace);
675
- try {
676
- return !await withFileLock(path, lockOptions, async () => {
677
- const { value } = await readJsonFileWithFallback(path, {});
678
- const data = sanitizeData(value);
679
- const seenAt = data[key];
680
- if (seenAt != null && (ttlMs <= 0 || now - seenAt < ttlMs)) return true;
681
- data[key] = now;
682
- pruneData(data, now, ttlMs, fileMaxEntries);
683
- await writeJsonFileAtomically(path, data);
684
- return false;
685
- });
686
- } catch (error) {
687
- onDiskError?.(error);
688
- return true;
689
- }
690
- }
691
- async function checkAndRecord(key, dedupeOptions) {
692
- const trimmed = key.trim();
693
- if (!trimmed) return true;
694
- const namespace = dedupeOptions?.namespace?.trim() || "global";
695
- const scopedKey = `${namespace}:${trimmed}`;
696
- if (inflight.has(scopedKey)) return false;
697
- const onDiskError = dedupeOptions?.onDiskError ?? options.onDiskError;
698
- const work = checkAndRecordInner(trimmed, namespace, scopedKey, dedupeOptions?.now ?? Date.now(), onDiskError);
699
- inflight.set(scopedKey, work);
700
- try {
701
- return await work;
702
- } finally {
703
- inflight.delete(scopedKey);
704
- }
705
- }
706
- return {
707
- checkAndRecord,
708
- clearMemory: () => memory.clear(),
709
- memorySize: () => memory.size()
710
- };
711
- }
712
-
713
- //#endregion
714
- //#region src/plugin-sdk/runtime.ts
715
- function createLoggerBackedRuntime(params) {
716
- return {
717
- log: (...args) => {
718
- params.logger.info(format(...args));
719
- },
720
- error: (...args) => {
721
- params.logger.error(format(...args));
722
- },
723
- exit: (code) => {
724
- throw params.exitError?.(code) ?? /* @__PURE__ */ new Error(`exit ${code}`);
725
- }
726
- };
727
- }
728
-
729
- //#endregion
730
- //#region src/line/flex-templates/basic-cards.ts
731
- /**
732
- * Create an info card with title, body, and optional footer
733
- *
734
- * Editorial design: Clean hierarchy with accent bar, generous spacing,
735
- * and subtle background zones for visual separation.
736
- */
737
- function createInfoCard(title, body, footer) {
738
- const bubble = {
739
- type: "bubble",
740
- size: "mega",
741
- body: {
742
- type: "box",
743
- layout: "vertical",
744
- contents: [{
745
- type: "box",
746
- layout: "horizontal",
747
- contents: [{
748
- type: "box",
749
- layout: "vertical",
750
- contents: [],
751
- width: "4px",
752
- backgroundColor: "#06C755",
753
- cornerRadius: "2px"
754
- }, {
755
- type: "text",
756
- text: title,
757
- weight: "bold",
758
- size: "xl",
759
- color: "#111111",
760
- wrap: true,
761
- flex: 1,
762
- margin: "lg"
763
- }]
764
- }, {
765
- type: "box",
766
- layout: "vertical",
767
- contents: [{
768
- type: "text",
769
- text: body,
770
- size: "md",
771
- color: "#444444",
772
- wrap: true,
773
- lineSpacing: "6px"
774
- }],
775
- margin: "xl",
776
- paddingAll: "lg",
777
- backgroundColor: "#F8F9FA",
778
- cornerRadius: "lg"
779
- }],
780
- paddingAll: "xl",
781
- backgroundColor: "#FFFFFF"
782
- }
783
- };
784
- if (footer) attachFooterText(bubble, footer);
785
- return bubble;
786
- }
787
- /**
788
- * Create a list card with title and multiple items
789
- *
790
- * Editorial design: Numbered/bulleted list with clear visual hierarchy,
791
- * accent dots for each item, and generous spacing.
792
- */
793
- function createListCard(title, items) {
794
- const itemContents = items.slice(0, 8).map((item, index) => {
795
- const itemContents = [{
796
- type: "text",
797
- text: item.title,
798
- size: "md",
799
- weight: "bold",
800
- color: "#1a1a1a",
801
- wrap: true
802
- }];
803
- if (item.subtitle) itemContents.push({
804
- type: "text",
805
- text: item.subtitle,
806
- size: "sm",
807
- color: "#888888",
808
- wrap: true,
809
- margin: "xs"
810
- });
811
- const itemBox = {
812
- type: "box",
813
- layout: "horizontal",
814
- contents: [{
815
- type: "box",
816
- layout: "vertical",
817
- contents: [{
818
- type: "box",
819
- layout: "vertical",
820
- contents: [],
821
- width: "8px",
822
- height: "8px",
823
- backgroundColor: index === 0 ? "#06C755" : "#DDDDDD",
824
- cornerRadius: "4px"
825
- }],
826
- width: "20px",
827
- alignItems: "center",
828
- paddingTop: "sm"
829
- }, {
830
- type: "box",
831
- layout: "vertical",
832
- contents: itemContents,
833
- flex: 1
834
- }],
835
- margin: index > 0 ? "lg" : void 0
836
- };
837
- if (item.action) itemBox.action = item.action;
838
- return itemBox;
839
- });
840
- return {
841
- type: "bubble",
842
- size: "mega",
843
- body: {
844
- type: "box",
845
- layout: "vertical",
846
- contents: [
847
- {
848
- type: "text",
849
- text: title,
850
- weight: "bold",
851
- size: "xl",
852
- color: "#111111",
853
- wrap: true
854
- },
855
- {
856
- type: "separator",
857
- margin: "lg",
858
- color: "#EEEEEE"
859
- },
860
- {
861
- type: "box",
862
- layout: "vertical",
863
- contents: itemContents,
864
- margin: "lg"
865
- }
866
- ],
867
- paddingAll: "xl",
868
- backgroundColor: "#FFFFFF"
869
- }
870
- };
871
- }
872
- /**
873
- * Create an image card with image, title, and optional body text
874
- */
875
- function createImageCard(imageUrl, title, body, options) {
876
- const bubble = {
877
- type: "bubble",
878
- hero: {
879
- type: "image",
880
- url: imageUrl,
881
- size: "full",
882
- aspectRatio: options?.aspectRatio ?? "20:13",
883
- aspectMode: options?.aspectMode ?? "cover",
884
- action: options?.action
885
- },
886
- body: {
887
- type: "box",
888
- layout: "vertical",
889
- contents: [{
890
- type: "text",
891
- text: title,
892
- weight: "bold",
893
- size: "xl",
894
- wrap: true
895
- }],
896
- paddingAll: "lg"
897
- }
898
- };
899
- if (body && bubble.body) bubble.body.contents.push({
900
- type: "text",
901
- text: body,
902
- size: "md",
903
- wrap: true,
904
- margin: "md",
905
- color: "#666666"
906
- });
907
- return bubble;
908
- }
909
- /**
910
- * Create an action card with title, body, and action buttons
911
- */
912
- function createActionCard(title, body, actions, options) {
913
- const bubble = {
914
- type: "bubble",
915
- body: {
916
- type: "box",
917
- layout: "vertical",
918
- contents: [{
919
- type: "text",
920
- text: title,
921
- weight: "bold",
922
- size: "xl",
923
- wrap: true
924
- }, {
925
- type: "text",
926
- text: body,
927
- size: "md",
928
- wrap: true,
929
- margin: "md",
930
- color: "#666666"
931
- }],
932
- paddingAll: "lg"
933
- },
934
- footer: {
935
- type: "box",
936
- layout: "vertical",
937
- contents: actions.slice(0, 4).map((action, index) => ({
938
- type: "button",
939
- action: action.action,
940
- style: index === 0 ? "primary" : "secondary",
941
- margin: index > 0 ? "sm" : void 0
942
- })),
943
- paddingAll: "md"
944
- }
945
- };
946
- if (options?.imageUrl) bubble.hero = {
947
- type: "image",
948
- url: options.imageUrl,
949
- size: "full",
950
- aspectRatio: options.aspectRatio ?? "20:13",
951
- aspectMode: "cover"
952
- };
953
- return bubble;
954
- }
955
-
956
- //#endregion
957
- //#region src/acp/acpx-mutating-wrapper-policy.ts
958
- const REQUIRED_MUTATING_WRAPPER_GATES = [
959
- "operator-scope",
960
- "operator-confirmation",
961
- "plugin-admin-rpc-grant",
962
- "plugin-source-allowlist",
963
- "audit",
964
- "rate-limit",
965
- "gateway-token",
966
- "explicit-wrapper-enable"
967
- ];
968
- const FORBIDDEN_MUTATING_WRAPPER_SURFACES = [
969
- "generic-gateway-dispatcher",
970
- "client-supplied-mcpServers",
971
- "cli-mcp",
972
- "untrusted-plugin-source",
973
- "bulk-enable-all-admin-rpcs"
974
- ];
975
- const ACPX_MUTATING_WRAPPER_DESIGNS = [
976
- {
977
- id: "fased_chat_inject_request",
978
- method: "chat.inject",
979
- status: "design-only",
980
- executionEnabled: false,
981
- description: "Future fixed wrapper for requesting an operator-approved chat injection into a scoped session.",
982
- requiredGates: REQUIRED_MUTATING_WRAPPER_GATES,
983
- forbiddenSurfaces: FORBIDDEN_MUTATING_WRAPPER_SURFACES
984
- },
985
- {
986
- id: "fased_push_test_request",
987
- method: "push.test",
988
- status: "design-only",
989
- executionEnabled: false,
990
- description: "Future fixed wrapper for requesting an operator-approved test push to a scoped node.",
991
- requiredGates: REQUIRED_MUTATING_WRAPPER_GATES,
992
- forbiddenSurfaces: FORBIDDEN_MUTATING_WRAPPER_SURFACES
993
- },
994
- {
995
- id: "fased_web_login_start_request",
996
- method: "web.login.start",
997
- status: "design-only",
998
- executionEnabled: false,
999
- description: "Future fixed wrapper for requesting an operator-approved web login start for a scoped account.",
1000
- requiredGates: REQUIRED_MUTATING_WRAPPER_GATES,
1001
- forbiddenSurfaces: FORBIDDEN_MUTATING_WRAPPER_SURFACES
1002
- },
1003
- {
1004
- id: "fased_web_login_wait_request",
1005
- method: "web.login.wait",
1006
- status: "design-only",
1007
- executionEnabled: false,
1008
- description: "Future fixed wrapper for requesting an operator-approved web login wait for a scoped account.",
1009
- requiredGates: REQUIRED_MUTATING_WRAPPER_GATES,
1010
- forbiddenSurfaces: FORBIDDEN_MUTATING_WRAPPER_SURFACES
1011
- }
1012
- ];
1013
- function findAcpxMutatingWrapperDesign(id) {
1014
- return ACPX_MUTATING_WRAPPER_DESIGNS.find((design) => design.id === id);
1015
- }
1016
- function uniqueStrings(values) {
1017
- return new Set((values ?? []).map((value) => value.trim()).filter(Boolean));
1018
- }
1019
- function evaluateAcpxMutatingWrapperRuntimeGate(input) {
1020
- const wrapperId = input.wrapperId.trim();
1021
- const design = findAcpxMutatingWrapperDesign(wrapperId);
1022
- if (!design) return {
1023
- wrapperId,
1024
- allowed: false,
1025
- reason: "unknown-wrapper",
1026
- missingGates: [],
1027
- activeForbiddenSurfaces: []
1028
- };
1029
- if (uniqueStrings(input.denyWrappers).has(design.id)) return {
1030
- wrapperId: design.id,
1031
- method: design.method,
1032
- allowed: false,
1033
- reason: "denied-wrapper",
1034
- missingGates: [],
1035
- activeForbiddenSurfaces: []
1036
- };
1037
- const allowWrappers = uniqueStrings(input.allowWrappers);
1038
- if (allowWrappers.size > 0 && !allowWrappers.has(design.id)) return {
1039
- wrapperId: design.id,
1040
- method: design.method,
1041
- allowed: false,
1042
- reason: "not-allowlisted",
1043
- missingGates: [],
1044
- activeForbiddenSurfaces: []
1045
- };
1046
- const activeForbiddenSurfaces = design.forbiddenSurfaces.filter((surface) => input.forbiddenSurfaces?.[surface] === true);
1047
- if (activeForbiddenSurfaces.length > 0) return {
1048
- wrapperId: design.id,
1049
- method: design.method,
1050
- allowed: false,
1051
- reason: "forbidden-surface",
1052
- missingGates: [],
1053
- activeForbiddenSurfaces
1054
- };
1055
- const missingGates = design.requiredGates.filter((gate) => input.gates?.[gate] !== true);
1056
- if (missingGates.length > 0) return {
1057
- wrapperId: design.id,
1058
- method: design.method,
1059
- allowed: false,
1060
- reason: "missing-gates",
1061
- missingGates,
1062
- activeForbiddenSurfaces: []
1063
- };
1064
- return {
1065
- wrapperId: design.id,
1066
- method: design.method,
1067
- allowed: true,
1068
- reason: "allowed",
1069
- missingGates: [],
1070
- activeForbiddenSurfaces: []
1071
- };
1072
- }
1073
-
1074
- //#endregion
1075
- //#region src/acp/acpx-push-test-approval-contract.ts
1076
- const ACPX_PUSH_TEST_WRAPPER_ID = "fased_push_test_request";
1077
- const ACPX_PUSH_TEST_METHOD = "push.test";
1078
- function normalizeForStableJson(value) {
1079
- if (value === null || typeof value === "string" || typeof value === "number") return value;
1080
- if (typeof value === "boolean") return value;
1081
- if (Array.isArray(value)) return value.map((entry) => normalizeForStableJson(entry));
1082
- if (typeof value === "object" && value) {
1083
- const normalized = {};
1084
- for (const key of Object.keys(value).toSorted()) {
1085
- const entry = value[key];
1086
- if (entry !== void 0) normalized[key] = normalizeForStableJson(entry);
1087
- }
1088
- return normalized;
1089
- }
1090
- return null;
1091
- }
1092
- function stableJson(value) {
1093
- return JSON.stringify(normalizeForStableJson(value));
1094
- }
1095
- function createAcpxPushTestRequestFingerprint(input) {
1096
- return createHash("sha256").update(stableJson({
1097
- method: input.method,
1098
- params: input.params,
1099
- wrapperId: input.wrapperId
1100
- })).digest("hex");
1101
- }
1102
- function createAcpxPushTestSafeSummary(params) {
1103
- const record = typeof params === "object" && params !== null && !Array.isArray(params) ? params : {};
1104
- const environment = record.environment === "sandbox" || record.environment === "production" ? record.environment : null;
1105
- return {
1106
- nodeId: typeof record.nodeId === "string" && record.nodeId.trim() ? record.nodeId.trim() : null,
1107
- environment,
1108
- titleProvided: typeof record.title === "string" && record.title.length > 0,
1109
- bodyProvided: typeof record.body === "string" && record.body.length > 0
1110
- };
1111
- }
1112
- function evaluateAcpxPushTestApprovalContract(request) {
1113
- const requestFingerprint = createAcpxPushTestRequestFingerprint({
1114
- wrapperId: request.wrapperId,
1115
- method: request.method,
1116
- params: request.params
1117
- });
1118
- const requestReasons = collectRequestDenyReasons(request);
1119
- if (requestReasons.length > 0) return deniedResponse({
1120
- request,
1121
- requestFingerprint,
1122
- stage: "request",
1123
- reasons: requestReasons
1124
- });
1125
- const approvalReasons = collectApprovalDenyReasons({
1126
- approval: request.approval,
1127
- requestFingerprint
1128
- });
1129
- if (approvalReasons.length > 0) return deniedResponse({
1130
- request,
1131
- requestFingerprint,
1132
- stage: "operator-approval",
1133
- reasons: approvalReasons
1134
- });
1135
- const gate = evaluateAcpxMutatingWrapperRuntimeGate({
1136
- wrapperId: request.wrapperId,
1137
- gates: request.gate.gates,
1138
- forbiddenSurfaces: request.gate.forbiddenSurfaces,
1139
- allowWrappers: request.gate.allowWrappers,
1140
- denyWrappers: request.gate.denyWrappers
1141
- });
1142
- if (!gate.allowed) return deniedResponse({
1143
- request,
1144
- requestFingerprint,
1145
- stage: "runtime-gate",
1146
- reasons: [`mutating wrapper runtime gate denied: ${gate.reason}`],
1147
- gate
1148
- });
1149
- return {
1150
- schemaVersion: 1,
1151
- kind: "acpx.mutating-wrapper.push-test.execution.response",
1152
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1153
- method: ACPX_PUSH_TEST_METHOD,
1154
- dryRun: true,
1155
- noExecutionPerformed: true,
1156
- requestId: request.requestId,
1157
- createdAt: request.createdAt,
1158
- status: "admitted",
1159
- stage: "admitted",
1160
- requestFingerprint,
1161
- reasons: [],
1162
- safeSummary: createAcpxPushTestSafeSummary(request.params),
1163
- gate
1164
- };
1165
- }
1166
- function collectRequestDenyReasons(request) {
1167
- const reasons = [];
1168
- if (request.schemaVersion !== 1) reasons.push("ACPX push-test execution request schema version is unsupported");
1169
- if (request.kind !== "acpx.mutating-wrapper.push-test.execution.request") reasons.push("ACPX push-test execution request kind is unsupported");
1170
- if (request.wrapperId !== ACPX_PUSH_TEST_WRAPPER_ID) reasons.push("ACPX push-test execution request wrapper is unsupported");
1171
- if (request.method !== ACPX_PUSH_TEST_METHOD) reasons.push("ACPX push-test execution request method is unsupported");
1172
- if (!request.dryRun) reasons.push("ACPX push-test execution contract must be evaluated as a dry run");
1173
- if (typeof request.requestId !== "string" || request.requestId.trim() === "") reasons.push("ACPX push-test execution request requires requestId");
1174
- if (typeof request.createdAt !== "string" || request.createdAt.trim() === "") reasons.push("ACPX push-test execution request requires createdAt");
1175
- if (!validatePushTestParams(request.params)) reasons.push("ACPX push-test execution request params are invalid");
1176
- return reasons;
1177
- }
1178
- function collectApprovalDenyReasons(params) {
1179
- const reasons = [];
1180
- if (params.approval.confirmation !== "operator-confirmed") reasons.push("ACPX push-test execution requires explicit operator confirmation");
1181
- if (params.approval.acceptedRequestFingerprint !== params.requestFingerprint) reasons.push("ACPX push-test approval fingerprint does not match request");
1182
- if (params.approval.confirmation === "operator-confirmed" && (typeof params.approval.approvedAt !== "string" || params.approval.approvedAt.trim() === "")) reasons.push("ACPX push-test approval requires approvedAt");
1183
- return reasons;
1184
- }
1185
- function deniedResponse(params) {
1186
- return {
1187
- schemaVersion: 1,
1188
- kind: "acpx.mutating-wrapper.push-test.execution.response",
1189
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1190
- method: ACPX_PUSH_TEST_METHOD,
1191
- dryRun: true,
1192
- noExecutionPerformed: true,
1193
- requestId: typeof params.request.requestId === "string" ? params.request.requestId : "",
1194
- createdAt: typeof params.request.createdAt === "string" ? params.request.createdAt : "",
1195
- status: "denied",
1196
- stage: params.stage,
1197
- requestFingerprint: params.requestFingerprint,
1198
- reasons: params.reasons,
1199
- safeSummary: createAcpxPushTestSafeSummary(params.request.params),
1200
- ...params.gate ? { gate: params.gate } : {}
1201
- };
1202
- }
1203
-
1204
- //#endregion
1205
- //#region src/acp/acpx-push-test-execution-adapter.ts
1206
- function sanitizePushResult(payload) {
1207
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) return {};
1208
- const record = payload;
1209
- return {
1210
- ok: typeof record.ok === "boolean" ? record.ok : void 0,
1211
- status: typeof record.status === "number" ? record.status : void 0,
1212
- reason: typeof record.reason === "string" ? record.reason : void 0,
1213
- environment: typeof record.environment === "string" ? record.environment : void 0,
1214
- apnsId: typeof record.apnsId === "string" ? record.apnsId : void 0,
1215
- tokenSuffix: typeof record.tokenSuffix === "string" ? record.tokenSuffix : void 0,
1216
- topic: typeof record.topic === "string" ? record.topic : void 0
1217
- };
1218
- }
1219
- function collectExecutionGateReasons(input) {
1220
- const reasons = [];
1221
- if (!input.executionGate.enabled) reasons.push("ACPX push-test execution adapter is disabled");
1222
- if (!input.executionGate.allowExecution) reasons.push("ACPX push-test execution is not explicitly enabled");
1223
- if (!input.executionGate.gatewayHandlerRegistered || !input.handler) reasons.push("ACPX push-test gateway handler is not registered");
1224
- const role = input.client?.connect?.role ?? "operator";
1225
- if (!input.client?.connect || role !== "operator") reasons.push("ACPX push-test execution requires an operator client");
1226
- else {
1227
- const auth = authorizeOperatorScopesForMethod(ACPX_PUSH_TEST_METHOD, input.client.connect.scopes ?? []);
1228
- if (!auth.allowed) reasons.push(`ACPX push-test execution requires ${auth.missingScope}`);
1229
- }
1230
- return reasons;
1231
- }
1232
- function deniedResult(params) {
1233
- logMutatingAdminRpcAudit({
1234
- context: params.input.context,
1235
- client: params.input.client,
1236
- method: ACPX_PUSH_TEST_METHOD,
1237
- outcome: "denied",
1238
- details: {
1239
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1240
- requestId: params.input.request.requestId,
1241
- reason: params.reasons.join("|")
1242
- }
1243
- });
1244
- return {
1245
- schemaVersion: 1,
1246
- kind: "acpx.mutating-wrapper.push-test.execution.result",
1247
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1248
- method: ACPX_PUSH_TEST_METHOD,
1249
- requestId: params.input.request.requestId,
1250
- status: "denied",
1251
- executionPerformed: false,
1252
- noGenericDispatcher: true,
1253
- contract: params.contract,
1254
- reasons: params.reasons,
1255
- safeSummary: createAcpxPushTestSafeSummary(params.input.request.params)
1256
- };
1257
- }
1258
- async function invokePushTestHandler(input) {
1259
- return await new Promise((resolve, reject) => {
1260
- let responded = false;
1261
- const respond = (ok, payload, error) => {
1262
- responded = true;
1263
- resolve({
1264
- ok,
1265
- payload,
1266
- error
1267
- });
1268
- };
1269
- Promise.resolve(input.handler({
1270
- req: {
1271
- type: "req",
1272
- id: `acpx-push-test:${input.request.requestId}`,
1273
- method: ACPX_PUSH_TEST_METHOD,
1274
- params: input.request.params
1275
- },
1276
- params: input.request.params,
1277
- client: input.client,
1278
- context: input.context,
1279
- isWebchatConnect: input.isWebchatConnect ?? (() => false),
1280
- respond
1281
- })).then(() => {
1282
- if (!responded) resolve({
1283
- ok: true,
1284
- payload: void 0
1285
- });
1286
- }, (err) => reject(err));
1287
- });
1288
- }
1289
- async function executeAcpxPushTestRequest(input) {
1290
- const contract = evaluateAcpxPushTestApprovalContract(input.request);
1291
- if (contract.status !== "admitted") return deniedResult({
1292
- input,
1293
- contract,
1294
- reasons: contract.reasons
1295
- });
1296
- const executionGateReasons = collectExecutionGateReasons(input);
1297
- if (executionGateReasons.length > 0) return deniedResult({
1298
- input,
1299
- contract,
1300
- reasons: executionGateReasons
1301
- });
1302
- const budget = consumeMutatingAdminRpcBudget({
1303
- method: ACPX_PUSH_TEST_METHOD,
1304
- client: input.client
1305
- });
1306
- if (budget.applies && !budget.allowed) return deniedResult({
1307
- input,
1308
- contract,
1309
- reasons: [`ACPX push-test execution rate-limited:${budget.policy.label}`]
1310
- });
1311
- try {
1312
- const response = await invokePushTestHandler({
1313
- ...input,
1314
- handler: input.handler
1315
- });
1316
- if (!response.ok) return {
1317
- schemaVersion: 1,
1318
- kind: "acpx.mutating-wrapper.push-test.execution.result",
1319
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1320
- method: ACPX_PUSH_TEST_METHOD,
1321
- requestId: input.request.requestId,
1322
- status: "failed",
1323
- executionPerformed: true,
1324
- noGenericDispatcher: true,
1325
- contract,
1326
- reasons: [response.error?.message ?? "push.test handler failed"],
1327
- safeSummary: createAcpxPushTestSafeSummary(input.request.params),
1328
- error: {
1329
- code: response.error?.code,
1330
- message: response.error?.message ?? "push.test handler failed"
1331
- }
1332
- };
1333
- return {
1334
- schemaVersion: 1,
1335
- kind: "acpx.mutating-wrapper.push-test.execution.result",
1336
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1337
- method: ACPX_PUSH_TEST_METHOD,
1338
- requestId: input.request.requestId,
1339
- status: "executed",
1340
- executionPerformed: true,
1341
- noGenericDispatcher: true,
1342
- contract,
1343
- reasons: [],
1344
- safeSummary: createAcpxPushTestSafeSummary(input.request.params),
1345
- result: sanitizePushResult(response.payload)
1346
- };
1347
- } catch (err) {
1348
- logMutatingAdminRpcAudit({
1349
- context: input.context,
1350
- client: input.client,
1351
- method: ACPX_PUSH_TEST_METHOD,
1352
- outcome: "failed",
1353
- details: {
1354
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1355
- requestId: input.request.requestId,
1356
- reason: "handler_threw"
1357
- }
1358
- });
1359
- return {
1360
- schemaVersion: 1,
1361
- kind: "acpx.mutating-wrapper.push-test.execution.result",
1362
- wrapperId: ACPX_PUSH_TEST_WRAPPER_ID,
1363
- method: ACPX_PUSH_TEST_METHOD,
1364
- requestId: input.request.requestId,
1365
- status: "failed",
1366
- executionPerformed: true,
1367
- noGenericDispatcher: true,
1368
- contract,
1369
- reasons: [err instanceof Error ? err.message : "push.test handler failed"],
1370
- safeSummary: createAcpxPushTestSafeSummary(input.request.params),
1371
- error: { message: err instanceof Error ? err.message : "push.test handler failed" }
1372
- };
1373
- }
1374
- }
1375
-
1376
- //#endregion
1377
- //#region src/agents/tool-description-summary.ts
1378
- function normalizeSummaryWhitespace(value) {
1379
- return value.replace(/\s+/g, " ").trim();
1380
- }
1381
- function truncateSummary(value, maxLen = 120) {
1382
- if (value.length <= maxLen) return value;
1383
- const sliced = value.slice(0, maxLen - 3);
1384
- const boundary = sliced.lastIndexOf(" ");
1385
- return `${(boundary >= 48 ? sliced.slice(0, boundary) : sliced).trimEnd()}...`;
1386
- }
1387
- function isToolDocBlockStart(line) {
1388
- const normalized = line.trim().toUpperCase();
1389
- if (!normalized) return false;
1390
- if (normalized === "ACTIONS:" || normalized === "JOB SCHEMA (FOR ADD ACTION):" || normalized === "JOB SCHEMA:" || normalized === "SESSION TARGET OPTIONS:" || normalized === "DEFAULT BEHAVIOR (UNCHANGED FOR BACKWARD COMPATIBILITY):" || normalized === "SCHEDULE TYPES (SCHEDULE.KIND):" || normalized === "PAYLOAD TYPES (PAYLOAD.KIND):" || normalized === "DELIVERY (TOP-LEVEL):" || normalized === "CRITICAL CONSTRAINTS:" || normalized === "WAKE MODES (FOR WAKE ACTION):") return true;
1391
- return normalized.endsWith(":") && normalized === normalized.toUpperCase() && normalized.length > 12;
1392
- }
1393
- function summarizeToolDescriptionText(params) {
1394
- const explicit = typeof params.displaySummary === "string" ? params.displaySummary.trim() : "";
1395
- if (explicit) return truncateSummary(normalizeSummaryWhitespace(explicit), params.maxLen);
1396
- const raw = typeof params.rawDescription === "string" ? params.rawDescription.trim() : "";
1397
- if (!raw) return "Tool";
1398
- const paragraphs = raw.split(/\n\s*\n/g).map((part) => part.trim()).filter(Boolean);
1399
- for (const paragraph of paragraphs) {
1400
- const lines = paragraph.split("\n").map((line) => line.trim()).filter(Boolean);
1401
- if (lines.length === 0) continue;
1402
- const first = lines[0] ?? "";
1403
- if (!first || isToolDocBlockStart(first)) continue;
1404
- if (first.startsWith("{") || first.startsWith("[") || first.startsWith("- ")) continue;
1405
- return truncateSummary(normalizeSummaryWhitespace(first), params.maxLen);
1406
- }
1407
- const firstLine = raw.split("\n").map((line) => line.trim()).find((line) => line.length > 0 && !isToolDocBlockStart(line) && !line.startsWith("{") && !line.startsWith("[") && !line.startsWith("- "));
1408
- return firstLine ? truncateSummary(normalizeSummaryWhitespace(firstLine), params.maxLen) : "Tool";
1409
- }
1410
-
1411
- //#endregion
1412
- //#region src/agents/tools-effective-inventory.ts
1413
- function resolveEffectiveToolLabel(tool) {
1414
- const rawLabel = typeof tool.label === "string" ? tool.label.trim() : "";
1415
- if (rawLabel && rawLabel.toLowerCase() !== tool.name.toLowerCase()) return rawLabel;
1416
- return resolveToolDisplay({ name: tool.name }).title;
1417
- }
1418
- function resolveRawToolDescription(tool) {
1419
- return typeof tool.description === "string" ? tool.description.trim() : "";
1420
- }
1421
- function summarizeToolDescription(tool) {
1422
- return summarizeToolDescriptionText({
1423
- rawDescription: resolveRawToolDescription(tool),
1424
- displaySummary: tool.displaySummary
1425
- });
1426
- }
1427
- function resolveEffectiveToolSource(tool) {
1428
- const pluginMeta = getPluginToolMeta(tool);
1429
- if (pluginMeta) return {
1430
- source: "plugin",
1431
- pluginId: pluginMeta.pluginId
1432
- };
1433
- const channelMeta = getChannelAgentToolMeta(tool);
1434
- if (channelMeta) return {
1435
- source: "channel",
1436
- channelId: channelMeta.channelId
1437
- };
1438
- return { source: "core" };
1439
- }
1440
- function groupLabel(source) {
1441
- switch (source) {
1442
- case "plugin": return "Connected tools";
1443
- case "channel": return "Channel tools";
1444
- default: return "Built-in tools";
1445
- }
1446
- }
1447
- function disambiguateLabels(entries) {
1448
- const counts = /* @__PURE__ */ new Map();
1449
- for (const entry of entries) counts.set(entry.label, (counts.get(entry.label) ?? 0) + 1);
1450
- return entries.map((entry) => {
1451
- if ((counts.get(entry.label) ?? 0) < 2) return entry;
1452
- const suffix = entry.pluginId ?? entry.channelId ?? entry.id;
1453
- return {
1454
- ...entry,
1455
- label: `${entry.label} (${suffix})`
1456
- };
1457
- });
1458
- }
1459
- function resolveEffectiveModelCompat(params) {
1460
- const provider = params.modelProvider?.trim();
1461
- const modelId = params.modelId?.trim();
1462
- if (!provider || !modelId) return;
1463
- try {
1464
- return resolveModel(provider, modelId, params.agentDir, params.cfg).model?.compat;
1465
- } catch {
1466
- return;
1467
- }
1468
- }
1469
- function resolveEffectiveToolInventory(params) {
1470
- const agentId = params.agentId?.trim() || resolveSessionAgentId({
1471
- sessionKey: params.sessionKey,
1472
- config: params.cfg
1473
- });
1474
- const workspaceDir = params.workspaceDir ?? resolveAgentWorkspaceDir(params.cfg, agentId);
1475
- const agentDir = params.agentDir ?? resolveAgentDir(params.cfg, agentId);
1476
- const modelCompat = resolveEffectiveModelCompat({
1477
- cfg: params.cfg,
1478
- agentDir,
1479
- modelProvider: params.modelProvider,
1480
- modelId: params.modelId
1481
- });
1482
- const effectiveTools = createFasedAgentCodingTools({
1483
- agentId,
1484
- sessionKey: params.sessionKey,
1485
- workspaceDir,
1486
- agentDir,
1487
- config: params.cfg,
1488
- modelProvider: params.modelProvider,
1489
- modelId: params.modelId,
1490
- modelCompat,
1491
- messageProvider: params.messageProvider,
1492
- senderIsOwner: params.senderIsOwner,
1493
- senderId: params.senderId,
1494
- senderName: params.senderName ?? void 0,
1495
- senderUsername: params.senderUsername ?? void 0,
1496
- senderE164: params.senderE164 ?? void 0,
1497
- agentAccountId: params.accountId ?? void 0,
1498
- currentChannelId: params.currentChannelId,
1499
- currentThreadTs: params.currentThreadTs,
1500
- currentMessageId: params.currentMessageId,
1501
- groupId: params.groupId ?? void 0,
1502
- groupChannel: params.groupChannel ?? void 0,
1503
- groupSpace: params.groupSpace ?? void 0,
1504
- replyToMode: params.replyToMode === "batched" ? "all" : params.replyToMode,
1505
- modelHasVision: params.modelHasVision,
1506
- requireExplicitMessageTarget: params.requireExplicitMessageTarget,
1507
- disableMessageTool: params.disableMessageTool
1508
- });
1509
- const effectivePolicy = resolveEffectiveToolPolicy({
1510
- config: params.cfg,
1511
- agentId,
1512
- sessionKey: params.sessionKey,
1513
- modelProvider: params.modelProvider,
1514
- modelId: params.modelId
1515
- });
1516
- const profile = effectivePolicy.providerProfile ?? effectivePolicy.profile ?? "full";
1517
- const entries = disambiguateLabels(effectiveTools.map((tool) => {
1518
- const source = resolveEffectiveToolSource(tool);
1519
- return {
1520
- id: tool.name,
1521
- label: resolveEffectiveToolLabel(tool),
1522
- description: summarizeToolDescription(tool),
1523
- rawDescription: resolveRawToolDescription(tool) || summarizeToolDescription(tool),
1524
- ...source
1525
- };
1526
- }).toSorted((a, b) => a.label.localeCompare(b.label)));
1527
- const groupsBySource = /* @__PURE__ */ new Map();
1528
- for (const entry of entries) {
1529
- const tools = groupsBySource.get(entry.source) ?? [];
1530
- tools.push(entry);
1531
- groupsBySource.set(entry.source, tools);
1532
- }
1533
- return {
1534
- agentId,
1535
- profile,
1536
- groups: [
1537
- "core",
1538
- "plugin",
1539
- "channel"
1540
- ].map((source) => {
1541
- const tools = groupsBySource.get(source);
1542
- if (!tools || tools.length === 0) return null;
1543
- return {
1544
- id: source,
1545
- label: groupLabel(source),
1546
- source,
1547
- tools
1548
- };
1549
- }).filter((group) => group !== null)
1550
- };
1551
- }
1552
-
1553
- //#endregion
1554
- //#region src/gateway/gateway-identity.ts
1555
- function getPublicGatewayIdentity() {
1556
- const identity = loadOrCreateDeviceIdentity();
1557
- return {
1558
- deviceId: identity.deviceId,
1559
- publicKey: publicKeyRawBase64UrlFromPem(identity.publicKeyPem)
1560
- };
1561
- }
1562
-
1563
- //#endregion
1564
- //#region src/infra/update-channels.ts
1565
- const DEFAULT_PACKAGE_CHANNEL = "stable";
1566
- const DEFAULT_GIT_CHANNEL = "stable";
1567
- function normalizeUpdateChannel(value) {
1568
- if (!value) return null;
1569
- const normalized = value.trim().toLowerCase();
1570
- if (normalized === "stable" || normalized === "beta" || normalized === "dev") return normalized;
1571
- return null;
1572
- }
1573
- function isBetaTag(tag) {
1574
- return /(?:^|[.-])beta(?:[.-]|$)/i.test(tag);
1575
- }
1576
- function resolveEffectiveUpdateChannel(params) {
1577
- if (params.configChannel) return {
1578
- channel: params.configChannel,
1579
- source: "config"
1580
- };
1581
- if (params.installKind === "git") {
1582
- const tag = params.git?.tag;
1583
- if (tag) return {
1584
- channel: isBetaTag(tag) ? "beta" : "stable",
1585
- source: "git-tag"
1586
- };
1587
- return {
1588
- channel: DEFAULT_GIT_CHANNEL,
1589
- source: "default"
1590
- };
1591
- }
1592
- if (params.installKind === "package") return {
1593
- channel: DEFAULT_PACKAGE_CHANNEL,
1594
- source: "default"
1595
- };
1596
- return {
1597
- channel: DEFAULT_PACKAGE_CHANNEL,
1598
- source: "default"
1599
- };
1600
- }
1601
- function formatUpdateChannelLabel(params) {
1602
- if (params.source === "config") return `${params.channel} (config)`;
1603
- if (params.source === "git-tag") return params.gitTag ? `${params.channel} (${params.gitTag})` : `${params.channel} (tag)`;
1604
- if (params.source === "git-branch") return params.gitBranch ? `${params.channel} (${params.gitBranch})` : `${params.channel} (branch)`;
1605
- return `${params.channel} (default)`;
1606
- }
1607
- function resolveUpdateChannelDisplay(params) {
1608
- const channelInfo = resolveEffectiveUpdateChannel({
1609
- configChannel: params.configChannel,
1610
- installKind: params.installKind,
1611
- git: params.gitTag || params.gitBranch ? {
1612
- tag: params.gitTag ?? null,
1613
- branch: params.gitBranch ?? null
1614
- } : void 0
1615
- });
1616
- return {
1617
- channel: channelInfo.channel,
1618
- source: channelInfo.source,
1619
- label: formatUpdateChannelLabel({
1620
- channel: channelInfo.channel,
1621
- source: channelInfo.source,
1622
- gitTag: params.gitTag ?? null,
1623
- gitBranch: params.gitBranch ?? null
1624
- })
1625
- };
1626
- }
1627
-
1628
- //#endregion
1629
- //#region src/infra/detect-package-manager.ts
1630
- async function detectPackageManager$1(root) {
1631
- try {
1632
- const raw = await fs$1.readFile(path.join(root, "package.json"), "utf-8");
1633
- const pm = JSON.parse(raw)?.packageManager?.split("@")[0]?.trim();
1634
- if (pm === "pnpm" || pm === "bun" || pm === "npm") return pm;
1635
- } catch {}
1636
- const files = await fs$1.readdir(root).catch(() => []);
1637
- if (files.includes("pnpm-lock.yaml")) return "pnpm";
1638
- if (files.includes("bun.lockb")) return "bun";
1639
- if (files.includes("package-lock.json")) return "npm";
1640
- return null;
1641
- }
1642
-
1643
- //#endregion
1644
- //#region src/infra/update-global.ts
1645
- const NPM_GLOBAL_INSTALL_QUIET_FLAGS = [
1646
- "--no-fund",
1647
- "--no-audit",
1648
- "--loglevel=error",
1649
- "--prefer-offline",
1650
- "--no-progress"
1651
- ];
1652
- const NPM_GLOBAL_INSTALL_OMIT_OPTIONAL_FLAGS = ["--omit=optional", ...NPM_GLOBAL_INSTALL_QUIET_FLAGS];
1653
- function resolveNodeModulesRootForPackageRoot(pkgRoot) {
1654
- const parent = path.dirname(pkgRoot);
1655
- if (path.basename(parent).startsWith("@")) return path.dirname(parent);
1656
- return parent;
1657
- }
1658
- function resolveHostedNpmInstallTarget(pkgRoot) {
1659
- const resolved = path.resolve(pkgRoot);
1660
- const prefixMarker = `${path.sep}.fased${path.sep}install-cache${path.sep}npm-global`;
1661
- const globalRootMarker = `${prefixMarker}${`${path.sep}lib${path.sep}node_modules`}`;
1662
- const markerIndex = resolved.indexOf(`${globalRootMarker}${path.sep}`);
1663
- if (markerIndex < 0) return null;
1664
- const prefix = resolved.slice(0, markerIndex + prefixMarker.length);
1665
- const globalRoot = path.join(prefix, "lib", "node_modules");
1666
- const cache = path.join(path.dirname(prefix), "npm-cache");
1667
- const expectedRoot = resolveNodeModulesRootForPackageRoot(resolved);
1668
- if (path.resolve(expectedRoot) !== path.resolve(globalRoot)) return null;
1669
- return {
1670
- manager: "npm",
1671
- globalRoot,
1672
- cacheRoot: path.dirname(prefix),
1673
- env: {
1674
- npm_config_prefix: prefix,
1675
- npm_config_cache: cache
1676
- }
1677
- };
1678
- }
1679
-
1680
- //#endregion
1681
- //#region src/infra/update-check.ts
1682
- const NPM_PACKAGE_NAME = "@fased/fased";
1683
- async function exists(p) {
1684
- try {
1685
- await fs$1.access(p);
1686
- return true;
1687
- } catch {
1688
- return false;
1689
- }
1690
- }
1691
- async function detectPackageManager(root) {
1692
- return await detectPackageManager$1(root) ?? "unknown";
1693
- }
1694
- async function detectGitRoot(root) {
1695
- const res = await runCommandWithTimeout([
1696
- "git",
1697
- "-C",
1698
- root,
1699
- "rev-parse",
1700
- "--show-toplevel"
1701
- ], { timeoutMs: 4e3 }).catch(() => null);
1702
- if (!res || res.code !== 0) return null;
1703
- const top = res.stdout.trim();
1704
- return top ? path.resolve(top) : null;
1705
- }
1706
- async function checkGitUpdateStatus(params) {
1707
- const timeoutMs = params.timeoutMs ?? 6e3;
1708
- const root = path.resolve(params.root);
1709
- const base = {
1710
- root,
1711
- sha: null,
1712
- tag: null,
1713
- branch: null,
1714
- upstream: null,
1715
- dirty: null,
1716
- ahead: null,
1717
- behind: null,
1718
- fetchOk: null
1719
- };
1720
- const branchRes = await runCommandWithTimeout([
1721
- "git",
1722
- "-C",
1723
- root,
1724
- "rev-parse",
1725
- "--abbrev-ref",
1726
- "HEAD"
1727
- ], { timeoutMs }).catch(() => null);
1728
- if (!branchRes || branchRes.code !== 0) return {
1729
- ...base,
1730
- error: branchRes?.stderr?.trim() || "git unavailable"
1731
- };
1732
- const branch = branchRes.stdout.trim() || null;
1733
- const shaRes = await runCommandWithTimeout([
1734
- "git",
1735
- "-C",
1736
- root,
1737
- "rev-parse",
1738
- "HEAD"
1739
- ], { timeoutMs }).catch(() => null);
1740
- const sha = shaRes && shaRes.code === 0 ? shaRes.stdout.trim() : null;
1741
- const tagRes = await runCommandWithTimeout([
1742
- "git",
1743
- "-C",
1744
- root,
1745
- "describe",
1746
- "--tags",
1747
- "--exact-match"
1748
- ], { timeoutMs }).catch(() => null);
1749
- const tag = tagRes && tagRes.code === 0 ? tagRes.stdout.trim() : null;
1750
- const upstreamRes = await runCommandWithTimeout([
1751
- "git",
1752
- "-C",
1753
- root,
1754
- "rev-parse",
1755
- "--abbrev-ref",
1756
- "@{upstream}"
1757
- ], { timeoutMs }).catch(() => null);
1758
- const upstream = upstreamRes && upstreamRes.code === 0 ? upstreamRes.stdout.trim() : null;
1759
- const dirtyRes = await runCommandWithTimeout([
1760
- "git",
1761
- "-C",
1762
- root,
1763
- "status",
1764
- "--porcelain",
1765
- "--",
1766
- ":!dist/control-ui/"
1767
- ], { timeoutMs }).catch(() => null);
1768
- const dirty = dirtyRes && dirtyRes.code === 0 ? dirtyRes.stdout.trim().length > 0 : null;
1769
- const fetchOk = params.fetch ? await runCommandWithTimeout([
1770
- "git",
1771
- "-C",
1772
- root,
1773
- "fetch",
1774
- "--quiet",
1775
- "--prune"
1776
- ], { timeoutMs }).then((r) => r.code === 0).catch(() => false) : null;
1777
- const counts = upstream && upstream.length > 0 ? await runCommandWithTimeout([
1778
- "git",
1779
- "-C",
1780
- root,
1781
- "rev-list",
1782
- "--left-right",
1783
- "--count",
1784
- `HEAD...${upstream}`
1785
- ], { timeoutMs }).catch(() => null) : null;
1786
- const parseCounts = (raw) => {
1787
- const parts = raw.trim().split(/\s+/);
1788
- if (parts.length < 2) return null;
1789
- const ahead = Number.parseInt(parts[0] ?? "", 10);
1790
- const behind = Number.parseInt(parts[1] ?? "", 10);
1791
- if (!Number.isFinite(ahead) || !Number.isFinite(behind)) return null;
1792
- return {
1793
- ahead,
1794
- behind
1795
- };
1796
- };
1797
- const parsed = counts && counts.code === 0 ? parseCounts(counts.stdout) : null;
1798
- return {
1799
- root,
1800
- sha,
1801
- tag,
1802
- branch,
1803
- upstream,
1804
- dirty,
1805
- ahead: parsed?.ahead ?? null,
1806
- behind: parsed?.behind ?? null,
1807
- fetchOk
1808
- };
1809
- }
1810
- async function statMtimeMs(p) {
1811
- try {
1812
- return (await fs$1.stat(p)).mtimeMs;
1813
- } catch {
1814
- return null;
1815
- }
1816
- }
1817
- function resolveDepsMarker(params) {
1818
- const root = params.root;
1819
- if (params.manager === "pnpm") return {
1820
- lockfilePath: path.join(root, "pnpm-lock.yaml"),
1821
- markerPath: path.join(root, "node_modules", ".modules.yaml")
1822
- };
1823
- if (params.manager === "bun") return {
1824
- lockfilePath: path.join(root, "bun.lockb"),
1825
- markerPath: path.join(root, "node_modules")
1826
- };
1827
- if (params.manager === "npm") return {
1828
- lockfilePath: path.join(root, "package-lock.json"),
1829
- markerPath: path.join(root, "node_modules")
1830
- };
1831
- return {
1832
- lockfilePath: null,
1833
- markerPath: null
1834
- };
1835
- }
1836
- async function checkDepsStatus(params) {
1837
- const { lockfilePath, markerPath } = resolveDepsMarker({
1838
- root: path.resolve(params.root),
1839
- manager: params.manager
1840
- });
1841
- if (!lockfilePath || !markerPath) return {
1842
- manager: params.manager,
1843
- status: "unknown",
1844
- lockfilePath,
1845
- markerPath,
1846
- reason: "unknown package manager"
1847
- };
1848
- const lockExists = await exists(lockfilePath);
1849
- const markerExists = await exists(markerPath);
1850
- if (!lockExists) return {
1851
- manager: params.manager,
1852
- status: "unknown",
1853
- lockfilePath,
1854
- markerPath,
1855
- reason: "lockfile missing"
1856
- };
1857
- if (!markerExists) return {
1858
- manager: params.manager,
1859
- status: "missing",
1860
- lockfilePath,
1861
- markerPath,
1862
- reason: "node_modules marker missing"
1863
- };
1864
- const lockMtime = await statMtimeMs(lockfilePath);
1865
- const markerMtime = await statMtimeMs(markerPath);
1866
- if (!lockMtime || !markerMtime) return {
1867
- manager: params.manager,
1868
- status: "unknown",
1869
- lockfilePath,
1870
- markerPath
1871
- };
1872
- if (lockMtime > markerMtime + 1e3) return {
1873
- manager: params.manager,
1874
- status: "stale",
1875
- lockfilePath,
1876
- markerPath,
1877
- reason: "lockfile newer than install marker"
1878
- };
1879
- return {
1880
- manager: params.manager,
1881
- status: "ok",
1882
- lockfilePath,
1883
- markerPath
1884
- };
1885
- }
1886
- async function fetchNpmLatestVersion(params) {
1887
- const res = await fetchNpmTagVersion({
1888
- tag: "latest",
1889
- timeoutMs: params?.timeoutMs
1890
- });
1891
- return {
1892
- latestVersion: res.version,
1893
- error: res.error
1894
- };
1895
- }
1896
- async function fetchNpmTagVersion(params) {
1897
- const timeoutMs = params?.timeoutMs ?? 3500;
1898
- const tag = params.tag;
1899
- try {
1900
- const res = await fetchWithTimeout(`https://registry.npmjs.org/${encodeURIComponent(NPM_PACKAGE_NAME)}/${encodeURIComponent(tag)}`, {}, Math.max(250, timeoutMs));
1901
- if (!res.ok) return {
1902
- tag,
1903
- version: null,
1904
- error: `HTTP ${res.status}`
1905
- };
1906
- const json = await res.json();
1907
- return {
1908
- tag,
1909
- version: typeof json?.version === "string" ? json.version : null
1910
- };
1911
- } catch (err) {
1912
- return {
1913
- tag,
1914
- version: null,
1915
- error: String(err)
1916
- };
1917
- }
1918
- }
1919
- function compareSemverStrings(a, b) {
1920
- const pa = parseComparableSemver(a);
1921
- const pb = parseComparableSemver(b);
1922
- if (!pa || !pb) return null;
1923
- if (pa.major !== pb.major) return pa.major < pb.major ? -1 : 1;
1924
- if (pa.minor !== pb.minor) return pa.minor < pb.minor ? -1 : 1;
1925
- if (pa.patch !== pb.patch) return pa.patch < pb.patch ? -1 : 1;
1926
- return comparePrerelease(pa.prerelease, pb.prerelease);
1927
- }
1928
- function parseComparableSemver(version) {
1929
- if (!version) return null;
1930
- const normalized = normalizeLegacyDotBetaVersion(version.trim());
1931
- const match = /^v?([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(normalized);
1932
- if (!match) return null;
1933
- const [, major, minor, patch, prereleaseRaw] = match;
1934
- if (!major || !minor || !patch) return null;
1935
- return {
1936
- major: Number.parseInt(major, 10),
1937
- minor: Number.parseInt(minor, 10),
1938
- patch: Number.parseInt(patch, 10),
1939
- prerelease: prereleaseRaw ? prereleaseRaw.split(".").filter(Boolean) : null
1940
- };
1941
- }
1942
- function normalizeLegacyDotBetaVersion(version) {
1943
- const trimmed = version.trim();
1944
- const dotBetaMatch = /^([vV]?[0-9]+\.[0-9]+\.[0-9]+)\.beta(?:\.([0-9A-Za-z.-]+))?$/.exec(trimmed);
1945
- if (!dotBetaMatch) return trimmed;
1946
- const base = dotBetaMatch[1];
1947
- const suffix = dotBetaMatch[2];
1948
- return suffix ? `${base}-beta.${suffix}` : `${base}-beta`;
1949
- }
1950
- function comparePrerelease(a, b) {
1951
- if (!a?.length && !b?.length) return 0;
1952
- if (!a?.length) return 1;
1953
- if (!b?.length) return -1;
1954
- const max = Math.max(a.length, b.length);
1955
- for (let i = 0; i < max; i += 1) {
1956
- const ai = a[i];
1957
- const bi = b[i];
1958
- if (ai == null && bi == null) return 0;
1959
- if (ai == null) return -1;
1960
- if (bi == null) return 1;
1961
- if (ai === bi) continue;
1962
- const aiNumeric = /^[0-9]+$/.test(ai);
1963
- const biNumeric = /^[0-9]+$/.test(bi);
1964
- if (aiNumeric && biNumeric) return Number.parseInt(ai, 10) < Number.parseInt(bi, 10) ? -1 : 1;
1965
- if (aiNumeric && !biNumeric) return -1;
1966
- if (!aiNumeric && biNumeric) return 1;
1967
- return ai < bi ? -1 : 1;
1968
- }
1969
- return 0;
1970
- }
1971
- async function checkUpdateStatus(params) {
1972
- const timeoutMs = params.timeoutMs ?? 6e3;
1973
- const root = params.root ? path.resolve(params.root) : null;
1974
- if (!root) return {
1975
- root: null,
1976
- installKind: "unknown",
1977
- packageManager: "unknown",
1978
- registry: params.includeRegistry ? await fetchNpmLatestVersion({ timeoutMs }) : void 0
1979
- };
1980
- const gitRoot = await detectGitRoot(root);
1981
- const isGit = gitRoot && path.resolve(gitRoot) === root;
1982
- const installKind = isGit ? "git" : "package";
1983
- const pm = (!isGit ? resolveHostedNpmInstallTarget(root) : null) ? "npm" : await detectPackageManager(root);
1984
- return {
1985
- root,
1986
- installKind,
1987
- packageManager: pm,
1988
- git: isGit ? await checkGitUpdateStatus({
1989
- root,
1990
- timeoutMs,
1991
- fetch: Boolean(params.fetchGit)
1992
- }) : void 0,
1993
- deps: await checkDepsStatus({
1994
- root,
1995
- manager: pm
1996
- }),
1997
- registry: params.includeRegistry ? await fetchNpmLatestVersion({ timeoutMs }) : void 0
1998
- };
1999
- }
2000
-
2001
- //#endregion
2002
- //#region src/infra/node-commands.ts
2003
- const NODE_SYSTEM_RUN_COMMANDS = [
2004
- "system.run.prepare",
2005
- "system.run",
2006
- "system.which"
2007
- ];
2008
- const NODE_SYSTEM_NOTIFY_COMMAND = "system.notify";
2009
- const NODE_BROWSER_PROXY_COMMAND = "browser.proxy";
2010
-
2011
- //#endregion
2012
- //#region src/gateway/node-command-policy.ts
2013
- const CANVAS_COMMANDS = [
2014
- "canvas.present",
2015
- "canvas.hide",
2016
- "canvas.navigate",
2017
- "canvas.eval",
2018
- "canvas.snapshot",
2019
- "canvas.a2ui.push",
2020
- "canvas.a2ui.pushJSONL",
2021
- "canvas.a2ui.reset"
2022
- ];
2023
- const CAMERA_COMMANDS = ["camera.list"];
2024
- const CAMERA_DANGEROUS_COMMANDS = ["camera.snap", "camera.clip"];
2025
- const SCREEN_DANGEROUS_COMMANDS = ["screen.record"];
2026
- const LOCATION_COMMANDS = ["location.get"];
2027
- const ANDROID_NOTIFICATION_COMMANDS = [...["notifications.list"], "notifications.actions"];
2028
- const DEVICE_COMMANDS = ["device.info", "device.status"];
2029
- const ANDROID_DEVICE_COMMANDS = [
2030
- ...DEVICE_COMMANDS,
2031
- "device.permissions",
2032
- "device.health"
2033
- ];
2034
- const CONTACTS_COMMANDS = ["contacts.search"];
2035
- const CONTACTS_DANGEROUS_COMMANDS = ["contacts.add"];
2036
- const CALENDAR_COMMANDS = ["calendar.events"];
2037
- const CALENDAR_DANGEROUS_COMMANDS = ["calendar.add"];
2038
- const REMINDERS_COMMANDS = ["reminders.list"];
2039
- const REMINDERS_DANGEROUS_COMMANDS = ["reminders.add"];
2040
- const PHOTOS_COMMANDS = ["photos.latest"];
2041
- const MOTION_COMMANDS = ["motion.activity", "motion.pedometer"];
2042
- const SMS_DANGEROUS_COMMANDS = ["sms.send"];
2043
- const IOS_SYSTEM_COMMANDS = [NODE_SYSTEM_NOTIFY_COMMAND];
2044
- const SYSTEM_COMMANDS = [
2045
- ...NODE_SYSTEM_RUN_COMMANDS,
2046
- NODE_SYSTEM_NOTIFY_COMMAND,
2047
- NODE_BROWSER_PROXY_COMMAND
2048
- ];
2049
- const DEFAULT_DANGEROUS_NODE_COMMANDS = [
2050
- ...CAMERA_DANGEROUS_COMMANDS,
2051
- ...SCREEN_DANGEROUS_COMMANDS,
2052
- ...CONTACTS_DANGEROUS_COMMANDS,
2053
- ...CALENDAR_DANGEROUS_COMMANDS,
2054
- ...REMINDERS_DANGEROUS_COMMANDS,
2055
- ...SMS_DANGEROUS_COMMANDS
2056
- ];
2057
- const PLATFORM_DEFAULTS = {
2058
- ios: [
2059
- ...CANVAS_COMMANDS,
2060
- ...CAMERA_COMMANDS,
2061
- ...LOCATION_COMMANDS,
2062
- ...DEVICE_COMMANDS,
2063
- ...CONTACTS_COMMANDS,
2064
- ...CALENDAR_COMMANDS,
2065
- ...REMINDERS_COMMANDS,
2066
- ...PHOTOS_COMMANDS,
2067
- ...MOTION_COMMANDS,
2068
- ...IOS_SYSTEM_COMMANDS
2069
- ],
2070
- android: [
2071
- ...CANVAS_COMMANDS,
2072
- ...CAMERA_COMMANDS,
2073
- ...LOCATION_COMMANDS,
2074
- ...ANDROID_NOTIFICATION_COMMANDS,
2075
- ...ANDROID_DEVICE_COMMANDS,
2076
- ...CONTACTS_COMMANDS,
2077
- ...CALENDAR_COMMANDS,
2078
- ...REMINDERS_COMMANDS,
2079
- ...PHOTOS_COMMANDS,
2080
- ...MOTION_COMMANDS
2081
- ],
2082
- macos: [
2083
- ...CANVAS_COMMANDS,
2084
- ...CAMERA_COMMANDS,
2085
- ...LOCATION_COMMANDS,
2086
- ...DEVICE_COMMANDS,
2087
- ...CONTACTS_COMMANDS,
2088
- ...CALENDAR_COMMANDS,
2089
- ...REMINDERS_COMMANDS,
2090
- ...PHOTOS_COMMANDS,
2091
- ...MOTION_COMMANDS,
2092
- ...SYSTEM_COMMANDS
2093
- ],
2094
- linux: [...SYSTEM_COMMANDS],
2095
- windows: [...SYSTEM_COMMANDS],
2096
- unknown: [
2097
- ...CANVAS_COMMANDS,
2098
- ...CAMERA_COMMANDS,
2099
- ...LOCATION_COMMANDS,
2100
- ...SYSTEM_COMMANDS
2101
- ]
2102
- };
2103
-
2104
- //#endregion
2105
- //#region src/gateway/server-startup-trace.ts
2106
- let lastGatewayStartupTraceSnapshot = null;
2107
- function getLastGatewayStartupTraceSnapshot() {
2108
- if (!lastGatewayStartupTraceSnapshot) return null;
2109
- return {
2110
- ...lastGatewayStartupTraceSnapshot,
2111
- entries: lastGatewayStartupTraceSnapshot.entries.map((entry) => ({ ...entry }))
2112
- };
2113
- }
2114
-
2115
- //#endregion
2116
- //#region src/infra/heartbeat-events-filter.ts
2117
- const HEARTBEAT_OK_PREFIX = HEARTBEAT_TOKEN.toLowerCase();
2118
-
2119
- //#endregion
2120
- //#region src/infra/heartbeat-runner.ts
2121
- const log = createSubsystemLogger("gateway/heartbeat");
2122
- const DEFAULT_HEARTBEAT_TARGET = "none";
2123
- function hasExplicitHeartbeatAgents(cfg) {
2124
- return (cfg.agents?.list ?? []).some((entry) => Boolean(entry?.heartbeat));
2125
- }
2126
- function isHeartbeatEnabledForAgent(cfg, agentId) {
2127
- const resolvedAgentId = normalizeAgentId(agentId ?? resolveDefaultAgentId(cfg));
2128
- const list = cfg.agents?.list ?? [];
2129
- if (hasExplicitHeartbeatAgents(cfg)) return list.some((entry) => Boolean(entry?.heartbeat) && normalizeAgentId(entry?.id) === resolvedAgentId);
2130
- return resolvedAgentId === resolveDefaultAgentId(cfg);
2131
- }
2132
- function resolveHeartbeatSummaryForAgent(cfg, agentId) {
2133
- const defaults = cfg.agents?.defaults?.heartbeat;
2134
- const overrides = agentId ? resolveAgentConfig(cfg, agentId)?.heartbeat : void 0;
2135
- if (!isHeartbeatEnabledForAgent(cfg, agentId)) return {
2136
- enabled: false,
2137
- every: "disabled",
2138
- everyMs: null,
2139
- prompt: resolveHeartbeatPrompt(defaults?.prompt),
2140
- target: defaults?.target ?? DEFAULT_HEARTBEAT_TARGET,
2141
- model: defaults?.model,
2142
- ackMaxChars: Math.max(0, defaults?.ackMaxChars ?? DEFAULT_HEARTBEAT_ACK_MAX_CHARS)
2143
- };
2144
- const merged = defaults || overrides ? {
2145
- ...defaults,
2146
- ...overrides
2147
- } : void 0;
2148
- return {
2149
- enabled: true,
2150
- every: merged?.every ?? defaults?.every ?? overrides?.every ?? DEFAULT_HEARTBEAT_EVERY,
2151
- everyMs: resolveHeartbeatIntervalMs(cfg, void 0, merged),
2152
- prompt: resolveHeartbeatPrompt(merged?.prompt ?? defaults?.prompt ?? overrides?.prompt),
2153
- target: merged?.target ?? defaults?.target ?? overrides?.target ?? DEFAULT_HEARTBEAT_TARGET,
2154
- model: merged?.model ?? defaults?.model ?? overrides?.model,
2155
- ackMaxChars: Math.max(0, merged?.ackMaxChars ?? defaults?.ackMaxChars ?? overrides?.ackMaxChars ?? DEFAULT_HEARTBEAT_ACK_MAX_CHARS)
2156
- };
2157
- }
2158
- function resolveHeartbeatIntervalMs(cfg, overrideEvery, heartbeat) {
2159
- const raw = overrideEvery ?? heartbeat?.every ?? cfg.agents?.defaults?.heartbeat?.every ?? DEFAULT_HEARTBEAT_EVERY;
2160
- if (!raw) return null;
2161
- const trimmed = String(raw).trim();
2162
- if (!trimmed) return null;
2163
- let ms;
2164
- try {
2165
- ms = parseDurationMs(trimmed, { defaultUnit: "m" });
2166
- } catch {
2167
- return null;
2168
- }
2169
- if (ms <= 0) return null;
2170
- return ms;
2171
- }
2172
-
2173
- //#endregion
2174
- //#region src/infra/brew.ts
2175
- function isExecutable(filePath) {
2176
- try {
2177
- fs.accessSync(filePath, fs.constants.X_OK);
2178
- return true;
2179
- } catch {
2180
- return false;
2181
- }
2182
- }
2183
- function normalizePathValue(value) {
2184
- if (typeof value !== "string") return;
2185
- const trimmed = value.trim();
2186
- return trimmed ? trimmed : void 0;
2187
- }
2188
- function resolveBrewExecutable(opts) {
2189
- const homeDir = opts?.homeDir ?? os.homedir();
2190
- const env = opts?.env ?? process.env;
2191
- const candidates = [];
2192
- const brewFile = normalizePathValue(env.HOMEBREW_BREW_FILE);
2193
- if (brewFile) candidates.push(brewFile);
2194
- const prefix = normalizePathValue(env.HOMEBREW_PREFIX);
2195
- if (prefix) candidates.push(path.join(prefix, "bin", "brew"));
2196
- candidates.push(path.join(homeDir, ".linuxbrew", "bin", "brew"));
2197
- candidates.push("/home/linuxbrew/.linuxbrew/bin/brew");
2198
- candidates.push("/opt/homebrew/bin/brew", "/usr/local/bin/brew");
2199
- for (const candidate of candidates) if (isExecutable(candidate)) return candidate;
2200
- }
2201
-
2202
- //#endregion
2203
- //#region src/agents/skills/bundled-context.ts
2204
- const skillsLogger = createSubsystemLogger("skills");
2205
-
2206
- //#endregion
2207
- //#region src/daemon/systemd-system.ts
2208
- const SERVICE_NAME = "fased-gateway";
2209
- const SYSTEM_UNIT_CANDIDATES = [
2210
- `/etc/systemd/system/${SERVICE_NAME}.service`,
2211
- `/usr/lib/systemd/system/${SERVICE_NAME}.service`,
2212
- `/lib/systemd/system/${SERVICE_NAME}.service`
2213
- ];
2214
-
2215
- //#endregion
2216
- //#region src/commands/status.acpx-bridge.ts
2217
- const ACPX_PUSH_TEST_TOOL_NAME = "fased_push_test_request";
2218
- const VALID_MODES = new Set([
2219
- "status-only",
2220
- "read-only-tools",
2221
- "operator-approved-mutating-tools"
2222
- ]);
2223
- function asRecord(value) {
2224
- return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2225
- }
2226
- function readToolList(value) {
2227
- if (!Array.isArray(value)) return [];
2228
- return [...new Set(value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0))].toSorted((left, right) => left.localeCompare(right));
2229
- }
2230
- function readConfiguredMode(value) {
2231
- return typeof value === "string" && VALID_MODES.has(value) ? value : "status-only";
2232
- }
2233
- function resolveAcpxMcpBridgeStatus(cfg) {
2234
- const pluginEntry = cfg.plugins?.entries?.acpx;
2235
- const pluginEnabled = cfg.plugins?.enabled !== false && pluginEntry?.enabled !== false;
2236
- const bridgeConfig = asRecord(asRecord(pluginEntry?.config).mcpBridge);
2237
- const configuredMode = readConfiguredMode(bridgeConfig.mode);
2238
- const bridgeEnabled = pluginEnabled && bridgeConfig.enabled === true;
2239
- const allowTools = readToolList(bridgeConfig.allowTools);
2240
- const denyTools = readToolList(bridgeConfig.denyTools);
2241
- const denied = denyTools.includes(ACPX_PUSH_TEST_TOOL_NAME);
2242
- const allowed = allowTools.includes(ACPX_PUSH_TEST_TOOL_NAME);
2243
- const enabled = bridgeEnabled && configuredMode === "operator-approved-mutating-tools" && allowed && !denied;
2244
- const reason = (() => {
2245
- if (!bridgeEnabled) return "mcpBridge.disabled";
2246
- if (configuredMode !== "operator-approved-mutating-tools") return "mcpBridge.not-mutating-mode";
2247
- if (denied) return "mcpBridge.denyTools";
2248
- if (!allowed) return "mcpBridge.allowTools";
2249
- return "enabled";
2250
- })();
2251
- return {
2252
- pluginId: "acpx",
2253
- enabled: bridgeEnabled,
2254
- mode: bridgeEnabled ? configuredMode : "disabled",
2255
- configuredMode,
2256
- allowTools,
2257
- denyTools,
2258
- fasedPushTestRequest: {
2259
- toolName: ACPX_PUSH_TEST_TOOL_NAME,
2260
- enabled,
2261
- allowed,
2262
- denied,
2263
- reason
2264
- }
2265
- };
2266
- }
2267
-
2268
- //#endregion
2269
- //#region src/commands/channel-account-context.ts
2270
- async function resolveDefaultChannelAccountContext(plugin, cfg) {
2271
- const accountIds = plugin.config.listAccountIds(cfg);
2272
- const defaultAccountId = resolveChannelDefaultAccountId({
2273
- plugin,
2274
- cfg,
2275
- accountIds
2276
- });
2277
- const account = plugin.config.resolveAccount(cfg, defaultAccountId);
2278
- return {
2279
- accountIds,
2280
- defaultAccountId,
2281
- account,
2282
- enabled: plugin.config.isEnabled ? plugin.config.isEnabled(account, cfg) : true,
2283
- configured: plugin.config.isConfigured ? await plugin.config.isConfigured(account, cfg) : true
2284
- };
2285
- }
2286
-
2287
- //#endregion
2288
- //#region src/commands/status.link-channel.ts
2289
- async function resolveLinkChannelContext(cfg) {
2290
- for (const plugin of listChannelPlugins()) {
2291
- const { defaultAccountId, account, enabled, configured } = await resolveDefaultChannelAccountContext(plugin, cfg);
2292
- const snapshot = plugin.config.describeAccount ? plugin.config.describeAccount(account, cfg) : {
2293
- accountId: defaultAccountId,
2294
- enabled,
2295
- configured
2296
- };
2297
- const summaryRecord = plugin.status?.buildChannelSummary ? await plugin.status.buildChannelSummary({
2298
- account,
2299
- cfg,
2300
- defaultAccountId,
2301
- snapshot
2302
- }) : void 0;
2303
- const linked = summaryRecord && typeof summaryRecord.linked === "boolean" ? summaryRecord.linked : null;
2304
- if (linked === null) continue;
2305
- return {
2306
- linked,
2307
- authAgeMs: summaryRecord && typeof summaryRecord.authAgeMs === "number" ? summaryRecord.authAgeMs : null,
2308
- account,
2309
- accountId: defaultAccountId,
2310
- plugin
2311
- };
2312
- }
2313
- return null;
2314
- }
2315
-
2316
- //#endregion
2317
- //#region src/commands/status.strict-agentic.ts
2318
- function hasMode(value) {
2319
- return value === "off" || value === "warn";
2320
- }
2321
- function resolveEnvironmentMode(env) {
2322
- return resolveStrictAgenticRuntimeMode(env) === "warn" ? "warn" : "off";
2323
- }
2324
- function resolveStrictAgenticPolicyStatus(cfg, agentIds, env = process.env) {
2325
- const defaultConfigMode = cfg.agents?.defaults?.strictAgentic?.mode;
2326
- const envFlagSet = Boolean(env.FASED_STRICT_AGENTIC_MODE?.trim());
2327
- const fallbackMode = resolveEnvironmentMode(env);
2328
- const defaultMode = hasMode(defaultConfigMode) ? defaultConfigMode : fallbackMode;
2329
- const defaultSource = hasMode(defaultConfigMode) ? "default-config" : envFlagSet ? "environment" : "implicit-default";
2330
- const configuredAgents = new Map((cfg.agents?.list ?? []).map((agent) => [agent.id.trim(), hasMode(agent.strictAgentic?.mode) ? agent.strictAgentic.mode : void 0]));
2331
- const agents = [...new Set(agentIds.map((agentId) => agentId.trim()).filter(Boolean))].toSorted((left, right) => left.localeCompare(right)).map((agentId) => {
2332
- const agentMode = configuredAgents.get(agentId);
2333
- const override = hasMode(agentMode);
2334
- return {
2335
- agentId,
2336
- mode: override ? agentMode : defaultMode,
2337
- source: override ? "agent-config" : defaultSource,
2338
- override
2339
- };
2340
- });
2341
- return {
2342
- mode: defaultMode,
2343
- source: defaultSource,
2344
- envFlagSet,
2345
- enforcementAvailable: false,
2346
- warningAgents: agents.filter((agent) => agent.mode === "warn").length,
2347
- totalAgents: agents.length,
2348
- agents
2349
- };
2350
- }
2351
-
2352
- //#endregion
2353
- //#region src/commands/status.summary.ts
2354
- const buildFlags = (entry) => {
2355
- if (!entry) return [];
2356
- const flags = [];
2357
- const think = entry?.thinkingLevel;
2358
- if (typeof think === "string" && think.length > 0) flags.push(`think:${think}`);
2359
- const verbose = entry?.verboseLevel;
2360
- if (typeof verbose === "string" && verbose.length > 0) flags.push(`verbose:${verbose}`);
2361
- const reasoning = entry?.reasoningLevel;
2362
- if (typeof reasoning === "string" && reasoning.length > 0) flags.push(`reasoning:${reasoning}`);
2363
- const elevated = entry?.elevatedLevel;
2364
- if (typeof elevated === "string" && elevated.length > 0) flags.push(`elevated:${elevated}`);
2365
- if (entry?.systemSent) flags.push("system");
2366
- if (entry?.abortedLastRun) flags.push("aborted");
2367
- const sessionId = entry?.sessionId;
2368
- if (typeof sessionId === "string" && sessionId.length > 0) flags.push(`id:${sessionId}`);
2369
- return flags;
2370
- };
2371
- function redactSensitiveStatusSummary(summary) {
2372
- return {
2373
- ...summary,
2374
- sessions: {
2375
- ...summary.sessions,
2376
- paths: [],
2377
- defaults: {
2378
- model: null,
2379
- contextTokens: null
2380
- },
2381
- recent: [],
2382
- byAgent: summary.sessions.byAgent.map((entry) => ({
2383
- ...entry,
2384
- path: "[redacted]",
2385
- recent: []
2386
- }))
2387
- }
2388
- };
2389
- }
2390
- async function getStatusSummary(options = {}) {
2391
- const { includeSensitive = true } = options;
2392
- const cfg = loadConfig();
2393
- const linkContext = await resolveLinkChannelContext(cfg);
2394
- const agentList = listAgentsForGateway(cfg);
2395
- const heartbeatAgents = agentList.agents.map((agent) => {
2396
- const summary = resolveHeartbeatSummaryForAgent(cfg, agent.id);
2397
- return {
2398
- agentId: agent.id,
2399
- enabled: summary.enabled,
2400
- every: summary.every,
2401
- everyMs: summary.everyMs
2402
- };
2403
- });
2404
- const channelSummary = await buildChannelSummary(cfg, {
2405
- colorize: true,
2406
- includeAllowFrom: true
2407
- });
2408
- const queuedSystemEvents = peekSystemEvents(resolveMainSessionKey(cfg));
2409
- const resolved = resolveConfiguredModelRef({
2410
- cfg,
2411
- defaultProvider: DEFAULT_PROVIDER,
2412
- defaultModel: DEFAULT_MODEL
2413
- });
2414
- const configModel = resolved.model ?? DEFAULT_MODEL;
2415
- const configContextTokens = resolveContextTokensForModel({
2416
- cfg,
2417
- provider: resolved.provider ?? DEFAULT_PROVIDER,
2418
- model: configModel,
2419
- contextTokensOverride: cfg.agents?.defaults?.contextTokens,
2420
- fallbackContextTokens: DEFAULT_CONTEXT_TOKENS
2421
- }) ?? DEFAULT_CONTEXT_TOKENS;
2422
- const now = Date.now();
2423
- const storeCache = /* @__PURE__ */ new Map();
2424
- const loadStore = (storePath) => {
2425
- const cached = storeCache.get(storePath);
2426
- if (cached) return cached;
2427
- const store = loadSessionStore(storePath);
2428
- storeCache.set(storePath, store);
2429
- return store;
2430
- };
2431
- const buildSessionRows = (store, opts = {}) => Object.entries(store).filter(([key]) => key !== "global" && key !== "unknown").map(([key, entry]) => {
2432
- const updatedAt = entry?.updatedAt ?? null;
2433
- const age = updatedAt ? now - updatedAt : null;
2434
- const resolvedModel = resolveSessionModelRef(cfg, entry, opts.agentIdOverride);
2435
- const model = resolvedModel.model ?? configModel ?? null;
2436
- const contextTokens = resolveContextTokensForModel({
2437
- cfg,
2438
- provider: resolvedModel.provider,
2439
- model,
2440
- contextTokensOverride: entry?.contextTokens,
2441
- fallbackContextTokens: configContextTokens ?? void 0
2442
- }) ?? null;
2443
- const total = resolveFreshSessionTotalTokens(entry);
2444
- const totalTokensFresh = typeof entry?.totalTokens === "number" ? entry?.totalTokensFresh !== false : false;
2445
- const remaining = contextTokens != null && total !== void 0 ? Math.max(0, contextTokens - total) : null;
2446
- const pct = contextTokens && contextTokens > 0 && total !== void 0 ? Math.min(999, Math.round(total / contextTokens * 100)) : null;
2447
- const parsedAgentId = parseAgentSessionKey(key)?.agentId;
2448
- return {
2449
- agentId: opts.agentIdOverride ?? parsedAgentId,
2450
- key,
2451
- kind: classifySessionKey(key, entry),
2452
- sessionId: entry?.sessionId,
2453
- updatedAt,
2454
- age,
2455
- thinkingLevel: entry?.thinkingLevel,
2456
- verboseLevel: entry?.verboseLevel,
2457
- reasoningLevel: entry?.reasoningLevel,
2458
- elevatedLevel: entry?.elevatedLevel,
2459
- systemSent: entry?.systemSent,
2460
- abortedLastRun: entry?.abortedLastRun,
2461
- inputTokens: entry?.inputTokens,
2462
- outputTokens: entry?.outputTokens,
2463
- cacheRead: entry?.cacheRead,
2464
- cacheWrite: entry?.cacheWrite,
2465
- totalTokens: total ?? null,
2466
- totalTokensFresh,
2467
- remainingTokens: remaining,
2468
- percentUsed: pct,
2469
- model,
2470
- contextTokens,
2471
- flags: buildFlags(entry)
2472
- };
2473
- }).sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
2474
- const paths = /* @__PURE__ */ new Set();
2475
- const byAgent = agentList.agents.map((agent) => {
2476
- const storePath = resolveStorePath(cfg.session?.store, { agentId: agent.id });
2477
- paths.add(storePath);
2478
- const sessions = buildSessionRows(loadStore(storePath), { agentIdOverride: agent.id });
2479
- return {
2480
- agentId: agent.id,
2481
- path: storePath,
2482
- count: sessions.length,
2483
- recent: sessions.slice(0, 10)
2484
- };
2485
- });
2486
- const allSessions = Array.from(paths).flatMap((storePath) => buildSessionRows(loadStore(storePath))).toSorted((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
2487
- const recent = allSessions.slice(0, 10);
2488
- const totalSessions = allSessions.length;
2489
- const summary = {
2490
- gatewayStartup: getLastGatewayStartupTraceSnapshot(),
2491
- acpxMcpBridge: resolveAcpxMcpBridgeStatus(cfg),
2492
- strictAgentic: resolveStrictAgenticPolicyStatus(cfg, agentList.agents.map((agent) => agent.id)),
2493
- linkChannel: linkContext ? {
2494
- id: linkContext.plugin.id,
2495
- label: linkContext.plugin.meta.label ?? "Channel",
2496
- linked: linkContext.linked,
2497
- authAgeMs: linkContext.authAgeMs
2498
- } : void 0,
2499
- heartbeat: {
2500
- defaultAgentId: agentList.defaultId,
2501
- agents: heartbeatAgents
2502
- },
2503
- channelSummary,
2504
- queuedSystemEvents,
2505
- sessions: {
2506
- paths: Array.from(paths),
2507
- count: totalSessions,
2508
- defaults: {
2509
- model: configModel ?? null,
2510
- contextTokens: configContextTokens ?? null
2511
- },
2512
- recent,
2513
- byAgent
2514
- }
2515
- };
2516
- return includeSensitive ? summary : redactSensitiveStatusSummary(summary);
2517
- }
2518
-
2519
- //#endregion
2520
- //#region src/commands/status.update.ts
2521
- function resolveUpdateAvailability(update, opts = {}) {
2522
- const latestVersion = update.registry?.latestVersion ?? null;
2523
- const registryCmp = latestVersion ? compareSemverStrings(VERSION, latestVersion) : null;
2524
- const hasRegistryUpdate = registryCmp != null && registryCmp < 0;
2525
- const gitBehind = (opts.channel == null || opts.channel === "dev") && update.installKind === "git" && typeof update.git?.behind === "number" ? update.git.behind : null;
2526
- const hasGitUpdate = gitBehind != null && gitBehind > 0;
2527
- return {
2528
- available: hasGitUpdate || hasRegistryUpdate,
2529
- hasGitUpdate,
2530
- hasRegistryUpdate,
2531
- latestVersion: hasRegistryUpdate ? latestVersion : null,
2532
- gitBehind
2533
- };
2534
- }
2535
- function formatUpdateOneLiner(update, opts = {}) {
2536
- const parts = [];
2537
- const appendRegistryUpdateSummary = () => {
2538
- if (update.registry?.latestVersion) {
2539
- const cmp = compareSemverStrings(VERSION, update.registry.latestVersion);
2540
- if (cmp === 0) parts.push(`npm latest ${update.registry.latestVersion}`);
2541
- else if (cmp != null && cmp < 0) parts.push(`npm update ${update.registry.latestVersion}`);
2542
- else parts.push(`npm latest ${update.registry.latestVersion} (local newer)`);
2543
- return;
2544
- }
2545
- if (update.registry?.error) parts.push("npm latest unknown");
2546
- };
2547
- if (update.installKind === "git" && update.git) {
2548
- if (opts.channel && opts.channel !== "dev") {
2549
- parts.push(`${opts.channel} channel`);
2550
- if (update.git.dirty === true) parts.push("dirty");
2551
- } else {
2552
- const branch = update.git.branch ? `git ${update.git.branch}` : "git";
2553
- parts.push(branch);
2554
- if (update.git.upstream) parts.push(`↔ ${update.git.upstream}`);
2555
- if (update.git.dirty === true) parts.push("dirty");
2556
- if (update.git.behind != null && update.git.ahead != null) {
2557
- if (update.git.behind === 0 && update.git.ahead === 0) parts.push("up to date");
2558
- else if (update.git.behind > 0 && update.git.ahead === 0) parts.push(`behind ${update.git.behind}`);
2559
- else if (update.git.behind === 0 && update.git.ahead > 0) parts.push(`ahead ${update.git.ahead}`);
2560
- else if (update.git.behind > 0 && update.git.ahead > 0) parts.push(`diverged (ahead ${update.git.ahead}, behind ${update.git.behind})`);
2561
- }
2562
- if (update.git.fetchOk === false) parts.push("fetch failed");
2563
- }
2564
- appendRegistryUpdateSummary();
2565
- } else {
2566
- parts.push(update.packageManager !== "unknown" ? update.packageManager : "pkg");
2567
- appendRegistryUpdateSummary();
2568
- }
2569
- if (update.deps) {
2570
- if (update.deps.status === "ok") parts.push("deps ok");
2571
- if (update.deps.status === "missing") parts.push("deps missing");
2572
- if (update.deps.status === "stale") parts.push("deps stale");
2573
- }
2574
- return `Update: ${parts.join(" · ")}`;
2575
- }
2576
-
2577
- //#endregion
2578
- //#region src/gateway/server-model-catalog.ts
2579
- function createGatewayModelCatalogCache() {
2580
- return {
2581
- lastSuccessfulCatalog: null,
2582
- inFlightRefresh: null,
2583
- staleGeneration: 0,
2584
- appliedGeneration: 0
2585
- };
2586
- }
2587
- const readOnlyModelCatalogCache = createGatewayModelCatalogCache();
2588
- const fullModelCatalogCache = createGatewayModelCatalogCache();
2589
- function isGatewayModelCatalogStale(cache) {
2590
- return cache.appliedGeneration < cache.staleGeneration;
2591
- }
2592
- function resolveGatewayModelCatalogCache(params) {
2593
- return params?.readOnly === false ? fullModelCatalogCache : readOnlyModelCatalogCache;
2594
- }
2595
- function resolveLoadModelCatalog(params) {
2596
- return params?.loadModelCatalog ?? loadModelCatalog;
2597
- }
2598
- function startGatewayModelCatalogRefresh(params) {
2599
- const cache = resolveGatewayModelCatalogCache(params);
2600
- const config = (params?.getConfig ?? loadConfig)();
2601
- const readOnly = params?.readOnly !== false;
2602
- const refreshGeneration = cache.staleGeneration;
2603
- const refresh = resolveLoadModelCatalog(params)({
2604
- config,
2605
- readOnly,
2606
- useCache: false
2607
- }).then((catalog) => {
2608
- if ((readOnly || catalog.length > 0) && refreshGeneration === cache.staleGeneration) {
2609
- cache.lastSuccessfulCatalog = catalog;
2610
- cache.appliedGeneration = cache.staleGeneration;
2611
- }
2612
- return catalog;
2613
- }).finally(() => {
2614
- if (cache.inFlightRefresh === refresh) cache.inFlightRefresh = null;
2615
- });
2616
- cache.inFlightRefresh = refresh;
2617
- return refresh;
2618
- }
2619
- async function loadGatewayModelCatalog(params) {
2620
- const cache = resolveGatewayModelCatalogCache(params);
2621
- if (!isGatewayModelCatalogStale(cache) && cache.lastSuccessfulCatalog !== null) return cache.lastSuccessfulCatalog;
2622
- if (isGatewayModelCatalogStale(cache) && cache.lastSuccessfulCatalog !== null) {
2623
- if (!cache.inFlightRefresh) startGatewayModelCatalogRefresh(params).catch(() => void 0);
2624
- return cache.lastSuccessfulCatalog;
2625
- }
2626
- if (cache.inFlightRefresh) return await cache.inFlightRefresh;
2627
- return await startGatewayModelCatalogRefresh(params);
2628
- }
2629
-
2630
- //#endregion
2631
- //#region src/agents/provider-extension-catalog-manifest.ts
2632
- const FASED_PROVIDER_EXTENSION_CATALOG_MANIFEST = [
2633
- {
2634
- upstreamProviderId: "anthropic",
2635
- upstreamCatalogPaths: ["extensions/anthropic/provider-discovery.ts"],
2636
- status: "mapped",
2637
- fasedProviderIds: ["anthropic"],
2638
- docsPath: "docs/providers/anthropic.md",
2639
- authSurface: "api-key",
2640
- authChoiceIds: ["apiKey", "token"]
2641
- },
2642
- {
2643
- upstreamProviderId: "byteplus",
2644
- upstreamCatalogPaths: ["extensions/byteplus/provider-catalog.ts", "extensions/byteplus/provider-discovery.ts"],
2645
- status: "mapped",
2646
- fasedProviderIds: [
2647
- "byteplus",
2648
- "byteplus-coding",
2649
- "byteplus-plan"
2650
- ],
2651
- docsPath: "docs/providers/volcengine.md",
2652
- authSurface: "api-key",
2653
- authChoiceIds: ["byteplus-api-key"]
2654
- },
2655
- {
2656
- upstreamProviderId: "chutes",
2657
- upstreamCatalogPaths: ["extensions/chutes/provider-catalog.ts"],
2658
- status: "mapped",
2659
- fasedProviderIds: ["chutes"],
2660
- docsPath: "docs/providers/chutes.md",
2661
- authSurface: "oauth",
2662
- authChoiceIds: ["chutes"]
2663
- },
2664
- {
2665
- upstreamProviderId: "codex",
2666
- upstreamCatalogPaths: ["extensions/codex/provider-catalog.ts", "extensions/codex/provider-discovery.ts"],
2667
- status: "mapped",
2668
- fasedProviderIds: ["openai-codex"],
2669
- fasedProviderAliases: ["codex"],
2670
- docsPath: "docs/providers/openai.md",
2671
- authSurface: "oauth",
2672
- authChoiceIds: ["openai-codex"]
2673
- },
2674
- {
2675
- upstreamProviderId: "huggingface",
2676
- upstreamCatalogPaths: ["extensions/huggingface/provider-catalog.ts"],
2677
- status: "mapped",
2678
- fasedProviderIds: ["huggingface"],
2679
- docsPath: "docs/providers/huggingface.md",
2680
- authSurface: "api-key",
2681
- authChoiceIds: ["huggingface-api-key"]
2682
- },
2683
- {
2684
- upstreamProviderId: "kimi-coding",
2685
- upstreamCatalogPaths: ["extensions/kimi-coding/provider-catalog.ts"],
2686
- status: "mapped",
2687
- fasedProviderIds: ["kimi"],
2688
- fasedProviderAliases: ["kimi-coding", "kimi-code"],
2689
- docsPath: "docs/providers/moonshot.md",
2690
- authSurface: "api-key",
2691
- authChoiceIds: ["kimi-code-api-key"]
2692
- },
2693
- {
2694
- upstreamProviderId: "litellm",
2695
- upstreamCatalogPaths: ["extensions/litellm/provider-catalog.ts"],
2696
- status: "mapped",
2697
- fasedProviderIds: ["litellm"],
2698
- docsPath: "docs/providers/litellm.md",
2699
- authSurface: "api-key",
2700
- authChoiceIds: ["litellm-api-key"]
2701
- },
2702
- {
2703
- upstreamProviderId: "minimax",
2704
- upstreamCatalogPaths: ["extensions/minimax/provider-catalog.ts"],
2705
- status: "mapped",
2706
- fasedProviderIds: [
2707
- "minimax",
2708
- "minimax-cn",
2709
- "minimax-portal"
2710
- ],
2711
- docsPath: "docs/providers/minimax.md",
2712
- authSurface: "api-key",
2713
- authChoiceIds: [
2714
- "minimax-portal",
2715
- "minimax-api",
2716
- "minimax-api-key-cn",
2717
- "minimax-api-lightning"
2718
- ]
2719
- },
2720
- {
2721
- upstreamProviderId: "mistral",
2722
- upstreamCatalogPaths: ["extensions/mistral/provider-catalog.ts"],
2723
- status: "mapped",
2724
- fasedProviderIds: ["mistral"],
2725
- docsPath: "docs/providers/mistral.md",
2726
- authSurface: "api-key",
2727
- authChoiceIds: ["mistral-api-key"]
2728
- },
2729
- {
2730
- upstreamProviderId: "moonshot",
2731
- upstreamCatalogPaths: ["extensions/moonshot/provider-catalog.ts", "extensions/moonshot/provider-discovery.ts"],
2732
- status: "mapped",
2733
- fasedProviderIds: ["moonshot"],
2734
- docsPath: "docs/providers/moonshot.md",
2735
- authSurface: "api-key",
2736
- authChoiceIds: ["moonshot-api-key", "moonshot-api-key-cn"]
2737
- },
2738
- {
2739
- upstreamProviderId: "openrouter",
2740
- upstreamCatalogPaths: ["extensions/openrouter/provider-catalog.ts"],
2741
- status: "mapped",
2742
- fasedProviderIds: ["openrouter"],
2743
- docsPath: "docs/providers/openrouter.md",
2744
- authSurface: "api-key",
2745
- authChoiceIds: ["openrouter-api-key"]
2746
- },
2747
- {
2748
- upstreamProviderId: "qianfan",
2749
- upstreamCatalogPaths: ["extensions/qianfan/provider-catalog.ts"],
2750
- status: "mapped",
2751
- fasedProviderIds: ["qianfan"],
2752
- docsPath: "docs/providers/qianfan.md",
2753
- authSurface: "api-key",
2754
- authChoiceIds: ["qianfan-api-key"]
2755
- },
2756
- {
2757
- upstreamProviderId: "qwen",
2758
- upstreamCatalogPaths: ["extensions/qwen/provider-catalog.ts"],
2759
- status: "mapped",
2760
- fasedProviderIds: ["qwen"],
2761
- docsPath: "docs/providers/qwen.md",
2762
- authSurface: "api-key",
2763
- authChoiceIds: ["qwen-coding-plan-api-key", "qwen-api-key"]
2764
- },
2765
- {
2766
- upstreamProviderId: "synthetic",
2767
- upstreamCatalogPaths: ["extensions/synthetic/provider-catalog.ts"],
2768
- status: "mapped",
2769
- fasedProviderIds: ["synthetic"],
2770
- docsPath: "docs/providers/synthetic.md",
2771
- authSurface: "api-key",
2772
- authChoiceIds: ["synthetic-api-key"]
2773
- },
2774
- {
2775
- upstreamProviderId: "together",
2776
- upstreamCatalogPaths: ["extensions/together/provider-catalog.ts"],
2777
- status: "mapped",
2778
- fasedProviderIds: ["together"],
2779
- docsPath: "docs/providers/together.md",
2780
- authSurface: "api-key",
2781
- authChoiceIds: ["together-api-key"]
2782
- },
2783
- {
2784
- upstreamProviderId: "venice",
2785
- upstreamCatalogPaths: ["extensions/venice/provider-catalog.ts"],
2786
- status: "mapped",
2787
- fasedProviderIds: ["venice"],
2788
- docsPath: "docs/providers/venice.md",
2789
- authSurface: "api-key",
2790
- authChoiceIds: ["venice-api-key"]
2791
- },
2792
- {
2793
- upstreamProviderId: "vercel-ai-gateway",
2794
- upstreamCatalogPaths: ["extensions/vercel-ai-gateway/provider-catalog.ts"],
2795
- status: "mapped",
2796
- fasedProviderIds: ["vercel-ai-gateway"],
2797
- docsPath: "docs/providers/vercel-ai-gateway.md",
2798
- authSurface: "api-key",
2799
- authChoiceIds: ["ai-gateway-api-key"]
2800
- },
2801
- {
2802
- upstreamProviderId: "volcengine",
2803
- upstreamCatalogPaths: ["extensions/volcengine/provider-catalog.ts", "extensions/volcengine/provider-discovery.ts"],
2804
- status: "mapped",
2805
- fasedProviderIds: [
2806
- "volcengine",
2807
- "volcengine-coding",
2808
- "volcengine-plan"
2809
- ],
2810
- docsPath: "docs/providers/volcengine.md",
2811
- authSurface: "api-key",
2812
- authChoiceIds: ["volcengine-api-key"]
2813
- },
2814
- {
2815
- upstreamProviderId: "xai",
2816
- upstreamCatalogPaths: ["extensions/xai/provider-catalog.ts", "extensions/xai/provider-discovery.ts"],
2817
- status: "mapped",
2818
- fasedProviderIds: ["xai"],
2819
- docsPath: "docs/providers/xai.md",
2820
- authSurface: "api-key",
2821
- authChoiceIds: [
2822
- "xai-oauth",
2823
- "xai-device-code",
2824
- "xai-api-key"
2825
- ]
2826
- },
2827
- {
2828
- upstreamProviderId: "xiaomi",
2829
- upstreamCatalogPaths: ["extensions/xiaomi/provider-catalog.ts"],
2830
- status: "mapped",
2831
- fasedProviderIds: ["xiaomi"],
2832
- docsPath: "docs/providers/xiaomi.md",
2833
- authSurface: "api-key",
2834
- authChoiceIds: ["xiaomi-api-key"]
2835
- }
2836
- ];
2837
- function listProviderExtensionCatalogManifestEntries() {
2838
- return FASED_PROVIDER_EXTENSION_CATALOG_MANIFEST;
2839
- }
2840
-
2841
- //#endregion
2842
- //#region src/agents/model-catalog-status.ts
2843
- const SOURCE_CONFIDENCE_RANK = {
2844
- configured: 600,
2845
- runtime: 500,
2846
- manifest: 400,
2847
- "provider-index": 300,
2848
- "current-preview": 200,
2849
- catalog: 100
2850
- };
2851
- function createCapabilityCounts() {
2852
- return {
2853
- textModels: 0,
2854
- visionModels: 0,
2855
- reasoningModels: 0,
2856
- toolsModels: 0,
2857
- jsonModels: 0,
2858
- audioModels: 0,
2859
- videoModels: 0,
2860
- speechModels: 0
2861
- };
2862
- }
2863
- function capabilityKey(feature) {
2864
- return `${feature}Models`;
2865
- }
2866
- function resolveProviderConfig(params) {
2867
- return params.cfg.models?.providers?.[params.provider];
2868
- }
2869
- function deriveStatusMetadata(params) {
2870
- return params.model.metadata ?? deriveModelMetadata({
2871
- model: params.model,
2872
- cfg: params.cfg,
2873
- providerConfig: resolveProviderConfig({
2874
- cfg: params.cfg,
2875
- provider: params.provider
2876
- })
2877
- });
2878
- }
2879
- function higherConfidence(left, right) {
2880
- return (SOURCE_CONFIDENCE_RANK[left] ?? 0) >= (SOURCE_CONFIDENCE_RANK[right] ?? 0) ? left : right;
2881
- }
2882
- function buildModelCatalogStatus(params) {
2883
- const configuredProviders = new Set(Object.keys(params.cfg.models?.providers ?? {}).map((provider) => normalizeProviderId(provider)));
2884
- const sourceCounts = {};
2885
- const providers = /* @__PURE__ */ new Map();
2886
- let reasoningModels = 0;
2887
- let visionModels = 0;
2888
- const capabilityCounts = createCapabilityCounts();
2889
- for (const model of params.catalog) {
2890
- const provider = normalizeProviderId(model.provider);
2891
- if (!provider) continue;
2892
- const source = model.catalogSource ?? "catalog";
2893
- sourceCounts[source] = (sourceCounts[source] ?? 0) + 1;
2894
- let entry = providers.get(provider);
2895
- if (!entry) {
2896
- entry = {
2897
- provider,
2898
- totalModels: 0,
2899
- configured: configuredProviders.has(provider),
2900
- reasoningModels: 0,
2901
- visionModels: 0,
2902
- sources: /* @__PURE__ */ new Set(),
2903
- sourceConfidence: source,
2904
- capabilityCounts: createCapabilityCounts(),
2905
- authModes: /* @__PURE__ */ new Set(),
2906
- privateNetwork: {
2907
- models: 0,
2908
- allowed: 0,
2909
- blocked: 0
2910
- }
2911
- };
2912
- providers.set(provider, entry);
2913
- }
2914
- entry.totalModels += 1;
2915
- entry.sources.add(source);
2916
- entry.sourceConfidence = higherConfidence(entry.sourceConfidence, source);
2917
- const metadata = deriveStatusMetadata({
2918
- cfg: params.cfg,
2919
- model,
2920
- provider
2921
- });
2922
- entry.authModes.add(metadata.authMode);
2923
- for (const feature of metadata.features) {
2924
- entry.capabilityCounts[capabilityKey(feature)] += 1;
2925
- capabilityCounts[capabilityKey(feature)] += 1;
2926
- }
2927
- if (metadata.privateNetwork) {
2928
- entry.privateNetwork.models += 1;
2929
- if (metadata.privateNetworkAllowed) entry.privateNetwork.allowed += 1;
2930
- else entry.privateNetwork.blocked += 1;
2931
- }
2932
- if (typeof metadata.contextWindow === "number") entry.maxContextWindow = Math.max(entry.maxContextWindow ?? 0, metadata.contextWindow);
2933
- if (typeof metadata.maxTokens === "number") entry.maxOutputTokens = Math.max(entry.maxOutputTokens ?? 0, metadata.maxTokens);
2934
- if (model.reasoning === true) {
2935
- reasoningModels += 1;
2936
- entry.reasoningModels += 1;
2937
- }
2938
- if (model.input?.includes("image")) {
2939
- visionModels += 1;
2940
- entry.visionModels += 1;
2941
- }
2942
- }
2943
- const providerRows = Array.from(providers.values()).map((provider) => ({
2944
- provider: provider.provider,
2945
- totalModels: provider.totalModels,
2946
- configured: provider.configured,
2947
- reasoningModels: provider.reasoningModels,
2948
- visionModels: provider.visionModels,
2949
- sources: Array.from(provider.sources).toSorted((left, right) => left.localeCompare(right)),
2950
- sourceConfidence: provider.sourceConfidence,
2951
- capabilityCounts: provider.capabilityCounts,
2952
- authModes: Array.from(provider.authModes).toSorted((left, right) => left.localeCompare(right)),
2953
- privateNetwork: provider.privateNetwork,
2954
- probeStatus: params.providerHealth?.[provider.provider] ? params.providerHealth[provider.provider].reachable === "ok" && params.providerHealth[provider.provider].auth !== "fail" ? "ok" : params.providerHealth[provider.provider].reachable === "fail" || params.providerHealth[provider.provider].auth === "fail" ? "fail" : "unknown" : "not-run",
2955
- ...params.providerHealth?.[provider.provider] ? { health: {
2956
- reachable: params.providerHealth[provider.provider].reachable,
2957
- auth: params.providerHealth[provider.provider].auth,
2958
- modelsDiscovered: params.providerHealth[provider.provider].modelsDiscovered,
2959
- privateNetworkApproved: params.providerHealth[provider.provider].privateNetworkApproved,
2960
- ...typeof params.providerHealth[provider.provider].checkedAtMs === "number" ? { checkedAtMs: params.providerHealth[provider.provider].checkedAtMs } : {},
2961
- ...params.providerHealth[provider.provider].detail ? { detail: params.providerHealth[provider.provider].detail } : {}
2962
- } } : {},
2963
- ...provider.maxContextWindow ? { maxContextWindow: provider.maxContextWindow } : {},
2964
- ...provider.maxOutputTokens ? { maxOutputTokens: provider.maxOutputTokens } : {}
2965
- })).toSorted((left, right) => left.provider.localeCompare(right.provider));
2966
- const manifestEntries = listProviderExtensionCatalogManifestEntries();
2967
- const mappedManifestProviderIds = [...new Set(manifestEntries.flatMap((entry) => entry.status === "mapped" ? entry.fasedProviderIds.map(normalizeProviderId) : []))].filter(Boolean).toSorted((left, right) => left.localeCompare(right));
2968
- const catalogProviderIds = new Set(providerRows.map((provider) => provider.provider));
2969
- const deferredProviderIds = manifestEntries.filter((entry) => entry.status === "deferred").map((entry) => normalizeProviderId(entry.upstreamProviderId)).filter(Boolean).toSorted((left, right) => left.localeCompare(right));
2970
- const providerExtensionEntries = (params.providerExtensionCatalog?.entries ?? []).map((entry) => ({
2971
- id: entry.id,
2972
- source: entry.source,
2973
- trusted: entry.trusted,
2974
- providerIds: entry.providerIds,
2975
- loadedProviderIds: entry.loadedProviderIds,
2976
- modelCount: entry.modelCount,
2977
- status: entry.status,
2978
- ...entry.error ? { error: entry.error } : {}
2979
- }));
2980
- const providerExtensionWarnings = providerExtensionEntries.filter((entry) => entry.status === "error" || entry.status === "skipped-untrusted");
2981
- return {
2982
- checkedAtMs: params.checkedAtMs ?? Date.now(),
2983
- cache: {
2984
- modelCatalog: "shared-loader",
2985
- providerExtensionCatalog: params.providerExtensionCatalog ? "fresh-status-load" : "not-loaded"
2986
- },
2987
- totalProviders: providerRows.length,
2988
- totalModels: params.catalog.length,
2989
- configuredProviders: providerRows.filter((provider) => provider.configured).length,
2990
- availableProviders: providerRows.filter((provider) => !provider.configured).length,
2991
- reasoningModels,
2992
- visionModels,
2993
- capabilityCounts,
2994
- sourceCounts,
2995
- providers: providerRows,
2996
- providerExtensionCatalog: {
2997
- totalEntries: providerExtensionEntries.length,
2998
- loadedEntries: providerExtensionEntries.filter((entry) => entry.status === "loaded").length,
2999
- skippedUntrustedEntries: providerExtensionEntries.filter((entry) => entry.status === "skipped-untrusted").length,
3000
- emptyEntries: providerExtensionEntries.filter((entry) => entry.status === "empty").length,
3001
- errorEntries: providerExtensionEntries.filter((entry) => entry.status === "error").length,
3002
- modelCount: providerExtensionEntries.reduce((total, entry) => total + entry.modelCount, 0),
3003
- loadedProviderIds: Object.keys(params.providerExtensionCatalog?.providers ?? {}).toSorted((left, right) => left.localeCompare(right)),
3004
- warnings: providerExtensionWarnings,
3005
- entries: providerExtensionEntries
3006
- },
3007
- providerExtensionManifest: {
3008
- upstreamProviderCount: manifestEntries.length,
3009
- mappedProviderCount: manifestEntries.filter((entry) => entry.status === "mapped").length,
3010
- deferredProviderCount: manifestEntries.filter((entry) => entry.status === "deferred").length,
3011
- mappedProviderIds: mappedManifestProviderIds,
3012
- deferredProviderIds,
3013
- missingMappedProviderIds: mappedManifestProviderIds.filter((providerId) => !catalogProviderIds.has(providerId))
3014
- }
3015
- };
3016
- }
3017
-
3018
- //#endregion
3019
- //#region src/gateway/update-status.ts
3020
- const DEFAULT_UPDATE_STATUS_TIMEOUT_MS = 3500;
3021
- function normalizeUpdateStatusTimeout(value) {
3022
- return typeof value === "number" && Number.isFinite(value) ? Math.max(1e3, Math.floor(value)) : DEFAULT_UPDATE_STATUS_TIMEOUT_MS;
3023
- }
3024
- async function getGatewayUpdateStatus(params) {
3025
- const timeoutMs = normalizeUpdateStatusTimeout(params?.timeoutMs);
3026
- const fetchGit = params?.fetchGit === true;
3027
- const includeRegistry = params?.includeRegistry === true;
3028
- const configSnapshot = await readConfigFileSnapshot();
3029
- const configChannel = configSnapshot.valid ? normalizeUpdateChannel(configSnapshot.config.update?.channel) : null;
3030
- const update = await checkUpdateStatus({
3031
- root: await resolveFasedAgentPackageRoot({
3032
- moduleUrl: import.meta.url,
3033
- argv1: process.argv[1],
3034
- cwd: process.cwd()
3035
- }) ?? process.cwd(),
3036
- timeoutMs,
3037
- fetchGit,
3038
- includeRegistry
3039
- });
3040
- const channel = resolveUpdateChannelDisplay({
3041
- configChannel,
3042
- installKind: update.installKind,
3043
- gitTag: update.git?.tag ?? null,
3044
- gitBranch: update.git?.branch ?? null
3045
- });
3046
- return {
3047
- ok: true,
3048
- update,
3049
- availability: resolveUpdateAvailability(update),
3050
- channel: {
3051
- ...channel,
3052
- config: configChannel
3053
- },
3054
- probes: {
3055
- fetchGit,
3056
- includeRegistry,
3057
- timeoutMs
3058
- },
3059
- summary: formatUpdateOneLiner(update)
3060
- };
3061
- }
3062
-
3063
- //#endregion
3064
- //#region src/gateway/server-methods/commands.ts
3065
- function normalizeOptionalLowercaseString(value) {
3066
- if (typeof value !== "string") return;
3067
- return value.trim().toLowerCase() || void 0;
3068
- }
3069
- function stripLeadingSlash(value) {
3070
- return value.startsWith("/") ? value.slice(1) : value;
3071
- }
3072
- function resolveTextAliases(cmd) {
3073
- const seen = /* @__PURE__ */ new Set();
3074
- const aliases = [];
3075
- for (const alias of cmd.textAliases) {
3076
- const trimmed = alias.trim();
3077
- if (!trimmed) continue;
3078
- const exactAlias = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
3079
- if (seen.has(exactAlias)) continue;
3080
- seen.add(exactAlias);
3081
- aliases.push(exactAlias);
3082
- }
3083
- if (aliases.length > 0) return aliases;
3084
- return [`/${cmd.key}`];
3085
- }
3086
- function resolvePrimaryTextName(cmd) {
3087
- return stripLeadingSlash(resolveTextAliases(cmd)[0] ?? `/${cmd.key}`);
3088
- }
3089
- function normalizeChoice(choice) {
3090
- return typeof choice === "string" ? {
3091
- value: choice,
3092
- label: choice
3093
- } : choice;
3094
- }
3095
- function serializeArg(arg) {
3096
- const isDynamic = typeof arg.choices === "function";
3097
- const staticChoices = Array.isArray(arg.choices) ? arg.choices.map(normalizeChoice) : void 0;
3098
- return {
3099
- name: arg.name,
3100
- description: arg.description,
3101
- type: arg.type,
3102
- ...arg.required ? { required: true } : {},
3103
- ...staticChoices ? { choices: staticChoices } : {},
3104
- ...isDynamic ? { dynamic: true } : {}
3105
- };
3106
- }
3107
- function mapCommand(params) {
3108
- const { cmd, includeArgs, nameSurface, provider, source } = params;
3109
- const shouldIncludeArgs = includeArgs && cmd.acceptsArgs && cmd.args?.length;
3110
- const nativeName = cmd.scope === "text" ? void 0 : resolveNativeCommandName(cmd, provider) ?? cmd.key;
3111
- return {
3112
- name: nameSurface === "text" ? resolvePrimaryTextName(cmd) : nativeName ?? cmd.key,
3113
- ...nativeName ? { nativeName } : {},
3114
- ...cmd.scope !== "native" ? { textAliases: resolveTextAliases(cmd) } : {},
3115
- description: cmd.description,
3116
- ...cmd.category ? { category: cmd.category } : {},
3117
- source,
3118
- scope: cmd.scope,
3119
- acceptsArgs: Boolean(cmd.acceptsArgs),
3120
- ...shouldIncludeArgs ? { args: cmd.args.map(serializeArg) } : {}
3121
- };
3122
- }
3123
- function buildPluginCommandEntries(params) {
3124
- const pluginTextSpecs = listPluginCommands();
3125
- const pluginNativeSpecs = getPluginCommandSpecs();
3126
- if (params.nameSurface === "text") return pluginTextSpecs.map((spec) => ({
3127
- name: spec.name,
3128
- textAliases: [`/${spec.name}`],
3129
- description: spec.description,
3130
- source: "plugin",
3131
- scope: "both",
3132
- acceptsArgs: spec.acceptsArgs
3133
- }));
3134
- return pluginNativeSpecs.map((spec) => ({
3135
- name: spec.name,
3136
- nativeName: spec.name,
3137
- textAliases: [`/${spec.name}`],
3138
- description: spec.description,
3139
- source: "plugin",
3140
- scope: "both",
3141
- acceptsArgs: spec.acceptsArgs
3142
- }));
3143
- }
3144
- function buildCommandsListResult(params) {
3145
- const includeArgs = params.includeArgs !== false;
3146
- const scopeFilter = params.scope ?? "both";
3147
- const nameSurface = scopeFilter === "text" ? "text" : "native";
3148
- const provider = normalizeOptionalLowercaseString(params.provider);
3149
- const skillCommands = listSkillCommandsForAgents({
3150
- cfg: params.cfg,
3151
- agentIds: [params.agentId]
3152
- });
3153
- const chatCommands = listChatCommandsForConfig(params.cfg, { skillCommands });
3154
- const skillKeys = new Set(skillCommands.map((command) => `skill:${command.skillName}`));
3155
- const commands = [];
3156
- for (const cmd of chatCommands) {
3157
- if (scopeFilter !== "both" && cmd.scope !== "both" && cmd.scope !== scopeFilter) continue;
3158
- commands.push(mapCommand({
3159
- cmd,
3160
- source: skillKeys.has(cmd.key) ? "skill" : "native",
3161
- includeArgs,
3162
- nameSurface,
3163
- provider
3164
- }));
3165
- }
3166
- commands.push(...buildPluginCommandEntries({ nameSurface }));
3167
- return { commands };
3168
- }
3169
-
3170
- //#endregion
3171
- //#region src/acp/status-snapshot.ts
3172
- function normalizeText(value) {
3173
- return typeof value === "string" && value.trim() ? value.trim() : null;
3174
- }
3175
- function normalizePositiveInteger(value) {
3176
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : null;
3177
- }
3178
- function resolveAcpBackendHealth(backend) {
3179
- if (!backend) return null;
3180
- if (!backend.healthy) return true;
3181
- try {
3182
- return backend.healthy();
3183
- } catch {
3184
- return false;
3185
- }
3186
- }
3187
- function sanitizeSession(entry) {
3188
- const acp = entry.acp;
3189
- if (!acp) return null;
3190
- const runtimeOptions = resolveRuntimeOptionsFromMeta(acp);
3191
- const backendExtrasKeys = Object.keys(runtimeOptions.backendExtras ?? {}).toSorted();
3192
- return {
3193
- sessionKey: entry.sessionKey,
3194
- backend: acp.backend,
3195
- agent: acp.agent,
3196
- mode: acp.mode,
3197
- state: acp.state,
3198
- lastActivityAt: acp.lastActivityAt,
3199
- ...acp.lastError ? { lastError: acp.lastError } : {},
3200
- ...acp.identity ? { identity: {
3201
- state: acp.identity.state,
3202
- source: acp.identity.source,
3203
- ...acp.identity.acpxRecordId ? { acpxRecordId: acp.identity.acpxRecordId } : {},
3204
- ...acp.identity.acpxSessionId ? { acpxSessionId: acp.identity.acpxSessionId } : {},
3205
- ...acp.identity.agentSessionId ? { agentSessionId: acp.identity.agentSessionId } : {},
3206
- lastUpdatedAt: acp.identity.lastUpdatedAt
3207
- } } : {},
3208
- runtimeOptions: {
3209
- ...runtimeOptions.runtimeMode ? { runtimeMode: runtimeOptions.runtimeMode } : {},
3210
- ...runtimeOptions.model ? { model: runtimeOptions.model } : {},
3211
- ...runtimeOptions.permissionProfile ? { permissionProfile: runtimeOptions.permissionProfile } : {},
3212
- ...runtimeOptions.timeoutSeconds ? { timeoutSeconds: runtimeOptions.timeoutSeconds } : {},
3213
- ...backendExtrasKeys.length > 0 ? { backendExtrasKeys } : {},
3214
- cwdConfigured: Boolean(acp.cwd || runtimeOptions.cwd)
3215
- }
3216
- };
3217
- }
3218
- async function getAcpStatusSnapshot(params) {
3219
- const cfg = params.cfg;
3220
- const requestedBackendId = normalizeText(cfg.acp?.backend) ?? "acpx";
3221
- const backend = getAcpRuntimeBackend(requestedBackendId);
3222
- const sessions = await listAcpSessionEntries({ cfg });
3223
- const limit = Math.max(0, Math.min(100, params.limit ?? 20));
3224
- const items = sessions.map(sanitizeSession).filter((session) => session !== null).toSorted((a, b) => b.lastActivityAt - a.lastActivityAt).slice(0, limit);
3225
- return {
3226
- policy: {
3227
- enabled: cfg.acp?.enabled !== false,
3228
- dispatchEnabled: cfg.acp?.dispatch?.enabled === true,
3229
- backend: requestedBackendId,
3230
- defaultAgent: normalizeText(cfg.acp?.defaultAgent),
3231
- allowedAgents: (cfg.acp?.allowedAgents ?? []).map((agent) => normalizeText(agent)).filter((agent) => agent !== null).toSorted(),
3232
- maxConcurrentSessions: normalizePositiveInteger(cfg.acp?.maxConcurrentSessions)
3233
- },
3234
- runtimeBackend: {
3235
- requestedId: requestedBackendId,
3236
- registered: backend != null,
3237
- selectedId: backend?.id ?? null,
3238
- healthy: resolveAcpBackendHealth(backend)
3239
- },
3240
- manager: getAcpSessionManager().getObservabilitySnapshot(cfg),
3241
- sessions: {
3242
- total: sessions.length,
3243
- returned: items.length,
3244
- limit,
3245
- items
3246
- }
3247
- };
3248
- }
3249
-
3250
- //#endregion
3251
- //#region src/infra/push-apns.ts
3252
- const APNS_STATE_FILENAME = "push/apns-registrations.json";
3253
- const APNS_JWT_TTL_MS = 3e3 * 1e3;
3254
- const DEFAULT_APNS_TIMEOUT_MS = 1e4;
3255
- const withLock = createAsyncLock();
3256
- let cachedJwt = null;
3257
- function resolveApnsRegistrationPath(baseDir) {
3258
- const root = baseDir ?? resolveStateDir();
3259
- return path.join(root, APNS_STATE_FILENAME);
3260
- }
3261
- function normalizeNodeId(value) {
3262
- return value.trim();
3263
- }
3264
- function normalizeApnsToken(value) {
3265
- return value.trim().replace(/[<>\s]/g, "").toLowerCase();
3266
- }
3267
- function normalizeTopic(value) {
3268
- return value.trim();
3269
- }
3270
- function isLikelyApnsToken(value) {
3271
- return /^[0-9a-f]{32,}$/i.test(value);
3272
- }
3273
- function parseReason(body) {
3274
- const trimmed = body.trim();
3275
- if (!trimmed) return;
3276
- try {
3277
- const parsed = JSON.parse(trimmed);
3278
- return typeof parsed.reason === "string" && parsed.reason.trim().length > 0 ? parsed.reason.trim() : trimmed.slice(0, 200);
3279
- } catch {
3280
- return trimmed.slice(0, 200);
3281
- }
3282
- }
3283
- function toBase64UrlBytes(value) {
3284
- return Buffer.from(value).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3285
- }
3286
- function toBase64UrlJson(value) {
3287
- return toBase64UrlBytes(Buffer.from(JSON.stringify(value)));
3288
- }
3289
- function getJwtCacheKey(auth) {
3290
- const keyHash = createHash("sha256").update(auth.privateKey).digest("hex");
3291
- return `${auth.teamId}:${auth.keyId}:${keyHash}`;
3292
- }
3293
- function getApnsBearerToken(auth, nowMs = Date.now()) {
3294
- const cacheKey = getJwtCacheKey(auth);
3295
- if (cachedJwt && cachedJwt.cacheKey === cacheKey && nowMs < cachedJwt.expiresAtMs) return cachedJwt.token;
3296
- const iat = Math.floor(nowMs / 1e3);
3297
- const signingInput = `${toBase64UrlJson({
3298
- alg: "ES256",
3299
- kid: auth.keyId,
3300
- typ: "JWT"
3301
- })}.${toBase64UrlJson({
3302
- iss: auth.teamId,
3303
- iat
3304
- })}`;
3305
- const token = `${signingInput}.${toBase64UrlBytes(sign("sha256", Buffer.from(signingInput, "utf8"), {
3306
- key: createPrivateKey(auth.privateKey),
3307
- dsaEncoding: "ieee-p1363"
3308
- }))}`;
3309
- cachedJwt = {
3310
- cacheKey,
3311
- token,
3312
- expiresAtMs: nowMs + APNS_JWT_TTL_MS
3313
- };
3314
- return token;
3315
- }
3316
- function normalizePrivateKey(value) {
3317
- return value.trim().replace(/\\n/g, "\n");
3318
- }
3319
- function normalizeNonEmptyString(value) {
3320
- const trimmed = value?.trim() ?? "";
3321
- return trimmed.length > 0 ? trimmed : null;
3322
- }
3323
- async function loadRegistrationsState(baseDir) {
3324
- const existing = await readJsonFile(resolveApnsRegistrationPath(baseDir));
3325
- if (!existing || typeof existing !== "object") return { registrationsByNodeId: {} };
3326
- return { registrationsByNodeId: existing.registrationsByNodeId && typeof existing.registrationsByNodeId === "object" && !Array.isArray(existing.registrationsByNodeId) ? existing.registrationsByNodeId : {} };
3327
- }
3328
- function normalizeApnsEnvironment(value) {
3329
- if (typeof value !== "string") return null;
3330
- const normalized = value.trim().toLowerCase();
3331
- if (normalized === "sandbox" || normalized === "production") return normalized;
3332
- return null;
3333
- }
3334
- async function loadApnsRegistration(nodeId, baseDir) {
3335
- const normalizedNodeId = normalizeNodeId(nodeId);
3336
- if (!normalizedNodeId) return null;
3337
- return (await loadRegistrationsState(baseDir)).registrationsByNodeId[normalizedNodeId] ?? null;
3338
- }
3339
- async function resolveApnsAuthConfigFromEnv(env = process.env) {
3340
- const teamId = normalizeNonEmptyString(env.FASED_APNS_TEAM_ID);
3341
- const keyId = normalizeNonEmptyString(env.FASED_APNS_KEY_ID);
3342
- if (!teamId || !keyId) return {
3343
- ok: false,
3344
- error: "APNs auth missing: set FASED_APNS_TEAM_ID and FASED_APNS_KEY_ID"
3345
- };
3346
- const inlineKeyRaw = normalizeNonEmptyString(env.FASED_APNS_PRIVATE_KEY_P8) ?? normalizeNonEmptyString(env.FASED_APNS_PRIVATE_KEY);
3347
- if (inlineKeyRaw) return {
3348
- ok: true,
3349
- value: {
3350
- teamId,
3351
- keyId,
3352
- privateKey: normalizePrivateKey(inlineKeyRaw)
3353
- }
3354
- };
3355
- const keyPath = normalizeNonEmptyString(env.FASED_APNS_PRIVATE_KEY_PATH);
3356
- if (!keyPath) return {
3357
- ok: false,
3358
- error: "APNs private key missing: set FASED_APNS_PRIVATE_KEY_P8 or FASED_APNS_PRIVATE_KEY_PATH"
3359
- };
3360
- try {
3361
- return {
3362
- ok: true,
3363
- value: {
3364
- teamId,
3365
- keyId,
3366
- privateKey: normalizePrivateKey(await fs$1.readFile(keyPath, "utf8"))
3367
- }
3368
- };
3369
- } catch (err) {
3370
- return {
3371
- ok: false,
3372
- error: `failed reading FASED_APNS_PRIVATE_KEY_PATH (${keyPath}): ${err instanceof Error ? err.message : String(err)}`
3373
- };
3374
- }
3375
- }
3376
- async function sendApnsRequest(params) {
3377
- const authority = params.environment === "production" ? "https://api.push.apple.com" : "https://api.sandbox.push.apple.com";
3378
- const body = JSON.stringify(params.payload);
3379
- const requestPath = `/3/device/${params.token}`;
3380
- return await new Promise((resolve, reject) => {
3381
- const client = http2.connect(authority);
3382
- let settled = false;
3383
- const fail = (err) => {
3384
- if (settled) return;
3385
- settled = true;
3386
- client.destroy();
3387
- reject(err);
3388
- };
3389
- const finish = (result) => {
3390
- if (settled) return;
3391
- settled = true;
3392
- client.close();
3393
- resolve(result);
3394
- };
3395
- client.once("error", (err) => fail(err));
3396
- const req = client.request({
3397
- ":method": "POST",
3398
- ":path": requestPath,
3399
- authorization: `bearer ${params.bearerToken}`,
3400
- "apns-topic": params.topic,
3401
- "apns-push-type": params.pushType,
3402
- "apns-priority": params.priority,
3403
- "apns-expiration": "0",
3404
- "content-type": "application/json",
3405
- "content-length": Buffer.byteLength(body).toString()
3406
- });
3407
- let statusCode = 0;
3408
- let apnsId;
3409
- let responseBody = "";
3410
- req.setEncoding("utf8");
3411
- req.setTimeout(params.timeoutMs, () => {
3412
- req.close(http2.constants.NGHTTP2_CANCEL);
3413
- fail(/* @__PURE__ */ new Error(`APNs request timed out after ${params.timeoutMs}ms`));
3414
- });
3415
- req.on("response", (headers) => {
3416
- const statusHeader = headers[":status"];
3417
- statusCode = typeof statusHeader === "number" ? statusHeader : Number(statusHeader ?? 0);
3418
- const idHeader = headers["apns-id"];
3419
- if (typeof idHeader === "string" && idHeader.trim().length > 0) apnsId = idHeader.trim();
3420
- });
3421
- req.on("data", (chunk) => {
3422
- if (typeof chunk === "string") responseBody += chunk;
3423
- });
3424
- req.on("end", () => {
3425
- finish({
3426
- status: statusCode,
3427
- apnsId,
3428
- body: responseBody
3429
- });
3430
- });
3431
- req.on("error", (err) => fail(err));
3432
- req.end(body);
3433
- });
3434
- }
3435
- function resolveApnsTimeoutMs(timeoutMs) {
3436
- return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) ? Math.max(1e3, Math.trunc(timeoutMs)) : DEFAULT_APNS_TIMEOUT_MS;
3437
- }
3438
- function resolveApnsSendContext(params) {
3439
- const token = normalizeApnsToken(params.registration.token);
3440
- if (!isLikelyApnsToken(token)) throw new Error("invalid APNs token");
3441
- const topic = normalizeTopic(params.registration.topic);
3442
- if (!topic) throw new Error("topic required");
3443
- return {
3444
- token,
3445
- topic,
3446
- environment: params.registration.environment,
3447
- bearerToken: getApnsBearerToken(params.auth)
3448
- };
3449
- }
3450
- function toApnsPushResult(params) {
3451
- return {
3452
- ok: params.response.status === 200,
3453
- status: params.response.status,
3454
- apnsId: params.response.apnsId,
3455
- reason: parseReason(params.response.body),
3456
- tokenSuffix: params.token.slice(-8),
3457
- topic: params.topic,
3458
- environment: params.environment
3459
- };
3460
- }
3461
- function createFasedAgentPushMetadata(params) {
3462
- return {
3463
- kind: params.kind,
3464
- nodeId: params.nodeId,
3465
- ts: Date.now(),
3466
- ...params.reason ? { reason: params.reason } : {}
3467
- };
3468
- }
3469
- async function sendApnsPush(params) {
3470
- const { token, topic, environment, bearerToken } = resolveApnsSendContext({
3471
- auth: params.auth,
3472
- registration: params.registration
3473
- });
3474
- return toApnsPushResult({
3475
- response: await (params.requestSender ?? sendApnsRequest)({
3476
- token,
3477
- topic,
3478
- environment,
3479
- bearerToken,
3480
- payload: params.payload,
3481
- timeoutMs: resolveApnsTimeoutMs(params.timeoutMs),
3482
- pushType: params.pushType,
3483
- priority: params.priority
3484
- }),
3485
- token,
3486
- topic,
3487
- environment
3488
- });
3489
- }
3490
- async function sendApnsAlert(params) {
3491
- const payload = {
3492
- aps: {
3493
- alert: {
3494
- title: params.title,
3495
- body: params.body
3496
- },
3497
- sound: "default"
3498
- },
3499
- fased: createFasedAgentPushMetadata({
3500
- kind: "push.test",
3501
- nodeId: params.nodeId
3502
- })
3503
- };
3504
- return await sendApnsPush({
3505
- auth: params.auth,
3506
- registration: params.registration,
3507
- payload,
3508
- timeoutMs: params.timeoutMs,
3509
- requestSender: params.requestSender,
3510
- pushType: "alert",
3511
- priority: "10"
3512
- });
3513
- }
3514
-
3515
- //#endregion
3516
- //#region src/gateway/ws-log.ts
3517
- const LOG_VALUE_LIMIT = 240;
3518
- const WS_LOG_REDACT_OPTIONS = {
3519
- mode: "tools",
3520
- patterns: getDefaultRedactPatterns()
3521
- };
3522
- const wsLog = createSubsystemLogger("gateway/ws");
3523
- function formatForLog(value) {
3524
- try {
3525
- if (value instanceof Error) {
3526
- const parts = [];
3527
- if (value.name) parts.push(value.name);
3528
- if (value.message) parts.push(value.message);
3529
- const code = "code" in value && (typeof value.code === "string" || typeof value.code === "number") ? String(value.code) : "";
3530
- if (code) parts.push(`code=${code}`);
3531
- const combined = parts.filter(Boolean).join(": ").trim();
3532
- if (combined) return combined.length > LOG_VALUE_LIMIT ? `${combined.slice(0, LOG_VALUE_LIMIT)}...` : combined;
3533
- }
3534
- if (value && typeof value === "object") {
3535
- const rec = value;
3536
- if (typeof rec.message === "string" && rec.message.trim()) {
3537
- const name = typeof rec.name === "string" ? rec.name.trim() : "";
3538
- const code = typeof rec.code === "string" || typeof rec.code === "number" ? String(rec.code) : "";
3539
- const parts = [name, rec.message.trim()].filter(Boolean);
3540
- if (code) parts.push(`code=${code}`);
3541
- const combined = parts.join(": ").trim();
3542
- return combined.length > LOG_VALUE_LIMIT ? `${combined.slice(0, LOG_VALUE_LIMIT)}...` : combined;
3543
- }
3544
- }
3545
- const str = typeof value === "string" || typeof value === "number" ? String(value) : JSON.stringify(value);
3546
- if (!str) return "";
3547
- const redacted = redactSensitiveText(str, WS_LOG_REDACT_OPTIONS);
3548
- return redacted.length > LOG_VALUE_LIMIT ? `${redacted.slice(0, LOG_VALUE_LIMIT)}...` : redacted;
3549
- } catch {
3550
- return String(value);
3551
- }
3552
- }
3553
-
3554
- //#endregion
3555
- //#region src/gateway/server-methods/nodes.helpers.ts
3556
- function respondInvalidParams(params) {
3557
- params.respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `invalid ${params.method} params: ${formatValidationErrors(params.validator.errors)}`));
3558
- }
3559
- async function respondUnavailableOnThrow(respond, fn) {
3560
- try {
3561
- await fn();
3562
- } catch (err) {
3563
- respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, formatForLog(err)));
3564
- }
3565
- }
3566
-
3567
- //#endregion
3568
- //#region src/gateway/server-methods/push.ts
3569
- function normalizeOptionalString(value) {
3570
- if (typeof value !== "string") return;
3571
- const trimmed = value.trim();
3572
- return trimmed.length > 0 ? trimmed : void 0;
3573
- }
3574
- const pushHandlers = { "push.test": async ({ params, respond, client, context }) => {
3575
- if (!validatePushTestParams(params)) {
3576
- respondInvalidParams({
3577
- respond,
3578
- method: "push.test",
3579
- validator: validatePushTestParams
3580
- });
3581
- return;
3582
- }
3583
- const nodeId = String(params.nodeId ?? "").trim();
3584
- if (!nodeId) {
3585
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "nodeId required"));
3586
- return;
3587
- }
3588
- const title = normalizeOptionalString(params.title) ?? "FasedAgent";
3589
- const body = normalizeOptionalString(params.body) ?? `Push test for node ${nodeId}`;
3590
- await respondUnavailableOnThrow(respond, async () => {
3591
- const registration = await loadApnsRegistration(nodeId);
3592
- if (!registration) {
3593
- logMutatingAdminRpcAudit({
3594
- context,
3595
- client,
3596
- method: "push.test",
3597
- outcome: "denied",
3598
- details: {
3599
- nodeId,
3600
- reason: "no_apns_registration"
3601
- }
3602
- });
3603
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `node ${nodeId} has no APNs registration (connect iOS node first)`));
3604
- return;
3605
- }
3606
- const auth = await resolveApnsAuthConfigFromEnv(process.env);
3607
- if (!auth.ok) {
3608
- logMutatingAdminRpcAudit({
3609
- context,
3610
- client,
3611
- method: "push.test",
3612
- outcome: "failed",
3613
- details: {
3614
- nodeId,
3615
- reason: "apns_auth_unavailable"
3616
- }
3617
- });
3618
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, auth.error));
3619
- return;
3620
- }
3621
- const overrideEnvironment = normalizeApnsEnvironment(params.environment);
3622
- const result = await sendApnsAlert({
3623
- auth: auth.value,
3624
- registration: {
3625
- ...registration,
3626
- environment: overrideEnvironment ?? registration.environment
3627
- },
3628
- nodeId,
3629
- title,
3630
- body
3631
- });
3632
- logMutatingAdminRpcAudit({
3633
- context,
3634
- client,
3635
- method: "push.test",
3636
- outcome: result.ok ? "succeeded" : "failed",
3637
- details: {
3638
- nodeId,
3639
- environment: overrideEnvironment ?? registration.environment,
3640
- status: result.status
3641
- }
3642
- });
3643
- respond(true, result, void 0);
3644
- });
3645
- } };
3646
-
3647
- //#endregion
3648
- //#region src/channels/plugins/onboarding/imessage.ts
3649
- const channel$1 = "imessage";
3650
- function parseIMessageAllowFromEntries(raw) {
3651
- return parseOnboardingEntriesAllowingWildcard(raw, (entry) => {
3652
- const lower = entry.toLowerCase();
3653
- if (lower.startsWith("chat_id:")) {
3654
- const id = entry.slice(8).trim();
3655
- if (!/^\d+$/.test(id)) return { error: `Invalid chat_id: ${entry}` };
3656
- return { value: entry };
3657
- }
3658
- if (lower.startsWith("chat_guid:")) {
3659
- if (!entry.slice(10).trim()) return { error: "Invalid chat_guid entry" };
3660
- return { value: entry };
3661
- }
3662
- if (lower.startsWith("chat_identifier:")) {
3663
- if (!entry.slice(16).trim()) return { error: "Invalid chat_identifier entry" };
3664
- return { value: entry };
3665
- }
3666
- if (!normalizeIMessageHandle(entry)) return { error: `Invalid handle: ${entry}` };
3667
- return { value: entry };
3668
- });
3669
- }
3670
- async function promptIMessageAllowFrom(params) {
3671
- return promptParsedAllowFromForScopedChannel({
3672
- cfg: params.cfg,
3673
- channel: "imessage",
3674
- accountId: params.accountId,
3675
- defaultAccountId: resolveDefaultIMessageAccountId(params.cfg),
3676
- prompter: params.prompter,
3677
- noteTitle: "iMessage allowlist",
3678
- noteLines: [
3679
- "Allowlist iMessage DMs by handle or chat target.",
3680
- "Examples:",
3681
- "- +15555550123",
3682
- "- user@example.com",
3683
- "- chat_id:123",
3684
- "- chat_guid:... or chat_identifier:...",
3685
- "Multiple entries: comma-separated.",
3686
- `Docs: ${formatDocsLink("/imessage", "imessage")}`
3687
- ],
3688
- message: "iMessage allowFrom (handle or chat_id)",
3689
- placeholder: "+15555550123, user@example.com, chat_id:123",
3690
- parseEntries: parseIMessageAllowFromEntries,
3691
- getExistingAllowFrom: ({ cfg, accountId }) => {
3692
- return resolveIMessageAccount({
3693
- cfg,
3694
- accountId
3695
- }).config.allowFrom ?? [];
3696
- }
3697
- });
3698
- }
3699
- const dmPolicy$1 = {
3700
- label: "iMessage",
3701
- channel: channel$1,
3702
- policyKey: "channels.imessage.dmPolicy",
3703
- allowFromKey: "channels.imessage.allowFrom",
3704
- getCurrent: (cfg) => cfg.channels?.imessage?.dmPolicy ?? "pairing",
3705
- setPolicy: (cfg, policy) => setChannelDmPolicyWithAllowFrom({
3706
- cfg,
3707
- channel: "imessage",
3708
- dmPolicy: policy
3709
- }),
3710
- promptAllowFrom: promptIMessageAllowFrom
3711
- };
3712
- const imessageOnboardingAdapter = {
3713
- channel: channel$1,
3714
- uiSetup: {
3715
- title: "iMessage",
3716
- detail: "macOS imsg bridge.",
3717
- notes: [
3718
- "This is still a work in progress.",
3719
- "Ensure FasedAgent has Full Disk Access to the Messages DB.",
3720
- "Grant Automation permission for Messages when prompted.",
3721
- "List chats with: imsg chats --limit 20"
3722
- ],
3723
- fields: [{
3724
- label: "CLI path",
3725
- path: [
3726
- "channels",
3727
- "imessage",
3728
- "cliPath"
3729
- ],
3730
- placeholder: "imsg"
3731
- }]
3732
- },
3733
- getStatus: async ({ cfg }) => {
3734
- const configured = listIMessageAccountIds(cfg).some((accountId) => resolveIMessageAccount({
3735
- cfg,
3736
- accountId
3737
- }).configured);
3738
- const imessageCliPath = cfg.channels?.imessage?.cliPath ?? "imsg";
3739
- const imessageCliDetected = await detectBinary(imessageCliPath);
3740
- return {
3741
- channel: channel$1,
3742
- configured,
3743
- statusLines: [`iMessage: ${configured ? "configured" : "needs setup"}`, `imsg: ${imessageCliDetected ? "found" : "missing"} (${imessageCliPath})`],
3744
- selectionHint: imessageCliDetected ? "imsg found" : "imsg missing",
3745
- quickstartScore: imessageCliDetected ? 1 : 0
3746
- };
3747
- },
3748
- configure: async ({ cfg, prompter, accountOverrides, shouldPromptAccountIds }) => {
3749
- const defaultIMessageAccountId = resolveDefaultIMessageAccountId(cfg);
3750
- const imessageAccountId = await resolveAccountIdForConfigure({
3751
- cfg,
3752
- prompter,
3753
- label: "iMessage",
3754
- accountOverride: accountOverrides.imessage,
3755
- shouldPromptAccountIds,
3756
- listAccountIds: listIMessageAccountIds,
3757
- defaultAccountId: defaultIMessageAccountId
3758
- });
3759
- let next = cfg;
3760
- let resolvedCliPath = resolveIMessageAccount({
3761
- cfg: next,
3762
- accountId: imessageAccountId
3763
- }).config.cliPath ?? "imsg";
3764
- if (!await detectBinary(resolvedCliPath)) {
3765
- const entered = await prompter.text({
3766
- message: "imsg CLI path",
3767
- initialValue: resolvedCliPath,
3768
- validate: (value) => value?.trim() ? void 0 : "Required"
3769
- });
3770
- resolvedCliPath = String(entered).trim();
3771
- if (!resolvedCliPath) await prompter.note("imsg CLI path required to enable iMessage.", "iMessage");
3772
- }
3773
- if (resolvedCliPath) next = patchChannelConfigForAccount({
3774
- cfg: next,
3775
- channel: "imessage",
3776
- accountId: imessageAccountId,
3777
- patch: { cliPath: resolvedCliPath }
3778
- });
3779
- await prompter.note([
3780
- "This is still a work in progress.",
3781
- "Ensure FasedAgent has Full Disk Access to Messages DB.",
3782
- "Grant Automation permission for Messages when prompted.",
3783
- "List chats with: imsg chats --limit 20",
3784
- `Docs: ${formatDocsLink("/imessage", "imessage")}`
3785
- ].join("\n"), "iMessage next steps");
3786
- return {
3787
- cfg: next,
3788
- accountId: imessageAccountId
3789
- };
3790
- },
3791
- dmPolicy: dmPolicy$1,
3792
- disable: (cfg) => setOnboardingChannelEnabled(cfg, channel$1, false)
3793
- };
3794
-
3795
- //#endregion
3796
- //#region src/channels/plugins/normalize/imessage.ts
3797
- const SERVICE_PREFIXES = [
3798
- "imessage:",
3799
- "sms:",
3800
- "auto:"
3801
- ];
3802
- const CHAT_TARGET_PREFIX_RE = /^(chat_id:|chatid:|chat:|chat_guid:|chatguid:|guid:|chat_identifier:|chatidentifier:|chatident:)/i;
3803
- function normalizeIMessageMessagingTarget(raw) {
3804
- const trimmed = trimMessagingTarget(raw);
3805
- if (!trimmed) return;
3806
- const lower = trimmed.toLowerCase();
3807
- for (const prefix of SERVICE_PREFIXES) if (lower.startsWith(prefix)) {
3808
- const normalizedHandle = normalizeIMessageHandle(trimmed.slice(prefix.length).trim());
3809
- if (!normalizedHandle) return;
3810
- if (CHAT_TARGET_PREFIX_RE.test(normalizedHandle)) return normalizedHandle;
3811
- return `${prefix}${normalizedHandle}`;
3812
- }
3813
- return normalizeIMessageHandle(trimmed) || void 0;
3814
- }
3815
- function looksLikeIMessageTargetId(raw) {
3816
- const trimmed = trimMessagingTarget(raw);
3817
- if (!trimmed) return false;
3818
- if (CHAT_TARGET_PREFIX_RE.test(trimmed)) return true;
3819
- return looksLikeHandleOrPhoneTarget({
3820
- raw: trimmed,
3821
- prefixPattern: /^(imessage:|sms:|auto:)/i
3822
- });
3823
- }
3824
-
3825
- //#endregion
3826
- //#region src/commands/signal-install.ts
3827
- /** @internal Exported for testing. */
3828
- async function extractSignalCliArchive(archivePath, installRoot, timeoutMs) {
3829
- await extractArchive({
3830
- archivePath,
3831
- destDir: installRoot,
3832
- timeoutMs
3833
- });
3834
- }
3835
- /** @internal Exported for testing. */
3836
- function looksLikeArchive(name) {
3837
- return name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".zip");
3838
- }
3839
- /**
3840
- * Pick a native release asset from the official GitHub releases.
3841
- *
3842
- * The official signal-cli releases only publish native (GraalVM) binaries for
3843
- * x86-64 Linux. On architectures where no native asset is available this
3844
- * returns `undefined` so the caller can fall back to a different install
3845
- * strategy (e.g. Homebrew).
3846
- */
3847
- /** @internal Exported for testing. */
3848
- function pickAsset(assets, platform, arch) {
3849
- const archives = assets.filter((asset) => Boolean(asset.name && asset.browser_download_url)).filter((a) => looksLikeArchive(a.name.toLowerCase()));
3850
- const byName = (pattern) => archives.find((asset) => pattern.test(asset.name.toLowerCase()));
3851
- if (platform === "linux") {
3852
- if (arch === "x64") return byName(/linux-native/) || byName(/linux/) || archives[0];
3853
- return;
3854
- }
3855
- if (platform === "darwin") return byName(/macos|osx|darwin/) || archives[0];
3856
- if (platform === "win32") return byName(/windows|win/) || archives[0];
3857
- return archives[0];
3858
- }
3859
- async function downloadToFile(url, dest, maxRedirects = 5) {
3860
- await new Promise((resolve, reject) => {
3861
- const req = request(url, (res) => {
3862
- if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400) {
3863
- const location = res.headers.location;
3864
- if (!location || maxRedirects <= 0) {
3865
- reject(/* @__PURE__ */ new Error("Redirect loop or missing Location header"));
3866
- return;
3867
- }
3868
- const redirectUrl = new URL(location, url).href;
3869
- resolve(downloadToFile(redirectUrl, dest, maxRedirects - 1));
3870
- return;
3871
- }
3872
- if (!res.statusCode || res.statusCode >= 400) {
3873
- reject(/* @__PURE__ */ new Error(`HTTP ${res.statusCode ?? "?"} downloading file`));
3874
- return;
3875
- }
3876
- pipeline(res, createWriteStream(dest)).then(resolve).catch(reject);
3877
- });
3878
- req.on("error", reject);
3879
- req.end();
3880
- });
3881
- }
3882
- async function findSignalCliBinary(root) {
3883
- const candidates = [];
3884
- const enqueue = async (dir, depth) => {
3885
- if (depth > 3) return;
3886
- const entries = await fs$1.readdir(dir, { withFileTypes: true }).catch(() => []);
3887
- for (const entry of entries) {
3888
- const full = path.join(dir, entry.name);
3889
- if (entry.isDirectory()) await enqueue(full, depth + 1);
3890
- else if (entry.isFile() && entry.name === "signal-cli") candidates.push(full);
3891
- }
3892
- };
3893
- await enqueue(root, 0);
3894
- return candidates[0] ?? null;
3895
- }
3896
- async function resolveBrewSignalCliPath(brewExe) {
3897
- try {
3898
- const result = await runCommandWithTimeout([
3899
- brewExe,
3900
- "--prefix",
3901
- "signal-cli"
3902
- ], { timeoutMs: 1e4 });
3903
- if (result.code === 0 && result.stdout.trim()) {
3904
- const prefix = result.stdout.trim();
3905
- const candidate = path.join(prefix, "bin", "signal-cli");
3906
- try {
3907
- await fs$1.access(candidate);
3908
- return candidate;
3909
- } catch {
3910
- return findSignalCliBinary(prefix);
3911
- }
3912
- }
3913
- } catch {}
3914
- return null;
3915
- }
3916
- async function installSignalCliViaBrew(runtime) {
3917
- const brewExe = resolveBrewExecutable();
3918
- if (!brewExe) return {
3919
- ok: false,
3920
- error: `No native signal-cli build is available for ${process.arch}. Install Homebrew (https://brew.sh) and try again, or install signal-cli manually.`
3921
- };
3922
- runtime.log(`Installing signal-cli via Homebrew (${brewExe})…`);
3923
- const result = await runCommandWithTimeout([
3924
- brewExe,
3925
- "install",
3926
- "signal-cli"
3927
- ], { timeoutMs: 15 * 6e4 });
3928
- if (result.code !== 0) return {
3929
- ok: false,
3930
- error: `brew install signal-cli failed (exit ${result.code}): ${result.stderr.trim().slice(0, 200)}`
3931
- };
3932
- const cliPath = await resolveBrewSignalCliPath(brewExe);
3933
- if (!cliPath) return {
3934
- ok: false,
3935
- error: "brew install succeeded but signal-cli binary was not found."
3936
- };
3937
- let version;
3938
- try {
3939
- version = (await runCommandWithTimeout([cliPath, "--version"], { timeoutMs: 1e4 })).stdout.trim().replace(/^signal-cli\s+/, "") || void 0;
3940
- } catch {}
3941
- return {
3942
- ok: true,
3943
- cliPath,
3944
- version
3945
- };
3946
- }
3947
- async function installSignalCliFromRelease(runtime) {
3948
- const response = await fetch("https://api.github.com/repos/AsamK/signal-cli/releases/latest", { headers: {
3949
- "User-Agent": "fased",
3950
- Accept: "application/vnd.github+json"
3951
- } });
3952
- if (!response.ok) return {
3953
- ok: false,
3954
- error: `Failed to fetch release info (${response.status})`
3955
- };
3956
- const payload = await response.json();
3957
- const version = payload.tag_name?.replace(/^v/, "") ?? "unknown";
3958
- const asset = pickAsset(payload.assets ?? [], process.platform, process.arch);
3959
- if (!asset) return {
3960
- ok: false,
3961
- error: "No compatible release asset found for this platform."
3962
- };
3963
- const tmpDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "fased-signal-"));
3964
- const archivePath = path.join(tmpDir, asset.name);
3965
- runtime.log(`Downloading signal-cli ${version} (${asset.name})…`);
3966
- await downloadToFile(asset.browser_download_url, archivePath);
3967
- const installRoot = path.join(CONFIG_DIR, "tools", "signal-cli", version);
3968
- await fs$1.mkdir(installRoot, { recursive: true });
3969
- if (!looksLikeArchive(asset.name.toLowerCase())) return {
3970
- ok: false,
3971
- error: `Unsupported archive type: ${asset.name}`
3972
- };
3973
- try {
3974
- await extractSignalCliArchive(archivePath, installRoot, 6e4);
3975
- } catch (err) {
3976
- const message = err instanceof Error ? err.message : String(err);
3977
- return {
3978
- ok: false,
3979
- error: `Failed to extract ${asset.name}: ${message}`
3980
- };
3981
- }
3982
- const cliPath = await findSignalCliBinary(installRoot);
3983
- if (!cliPath) return {
3984
- ok: false,
3985
- error: `signal-cli binary not found after extracting ${asset.name}`
3986
- };
3987
- await fs$1.chmod(cliPath, 493).catch(() => {});
3988
- return {
3989
- ok: true,
3990
- cliPath,
3991
- version
3992
- };
3993
- }
3994
- async function installSignalCli(runtime) {
3995
- if (process.platform === "win32") return {
3996
- ok: false,
3997
- error: "Signal CLI auto-install is not supported on Windows yet."
3998
- };
3999
- if (process.platform !== "linux" || process.arch === "x64") return installSignalCliFromRelease(runtime);
4000
- return installSignalCliViaBrew(runtime);
4001
- }
4002
-
4003
- //#endregion
4004
- //#region src/channels/plugins/onboarding/signal.ts
4005
- const channel = "signal";
4006
- const MIN_E164_DIGITS = 5;
4007
- const MAX_E164_DIGITS = 15;
4008
- const DIGITS_ONLY = /^\d+$/;
4009
- const INVALID_SIGNAL_ACCOUNT_ERROR = "Invalid E.164 phone number (must start with + and country code, e.g. +15555550123)";
4010
- function normalizeSignalAccountInput(value) {
4011
- const trimmed = value?.trim();
4012
- if (!trimmed) return null;
4013
- const digits = normalizeE164(trimmed).slice(1);
4014
- if (!DIGITS_ONLY.test(digits)) return null;
4015
- if (digits.length < MIN_E164_DIGITS || digits.length > MAX_E164_DIGITS) return null;
4016
- return `+${digits}`;
4017
- }
4018
- function isUuidLike(value) {
4019
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
4020
- }
4021
- function parseSignalAllowFromEntries(raw) {
4022
- return parseOnboardingEntriesAllowingWildcard(raw, (entry) => {
4023
- if (entry.toLowerCase().startsWith("uuid:")) {
4024
- const id = entry.slice(5).trim();
4025
- if (!id) return { error: "Invalid uuid entry" };
4026
- return { value: `uuid:${id}` };
4027
- }
4028
- if (isUuidLike(entry)) return { value: `uuid:${entry}` };
4029
- const normalized = normalizeSignalAccountInput(entry);
4030
- if (!normalized) return { error: `Invalid entry: ${entry}` };
4031
- return { value: normalized };
4032
- });
4033
- }
4034
- async function promptSignalAllowFrom(params) {
4035
- return promptParsedAllowFromForScopedChannel({
4036
- cfg: params.cfg,
4037
- channel: "signal",
4038
- accountId: params.accountId,
4039
- defaultAccountId: resolveDefaultSignalAccountId(params.cfg),
4040
- prompter: params.prompter,
4041
- noteTitle: "Signal allowlist",
4042
- noteLines: [
4043
- "Allowlist Signal DMs by sender id.",
4044
- "Examples:",
4045
- "- +15555550123",
4046
- "- uuid:123e4567-e89b-12d3-a456-426614174000",
4047
- "Multiple entries: comma-separated.",
4048
- `Docs: ${formatDocsLink("/signal", "signal")}`
4049
- ],
4050
- message: "Signal allowFrom (E.164 or uuid)",
4051
- placeholder: "+15555550123, uuid:123e4567-e89b-12d3-a456-426614174000",
4052
- parseEntries: parseSignalAllowFromEntries,
4053
- getExistingAllowFrom: ({ cfg, accountId }) => {
4054
- return resolveSignalAccount({
4055
- cfg,
4056
- accountId
4057
- }).config.allowFrom ?? [];
4058
- }
4059
- });
4060
- }
4061
- const dmPolicy = {
4062
- label: "Signal",
4063
- channel,
4064
- policyKey: "channels.signal.dmPolicy",
4065
- allowFromKey: "channels.signal.allowFrom",
4066
- getCurrent: (cfg) => cfg.channels?.signal?.dmPolicy ?? "pairing",
4067
- setPolicy: (cfg, policy) => setChannelDmPolicyWithAllowFrom({
4068
- cfg,
4069
- channel: "signal",
4070
- dmPolicy: policy
4071
- }),
4072
- promptAllowFrom: promptSignalAllowFrom
4073
- };
4074
- const signalOnboardingAdapter = {
4075
- channel,
4076
- uiSetup: {
4077
- title: "Signal",
4078
- detail: "signal-cli account.",
4079
- notes: [
4080
- "Install signal-cli if it is missing.",
4081
- "Set the Signal bot number in E.164 format.",
4082
- "Link device with: signal-cli link -n \"FasedAgent\"",
4083
- "Scan the QR in Signal -> Linked Devices."
4084
- ],
4085
- fields: [{
4086
- label: "Signal number",
4087
- path: [
4088
- "channels",
4089
- "signal",
4090
- "account"
4091
- ],
4092
- placeholder: "+15551234567"
4093
- }, {
4094
- label: "CLI path",
4095
- path: [
4096
- "channels",
4097
- "signal",
4098
- "cliPath"
4099
- ],
4100
- placeholder: "signal-cli"
4101
- }]
4102
- },
4103
- getStatus: async ({ cfg }) => {
4104
- const configured = listSignalAccountIds(cfg).some((accountId) => resolveSignalAccount({
4105
- cfg,
4106
- accountId
4107
- }).configured);
4108
- const signalCliPath = cfg.channels?.signal?.cliPath ?? "signal-cli";
4109
- const signalCliDetected = await detectBinary(signalCliPath);
4110
- return {
4111
- channel,
4112
- configured,
4113
- statusLines: [`Signal: ${configured ? "configured" : "needs setup"}`, `signal-cli: ${signalCliDetected ? "found" : "missing"} (${signalCliPath})`],
4114
- selectionHint: signalCliDetected ? "signal-cli found" : "signal-cli missing",
4115
- quickstartScore: signalCliDetected ? 1 : 0
4116
- };
4117
- },
4118
- configure: async ({ cfg, runtime, prompter, accountOverrides, shouldPromptAccountIds, options }) => {
4119
- const defaultSignalAccountId = resolveDefaultSignalAccountId(cfg);
4120
- const signalAccountId = await resolveAccountIdForConfigure({
4121
- cfg,
4122
- prompter,
4123
- label: "Signal",
4124
- accountOverride: accountOverrides.signal,
4125
- shouldPromptAccountIds,
4126
- listAccountIds: listSignalAccountIds,
4127
- defaultAccountId: defaultSignalAccountId
4128
- });
4129
- let next = cfg;
4130
- const accountConfig = resolveSignalAccount({
4131
- cfg: next,
4132
- accountId: signalAccountId
4133
- }).config;
4134
- let resolvedCliPath = accountConfig.cliPath ?? "signal-cli";
4135
- let cliDetected = await detectBinary(resolvedCliPath);
4136
- if (options?.allowSignalInstall) {
4137
- if (await prompter.confirm({
4138
- message: cliDetected ? "signal-cli detected. Reinstall/update now?" : "signal-cli not found. Install now?",
4139
- initialValue: !cliDetected
4140
- })) try {
4141
- const result = await installSignalCli(runtime);
4142
- if (result.ok && result.cliPath) {
4143
- cliDetected = true;
4144
- resolvedCliPath = result.cliPath;
4145
- await prompter.note(`Installed signal-cli at ${result.cliPath}`, "Signal");
4146
- } else if (!result.ok) await prompter.note(result.error ?? "signal-cli install failed.", "Signal");
4147
- } catch (err) {
4148
- await prompter.note(`signal-cli install failed: ${String(err)}`, "Signal");
4149
- }
4150
- }
4151
- if (!cliDetected) await prompter.note("signal-cli not found. Install it, then rerun this step or set channels.signal.cliPath.", "Signal");
4152
- let account = accountConfig.account ?? "";
4153
- if (account) {
4154
- const normalizedExisting = normalizeSignalAccountInput(account);
4155
- if (!normalizedExisting) {
4156
- await prompter.note("Existing Signal account isn't a valid E.164 number. Please enter it again.", "Signal");
4157
- account = "";
4158
- } else {
4159
- account = normalizedExisting;
4160
- if (!await prompter.confirm({
4161
- message: `Signal account set (${account}). Keep it?`,
4162
- initialValue: true
4163
- })) account = "";
4164
- }
4165
- }
4166
- if (!account) account = normalizeSignalAccountInput(String(await prompter.text({
4167
- message: "Signal bot number (E.164)",
4168
- validate: (value) => normalizeSignalAccountInput(String(value ?? "")) ? void 0 : INVALID_SIGNAL_ACCOUNT_ERROR
4169
- }))) ?? "";
4170
- if (account) next = patchChannelConfigForAccount({
4171
- cfg: next,
4172
- channel: "signal",
4173
- accountId: signalAccountId,
4174
- patch: {
4175
- account,
4176
- cliPath: resolvedCliPath ?? "signal-cli"
4177
- }
4178
- });
4179
- await prompter.note([
4180
- "Link device with: signal-cli link -n \"FasedAgent\"",
4181
- "Scan QR in Signal → Linked Devices",
4182
- `Then run: ${formatCliCommand("fased gateway call channels.status --params '{\"probe\":true}'")}`,
4183
- `Docs: ${formatDocsLink("/signal", "signal")}`
4184
- ].join("\n"), "Signal next steps");
4185
- return {
4186
- cfg: next,
4187
- accountId: signalAccountId
4188
- };
4189
- },
4190
- dmPolicy,
4191
- disable: (cfg) => setOnboardingChannelEnabled(cfg, channel, false)
4192
- };
4193
-
4194
- //#endregion
4195
- //#region src/channels/plugins/status-issues/bluebubbles.ts
4196
- function readBlueBubblesAccountStatus(value) {
4197
- if (!isRecord(value)) return null;
4198
- return {
4199
- accountId: value.accountId,
4200
- enabled: value.enabled,
4201
- configured: value.configured,
4202
- running: value.running,
4203
- baseUrl: value.baseUrl,
4204
- lastError: value.lastError,
4205
- probe: value.probe
4206
- };
4207
- }
4208
- function readBlueBubblesProbeResult(value) {
4209
- if (!isRecord(value)) return null;
4210
- return {
4211
- ok: typeof value.ok === "boolean" ? value.ok : void 0,
4212
- status: typeof value.status === "number" ? value.status : null,
4213
- error: asString(value.error) ?? null
4214
- };
4215
- }
4216
- function collectBlueBubblesStatusIssues(accounts) {
4217
- return collectIssuesForEnabledAccounts({
4218
- accounts,
4219
- readAccount: readBlueBubblesAccountStatus,
4220
- collectIssues: ({ account, accountId, issues }) => {
4221
- const configured = account.configured === true;
4222
- const running = account.running === true;
4223
- const lastError = asString(account.lastError);
4224
- const probe = readBlueBubblesProbeResult(account.probe);
4225
- if (!configured) {
4226
- issues.push({
4227
- channel: "bluebubbles",
4228
- accountId,
4229
- kind: "config",
4230
- message: "Not configured (missing serverUrl or password).",
4231
- fix: "Run: fased channels add bluebubbles --http-url <server-url> --password <password>"
4232
- });
4233
- return;
4234
- }
4235
- if (probe && probe.ok === false) {
4236
- const errorDetail = probe.error ? `: ${probe.error}` : probe.status ? ` (HTTP ${probe.status})` : "";
4237
- issues.push({
4238
- channel: "bluebubbles",
4239
- accountId,
4240
- kind: "runtime",
4241
- message: `BlueBubbles server unreachable${errorDetail}`,
4242
- fix: "Check that the BlueBubbles server is running and accessible. Verify serverUrl and password in your config."
4243
- });
4244
- }
4245
- if (running && lastError) issues.push({
4246
- channel: "bluebubbles",
4247
- accountId,
4248
- kind: "runtime",
4249
- message: `Channel error: ${lastError}`,
4250
- fix: "Check gateway logs for details. If the webhook is failing, verify the webhook URL is configured in BlueBubbles server settings."
4251
- });
4252
- }
4253
- });
4254
- }
4255
-
4256
- //#endregion
4257
- //#region src/line/config-schema.ts
4258
- const DmPolicySchema$1 = z.enum([
4259
- "open",
4260
- "allowlist",
4261
- "pairing",
4262
- "disabled"
4263
- ]);
4264
- const GroupPolicySchema$1 = z.enum([
4265
- "open",
4266
- "allowlist",
4267
- "disabled"
4268
- ]);
4269
- const LineCommonConfigSchema = z.object({
4270
- enabled: z.boolean().optional(),
4271
- channelAccessToken: z.string().optional(),
4272
- channelSecret: z.string().optional(),
4273
- tokenFile: z.string().optional(),
4274
- secretFile: z.string().optional(),
4275
- name: z.string().optional(),
4276
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
4277
- groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
4278
- dmPolicy: DmPolicySchema$1.optional().default("pairing"),
4279
- groupPolicy: GroupPolicySchema$1.optional().default("allowlist"),
4280
- responsePrefix: z.string().optional(),
4281
- mediaMaxMb: z.number().optional(),
4282
- webhookPath: z.string().optional()
4283
- });
4284
- const LineGroupConfigSchema = z.object({
4285
- enabled: z.boolean().optional(),
4286
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
4287
- requireMention: z.boolean().optional(),
4288
- systemPrompt: z.string().optional(),
4289
- skills: z.array(z.string()).optional()
4290
- }).strict();
4291
- const LineAccountConfigSchema = LineCommonConfigSchema.extend({ groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional() }).strict();
4292
- const LineConfigSchema = LineCommonConfigSchema.extend({
4293
- accounts: z.record(z.string(), LineAccountConfigSchema.optional()).optional(),
4294
- groups: z.record(z.string(), LineGroupConfigSchema.optional()).optional()
4295
- }).strict();
4296
-
4297
- //#endregion
4298
- export { ACPX_PUSH_TEST_METHOD, ACPX_PUSH_TEST_WRAPPER_ID, AcpRuntimeError, BLUEBUBBLES_ACTIONS, BLUEBUBBLES_ACTION_NAMES, BLUEBUBBLES_GROUP_ACTIONS, BlockStreamingCoalesceSchema, CHANNEL_MESSAGE_ACTION_NAMES, DEFAULT_ACCOUNT_ID, DEFAULT_FEDERATION_BASE_URL, DEFAULT_GROUP_HISTORY_LIMIT, DEFAULT_VIDEO_GENERATION_DURATION_SECONDS, DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, DEFAULT_VIDEO_RESOLUTION_TO_SIZE, DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, DEFAULT_WEBHOOK_MAX_BODY_BYTES, DM_GROUP_ACCESS_REASON, DmConfigSchema, DmPolicySchema, GROUP_POLICY_BLOCKED_LABEL, GoogleChatConfigSchema, GroupPolicySchema, IMessageConfigSchema, LineConfigSchema, MSTeamsConfigSchema, MarkdownConfigSchema, MarkdownTableModeSchema, PAIRING_APPROVED_MESSAGE, ReplyRuntimeConfigSchemaShape, RequestBodyLimitError, SILENT_REPLY_TOKEN, SignalConfigSchema, SsrFBlockedError, ToolPolicySchema, TtsAutoSchema, TtsConfigSchema, TtsModeSchema, TtsProviderSchema, acquireFileLock, addWildcardAllowFrom, applyAccountNameToChannelSection, approveDevicePairing, buildAgentMediaPayload, buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, buildChannelConfigSchema, buildChannelKeyCandidates, buildCommandsListResult, buildDashscopeVideoGenerationInput, buildDashscopeVideoGenerationParameters, buildHostnameAllowlistPolicyFromSuffixAllowlist, buildMediaPayload, buildModelCatalogStatus, buildOauthProviderAuthResult, buildPendingHistoryContextFromMap, buildTokenChannelStatusSummary, canonicalizeRealtimeTranscriptionProviderId, canonicalizeRealtimeVoiceProviderId, chunkTextForOutbound, clamp, clearHistoryEntries, clearHistoryEntriesIfEnabled, collectBlueBubblesStatusIssues, collectStatusIssuesFromLastError, createActionCard, createActionGate, createDedupeCache, createDefaultChannelRuntimeState, createImageCard, createInfoCard, createListCard, createLoggerBackedRuntime, createNormalizedOutboundDeliverer, createPersistentDedupe, createReceiptCard, createReplyPrefixContext, createReplyPrefixOptions, createScopedPairingAccess, createTypingCallbacks, deleteAccountFromConfigSection, detectMime, downloadDashscopeGeneratedVideos, emitDiagnosticEvent, emptyPluginConfigSchema, escapeRegExp, evaluateSenderGroupAccess, evictOldHistoryKeys, executeAcpxPushTestRequest, extensionForMime, extractDashscopeVideoUrls, extractOriginalFilename, extractToolSend, fetchWithBearerAuthScopeFallback, fetchWithSsrFGuard, formatAllowFromLowercase, formatAllowlistMatchMeta, formatDocsLink, formatErrorMessage, formatInboundFromLabel, formatLocationText, formatPairingApproveHint, formatTextWithAttachmentLinks, getAcpStatusSnapshot, getChatChannelMeta, getFileExtension, getGatewayUpdateStatus, getPublicGatewayIdentity, getRealtimeTranscriptionProvider, getRealtimeVoiceProvider, getStatusSummary, hasMarkdownToConvert, imessageOnboardingAdapter, installRequestBodyLimitGuard, isAllowedParsedChatSender, isBlockedHostname, isBlockedHostnameOrIp, isDangerousNameMatchingEnabled, isDiagnosticsEnabled, isHttpsUrlAllowedByHostnameSuffixAllowlist, isNormalizedSenderAllowed, isPrivateIpAddress, isRequestBodyLimitError, isSilentReplyText, isTruthyEnvValue, isWSL2Sync, isWSLEnv, isWSLSync, issuePairingChallenge, jsonResult, listAgentIds, listDevicePairing, listIMessageAccountIds, listLineAccountIds, listRealtimeTranscriptionProviders, listRealtimeVoiceProviders, listSignalAccountIds, loadGatewayModelCatalog, loadWebMedia, logAckFailure, logInboundDrop, logTypingFailure, looksLikeIMessageTargetId, looksLikeSignalTargetId, mergeAllowFromEntries, mergeAllowlist, migrateBaseNameToDefaultAccount, missingTargetError, normalizeAccountId, normalizeAllowFrom, normalizeChannelSlug, normalizeE164, normalizeHandle, normalizeHostnameSuffixAllowlist, normalizeIMessageMessagingTarget, normalizeAccountId$1 as normalizeLineAccountId, normalizePluginHttpPath, normalizeRealtimeTranscriptionProviderId, normalizeRealtimeVoiceProviderId, normalizeSignalMessagingTarget, normalizeWebhookPath, onDiagnosticEvent, optionalStringEnum, parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, pollDashscopeVideoTaskUntilComplete, processLineMessage, promptAccountId, promptChannelAccessConfig, pushHandlers, rawDataToString, readJsonBodyWithLimit, readJsonFileWithFallback, readNumberParam, readReactionParams, readRequestBodyWithLimit, readStoreAllowFromForDmPolicy, readStringParam, recordInboundSession, recordPendingHistoryEntry, recordPendingHistoryEntryIfEnabled, redactSensitiveText, registerAcpRuntimeBackend, registerLogTransport, registerPluginHttpRoute, registerWebhookTarget, rejectDevicePairing, rejectNonPostWebhookRequest, removeAckReactionAfterReply, requestBodyErrorToText, requireOpenAllowFrom, resolveAckReaction, resolveAgentPublicOrigin, resolveAllowlistMatchSimple, resolveAllowlistProviderRuntimeGroupPolicy, resolveBlueBubblesGroupRequireMention, resolveBlueBubblesGroupToolPolicy, resolveChannelAccountConfigBasePath, resolveChannelEntryMatch, resolveChannelEntryMatchWithFallback, resolveChannelMediaMaxBytes, resolveControlCommandGate, resolveDefaultAgentId, resolveDefaultGroupPolicy, resolveDefaultIMessageAccountId, resolveDefaultLineAccountId, resolveDefaultSignalAccountId, resolveDmGroupAccessWithCommandGate, resolveDmGroupAccessWithLists, resolveEffectiveAllowFromLists, resolveEffectiveToolInventory, resolveFederationBaseUrl, resolveFederationHandle, resolveGatewayBindUrl, resolveGoogleChatGroupRequireMention, resolveGoogleChatGroupToolPolicy, resolveIMessageAccount, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, resolveLineAccount, resolveMentionGating, resolveMentionGatingWithBypass, resolveNestedAllowlistDecision, resolveOpenProviderRuntimeGroupPolicy, resolveOutboundMediaUrls, resolvePreferredFasedAgentTmpDir, resolveSenderCommandAuthorization, resolveServicePrefixedAllowTarget, resolveServicePrefixedTarget, resolveSignalAccount, resolveSingleWebhookTarget, resolveSingleWebhookTargetAsync, resolveTailnetHostWithRunner, resolveThreadSessionKeys, resolveToolsBySender, resolveVideoGenerationReferenceUrls, resolveWebhookPath, resolveWebhookTargets, runEmbeddedPiAgent, runFederationAutoConnectOnce, runPluginCommandWithTimeout, safeParseJson, sendMediaWithLeadingCaption, setAccountEnabledInConfigSection, shouldAckReaction, shouldAckReactionForWhatsApp, signalOnboardingAdapter, sleep, startFederationAutoConnect, stringEnum, stripAnsi, stripMarkdown, summarizeMapping, toLocationContext, unregisterAcpRuntimeBackend, waitForAbortSignal, warnMissingProviderGroupPolicyFallbackOnce, withFileLock, withTempDownloadPath, writeJsonFileAtomically };
13
+ import "./exec-DQ8j4Fm3.js";
14
+ import "./accounts-DzLdrOVC.js";
15
+ import { C as resolveNestedAllowlistDecision, S as resolveChannelEntryMatchWithFallback, b as normalizeChannelSlug, x as resolveChannelEntryMatch, y as buildChannelKeyCandidates } from "./allow-list-BYeKk0Sy.js";
16
+ import { n as redactSensitiveText } from "./redact-Bm8vu_ju.js";
17
+ import "./github-copilot-token-CUK__1s1.js";
18
+ import "./retry-DstNBhDW.js";
19
+ import "./paths-CTZ2RS_E.js";
20
+ import { a as deleteAccountFromConfigSection, c as formatPairingApproveHint, n as applyAccountNameToChannelSection, o as setAccountEnabledInConfigSection, r as migrateBaseNameToDefaultAccount, s as buildChannelConfigSchema, t as PAIRING_APPROVED_MESSAGE, u as emptyPluginConfigSchema } from "./pairing-message-D01_6FkJ.js";
21
+ import "./ip-C70a-YlD.js";
22
+ import { a as isBlockedHostnameOrIp, i as isBlockedHostname, o as isPrivateIpAddress, t as SsrFBlockedError } from "./ssrf-BZG8Ztod.js";
23
+ import { t as fetchWithSsrFGuard } from "./fetch-guard-BuYrl6q2.js";
24
+ import { n as redactSensitiveUrlLikeString, t as redactSensitiveUrl } from "./redact-sensitive-url-dPvnFFsK.js";
25
+ import { d as parseChatTargetPrefixesOrThrow, f as resolveServicePrefixedAllowTarget, g as isNormalizedSenderAllowed, h as isAllowedParsedChatSender, m as formatAllowFromLowercase, p as resolveServicePrefixedTarget, u as parseChatAllowTargetPrefixes } from "./send-FcEJfLTd.js";
26
+ import { A as resolveDefaultGroupPolicy, C as buildBaseChannelStatusSummary, D as formatDocsLink, E as createDefaultChannelRuntimeState, M as warnMissingProviderGroupPolicyFallbackOnce, O as GROUP_POLICY_BLOCKED_LABEL, S as buildBaseAccountStatusSnapshot, T as collectStatusIssuesFromLastError, j as resolveOpenProviderRuntimeGroupPolicy, k as resolveAllowlistProviderRuntimeGroupPolicy, r as mergeAllowFromEntries, t as addWildcardAllowFrom, u as promptAccountId, w as buildTokenChannelStatusSummary } from "./helpers-0E444CR0.js";
27
+ import { D as formatLocationText, O as toLocationContext, n as isWSLEnv, r as isWSLSync, t as isWSL2Sync } from "./wsl-CXVwPntb.js";
28
+ import { o as readJsonFileWithFallback, s as writeJsonFileAtomically } from "./pairing-store-DADXOv-J.js";
29
+ import "./chunk-CwN3c1Fq.js";
30
+ import { n as resolveGatewayBindUrl, r as runPluginCommandWithTimeout, t as resolveTailnetHostWithRunner } from "./tailscale-status-ClsquRGs.js";
31
+ import { a as resolveAckReaction, n as createReplyPrefixOptions, t as createReplyPrefixContext } from "./reply-prefix-Bqzm6DC1.js";
32
+ import { i as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-BvtlOzVP.js";
33
+ import { i as rejectDevicePairing, r as listDevicePairing, t as approveDevicePairing } from "./device-pairing-D2Yq-_U6.js";
34
+ import "./pairing-token-N_6Jbt1L.js";
35
+ import { h as onDiagnosticEvent, m as isDiagnosticsEnabled, p as emitDiagnosticEvent } from "./diagnostic-Dfn1iERm.js";
36
+ import "./diagnostic-session-state-HO94DMou.js";
37
+ import "./optional-runtime-dependency-BaVO1F3i.js";
38
+ import { c as detectMime, l as extensionForMime, u as getFileExtension } from "./image-ops-BYc-Ol7C.js";
39
+ import { C as resolveFederationHandle, S as resolveFederationBaseUrl, b as normalizeHandle, x as resolveAgentPublicOrigin, y as DEFAULT_FEDERATION_BASE_URL } from "./wallet-status-2yrXvqSS.js";
40
+ import "./pi-model-discovery-D9-CQFS2.js";
41
+ import "./runtime-dependency-D6tYtvtU.js";
42
+ import { t as rawDataToString } from "./ws-CocpWGhl.js";
43
+ import "./path-alias-guards-Dg3gU-MA.js";
44
+ import "./fs-safe-BG-VzVkL.js";
45
+ import "./markdown-tables-CpNefu6e.js";
46
+ import { n as loadWebMedia } from "./media-QBCmvhBQ.js";
47
+ import "./send-CNxLDNQ9.js";
48
+ import { r as extractOriginalFilename } from "./outbound-attachment-Dhi2Q-_f.js";
49
+ import "./fetch-Cu-ahkie.js";
50
+ import "./thread-bindings.state-DRZAbcUu.js";
51
+ import "./memory-search-C3C0bD2H.js";
52
+ import "./manager-VNI6sxbG.js";
53
+ import "./query-expansion-Zr9qQixm.js";
54
+ import { a as jsonResult, c as readReactionParams, d as readStringParam, n as createActionGate, s as readNumberParam } from "./common-BJPuBxmx.js";
55
+ import "./commands-registry-Bea-V_lR.js";
56
+ import "./skill-commands-C2CnUTPX.js";
57
+ import "./directory-live-DatqU-eS.js";
58
+ import "./targets-eG595pY0.js";
59
+ import "./sandbox-paths-lj7_EVuA.js";
60
+ import { n as missingTargetError } from "./target-errors-C_SVKoEv.js";
61
+ import "./resolve-route-BPkfG5Pg.js";
62
+ import "./render-Bwu_WxwA.js";
63
+ import "./tables-L5mXZ5y_.js";
64
+ import { t as promptChannelAccessConfig } from "./channel-access-BEin0yA4.js";
65
+ import "./shared-clhhbWN3.js";
66
+
67
+ export { ACPX_PUSH_TEST_METHOD, ACPX_PUSH_TEST_WRAPPER_ID, AcpRuntimeError, BLUEBUBBLES_ACTIONS, BLUEBUBBLES_ACTION_NAMES, BLUEBUBBLES_GROUP_ACTIONS, BlockStreamingCoalesceSchema, CHANNEL_MESSAGE_ACTION_NAMES, DEFAULT_ACCOUNT_ID, DEFAULT_FEDERATION_BASE_URL, DEFAULT_GROUP_HISTORY_LIMIT, DEFAULT_VIDEO_GENERATION_DURATION_SECONDS, DEFAULT_VIDEO_GENERATION_TIMEOUT_MS, DEFAULT_VIDEO_RESOLUTION_TO_SIZE, DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, DEFAULT_WEBHOOK_MAX_BODY_BYTES, DM_GROUP_ACCESS_REASON, DmConfigSchema, DmPolicySchema, GROUP_POLICY_BLOCKED_LABEL, GoogleChatConfigSchema, GroupPolicySchema, IMessageConfigSchema, LineConfigSchema, MSTeamsConfigSchema, MarkdownConfigSchema, MarkdownTableModeSchema, PAIRING_APPROVED_MESSAGE, ReplyRuntimeConfigSchemaShape, RequestBodyLimitError, SILENT_REPLY_TOKEN, SignalConfigSchema, SsrFBlockedError, ToolPolicySchema, TtsAutoSchema, TtsConfigSchema, TtsModeSchema, TtsProviderSchema, acquireFileLock, addWildcardAllowFrom, applyAccountNameToChannelSection, approveDevicePairing, buildAgentMediaPayload, buildBaseAccountStatusSnapshot, buildBaseChannelStatusSummary, buildChannelConfigSchema, buildChannelKeyCandidates, buildCommandsListResult, buildDashscopeVideoGenerationInput, buildDashscopeVideoGenerationParameters, buildHostnameAllowlistPolicyFromSuffixAllowlist, buildMediaPayload, buildModelCatalogStatus, buildOauthProviderAuthResult, buildPendingHistoryContextFromMap, buildTokenChannelStatusSummary, canonicalizeRealtimeTranscriptionProviderId, canonicalizeRealtimeVoiceProviderId, chunkTextForOutbound, clamp, clearHistoryEntries, clearHistoryEntriesIfEnabled, collectBlueBubblesStatusIssues, collectStatusIssuesFromLastError, createActionCard, createActionGate, createDedupeCache, createDefaultChannelRuntimeState, createImageCard, createInfoCard, createListCard, createLoggerBackedRuntime, createNormalizedOutboundDeliverer, createPersistentDedupe, createReceiptCard, createReplyPrefixContext, createReplyPrefixOptions, createScopedPairingAccess, createTypingCallbacks, deleteAccountFromConfigSection, detectMime, downloadDashscopeGeneratedVideos, emitDiagnosticEvent, emptyPluginConfigSchema, escapeRegExp, evaluateSenderGroupAccess, evictOldHistoryKeys, executeAcpxPushTestRequest, extensionForMime, extractDashscopeVideoUrls, extractOriginalFilename, extractToolSend, fetchWithBearerAuthScopeFallback, fetchWithSsrFGuard, formatAllowFromLowercase, formatAllowlistMatchMeta, formatDocsLink, formatErrorMessage, formatInboundFromLabel, formatLocationText, formatPairingApproveHint, formatTextWithAttachmentLinks, getAcpStatusSnapshot, getChatChannelMeta, getFileExtension, getGatewayUpdateStatus, getPublicGatewayIdentity, getRealtimeTranscriptionProvider, getRealtimeVoiceProvider, getStatusSummary, hasMarkdownToConvert, imessageOnboardingAdapter, installRequestBodyLimitGuard, isAllowedParsedChatSender, isBlockedHostname, isBlockedHostnameOrIp, isDangerousNameMatchingEnabled, isDiagnosticsEnabled, isHttpsUrlAllowedByHostnameSuffixAllowlist, isNormalizedSenderAllowed, isPrivateIpAddress, isRequestBodyLimitError, isSilentReplyText, isTruthyEnvValue, isWSL2Sync, isWSLEnv, isWSLSync, issuePairingChallenge, jsonResult, listAgentIds, listDevicePairing, listIMessageAccountIds, listLineAccountIds, listRealtimeTranscriptionProviders, listRealtimeVoiceProviders, listSignalAccountIds, loadGatewayModelCatalog, loadWebMedia, logAckFailure, logInboundDrop, logTypingFailure, looksLikeIMessageTargetId, looksLikeSignalTargetId, mergeAllowFromEntries, mergeAllowlist, migrateBaseNameToDefaultAccount, missingTargetError, normalizeAccountId, normalizeAllowFrom, normalizeChannelSlug, normalizeE164, normalizeHandle, normalizeHostnameSuffixAllowlist, normalizeIMessageMessagingTarget, normalizeAccountId$1 as normalizeLineAccountId, normalizePluginHttpPath, normalizeRealtimeTranscriptionProviderId, normalizeRealtimeVoiceProviderId, normalizeSignalMessagingTarget, normalizeWebhookPath, onDiagnosticEvent, optionalStringEnum, parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, pollDashscopeVideoTaskUntilComplete, processLineMessage, promptAccountId, promptChannelAccessConfig, pushHandlers, rawDataToString, readJsonBodyWithLimit, readJsonFileWithFallback, readNumberParam, readReactionParams, readRequestBodyWithLimit, readStoreAllowFromForDmPolicy, readStringParam, recordInboundSession, recordPendingHistoryEntry, recordPendingHistoryEntryIfEnabled, redactSensitiveText, redactSensitiveUrl, redactSensitiveUrlLikeString, registerAcpRuntimeBackend, registerLogTransport, registerPluginHttpRoute, registerWebhookTarget, rejectDevicePairing, rejectNonPostWebhookRequest, removeAckReactionAfterReply, requestBodyErrorToText, requireOpenAllowFrom, resolveAckReaction, resolveAgentPublicOrigin, resolveAllowlistMatchSimple, resolveAllowlistProviderRuntimeGroupPolicy, resolveBlueBubblesGroupRequireMention, resolveBlueBubblesGroupToolPolicy, resolveChannelAccountConfigBasePath, resolveChannelEntryMatch, resolveChannelEntryMatchWithFallback, resolveChannelMediaMaxBytes, resolveControlCommandGate, resolveDefaultAgentId, resolveDefaultGroupPolicy, resolveDefaultIMessageAccountId, resolveDefaultLineAccountId, resolveDefaultSignalAccountId, resolveDmGroupAccessWithCommandGate, resolveDmGroupAccessWithLists, resolveEffectiveAllowFromLists, resolveEffectiveToolInventory, resolveFederationBaseUrl, resolveFederationHandle, resolveGatewayBindUrl, resolveGoogleChatGroupRequireMention, resolveGoogleChatGroupToolPolicy, resolveIMessageAccount, resolveIMessageGroupRequireMention, resolveIMessageGroupToolPolicy, resolveLineAccount, resolveMentionGating, resolveMentionGatingWithBypass, resolveNestedAllowlistDecision, resolveOpenProviderRuntimeGroupPolicy, resolveOutboundMediaUrls, resolvePreferredFasedAgentTmpDir, resolveSenderCommandAuthorization, resolveServicePrefixedAllowTarget, resolveServicePrefixedTarget, resolveSignalAccount, resolveSingleWebhookTarget, resolveSingleWebhookTargetAsync, resolveTailnetHostWithRunner, resolveThreadSessionKeys, resolveToolsBySender, resolveVideoGenerationReferenceUrls, resolveWebhookPath, resolveWebhookTargets, runEmbeddedPiAgent, runFederationAutoConnectOnce, runPluginCommandWithTimeout, safeParseJson, sendMediaWithLeadingCaption, setAccountEnabledInConfigSection, shouldAckReaction, shouldAckReactionForWhatsApp, signalOnboardingAdapter, sleep, startFederationAutoConnect, stringEnum, stripAnsi, stripMarkdown, summarizeMapping, toLocationContext, unregisterAcpRuntimeBackend, waitForAbortSignal, warnMissingProviderGroupPolicyFallbackOnce, withFileLock, withTempDownloadPath, writeJsonFileAtomically };