aimeat 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/dist/.env.example +33 -0
  2. package/dist/build-stamp.json +13 -0
  3. package/dist/locales/en.json +186 -20
  4. package/dist/locales/fi.json +186 -20
  5. package/dist/public/components/VoiceRecorder.js +116 -0
  6. package/dist/public/connection-done.html +53 -0
  7. package/dist/public/css/components/voice-recorder.css +66 -0
  8. package/dist/public/css/views/inbox.css +41 -0
  9. package/dist/public/css/views/profile.css +171 -95
  10. package/dist/public/css/views/transparency.css +5 -0
  11. package/dist/public/js/services/audio-recorder.js +171 -0
  12. package/dist/public/js/services/messages.js +21 -2
  13. package/dist/public/spa.html +3 -0
  14. package/dist/public/views/landing.js +4 -0
  15. package/dist/public/views/profile/access-tab/connections.js +264 -0
  16. package/dist/public/views/profile/access-tab.js +2 -0
  17. package/dist/public/views/profile/ai-transparency-card.js +22 -17
  18. package/dist/public/views/profile/inbox-tab/components.js +60 -10
  19. package/dist/public/views/profile/inbox-tab/helpers.js +33 -0
  20. package/dist/public/views/profile/inbox-tab/panels.js +6 -1
  21. package/dist/public/views/profile/inbox-tab/use-voice.js +50 -0
  22. package/dist/public/views/profile/inbox-tab/voice-parts.js +111 -0
  23. package/dist/public/views/profile/inbox-tab.js +18 -24
  24. package/dist/public/views/profile/openrouter/budget-panel.js +224 -0
  25. package/dist/public/views/profile/openrouter/model-picker.js +150 -0
  26. package/dist/public/views/profile/openrouter/pricing.js +139 -0
  27. package/dist/public/views/profile/openrouter-settings.js +425 -488
  28. package/dist/public/views/transparency.js +50 -0
  29. package/dist/scripts/build-sdk-libs.d.ts.map +1 -1
  30. package/dist/scripts/build-sdk-libs.js +1 -0
  31. package/dist/scripts/build-sdk-libs.js.map +1 -1
  32. package/dist/scripts/check-ai-disclosure.d.ts.map +1 -1
  33. package/dist/scripts/check-ai-disclosure.js +182 -0
  34. package/dist/scripts/check-ai-disclosure.js.map +1 -1
  35. package/dist/src/cli/connect/ai-provenance-carry.d.ts +247 -0
  36. package/dist/src/cli/connect/ai-provenance-carry.d.ts.map +1 -0
  37. package/dist/src/cli/connect/ai-provenance-carry.js +334 -0
  38. package/dist/src/cli/connect/ai-provenance-carry.js.map +1 -0
  39. package/dist/src/cli/connect/api-client.d.ts +11 -0
  40. package/dist/src/cli/connect/api-client.d.ts.map +1 -1
  41. package/dist/src/cli/connect/api-client.js +2 -0
  42. package/dist/src/cli/connect/api-client.js.map +1 -1
  43. package/dist/src/cli/connect/mcp/local-server.d.ts.map +1 -1
  44. package/dist/src/cli/connect/mcp/local-server.js +11 -0
  45. package/dist/src/cli/connect/mcp/local-server.js.map +1 -1
  46. package/dist/src/cli/connect/mcp/tools/agent-messages.d.ts +2 -0
  47. package/dist/src/cli/connect/mcp/tools/agent-messages.d.ts.map +1 -1
  48. package/dist/src/cli/connect/mcp/tools/agent-messages.js +5 -2
  49. package/dist/src/cli/connect/mcp/tools/agent-messages.js.map +1 -1
  50. package/dist/src/cli/connect/mcp/tools/agent-tasks.d.ts +2 -0
  51. package/dist/src/cli/connect/mcp/tools/agent-tasks.d.ts.map +1 -1
  52. package/dist/src/cli/connect/mcp/tools/agent-tasks.js +5 -2
  53. package/dist/src/cli/connect/mcp/tools/agent-tasks.js.map +1 -1
  54. package/dist/src/cli/connect/mcp/tools/apps.d.ts +3 -0
  55. package/dist/src/cli/connect/mcp/tools/apps.d.ts.map +1 -1
  56. package/dist/src/cli/connect/mcp/tools/apps.js +13 -5
  57. package/dist/src/cli/connect/mcp/tools/apps.js.map +1 -1
  58. package/dist/src/cli/connect/mcp/tools/boards.d.ts +3 -0
  59. package/dist/src/cli/connect/mcp/tools/boards.d.ts.map +1 -1
  60. package/dist/src/cli/connect/mcp/tools/boards.js +5 -2
  61. package/dist/src/cli/connect/mcp/tools/boards.js.map +1 -1
  62. package/dist/src/cli/connect/mcp/tools/core.d.ts +5 -0
  63. package/dist/src/cli/connect/mcp/tools/core.d.ts.map +1 -1
  64. package/dist/src/cli/connect/mcp/tools/core.js +25 -5
  65. package/dist/src/cli/connect/mcp/tools/core.js.map +1 -1
  66. package/dist/src/cli/connect/mcp/tools/dm-messages.d.ts +2 -0
  67. package/dist/src/cli/connect/mcp/tools/dm-messages.d.ts.map +1 -1
  68. package/dist/src/cli/connect/mcp/tools/dm-messages.js +11 -6
  69. package/dist/src/cli/connect/mcp/tools/dm-messages.js.map +1 -1
  70. package/dist/src/cli/connect/mcp/tools/exchange.d.ts +2 -0
  71. package/dist/src/cli/connect/mcp/tools/exchange.d.ts.map +1 -1
  72. package/dist/src/cli/connect/mcp/tools/exchange.js +8 -2
  73. package/dist/src/cli/connect/mcp/tools/exchange.js.map +1 -1
  74. package/dist/src/cli/connect/mcp/tools/knowledge.d.ts +3 -0
  75. package/dist/src/cli/connect/mcp/tools/knowledge.d.ts.map +1 -1
  76. package/dist/src/cli/connect/mcp/tools/knowledge.js +7 -3
  77. package/dist/src/cli/connect/mcp/tools/knowledge.js.map +1 -1
  78. package/dist/src/cli/connect/mcp/tools/organisms.d.ts +2 -0
  79. package/dist/src/cli/connect/mcp/tools/organisms.d.ts.map +1 -1
  80. package/dist/src/cli/connect/mcp/tools/organisms.js +7 -2
  81. package/dist/src/cli/connect/mcp/tools/organisms.js.map +1 -1
  82. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts +3 -0
  83. package/dist/src/cli/connect/mcp/tools/workspaces.d.ts.map +1 -1
  84. package/dist/src/cli/connect/mcp/tools/workspaces.js +8 -2
  85. package/dist/src/cli/connect/mcp/tools/workspaces.js.map +1 -1
  86. package/dist/src/cli/connect/tool-call-defs-core.d.ts +3 -0
  87. package/dist/src/cli/connect/tool-call-defs-core.d.ts.map +1 -1
  88. package/dist/src/cli/connect/tool-call-defs-core.js +7 -0
  89. package/dist/src/cli/connect/tool-call-defs-core.js.map +1 -1
  90. package/dist/src/cli/connect/tool-call.d.ts +3 -0
  91. package/dist/src/cli/connect/tool-call.d.ts.map +1 -1
  92. package/dist/src/cli/connect/tool-call.js +11 -1
  93. package/dist/src/cli/connect/tool-call.js.map +1 -1
  94. package/dist/src/config-types.d.ts +14 -0
  95. package/dist/src/config-types.d.ts.map +1 -1
  96. package/dist/src/config.d.ts.map +1 -1
  97. package/dist/src/config.js +10 -0
  98. package/dist/src/config.js.map +1 -1
  99. package/dist/src/data/public-pages.d.ts +12 -0
  100. package/dist/src/data/public-pages.d.ts.map +1 -1
  101. package/dist/src/data/public-pages.js +12 -0
  102. package/dist/src/data/public-pages.js.map +1 -1
  103. package/dist/src/generated/api-types.d.ts +969 -85
  104. package/dist/src/generated/api-types.d.ts.map +1 -1
  105. package/dist/src/mcp/ai-provenance-input.d.ts +45 -2
  106. package/dist/src/mcp/ai-provenance-input.d.ts.map +1 -1
  107. package/dist/src/mcp/ai-provenance-input.js +48 -2
  108. package/dist/src/mcp/ai-provenance-input.js.map +1 -1
  109. package/dist/src/mcp/apps.d.ts +7 -0
  110. package/dist/src/mcp/apps.d.ts.map +1 -1
  111. package/dist/src/mcp/apps.js +20 -2
  112. package/dist/src/mcp/apps.js.map +1 -1
  113. package/dist/src/models/ai-provenance-schemas.d.ts +7 -1
  114. package/dist/src/models/ai-provenance-schemas.d.ts.map +1 -1
  115. package/dist/src/models/ai-provenance-schemas.js +11 -1
  116. package/dist/src/models/ai-provenance-schemas.js.map +1 -1
  117. package/dist/src/models/connection-schemas.d.ts +203 -0
  118. package/dist/src/models/connection-schemas.d.ts.map +1 -0
  119. package/dist/src/models/connection-schemas.js +33 -0
  120. package/dist/src/models/connection-schemas.js.map +1 -0
  121. package/dist/src/models/message-schemas.d.ts +40 -0
  122. package/dist/src/models/message-schemas.d.ts.map +1 -1
  123. package/dist/src/models/message-schemas.js +23 -0
  124. package/dist/src/models/message-schemas.js.map +1 -1
  125. package/dist/src/routes/ai-provenance.d.ts +6 -0
  126. package/dist/src/routes/ai-provenance.d.ts.map +1 -1
  127. package/dist/src/routes/ai-provenance.js +34 -1
  128. package/dist/src/routes/ai-provenance.js.map +1 -1
  129. package/dist/src/routes/ai-transparency.d.ts +6 -1
  130. package/dist/src/routes/ai-transparency.d.ts.map +1 -1
  131. package/dist/src/routes/ai-transparency.js +17 -3
  132. package/dist/src/routes/ai-transparency.js.map +1 -1
  133. package/dist/src/routes/ai.d.ts +5 -0
  134. package/dist/src/routes/ai.d.ts.map +1 -1
  135. package/dist/src/routes/ai.js +83 -0
  136. package/dist/src/routes/ai.js.map +1 -1
  137. package/dist/src/routes/app-grants.d.ts.map +1 -1
  138. package/dist/src/routes/app-grants.js +4 -0
  139. package/dist/src/routes/app-grants.js.map +1 -1
  140. package/dist/src/routes/apps/drafts.d.ts +3 -0
  141. package/dist/src/routes/apps/drafts.d.ts.map +1 -1
  142. package/dist/src/routes/apps/drafts.js +13 -0
  143. package/dist/src/routes/apps/drafts.js.map +1 -1
  144. package/dist/src/routes/apps/publish.d.ts +5 -0
  145. package/dist/src/routes/apps/publish.d.ts.map +1 -1
  146. package/dist/src/routes/apps/publish.js +21 -5
  147. package/dist/src/routes/apps/publish.js.map +1 -1
  148. package/dist/src/routes/connections.d.ts +35 -0
  149. package/dist/src/routes/connections.d.ts.map +1 -0
  150. package/dist/src/routes/connections.js +406 -0
  151. package/dist/src/routes/connections.js.map +1 -0
  152. package/dist/src/routes/libs.js +1 -1
  153. package/dist/src/routes/libs.js.map +1 -1
  154. package/dist/src/routes/messages.d.ts +5 -0
  155. package/dist/src/routes/messages.d.ts.map +1 -1
  156. package/dist/src/routes/messages.js +92 -0
  157. package/dist/src/routes/messages.js.map +1 -1
  158. package/dist/src/routes/openrouter.d.ts +6 -1
  159. package/dist/src/routes/openrouter.d.ts.map +1 -1
  160. package/dist/src/routes/openrouter.js +37 -7
  161. package/dist/src/routes/openrouter.js.map +1 -1
  162. package/dist/src/routes/upload.d.ts +5 -0
  163. package/dist/src/routes/upload.d.ts.map +1 -1
  164. package/dist/src/routes/upload.js +32 -0
  165. package/dist/src/routes/upload.js.map +1 -1
  166. package/dist/src/server-bootstrap/routes-loader.d.ts.map +1 -1
  167. package/dist/src/server-bootstrap/routes-loader.js +2 -0
  168. package/dist/src/server-bootstrap/routes-loader.js.map +1 -1
  169. package/dist/src/services/ai-completion.d.ts +48 -0
  170. package/dist/src/services/ai-completion.d.ts.map +1 -1
  171. package/dist/src/services/ai-completion.js +112 -72
  172. package/dist/src/services/ai-completion.js.map +1 -1
  173. package/dist/src/services/ai-disclosure.d.ts +6 -0
  174. package/dist/src/services/ai-disclosure.d.ts.map +1 -1
  175. package/dist/src/services/ai-disclosure.js +20 -2
  176. package/dist/src/services/ai-disclosure.js.map +1 -1
  177. package/dist/src/services/ai-provenance-page.d.ts +59 -0
  178. package/dist/src/services/ai-provenance-page.d.ts.map +1 -0
  179. package/dist/src/services/ai-provenance-page.js +185 -0
  180. package/dist/src/services/ai-provenance-page.js.map +1 -0
  181. package/dist/src/services/ai-provenance.d.ts +6 -0
  182. package/dist/src/services/ai-provenance.d.ts.map +1 -1
  183. package/dist/src/services/ai-provenance.js +5 -0
  184. package/dist/src/services/ai-provenance.js.map +1 -1
  185. package/dist/src/services/ai-transcription.d.ts +66 -0
  186. package/dist/src/services/ai-transcription.d.ts.map +1 -0
  187. package/dist/src/services/ai-transcription.js +90 -0
  188. package/dist/src/services/ai-transcription.js.map +1 -0
  189. package/dist/src/services/app-publish.d.ts.map +1 -1
  190. package/dist/src/services/app-publish.js +16 -1
  191. package/dist/src/services/app-publish.js.map +1 -1
  192. package/dist/src/services/build-app-prompt.d.ts.map +1 -1
  193. package/dist/src/services/build-app-prompt.js +2 -1
  194. package/dist/src/services/build-app-prompt.js.map +1 -1
  195. package/dist/src/services/connections/attach.d.ts +62 -0
  196. package/dist/src/services/connections/attach.d.ts.map +1 -0
  197. package/dist/src/services/connections/attach.js +168 -0
  198. package/dist/src/services/connections/attach.js.map +1 -0
  199. package/dist/src/services/connections/credential.d.ts +39 -0
  200. package/dist/src/services/connections/credential.d.ts.map +1 -0
  201. package/dist/src/services/connections/credential.js +66 -0
  202. package/dist/src/services/connections/credential.js.map +1 -0
  203. package/dist/src/services/connections/instance.d.ts +65 -0
  204. package/dist/src/services/connections/instance.d.ts.map +1 -0
  205. package/dist/src/services/connections/instance.js +144 -0
  206. package/dist/src/services/connections/instance.js.map +1 -0
  207. package/dist/src/services/connections/oauth.d.ts +77 -0
  208. package/dist/src/services/connections/oauth.d.ts.map +1 -0
  209. package/dist/src/services/connections/oauth.js +290 -0
  210. package/dist/src/services/connections/oauth.js.map +1 -0
  211. package/dist/src/services/connections/providers.d.ts +118 -0
  212. package/dist/src/services/connections/providers.d.ts.map +1 -0
  213. package/dist/src/services/connections/providers.js +260 -0
  214. package/dist/src/services/connections/providers.js.map +1 -0
  215. package/dist/src/services/connections/publish-gate.d.ts +103 -0
  216. package/dist/src/services/connections/publish-gate.d.ts.map +1 -0
  217. package/dist/src/services/connections/publish-gate.js +0 -0
  218. package/dist/src/services/connections/publish-gate.js.map +1 -0
  219. package/dist/src/services/connections/publish.d.ts +60 -0
  220. package/dist/src/services/connections/publish.d.ts.map +1 -0
  221. package/dist/src/services/connections/publish.js +340 -0
  222. package/dist/src/services/connections/publish.js.map +1 -0
  223. package/dist/src/services/connections/refresh.d.ts +55 -0
  224. package/dist/src/services/connections/refresh.d.ts.map +1 -0
  225. package/dist/src/services/connections/refresh.js +307 -0
  226. package/dist/src/services/connections/refresh.js.map +1 -0
  227. package/dist/src/services/markdown-negotiation.d.ts +17 -0
  228. package/dist/src/services/markdown-negotiation.d.ts.map +1 -1
  229. package/dist/src/services/markdown-negotiation.js +15 -0
  230. package/dist/src/services/markdown-negotiation.js.map +1 -1
  231. package/dist/src/services/message-send.d.ts.map +1 -1
  232. package/dist/src/services/message-send.js +16 -2
  233. package/dist/src/services/message-send.js.map +1 -1
  234. package/dist/src/services/openrouter.d.ts +67 -1
  235. package/dist/src/services/openrouter.d.ts.map +1 -1
  236. package/dist/src/services/openrouter.js +102 -11
  237. package/dist/src/services/openrouter.js.map +1 -1
  238. package/dist/src/services/upload-token.d.ts +5 -1
  239. package/dist/src/services/upload-token.d.ts.map +1 -1
  240. package/dist/src/services/upload-token.js +13 -1
  241. package/dist/src/services/upload-token.js.map +1 -1
  242. package/dist/src/services/workflow/engine-util.d.ts +18 -0
  243. package/dist/src/services/workflow/engine-util.d.ts.map +1 -1
  244. package/dist/src/services/workflow/engine-util.js +27 -0
  245. package/dist/src/services/workflow/engine-util.js.map +1 -1
  246. package/dist/src/services/workflow/engine.d.ts.map +1 -1
  247. package/dist/src/services/workflow/engine.js +4 -2
  248. package/dist/src/services/workflow/engine.js.map +1 -1
  249. package/dist/src/storage/interface.d.ts +2 -1
  250. package/dist/src/storage/interface.d.ts.map +1 -1
  251. package/dist/src/storage/providers/postgres-kysely/db-types.d.ts +65 -0
  252. package/dist/src/storage/providers/postgres-kysely/db-types.d.ts.map +1 -1
  253. package/dist/src/storage/providers/postgres-kysely/index.d.ts.map +1 -1
  254. package/dist/src/storage/providers/postgres-kysely/index.js +2 -1
  255. package/dist/src/storage/providers/postgres-kysely/index.js.map +1 -1
  256. package/dist/src/storage/providers/postgres-kysely/methods/connections.d.ts +44 -0
  257. package/dist/src/storage/providers/postgres-kysely/methods/connections.d.ts.map +1 -0
  258. package/dist/src/storage/providers/postgres-kysely/methods/connections.js +308 -0
  259. package/dist/src/storage/providers/postgres-kysely/methods/connections.js.map +1 -0
  260. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.d.ts.map +1 -1
  261. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.js +4 -2
  262. package/dist/src/storage/providers/postgres-kysely/methods/node-infra.js.map +1 -1
  263. package/dist/src/storage/providers/postgres-kysely/migrations/0021_connections.sql +116 -0
  264. package/dist/src/storage/providers/postgres-kysely/migrations/0022_provider_clients.sql +36 -0
  265. package/dist/src/storage/providers/postgres-kysely/migrations/0023_nonce_payload.sql +13 -0
  266. package/dist/src/storage/providers/sqlite/index.d.ts.map +1 -1
  267. package/dist/src/storage/providers/sqlite/index.js +2 -1
  268. package/dist/src/storage/providers/sqlite/index.js.map +1 -1
  269. package/dist/src/storage/providers/sqlite/methods/community.d.ts.map +1 -1
  270. package/dist/src/storage/providers/sqlite/methods/community.js +2 -1
  271. package/dist/src/storage/providers/sqlite/methods/community.js.map +1 -1
  272. package/dist/src/storage/providers/sqlite/methods/connections.d.ts +60 -0
  273. package/dist/src/storage/providers/sqlite/methods/connections.d.ts.map +1 -0
  274. package/dist/src/storage/providers/sqlite/methods/connections.js +287 -0
  275. package/dist/src/storage/providers/sqlite/methods/connections.js.map +1 -0
  276. package/dist/src/storage/providers/sqlite/schema-tables-1.d.ts.map +1 -1
  277. package/dist/src/storage/providers/sqlite/schema-tables-1.js +4 -0
  278. package/dist/src/storage/providers/sqlite/schema-tables-1.js.map +1 -1
  279. package/dist/src/storage/providers/sqlite/schema-tables-3.d.ts.map +1 -1
  280. package/dist/src/storage/providers/sqlite/schema-tables-3.js +106 -0
  281. package/dist/src/storage/providers/sqlite/schema-tables-3.js.map +1 -1
  282. package/dist/src/storage/providers/sqlite/schema.d.ts.map +1 -1
  283. package/dist/src/storage/providers/sqlite/schema.js +2 -0
  284. package/dist/src/storage/providers/sqlite/schema.js.map +1 -1
  285. package/dist/src/storage/repositories/connection.repository.d.ts +124 -0
  286. package/dist/src/storage/repositories/connection.repository.d.ts.map +1 -0
  287. package/dist/src/storage/repositories/connection.repository.js +2 -0
  288. package/dist/src/storage/repositories/connection.repository.js.map +1 -0
  289. package/dist/src/storage/types/agents-messaging.d.ts +19 -0
  290. package/dist/src/storage/types/agents-messaging.d.ts.map +1 -1
  291. package/dist/src/storage/types/agents-messaging.js.map +1 -1
  292. package/dist/src/storage/types/auth.d.ts +8 -1
  293. package/dist/src/storage/types/auth.d.ts.map +1 -1
  294. package/dist/src/utils/build-stamp.d.ts +56 -0
  295. package/dist/src/utils/build-stamp.d.ts.map +1 -0
  296. package/dist/src/utils/build-stamp.js +142 -0
  297. package/dist/src/utils/build-stamp.js.map +1 -0
  298. package/dist/src/utils/messaging.d.ts +14 -0
  299. package/dist/src/utils/messaging.d.ts.map +1 -1
  300. package/dist/src/utils/messaging.js +0 -0
  301. package/dist/src/utils/messaging.js.map +1 -1
  302. package/dist/static/sdk-libs/connect/index.js +199 -0
  303. package/dist/static/sdk-libs/connect/notes.js +47 -0
  304. package/dist/static/sdk-libs/connect/panel.js +238 -0
  305. package/dist/static/sdk-libs/data/index.js +63 -11
  306. package/dist/static/sdk-libs/dist/aimeat-connect.js +357 -0
  307. package/dist/static/sdk-libs/dist/aimeat-data.js +40 -9
  308. package/package.json +2 -2
@@ -0,0 +1,307 @@
1
+ /**
2
+ * @file refresh.ts
3
+ * @description Keeping a connection's credential usable, and taking it away (TARGET-057).
4
+ *
5
+ * SINGLE FLIGHT, AND WHY. Several providers invalidate the old refresh token as part of issuing a
6
+ * new one. Two concurrent publishes on one connection therefore refresh twice, and the second
7
+ * exchange presents a token the provider has already retired: one publish works, the other parks
8
+ * the connection in `needs_reauth`, and the owner is told to reconnect an account that was never
9
+ * broken. The claim in the store makes exactly one caller refresh; the others wait and re-read.
10
+ *
11
+ * REFRESH BEFORE EXPIRY, NOT AFTER. A token that expires mid-upload fails a request that has
12
+ * already moved bytes. The skew below is what turns "it expired" into "it was replaced".
13
+ *
14
+ * REVOKING MEANS REVOKING. Deleting our row while the provider still honours the token is not a
15
+ * revocation, it is forgetting. The provider is told first, wherever it offers a way to be told.
16
+ * @structure ensureFreshCredential · revokeConnection
17
+ * @usage import { ensureFreshCredential } from './refresh.js';
18
+ * @version-history
19
+ * v1.0.0 — 2026-08-02 — TARGET-057 Phase 1c.
20
+ */
21
+ import { safeFetch } from '../../utils/url-validator.js';
22
+ import { logger } from '../../utils/logger.js';
23
+ import { sealCredential, openCredential } from './credential.js';
24
+ import { findProvider } from './providers.js';
25
+ import { mintSession } from './attach.js';
26
+ /** Refresh this far ahead of expiry, so a long upload does not start on a token about to die. */
27
+ const REFRESH_SKEW_MS = 5 * 60 * 1000;
28
+ /** A claim older than this is treated as abandoned — a crash mid-refresh must not wedge a connection. */
29
+ const CLAIM_STALE_MS = 60 * 1000;
30
+ /** How long a loser of the claim waits for the winner before giving up. */
31
+ const WAIT_TOTAL_MS = 15 * 1000;
32
+ const WAIT_STEP_MS = 250;
33
+ function needsRefresh(c) {
34
+ // null expiry is a provider that does not expire tokens, not an unknown. Treating it as expired
35
+ // would refresh a Mastodon connection forever, using a refresh token it does not have.
36
+ if (!c.expiresAt)
37
+ return false;
38
+ return new Date(c.expiresAt).getTime() - Date.now() < REFRESH_SKEW_MS;
39
+ }
40
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
41
+ /**
42
+ * A credential that will still be valid when it is used.
43
+ *
44
+ * Returns a failure rather than throwing for every expected outcome — a dead refresh token, a
45
+ * missing key, a provider that is gone — because every caller has to show the owner something, and
46
+ * an exception at this depth surfaces as a 500 in whatever background job touched it first.
47
+ */
48
+ export async function ensureFreshCredential(ctx, connectionId) {
49
+ let conn = await ctx.storage.getConnection(connectionId);
50
+ if (!conn)
51
+ return { ok: false, code: 'NOT_FOUND', reason: 'no such connection' };
52
+ if (conn.status === 'revoked')
53
+ return { ok: false, code: 'REVOKED', reason: 'this connection was revoked' };
54
+ if (!needsRefresh(conn)) {
55
+ const credential = openCredential(conn.credential, ctx.key);
56
+ if (!credential) {
57
+ // Unreadable ciphertext is a rotated key or a restored backup. The honest thing to tell the
58
+ // owner is "reconnect", so the connection is parked rather than the request 500ing.
59
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', 'stored credential cannot be read');
60
+ return { ok: false, code: 'UNREADABLE', reason: 'stored credential cannot be read; reconnect this account' };
61
+ }
62
+ return { ok: true, credential, connection: conn };
63
+ }
64
+ const won = await ctx.storage.claimConnectionRefresh(conn.id, CLAIM_STALE_MS);
65
+ if (!won) {
66
+ // Someone else is refreshing. Wait for their result instead of racing them into the failure
67
+ // this whole mechanism exists to prevent.
68
+ for (let waited = 0; waited < WAIT_TOTAL_MS; waited += WAIT_STEP_MS) {
69
+ await sleep(WAIT_STEP_MS);
70
+ const latest = await ctx.storage.getConnection(conn.id);
71
+ if (!latest)
72
+ return { ok: false, code: 'NOT_FOUND', reason: 'no such connection' };
73
+ if (latest.status === 'needs_reauth') {
74
+ return { ok: false, code: 'NEEDS_REAUTH', reason: latest.lastError ?? 'this account needs to be reconnected' };
75
+ }
76
+ if (!needsRefresh(latest)) {
77
+ const credential = openCredential(latest.credential, ctx.key);
78
+ if (!credential)
79
+ return { ok: false, code: 'UNREADABLE', reason: 'stored credential cannot be read' };
80
+ return { ok: true, credential, connection: latest };
81
+ }
82
+ }
83
+ return { ok: false, code: 'REFRESH_BUSY', reason: 'another refresh is still running; try again' };
84
+ }
85
+ try {
86
+ // Re-read under the claim: the winner may have been queued behind a refresh that already
87
+ // finished, and refreshing again would burn a token that was just issued.
88
+ conn = (await ctx.storage.getConnection(conn.id)) ?? conn;
89
+ if (!needsRefresh(conn)) {
90
+ const credential = openCredential(conn.credential, ctx.key);
91
+ if (!credential)
92
+ return { ok: false, code: 'UNREADABLE', reason: 'stored credential cannot be read' };
93
+ return { ok: true, credential, connection: conn };
94
+ }
95
+ return await performRefresh(ctx, conn);
96
+ }
97
+ finally {
98
+ await ctx.storage.releaseConnectionRefresh(conn.id);
99
+ }
100
+ }
101
+ /** The exchange itself. Only ever runs inside a held claim. */
102
+ async function performRefresh(ctx, conn) {
103
+ const current = openCredential(conn.credential, ctx.key);
104
+ if (!current) {
105
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', 'stored credential cannot be read');
106
+ return { ok: false, code: 'UNREADABLE', reason: 'stored credential cannot be read; reconnect this account' };
107
+ }
108
+ const provider = findProvider(ctx.providers, conn.provider);
109
+ if (!provider) {
110
+ return { ok: false, code: 'PROVIDER_GONE', reason: 'that provider is no longer configured on this node' };
111
+ }
112
+ // BEFORE the refresh-token guard below, and that order is load-bearing: a session-shaped
113
+ // credential whose refresh token is gone can still be re-minted from the stored secret, and
114
+ // checking for a refresh token first would park exactly the connection that has a second chance.
115
+ if (current.shape === 'session')
116
+ return refreshSession(ctx, conn, current);
117
+ if (!current.refreshToken) {
118
+ // An expiring token with no way to renew it. Google does this when access_type=offline was
119
+ // missing, and the connection is genuinely finished — say so instead of retrying forever.
120
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', 'no refresh token; reconnect this account');
121
+ return { ok: false, code: 'NEEDS_REAUTH', reason: 'this account needs to be reconnected' };
122
+ }
123
+ const endpoints = provider.endpoints(conn.instance);
124
+ if (!endpoints) {
125
+ return { ok: false, code: 'PROVIDER_GONE', reason: 'that provider is no longer configured on this node' };
126
+ }
127
+ const client = provider.instanceScoped
128
+ ? await (async () => {
129
+ const pc = conn.instance ? await ctx.storage.getProviderClient(provider.id, conn.instance) : undefined;
130
+ if (!pc)
131
+ return null;
132
+ const secret = openCredential(pc.clientSecret, ctx.key);
133
+ return secret ? { clientId: pc.clientId, clientSecret: secret.accessToken } : null;
134
+ })()
135
+ : provider.client ? { clientId: provider.client.id, clientSecret: provider.client.secret } : null;
136
+ if (!client)
137
+ return { ok: false, code: 'CLIENT_UNAVAILABLE', reason: 'no client credentials for this provider' };
138
+ const body = new URLSearchParams({
139
+ grant_type: 'refresh_token',
140
+ refresh_token: current.refreshToken,
141
+ client_id: client.clientId,
142
+ client_secret: client.clientSecret,
143
+ });
144
+ let res;
145
+ try {
146
+ res = await safeFetch(endpoints.token, {
147
+ method: 'POST',
148
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },
149
+ body: body.toString(),
150
+ signal: AbortSignal.timeout(20_000),
151
+ });
152
+ }
153
+ catch (err) {
154
+ // A network failure is NOT a dead token. Leaving the status alone means the next attempt tries
155
+ // again; parking it here would make an outage at the provider look like a revoked account.
156
+ return { ok: false, code: 'REFRESH_UNREACHABLE', reason: `could not reach the provider: ${err.message}` };
157
+ }
158
+ if (!res.ok) {
159
+ // 4xx from a token endpoint means the grant is gone: revoked at the provider, expired past its
160
+ // limit, or a testing-mode token past its seven days. That IS a reconnect.
161
+ if (res.status >= 400 && res.status < 500) {
162
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', 'the provider no longer accepts this authorization');
163
+ return { ok: false, code: 'NEEDS_REAUTH', reason: 'this account needs to be reconnected' };
164
+ }
165
+ return { ok: false, code: 'REFRESH_FAILED', reason: `the provider failed the refresh (HTTP ${res.status})` };
166
+ }
167
+ const json = await res.json().catch((err) => {
168
+ // A 200 that is not JSON is a different fault from a 200 whose JSON lacks access_token, and both
169
+ // end at the same message below. Logged so the two can be told apart in production.
170
+ logger.warn('connections: refresh response was unparseable', {
171
+ connectionId: conn.id, provider: conn.provider, error: String(err),
172
+ });
173
+ return null;
174
+ });
175
+ const accessToken = typeof json?.access_token === 'string' ? json.access_token : '';
176
+ if (!accessToken)
177
+ return { ok: false, code: 'REFRESH_FAILED', reason: 'the provider returned no access token' };
178
+ const next = {
179
+ shape: current.shape,
180
+ accessToken,
181
+ // A refresh response that omits refresh_token means "keep using the one you have". Dropping it
182
+ // here would leave the connection unable to renew again, one refresh from now.
183
+ ...(typeof json?.refresh_token === 'string' ? { refreshToken: json.refresh_token } : current.refreshToken ? { refreshToken: current.refreshToken } : {}),
184
+ ...(current.extra ? { extra: current.extra } : {}),
185
+ };
186
+ const expiresAt = typeof json?.expires_in === 'number'
187
+ ? new Date(Date.now() + json.expires_in * 1000).toISOString()
188
+ : null;
189
+ await ctx.storage.updateConnectionCredential(conn.id, sealCredential(next, ctx.key), expiresAt);
190
+ const updated = await ctx.storage.getConnection(conn.id);
191
+ return { ok: true, credential: next, connection: updated ?? conn };
192
+ }
193
+ /**
194
+ * Renew a session-shaped credential, with a fallback the OAuth path does not have.
195
+ *
196
+ * AT Proto refreshes by presenting the refresh token as a BEARER, not as a form field, which is why
197
+ * this is a separate function rather than a parameter on the OAuth exchange. And when that is
198
+ * refused — rotated away, expired, revoked — the stored app password can mint a fresh session. A
199
+ * user who supplied a non-expiring secret should not be asked for it twice.
200
+ */
201
+ async function refreshSession(ctx, conn, current) {
202
+ const pds = current.extra?.pds ?? '';
203
+ if (current.refreshToken && pds) {
204
+ try {
205
+ const r = await safeFetch(`${pds}/xrpc/com.atproto.server.refreshSession`, {
206
+ method: 'POST',
207
+ headers: { Authorization: `Bearer ${current.refreshToken}` },
208
+ signal: AbortSignal.timeout(15_000),
209
+ });
210
+ if (r.ok) {
211
+ const j = await r.json().catch((err) => {
212
+ logger.warn('connections: session refresh response was unparseable', {
213
+ connectionId: conn.id, provider: conn.provider, error: String(err),
214
+ });
215
+ return null;
216
+ });
217
+ const accessToken = typeof j?.accessJwt === 'string' ? j.accessJwt : '';
218
+ if (accessToken) {
219
+ const next = {
220
+ shape: 'session',
221
+ accessToken,
222
+ ...(typeof j?.refreshJwt === 'string' ? { refreshToken: j.refreshJwt } : current.refreshToken ? { refreshToken: current.refreshToken } : {}),
223
+ ...(current.extra ? { extra: current.extra } : {}),
224
+ };
225
+ await ctx.storage.updateConnectionCredential(conn.id, sealCredential(next, ctx.key), null);
226
+ const updated = await ctx.storage.getConnection(conn.id);
227
+ return { ok: true, credential: next, connection: updated ?? conn };
228
+ }
229
+ }
230
+ }
231
+ catch (err) {
232
+ // Not fatal and not final: the mint below is the second chance, and reaching it is the point.
233
+ logger.warn('connections: session refresh failed; falling back to re-minting from the stored secret', {
234
+ connectionId: conn.id, provider: conn.provider, error: String(err),
235
+ });
236
+ }
237
+ }
238
+ const secret = current.extra?.appPassword;
239
+ const identifier = current.extra?.identifier;
240
+ if (!secret || !identifier) {
241
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', 'the session expired and no stored secret can renew it');
242
+ return { ok: false, code: 'NEEDS_REAUTH', reason: 'this account needs to be connected again' };
243
+ }
244
+ const minted = await mintSession(conn.provider, { identifier, password: secret }, ctx.config.connectFakeBaseUrl);
245
+ if ('error' in minted) {
246
+ // The secret itself no longer works — revoked at the provider, or the account changed. That IS
247
+ // a reconnect, and the reason is the one the owner can act on.
248
+ await ctx.storage.setConnectionStatus(conn.id, 'needs_reauth', minted.error);
249
+ return { ok: false, code: 'NEEDS_REAUTH', reason: minted.error };
250
+ }
251
+ await ctx.storage.updateConnectionCredential(conn.id, sealCredential(minted.credential, ctx.key), minted.expiresAt);
252
+ const updated = await ctx.storage.getConnection(conn.id);
253
+ return { ok: true, credential: minted.credential, connection: updated ?? conn };
254
+ }
255
+ /**
256
+ * Revoke: tell the provider first where it offers a way to be told, then drop the credential.
257
+ *
258
+ * The provider call is best-effort and its failure does NOT stop the local removal. An owner who
259
+ * asked to disconnect an account must end up disconnected even when the provider is down; the
260
+ * alternative is a button that sometimes silently does nothing.
261
+ */
262
+ export async function revokeConnection(ctx, connectionId) {
263
+ const conn = await ctx.storage.getConnection(connectionId);
264
+ if (!conn)
265
+ return { ok: false, code: 'NOT_FOUND', reason: 'no such connection' };
266
+ let toldProvider = false;
267
+ const provider = findProvider(ctx.providers, conn.provider);
268
+ const revokeUrl = provider?.endpoints(conn.instance)?.revoke ?? null;
269
+ const credential = openCredential(conn.credential, ctx.key);
270
+ if (revokeUrl && credential) {
271
+ try {
272
+ const body = new URLSearchParams({ token: credential.refreshToken ?? credential.accessToken });
273
+ if (provider?.instanceScoped && conn.instance) {
274
+ const pc = await ctx.storage.getProviderClient(provider.id, conn.instance);
275
+ const secret = pc ? openCredential(pc.clientSecret, ctx.key) : null;
276
+ if (pc && secret) {
277
+ body.set('client_id', pc.clientId);
278
+ body.set('client_secret', secret.accessToken);
279
+ }
280
+ }
281
+ else if (provider?.client) {
282
+ body.set('client_id', provider.client.id);
283
+ body.set('client_secret', provider.client.secret);
284
+ }
285
+ const r = await safeFetch(revokeUrl, {
286
+ method: 'POST',
287
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
288
+ body: body.toString(),
289
+ signal: AbortSignal.timeout(10_000),
290
+ });
291
+ toldProvider = r.ok;
292
+ }
293
+ catch (err) {
294
+ // NOT swallowed: the local removal below is what the owner asked for and must happen whether
295
+ // or not the provider is reachable, but a token still live at the provider is exactly the kind
296
+ // of thing an operator needs to be able to find later. `toldProvider` reports it to the caller
297
+ // and this reports it to the log.
298
+ logger.warn('connections: provider revocation failed; the local credential was still removed', {
299
+ connectionId: conn.id, provider: conn.provider, error: String(err),
300
+ });
301
+ toldProvider = false;
302
+ }
303
+ }
304
+ await ctx.storage.deleteConnection(conn.id);
305
+ return { ok: true, toldProvider };
306
+ }
307
+ //# sourceMappingURL=refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../../src/services/connections/refresh.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@
9
9
  * getting HTML; API JSON and authenticated SPA app routes are never negotiated.
10
10
  * @structure
11
11
  * - prefersMarkdown(req) — Accept-header check (q-value aware via req.accepts)
12
+ * - prefersHtmlPage(req) — the browser-vs-machine check, for a JSON route with a human page
12
13
  * - sendMarkdown(res, md, originalHtml?) — headers + body for a negotiated response
13
14
  * - htmlToMarkdown(html) — dependency-free converter for the simple static info pages
14
15
  * - buildLandingMarkdown(config) — the markdown landing page for / and /v1/portal (the SPA
@@ -18,6 +19,9 @@
18
19
  * import { prefersMarkdown, sendMarkdown, htmlToMarkdown } from '../services/markdown-negotiation.js';
19
20
  * if (prefersMarkdown(req)) { sendMarkdown(res, htmlToMarkdown(html), html); return; }
20
21
  * @version-history
22
+ * v1.1.0 — 2026-08-01 — prefersHtmlPage(): the same negotiation question asked the other way,
23
+ * so /v1/ai-transparency can send a person who pasted the machine URL into a browser to the
24
+ * page at /v1/transparency while every machine keeps getting JSON (TARGET-058 Phase 10b).
21
25
  * v1.0.0 — 2026-07-14 — Initial: Markdown for Agents negotiation (agent readiness)
22
26
  */
23
27
  import type { Request, Response } from 'express';
@@ -29,6 +33,19 @@ import type { AimeatConfig } from '../config.js';
29
33
  * (curl default) and application/json callers are unaffected.
30
34
  */
31
35
  export declare function prefersMarkdown(req: Request): boolean;
36
+ /**
37
+ * True when the caller is a browser asking for a page rather than a client asking for data.
38
+ *
39
+ * The mirror image of prefersMarkdown(), and here for the same reason: negotiation predicates
40
+ * belong in one place or a second, subtly different one gets written at the next call site.
41
+ *
42
+ * JSON IS THE DEFAULT, DELIBERATELY. `application/json` is listed FIRST, so a caller sending
43
+ * `Accept: * / *` — curl, fetch(), most agents — gets JSON, and only a client that ranks
44
+ * text/html ABOVE json (which is exactly what a browser's Accept header does) is treated as a
45
+ * reader. A JSON endpoint linked from llms.txt, /.well-known/ and the bootstrap document must
46
+ * never start answering HTML to the machines that follow those links.
47
+ */
48
+ export declare function prefersHtmlPage(req: Request): boolean;
32
49
  /** Cheap token estimate for the x-markdown-tokens / x-original-tokens headers (~4 chars/token). */
33
50
  export declare function estimateTokens(text: string): number;
34
51
  /** Send a negotiated markdown response with the convention's headers. */
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-negotiation.d.ts","sourceRoot":"","sources":["../../../src/services/markdown-negotiation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAOzF;AA2BD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BnD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA0BjE"}
1
+ {"version":3,"file":"markdown-negotiation.d.ts","sourceRoot":"","sources":["../../../src/services/markdown-negotiation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAOzF;AA2BD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BnD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA0BjE"}
@@ -7,6 +7,21 @@
7
7
  export function prefersMarkdown(req) {
8
8
  return req.accepts(['text/html', 'text/markdown']) === 'text/markdown';
9
9
  }
10
+ /**
11
+ * True when the caller is a browser asking for a page rather than a client asking for data.
12
+ *
13
+ * The mirror image of prefersMarkdown(), and here for the same reason: negotiation predicates
14
+ * belong in one place or a second, subtly different one gets written at the next call site.
15
+ *
16
+ * JSON IS THE DEFAULT, DELIBERATELY. `application/json` is listed FIRST, so a caller sending
17
+ * `Accept: * / *` — curl, fetch(), most agents — gets JSON, and only a client that ranks
18
+ * text/html ABOVE json (which is exactly what a browser's Accept header does) is treated as a
19
+ * reader. A JSON endpoint linked from llms.txt, /.well-known/ and the bootstrap document must
20
+ * never start answering HTML to the machines that follow those links.
21
+ */
22
+ export function prefersHtmlPage(req) {
23
+ return req.accepts(['application/json', 'text/html']) === 'text/html';
24
+ }
10
25
  /** Cheap token estimate for the x-markdown-tokens / x-original-tokens headers (~4 chars/token). */
11
26
  export function estimateTokens(text) {
12
27
  return Math.ceil(text.length / 4);
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-negotiation.js","sourceRoot":"","sources":["../../../src/services/markdown-negotiation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown-negotiation.js","sourceRoot":"","sources":["../../../src/services/markdown-negotiation.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"message-send.d.ts","sourceRoot":"","sources":["../../../src/services/message-send.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAK3E,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG5F,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC;mFAC+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,oGAAoG;IACpG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yGAAyG;IACzG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iGAAiG;IACjG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,sBAAsB,EAAE,EAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,uBAAuB,EAAE,CAa3B;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC1C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,CAAA;CAAE,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8I7G"}
1
+ {"version":3,"file":"message-send.d.ts","sourceRoot":"","sources":["../../../src/services/message-send.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAK3E,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG5F,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACxC;mFAC+E;IAC/E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,oGAAoG;IACpG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yGAAyG;IACzG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iGAAiG;IACjG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,sBAAsB,EAAE,EAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,uBAAuB,EAAE,CA2B3B;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC1C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,GAAG,SAAS,CAAA;CAAE,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8I7G"}
@@ -26,7 +26,7 @@
26
26
  */
27
27
  import { randomUUID } from 'node:crypto';
28
28
  import { isSameOwner, parseGaiiLoose } from '../utils/gaii.js';
29
- import { conversationIdFor, messagePreview, deliveryTargetFor } from '../utils/messaging.js';
29
+ import { conversationIdFor, messagePreview, messagePreviewWithAttachments, deliveryTargetFor } from '../utils/messaging.js';
30
30
  import { notify } from './notify.js';
31
31
  import { emitChange, emitDelivery } from './event-bus.js';
32
32
  import { deliverDirectMessage, logDelivery } from './message-delivery.js';
@@ -49,6 +49,20 @@ export function mapMessageAttachments(input, senderGhii, nodeId) {
49
49
  size: a.size,
50
50
  name: a.name,
51
51
  kind: a.kind,
52
+ durationSeconds: a.duration_seconds,
53
+ // A transcript that arrives with a message is the SENDER's, whatever the client claimed: `by` is
54
+ // provenance, and a reader deciding whether to trust the text needs it to mean something. A
55
+ // recipient's own transcript is written to their own copy after delivery, never sent.
56
+ transcript: a.transcript
57
+ ? {
58
+ text: a.transcript.text,
59
+ by: 'sender',
60
+ model: a.transcript.model,
61
+ lang: a.transcript.lang,
62
+ seconds: a.transcript.seconds,
63
+ at: a.transcript.at ?? new Date().toISOString(),
64
+ }
65
+ : undefined,
52
66
  }));
53
67
  }
54
68
  /**
@@ -147,7 +161,7 @@ export async function sendDirectMessage(ctx, input) {
147
161
  await notify(storage, deliveryGhii, {
148
162
  type: isRequest ? 'direct_message_request' : 'direct_message',
149
163
  title: isRequest ? `${senderGhii} wants to message you` : `New message from ${senderGhii}`,
150
- body: messagePreview(body),
164
+ body: messagePreviewWithAttachments(body, attachments),
151
165
  // Request → 'req:<conversationId>': while pending it lands on the inbox requests list, but once
152
166
  // the request is accepted the same notification opens the now-existing thread (see inbox-tab
153
167
  // consumeDeepLink). A delivered DM deep-links straight to its conversation.
@@ -1 +1 @@
1
- {"version":3,"file":"message-send.js","sourceRoot":"","sources":["../../../src/services/message-send.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"message-send.js","sourceRoot":"","sources":["../../../src/services/message-send.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,50 @@ export interface OpenRouterModel {
25
25
  pricing?: {
26
26
  prompt: string;
27
27
  completion: string;
28
+ image?: string;
29
+ audio?: string;
30
+ };
31
+ /**
32
+ * What the model ACCEPTS, straight from `architecture.input_modalities` (`text`, `image`, `audio`,
33
+ * `file`). A picker filters on this instead of guessing from the name: 180 of the 336 catalogue
34
+ * models read images, and no naming convention identifies them.
35
+ */
36
+ input_modalities?: string[];
37
+ /** What the model PRODUCES (`text`, `transcription`, `speech`, `image`). */
38
+ output_modalities?: string[];
39
+ }
40
+ /**
41
+ * Which slice of a provider's catalogue to list.
42
+ *
43
+ * `chat` is the plain `/models` catalogue. `transcription` and `speech` exist only behind
44
+ * OpenRouter's `output_modalities` filter — they are NOT in the default listing, so asking for the
45
+ * default and filtering client-side returns nothing.
46
+ */
47
+ export type ModelModality = 'chat' | 'transcription' | 'speech';
48
+ /** Audio bytes handed to transcribe(). `filename` only decides the multipart part name the provider
49
+ * sees; `mime` is what actually tells it how to decode. */
50
+ export interface TranscriptionAudio {
51
+ data: Buffer;
52
+ mime: string;
53
+ filename: string;
54
+ }
55
+ export interface TranscriptionResult {
56
+ text: string;
57
+ model: string;
58
+ /** Detected (or echoed) language, present with response_format=verbose_json. */
59
+ language?: string;
60
+ /**
61
+ * Provider-reported usage. `seconds` is the measured audio duration and `cost_usd` the actual
62
+ * charge — for STT this is the ONLY trustworthy price signal: the catalogue's `pricing.prompt`
63
+ * for an audio model is per-minute on one provider and per-hour on another (Whisper Large V3:
64
+ * Together 0.0015, Groq 0.111) with nothing in the API saying which.
65
+ */
66
+ usage?: {
67
+ seconds?: number;
68
+ input_tokens?: number;
69
+ output_tokens?: number;
70
+ total_tokens?: number;
71
+ cost_usd?: number;
28
72
  };
29
73
  }
30
74
  /**
@@ -53,8 +97,30 @@ export interface CompletionOptions {
53
97
  presence_penalty?: number;
54
98
  }
55
99
  export declare function complete(apiKey: string | undefined, model: string, prompt: string, systemPrompt?: string, baseUrl?: string, options?: CompletionOptions, images?: string[]): Promise<OpenRouterCompletionResult>;
100
+ /**
101
+ * Transcribe audio with an OpenAI-compatible speech-to-text endpoint.
102
+ *
103
+ * multipart/form-data, not the JSON `input_audio` form OpenRouter also accepts. Two reasons: the
104
+ * bytes are already a Buffer on this side (base64 would inflate them by 4/3 for nothing), and
105
+ * multipart is the shape every OpenAI-compatible STT server understands, so the same call reaches a
106
+ * self-hosted whisper.cpp / faster-whisper endpoint. `FormData` and `Blob` are globals on Node 24, so
107
+ * this adds no dependency.
108
+ *
109
+ * Content-Type is deliberately NOT set: fetch derives it from the FormData together with the
110
+ * multipart boundary, and setting it by hand produces a body the provider cannot parse.
111
+ */
112
+ export declare function transcribe(apiKey: string | undefined, model: string, audio: TranscriptionAudio, baseUrl?: string, opts?: {
113
+ language?: string;
114
+ temperature?: number;
115
+ verbose?: boolean;
116
+ }): Promise<TranscriptionResult>;
56
117
  /**
57
118
  * Fetch available models from an OpenAI-compatible API.
119
+ *
120
+ * `modality` appends OpenRouter's `output_modalities` filter. STT and TTS models are absent from the
121
+ * default catalogue entirely, so `chat` and `transcription` are genuinely different listings, not the
122
+ * same list filtered twice. Other OpenAI-compatible providers ignore the unknown query parameter and
123
+ * return their whole catalogue, which is the sane fallback.
58
124
  */
59
- export declare function listModels(apiKey: string | undefined, baseUrl?: string): Promise<OpenRouterModel[]>;
125
+ export declare function listModels(apiKey: string | undefined, baseUrl?: string, modality?: ModelModality): Promise<OpenRouterModel[]>;
60
126
  //# sourceMappingURL=openrouter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../src/services/openrouter.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE;QACN,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEhE;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAI1D,CAAC;AAKF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAOD,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,GAAE,MAAwB,EACjC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,0BAA0B,CAAC,CAqFrC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,GAAE,MAAwB,GAChC,OAAO,CAAC,eAAe,EAAE,CAAC,CA0B5B"}
1
+ {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../../../src/services/openrouter.ts"],"names":[],"mappings":"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"}