@jini-ai/agent-runtime 0.1.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 (399) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +43 -0
  3. package/dist/acp-model-probe.d.ts +48 -0
  4. package/dist/acp-model-probe.d.ts.map +1 -0
  5. package/dist/acp-model-probe.js +15 -0
  6. package/dist/acp-model-probe.js.map +1 -0
  7. package/dist/agent-protocol/acp/account-failure.d.ts +54 -0
  8. package/dist/agent-protocol/acp/account-failure.d.ts.map +1 -0
  9. package/dist/agent-protocol/acp/account-failure.js +37 -0
  10. package/dist/agent-protocol/acp/account-failure.js.map +1 -0
  11. package/dist/agent-protocol/acp/constants.d.ts +26 -0
  12. package/dist/agent-protocol/acp/constants.d.ts.map +1 -0
  13. package/dist/agent-protocol/acp/constants.js +39 -0
  14. package/dist/agent-protocol/acp/constants.js.map +1 -0
  15. package/dist/agent-protocol/acp/index.d.ts +14 -0
  16. package/dist/agent-protocol/acp/index.d.ts.map +1 -0
  17. package/dist/agent-protocol/acp/index.js +14 -0
  18. package/dist/agent-protocol/acp/index.js.map +1 -0
  19. package/dist/agent-protocol/acp/json.d.ts +82 -0
  20. package/dist/agent-protocol/acp/json.d.ts.map +1 -0
  21. package/dist/agent-protocol/acp/json.js +144 -0
  22. package/dist/agent-protocol/acp/json.js.map +1 -0
  23. package/dist/agent-protocol/acp/models.d.ts +112 -0
  24. package/dist/agent-protocol/acp/models.d.ts.map +1 -0
  25. package/dist/agent-protocol/acp/models.js +293 -0
  26. package/dist/agent-protocol/acp/models.js.map +1 -0
  27. package/dist/agent-protocol/acp/rpc.d.ts +107 -0
  28. package/dist/agent-protocol/acp/rpc.d.ts.map +1 -0
  29. package/dist/agent-protocol/acp/rpc.js +162 -0
  30. package/dist/agent-protocol/acp/rpc.js.map +1 -0
  31. package/dist/agent-protocol/acp/session-params.d.ts +55 -0
  32. package/dist/agent-protocol/acp/session-params.d.ts.map +1 -0
  33. package/dist/agent-protocol/acp/session-params.js +81 -0
  34. package/dist/agent-protocol/acp/session-params.js.map +1 -0
  35. package/dist/agent-protocol/acp/session.d.ts +101 -0
  36. package/dist/agent-protocol/acp/session.d.ts.map +1 -0
  37. package/dist/agent-protocol/acp/session.js +832 -0
  38. package/dist/agent-protocol/acp/session.js.map +1 -0
  39. package/dist/agent-protocol/acp/text-suppression.d.ts +73 -0
  40. package/dist/agent-protocol/acp/text-suppression.d.ts.map +1 -0
  41. package/dist/agent-protocol/acp/text-suppression.js +229 -0
  42. package/dist/agent-protocol/acp/text-suppression.js.map +1 -0
  43. package/dist/agent-protocol/acp/types.d.ts +27 -0
  44. package/dist/agent-protocol/acp/types.d.ts.map +1 -0
  45. package/dist/agent-protocol/acp/types.js +2 -0
  46. package/dist/agent-protocol/acp/types.js.map +1 -0
  47. package/dist/agent-protocol/acp/updates.d.ts +166 -0
  48. package/dist/agent-protocol/acp/updates.d.ts.map +1 -0
  49. package/dist/agent-protocol/acp/updates.js +268 -0
  50. package/dist/agent-protocol/acp/updates.js.map +1 -0
  51. package/dist/agent-protocol/core/index.d.ts +6 -0
  52. package/dist/agent-protocol/core/index.d.ts.map +1 -0
  53. package/dist/agent-protocol/core/index.js +6 -0
  54. package/dist/agent-protocol/core/index.js.map +1 -0
  55. package/dist/agent-protocol/core/json-line-stream.d.ts +42 -0
  56. package/dist/agent-protocol/core/json-line-stream.d.ts.map +1 -0
  57. package/dist/agent-protocol/core/json-line-stream.js +333 -0
  58. package/dist/agent-protocol/core/json-line-stream.js.map +1 -0
  59. package/dist/agent-protocol/index.d.ts +8 -0
  60. package/dist/agent-protocol/index.d.ts.map +1 -0
  61. package/dist/agent-protocol/index.js +8 -0
  62. package/dist/agent-protocol/index.js.map +1 -0
  63. package/dist/agent-protocol/pi-rpc/events.d.ts +26 -0
  64. package/dist/agent-protocol/pi-rpc/events.d.ts.map +1 -0
  65. package/dist/agent-protocol/pi-rpc/events.js +167 -0
  66. package/dist/agent-protocol/pi-rpc/events.js.map +1 -0
  67. package/dist/agent-protocol/pi-rpc/index.d.ts +11 -0
  68. package/dist/agent-protocol/pi-rpc/index.d.ts.map +1 -0
  69. package/dist/agent-protocol/pi-rpc/index.js +11 -0
  70. package/dist/agent-protocol/pi-rpc/index.js.map +1 -0
  71. package/dist/agent-protocol/pi-rpc/internal.d.ts +45 -0
  72. package/dist/agent-protocol/pi-rpc/internal.d.ts.map +1 -0
  73. package/dist/agent-protocol/pi-rpc/internal.js +41 -0
  74. package/dist/agent-protocol/pi-rpc/internal.js.map +1 -0
  75. package/dist/agent-protocol/pi-rpc/models.d.ts +21 -0
  76. package/dist/agent-protocol/pi-rpc/models.d.ts.map +1 -0
  77. package/dist/agent-protocol/pi-rpc/models.js +48 -0
  78. package/dist/agent-protocol/pi-rpc/models.js.map +1 -0
  79. package/dist/agent-protocol/pi-rpc/session.d.ts +106 -0
  80. package/dist/agent-protocol/pi-rpc/session.d.ts.map +1 -0
  81. package/dist/agent-protocol/pi-rpc/session.js +371 -0
  82. package/dist/agent-protocol/pi-rpc/session.js.map +1 -0
  83. package/dist/amr-model-cache.d.ts +40 -0
  84. package/dist/amr-model-cache.d.ts.map +1 -0
  85. package/dist/amr-model-cache.js +79 -0
  86. package/dist/amr-model-cache.js.map +1 -0
  87. package/dist/amr-profile-resolver.d.ts +21 -0
  88. package/dist/amr-profile-resolver.d.ts.map +1 -0
  89. package/dist/amr-profile-resolver.js +4 -0
  90. package/dist/amr-profile-resolver.js.map +1 -0
  91. package/dist/artifact-taxonomy.d.ts +27 -0
  92. package/dist/artifact-taxonomy.d.ts.map +1 -0
  93. package/dist/artifact-taxonomy.js +5 -0
  94. package/dist/artifact-taxonomy.js.map +1 -0
  95. package/dist/auth.d.ts +25 -0
  96. package/dist/auth.d.ts.map +1 -0
  97. package/dist/auth.js +332 -0
  98. package/dist/auth.js.map +1 -0
  99. package/dist/capabilities.d.ts +9 -0
  100. package/dist/capabilities.d.ts.map +1 -0
  101. package/dist/capabilities.js +2 -0
  102. package/dist/capabilities.js.map +1 -0
  103. package/dist/claude-stream.d.ts +37 -0
  104. package/dist/claude-stream.d.ts.map +1 -0
  105. package/dist/claude-stream.js +660 -0
  106. package/dist/claude-stream.js.map +1 -0
  107. package/dist/copilot-stream.d.ts +37 -0
  108. package/dist/copilot-stream.d.ts.map +1 -0
  109. package/dist/copilot-stream.js +136 -0
  110. package/dist/copilot-stream.js.map +1 -0
  111. package/dist/defs/aider.d.ts +13 -0
  112. package/dist/defs/aider.d.ts.map +1 -0
  113. package/dist/defs/aider.js +63 -0
  114. package/dist/defs/aider.js.map +1 -0
  115. package/dist/defs/amp.d.ts +12 -0
  116. package/dist/defs/amp.d.ts.map +1 -0
  117. package/dist/defs/amp.js +56 -0
  118. package/dist/defs/amp.js.map +1 -0
  119. package/dist/defs/amr.d.ts +37 -0
  120. package/dist/defs/amr.d.ts.map +1 -0
  121. package/dist/defs/amr.js +303 -0
  122. package/dist/defs/amr.js.map +1 -0
  123. package/dist/defs/antigravity.d.ts +25 -0
  124. package/dist/defs/antigravity.d.ts.map +1 -0
  125. package/dist/defs/antigravity.js +213 -0
  126. package/dist/defs/antigravity.js.map +1 -0
  127. package/dist/defs/claude.d.ts +30 -0
  128. package/dist/defs/claude.d.ts.map +1 -0
  129. package/dist/defs/claude.js +130 -0
  130. package/dist/defs/claude.js.map +1 -0
  131. package/dist/defs/codebuddy.d.ts +26 -0
  132. package/dist/defs/codebuddy.d.ts.map +1 -0
  133. package/dist/defs/codebuddy.js +124 -0
  134. package/dist/defs/codebuddy.js.map +1 -0
  135. package/dist/defs/codex.d.ts +30 -0
  136. package/dist/defs/codex.d.ts.map +1 -0
  137. package/dist/defs/codex.js +196 -0
  138. package/dist/defs/codex.js.map +1 -0
  139. package/dist/defs/copilot.d.ts +12 -0
  140. package/dist/defs/copilot.d.ts.map +1 -0
  141. package/dist/defs/copilot.js +88 -0
  142. package/dist/defs/copilot.js.map +1 -0
  143. package/dist/defs/cursor-agent.d.ts +27 -0
  144. package/dist/defs/cursor-agent.d.ts.map +1 -0
  145. package/dist/defs/cursor-agent.js +93 -0
  146. package/dist/defs/cursor-agent.js.map +1 -0
  147. package/dist/defs/deepseek.d.ts +12 -0
  148. package/dist/defs/deepseek.d.ts.map +1 -0
  149. package/dist/defs/deepseek.js +53 -0
  150. package/dist/defs/deepseek.js.map +1 -0
  151. package/dist/defs/devin.d.ts +12 -0
  152. package/dist/defs/devin.d.ts.map +1 -0
  153. package/dist/defs/devin.js +45 -0
  154. package/dist/defs/devin.js.map +1 -0
  155. package/dist/defs/grok-build.d.ts +26 -0
  156. package/dist/defs/grok-build.d.ts.map +1 -0
  157. package/dist/defs/grok-build.js +105 -0
  158. package/dist/defs/grok-build.js.map +1 -0
  159. package/dist/defs/hermes.d.ts +13 -0
  160. package/dist/defs/hermes.d.ts.map +1 -0
  161. package/dist/defs/hermes.js +51 -0
  162. package/dist/defs/hermes.js.map +1 -0
  163. package/dist/defs/index.d.ts +33 -0
  164. package/dist/defs/index.d.ts.map +1 -0
  165. package/dist/defs/index.js +33 -0
  166. package/dist/defs/index.js.map +1 -0
  167. package/dist/defs/kilo.d.ts +12 -0
  168. package/dist/defs/kilo.d.ts.map +1 -0
  169. package/dist/defs/kilo.js +20 -0
  170. package/dist/defs/kilo.js.map +1 -0
  171. package/dist/defs/kimi.d.ts +13 -0
  172. package/dist/defs/kimi.d.ts.map +1 -0
  173. package/dist/defs/kimi.js +26 -0
  174. package/dist/defs/kimi.js.map +1 -0
  175. package/dist/defs/kiro.d.ts +12 -0
  176. package/dist/defs/kiro.d.ts.map +1 -0
  177. package/dist/defs/kiro.js +20 -0
  178. package/dist/defs/kiro.js.map +1 -0
  179. package/dist/defs/mimo.d.ts +13 -0
  180. package/dist/defs/mimo.d.ts.map +1 -0
  181. package/dist/defs/mimo.js +26 -0
  182. package/dist/defs/mimo.js.map +1 -0
  183. package/dist/defs/opencode.d.ts +27 -0
  184. package/dist/defs/opencode.d.ts.map +1 -0
  185. package/dist/defs/opencode.js +89 -0
  186. package/dist/defs/opencode.js.map +1 -0
  187. package/dist/defs/pi.d.ts +18 -0
  188. package/dist/defs/pi.d.ts.map +1 -0
  189. package/dist/defs/pi.js +94 -0
  190. package/dist/defs/pi.js.map +1 -0
  191. package/dist/defs/qoder.d.ts +11 -0
  192. package/dist/defs/qoder.d.ts.map +1 -0
  193. package/dist/defs/qoder.js +50 -0
  194. package/dist/defs/qoder.js.map +1 -0
  195. package/dist/defs/qwen.d.ts +11 -0
  196. package/dist/defs/qwen.d.ts.map +1 -0
  197. package/dist/defs/qwen.js +28 -0
  198. package/dist/defs/qwen.js.map +1 -0
  199. package/dist/defs/reasonix.d.ts +20 -0
  200. package/dist/defs/reasonix.d.ts.map +1 -0
  201. package/dist/defs/reasonix.js +60 -0
  202. package/dist/defs/reasonix.js.map +1 -0
  203. package/dist/defs/shared.d.ts +23 -0
  204. package/dist/defs/shared.d.ts.map +1 -0
  205. package/dist/defs/shared.js +58 -0
  206. package/dist/defs/shared.js.map +1 -0
  207. package/dist/defs/trae-cli.d.ts +14 -0
  208. package/dist/defs/trae-cli.d.ts.map +1 -0
  209. package/dist/defs/trae-cli.js +22 -0
  210. package/dist/defs/trae-cli.js.map +1 -0
  211. package/dist/defs/vibe.d.ts +12 -0
  212. package/dist/defs/vibe.d.ts.map +1 -0
  213. package/dist/defs/vibe.js +20 -0
  214. package/dist/defs/vibe.js.map +1 -0
  215. package/dist/detection.d.ts +14 -0
  216. package/dist/detection.d.ts.map +1 -0
  217. package/dist/detection.js +266 -0
  218. package/dist/detection.js.map +1 -0
  219. package/dist/diagnostics.d.ts +8 -0
  220. package/dist/diagnostics.d.ts.map +1 -0
  221. package/dist/diagnostics.js +95 -0
  222. package/dist/diagnostics.js.map +1 -0
  223. package/dist/env.d.ts +19 -0
  224. package/dist/env.d.ts.map +1 -0
  225. package/dist/env.js +95 -0
  226. package/dist/env.js.map +1 -0
  227. package/dist/executables.d.ts +24 -0
  228. package/dist/executables.d.ts.map +1 -0
  229. package/dist/executables.js +349 -0
  230. package/dist/executables.js.map +1 -0
  231. package/dist/index.d.ts +74 -0
  232. package/dist/index.d.ts.map +1 -0
  233. package/dist/index.js +102 -0
  234. package/dist/index.js.map +1 -0
  235. package/dist/invocation.d.ts +6 -0
  236. package/dist/invocation.d.ts.map +1 -0
  237. package/dist/invocation.js +47 -0
  238. package/dist/invocation.js.map +1 -0
  239. package/dist/json-event-stream.d.ts +9 -0
  240. package/dist/json-event-stream.d.ts.map +1 -0
  241. package/dist/json-event-stream.js +856 -0
  242. package/dist/json-event-stream.js.map +1 -0
  243. package/dist/launch.d.ts +12 -0
  244. package/dist/launch.d.ts.map +1 -0
  245. package/dist/launch.js +221 -0
  246. package/dist/launch.js.map +1 -0
  247. package/dist/mcp.d.ts +44 -0
  248. package/dist/mcp.d.ts.map +1 -0
  249. package/dist/mcp.js +12 -0
  250. package/dist/mcp.js.map +1 -0
  251. package/dist/metadata.d.ts +24 -0
  252. package/dist/metadata.d.ts.map +1 -0
  253. package/dist/metadata.js +100 -0
  254. package/dist/metadata.js.map +1 -0
  255. package/dist/mmd-routes.d.ts +12 -0
  256. package/dist/mmd-routes.d.ts.map +1 -0
  257. package/dist/mmd-routes.js +146 -0
  258. package/dist/mmd-routes.js.map +1 -0
  259. package/dist/model-registry.d.ts +120 -0
  260. package/dist/model-registry.d.ts.map +1 -0
  261. package/dist/model-registry.js +77 -0
  262. package/dist/model-registry.js.map +1 -0
  263. package/dist/models.d.ts +16 -0
  264. package/dist/models.d.ts.map +1 -0
  265. package/dist/models.js +93 -0
  266. package/dist/models.js.map +1 -0
  267. package/dist/opencode-log.d.ts +16 -0
  268. package/dist/opencode-log.d.ts.map +1 -0
  269. package/dist/opencode-log.js +163 -0
  270. package/dist/opencode-log.js.map +1 -0
  271. package/dist/paths.d.ts +3 -0
  272. package/dist/paths.d.ts.map +1 -0
  273. package/dist/paths.js +29 -0
  274. package/dist/paths.js.map +1 -0
  275. package/dist/pi-models.d.ts +13 -0
  276. package/dist/pi-models.d.ts.map +1 -0
  277. package/dist/pi-models.js +36 -0
  278. package/dist/pi-models.js.map +1 -0
  279. package/dist/prompt-augmenter.d.ts +60 -0
  280. package/dist/prompt-augmenter.d.ts.map +1 -0
  281. package/dist/prompt-augmenter.js +26 -0
  282. package/dist/prompt-augmenter.js.map +1 -0
  283. package/dist/prompt-budget.d.ts +20 -0
  284. package/dist/prompt-budget.d.ts.map +1 -0
  285. package/dist/prompt-budget.js +226 -0
  286. package/dist/prompt-budget.js.map +1 -0
  287. package/dist/prompt-file.d.ts +7 -0
  288. package/dist/prompt-file.d.ts.map +1 -0
  289. package/dist/prompt-file.js +27 -0
  290. package/dist/prompt-file.js.map +1 -0
  291. package/dist/providers/aihubmix.d.ts +99 -0
  292. package/dist/providers/aihubmix.d.ts.map +1 -0
  293. package/dist/providers/aihubmix.js +239 -0
  294. package/dist/providers/aihubmix.js.map +1 -0
  295. package/dist/providers/anthropic-messages.d.ts +116 -0
  296. package/dist/providers/anthropic-messages.d.ts.map +1 -0
  297. package/dist/providers/anthropic-messages.js +313 -0
  298. package/dist/providers/anthropic-messages.js.map +1 -0
  299. package/dist/providers/azure-chat.d.ts +99 -0
  300. package/dist/providers/azure-chat.d.ts.map +1 -0
  301. package/dist/providers/azure-chat.js +164 -0
  302. package/dist/providers/azure-chat.js.map +1 -0
  303. package/dist/providers/connection-guard.d.ts +67 -0
  304. package/dist/providers/connection-guard.d.ts.map +1 -0
  305. package/dist/providers/connection-guard.js +211 -0
  306. package/dist/providers/connection-guard.js.map +1 -0
  307. package/dist/providers/elevenlabs.d.ts +28 -0
  308. package/dist/providers/elevenlabs.d.ts.map +1 -0
  309. package/dist/providers/elevenlabs.js +138 -0
  310. package/dist/providers/elevenlabs.js.map +1 -0
  311. package/dist/providers/google-messages.d.ts +108 -0
  312. package/dist/providers/google-messages.d.ts.map +1 -0
  313. package/dist/providers/google-messages.js +284 -0
  314. package/dist/providers/google-messages.js.map +1 -0
  315. package/dist/providers/google.d.ts +20 -0
  316. package/dist/providers/google.d.ts.map +1 -0
  317. package/dist/providers/google.js +42 -0
  318. package/dist/providers/google.js.map +1 -0
  319. package/dist/providers/index.d.ts +39 -0
  320. package/dist/providers/index.d.ts.map +1 -0
  321. package/dist/providers/index.js +39 -0
  322. package/dist/providers/index.js.map +1 -0
  323. package/dist/providers/model-catalog.d.ts +32 -0
  324. package/dist/providers/model-catalog.d.ts.map +1 -0
  325. package/dist/providers/model-catalog.js +394 -0
  326. package/dist/providers/model-catalog.js.map +1 -0
  327. package/dist/providers/oauth-callback-server.d.ts +35 -0
  328. package/dist/providers/oauth-callback-server.d.ts.map +1 -0
  329. package/dist/providers/oauth-callback-server.js +217 -0
  330. package/dist/providers/oauth-callback-server.js.map +1 -0
  331. package/dist/providers/oauth-credentials.d.ts +29 -0
  332. package/dist/providers/oauth-credentials.d.ts.map +1 -0
  333. package/dist/providers/oauth-credentials.js +70 -0
  334. package/dist/providers/oauth-credentials.js.map +1 -0
  335. package/dist/providers/oauth-provider.d.ts +95 -0
  336. package/dist/providers/oauth-provider.d.ts.map +1 -0
  337. package/dist/providers/oauth-provider.js +130 -0
  338. package/dist/providers/oauth-provider.js.map +1 -0
  339. package/dist/providers/oauth-tokens.d.ts +35 -0
  340. package/dist/providers/oauth-tokens.d.ts.map +1 -0
  341. package/dist/providers/oauth-tokens.js +136 -0
  342. package/dist/providers/oauth-tokens.js.map +1 -0
  343. package/dist/providers/ollama-chat.d.ts +106 -0
  344. package/dist/providers/ollama-chat.d.ts.map +1 -0
  345. package/dist/providers/ollama-chat.js +292 -0
  346. package/dist/providers/ollama-chat.js.map +1 -0
  347. package/dist/providers/openai-chat.d.ts +147 -0
  348. package/dist/providers/openai-chat.d.ts.map +1 -0
  349. package/dist/providers/openai-chat.js +302 -0
  350. package/dist/providers/openai-chat.js.map +1 -0
  351. package/dist/providers/pkce.d.ts +81 -0
  352. package/dist/providers/pkce.d.ts.map +1 -0
  353. package/dist/providers/pkce.js +176 -0
  354. package/dist/providers/pkce.js.map +1 -0
  355. package/dist/providers/sse-decode.d.ts +47 -0
  356. package/dist/providers/sse-decode.d.ts.map +1 -0
  357. package/dist/providers/sse-decode.js +109 -0
  358. package/dist/providers/sse-decode.js.map +1 -0
  359. package/dist/providers/token-params.d.ts +29 -0
  360. package/dist/providers/token-params.d.ts.map +1 -0
  361. package/dist/providers/token-params.js +41 -0
  362. package/dist/providers/token-params.js.map +1 -0
  363. package/dist/providers/turn-end-guard.d.ts +37 -0
  364. package/dist/providers/turn-end-guard.d.ts.map +1 -0
  365. package/dist/providers/turn-end-guard.js +42 -0
  366. package/dist/providers/turn-end-guard.js.map +1 -0
  367. package/dist/providers/types.d.ts +36 -0
  368. package/dist/providers/types.d.ts.map +1 -0
  369. package/dist/providers/types.js +13 -0
  370. package/dist/providers/types.js.map +1 -0
  371. package/dist/qoder-stream.d.ts +19 -0
  372. package/dist/qoder-stream.d.ts.map +1 -0
  373. package/dist/qoder-stream.js +167 -0
  374. package/dist/qoder-stream.js.map +1 -0
  375. package/dist/registry.d.ts +5 -0
  376. package/dist/registry.d.ts.map +1 -0
  377. package/dist/registry.js +58 -0
  378. package/dist/registry.js.map +1 -0
  379. package/dist/resolution.d.ts +2 -0
  380. package/dist/resolution.d.ts.map +1 -0
  381. package/dist/resolution.js +19 -0
  382. package/dist/resolution.js.map +1 -0
  383. package/dist/role-marker-guard.d.ts +53 -0
  384. package/dist/role-marker-guard.d.ts.map +1 -0
  385. package/dist/role-marker-guard.js +280 -0
  386. package/dist/role-marker-guard.js.map +1 -0
  387. package/dist/telemetry-sink.d.ts +35 -0
  388. package/dist/telemetry-sink.d.ts.map +1 -0
  389. package/dist/telemetry-sink.js +5 -0
  390. package/dist/telemetry-sink.js.map +1 -0
  391. package/dist/terminal-launch.d.ts +11 -0
  392. package/dist/terminal-launch.d.ts.map +1 -0
  393. package/dist/terminal-launch.js +123 -0
  394. package/dist/terminal-launch.js.map +1 -0
  395. package/dist/types.d.ts +185 -0
  396. package/dist/types.d.ts.map +1 -0
  397. package/dist/types.js +2 -0
  398. package/dist/types.js.map +1 -0
  399. package/package.json +47 -0
@@ -0,0 +1,394 @@
1
+ /**
2
+ * @module providers/model-catalog
3
+ *
4
+ * Live model-catalog discovery for BYOK providers (OpenAI-compatible,
5
+ * Anthropic, Google, AIHubMix, SenseAudio, plus static seeds for Bedrock and
6
+ * an explicit "unsupported" response for Azure). Ported from OD's
7
+ * `integrations/provider-models.ts` (`listProviderModels`) with its
8
+ * upstream contracts-package type imports repointed at this package's own
9
+ * vendored `types.ts`, and its `../connectionTest.js` SSRF-guard /
10
+ * secret-redaction imports repointed at this package's own vendored
11
+ * `connection-guard.ts` (see that module's doc comment for what was and
12
+ * wasn't pulled from the 2,600-line origin file). Logic is otherwise
13
+ * unchanged — product-neutral as found (a bare BYOK-protocol model lister,
14
+ * no OD-branded strings).
15
+ */
16
+ import { defaultDnsLookup, redactSecrets, validateBaseUrlResolved } from './connection-guard.js';
17
+ import { aihubmixCatalogUrl, aihubmixHeaders, parseAIHubMixCatalog } from './aihubmix.js';
18
+ import { googleProviderModelsUrl, normalizeGoogleModelId } from './google.js';
19
+ const PROVIDER_MODELS_TIMEOUT_MS = 12_000;
20
+ const BEDROCK_MODEL_OPTIONS = [
21
+ { id: 'anthropic.claude-3-5-sonnet-20241022-v2:0', label: 'Claude 3.5 Sonnet v2' },
22
+ { id: 'anthropic.claude-3-5-haiku-20241022-v1:0', label: 'Claude 3.5 Haiku' },
23
+ { id: 'anthropic.claude-3-haiku-20240307-v1:0', label: 'Claude 3 Haiku' },
24
+ { id: 'amazon.nova-pro-v1:0', label: 'Amazon Nova Pro' },
25
+ { id: 'amazon.nova-lite-v1:0', label: 'Amazon Nova Lite' },
26
+ { id: 'amazon.nova-micro-v1:0', label: 'Amazon Nova Micro' },
27
+ ];
28
+ function appendVersionedApiPath(baseUrl, suffix) {
29
+ const url = new URL(baseUrl);
30
+ const pathname = url.pathname.replace(/\/+$/, '');
31
+ url.pathname = /\/v\d+(\/|$)/.test(pathname)
32
+ ? `${pathname}${suffix}`
33
+ : `${pathname}/v1${suffix}`;
34
+ return url.toString();
35
+ }
36
+ function statusToKind(status) {
37
+ if (status === 401)
38
+ return 'auth_failed';
39
+ if (status === 403)
40
+ return 'forbidden';
41
+ if (status === 404)
42
+ return 'invalid_base_url';
43
+ if (status === 429)
44
+ return 'rate_limited';
45
+ if (status >= 500)
46
+ return 'upstream_unavailable';
47
+ return 'unknown';
48
+ }
49
+ function extractProviderErrorDetail(data, rawText) {
50
+ const obj = data && typeof data === 'object' ? data : null;
51
+ const error = obj ? obj.error : null;
52
+ if (typeof error === 'string')
53
+ return error;
54
+ if (error && typeof error === 'object') {
55
+ const message = error.message;
56
+ if (typeof message === 'string' && message.trim())
57
+ return message;
58
+ }
59
+ const message = obj ? obj.message : null;
60
+ if (typeof message === 'string' && message.trim())
61
+ return message;
62
+ return rawText.trim().slice(0, 240);
63
+ }
64
+ function networkErrorToKind(err) {
65
+ if (err instanceof Error) {
66
+ if (err.name === 'AbortError')
67
+ return 'timeout';
68
+ const cause = err.cause;
69
+ const code = cause?.code;
70
+ if (code === 'ENOTFOUND' ||
71
+ code === 'EAI_AGAIN' ||
72
+ code === 'ECONNREFUSED' ||
73
+ code === 'ECONNRESET' ||
74
+ code === 'ETIMEDOUT' ||
75
+ code === 'EHOSTUNREACH' ||
76
+ code === 'ENETUNREACH' ||
77
+ code === 'CERT_HAS_EXPIRED' ||
78
+ code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {
79
+ return 'invalid_base_url';
80
+ }
81
+ }
82
+ return 'unknown';
83
+ }
84
+ function uniqueModels(models) {
85
+ const seen = new Set();
86
+ const out = [];
87
+ for (const model of models) {
88
+ const id = model.id.trim();
89
+ if (!id || seen.has(id))
90
+ continue;
91
+ seen.add(id);
92
+ out.push({ id, label: model.label.trim() || id });
93
+ }
94
+ return out.sort((a, b) => a.id.localeCompare(b.id));
95
+ }
96
+ function isOpenAiChatModelId(id) {
97
+ const normalized = id.trim().toLowerCase();
98
+ if (!normalized)
99
+ return false;
100
+ if (normalized.includes('embedding') ||
101
+ normalized.includes('moderation') ||
102
+ normalized.includes('rerank') ||
103
+ normalized.includes('whisper') ||
104
+ normalized.includes('tts') ||
105
+ normalized.includes('transcribe') ||
106
+ normalized.includes('speech') ||
107
+ normalized.includes('image') ||
108
+ normalized.includes('video') ||
109
+ normalized.includes('dall-e') ||
110
+ normalized.includes('stable-diffusion') ||
111
+ normalized.includes('flux') ||
112
+ (normalized.includes('wan') &&
113
+ /(?:^|[-_.:])(?:t2v|i2v|v2v)(?:[-_.:]|$)/u.test(normalized))) {
114
+ return false;
115
+ }
116
+ return !/(?:^|[-_.:])(?:t2i|i2i|t2v|i2v|v2v|tts|asr|ocr)(?:[-_.:]|$)/u.test(normalized);
117
+ }
118
+ function extractOpenAiModels(data) {
119
+ const items = data.data;
120
+ if (!Array.isArray(items))
121
+ return [];
122
+ return uniqueModels(items
123
+ .map((item) => item?.id)
124
+ .filter((id) => typeof id === 'string' && id.length > 0)
125
+ .filter(isOpenAiChatModelId)
126
+ .map((id) => ({ id, label: id })));
127
+ }
128
+ function extractAnthropicModels(data) {
129
+ const items = data.data;
130
+ if (!Array.isArray(items))
131
+ return [];
132
+ return uniqueModels(items
133
+ .map((item) => {
134
+ const obj = item && typeof item === 'object'
135
+ ? item
136
+ : null;
137
+ const id = typeof obj?.id === 'string' ? obj.id : '';
138
+ const label = typeof obj?.display_name === 'string'
139
+ ? obj.display_name
140
+ : typeof obj?.displayName === 'string'
141
+ ? obj.displayName
142
+ : id;
143
+ return id ? { id, label } : null;
144
+ })
145
+ .filter((item) => item != null));
146
+ }
147
+ function googleModelId(rawName, rawBaseModelId) {
148
+ if (typeof rawBaseModelId === 'string' && rawBaseModelId.trim()) {
149
+ return normalizeGoogleModelId(rawBaseModelId);
150
+ }
151
+ if (typeof rawName !== 'string')
152
+ return '';
153
+ return normalizeGoogleModelId(rawName);
154
+ }
155
+ function supportsGoogleGenerateContent(item) {
156
+ const methods = item
157
+ ?.supportedGenerationMethods
158
+ ?? item?.supported_actions;
159
+ return Array.isArray(methods) && methods.includes('generateContent');
160
+ }
161
+ function extractGoogleModels(data) {
162
+ const items = data.models;
163
+ if (!Array.isArray(items))
164
+ return [];
165
+ return uniqueModels(items
166
+ // supportsGoogleGenerateContent only returns true for an item whose
167
+ // (optionally-chained) supportedGenerationMethods/supported_actions
168
+ // resolves to an array — a non-object item can never satisfy that, so
169
+ // every item reaching .map() below is already known to be an object.
170
+ // No redundant `typeof item === 'object'` re-check here.
171
+ .filter(supportsGoogleGenerateContent)
172
+ .map((item) => {
173
+ const obj = item;
174
+ const id = googleModelId(obj.name, obj.baseModelId);
175
+ const label = typeof obj.displayName === 'string' && obj.displayName.trim()
176
+ ? obj.displayName
177
+ : id;
178
+ return id ? { id, label } : null;
179
+ })
180
+ .filter((item) => item != null));
181
+ }
182
+ function providerModelsUrl(protocol, baseUrl, apiKey) {
183
+ if (protocol === 'aihubmix') {
184
+ // AIHubMix exposes its chat catalogue on a dedicated endpoint
185
+ // (GET /api/v1/models?type=llm), not the OpenAI /v1/models route.
186
+ return aihubmixCatalogUrl(baseUrl, 'llm');
187
+ }
188
+ if (protocol === 'openai' || protocol === 'senseaudio') {
189
+ return appendVersionedApiPath(baseUrl, '/models');
190
+ }
191
+ if (protocol === 'anthropic') {
192
+ const url = new URL(appendVersionedApiPath(baseUrl, '/models'));
193
+ url.searchParams.set('limit', '1000');
194
+ return url.toString();
195
+ }
196
+ if (protocol === 'google') {
197
+ return googleProviderModelsUrl(baseUrl, apiKey);
198
+ }
199
+ throw new Error(`Unsupported protocol: ${protocol}`);
200
+ }
201
+ function providerModelsHeaders(protocol, apiKey) {
202
+ if (protocol === 'openai' || protocol === 'senseaudio') {
203
+ return { authorization: `Bearer ${apiKey}` };
204
+ }
205
+ if (protocol === 'aihubmix') {
206
+ // The catalogue is public — only attach Bearer auth (+ APP-Code) when the
207
+ // caller actually supplied a key. An empty `Bearer ` would be rejected by
208
+ // some gateways, so send no headers when the key is blank.
209
+ return apiKey.trim() ? aihubmixHeaders(apiKey) : {};
210
+ }
211
+ if (protocol === 'anthropic') {
212
+ return {
213
+ 'x-api-key': apiKey,
214
+ 'anthropic-version': '2023-06-01',
215
+ };
216
+ }
217
+ return {};
218
+ }
219
+ function extractModels(protocol, data) {
220
+ // SenseAudio's /v1/models response follows the OpenAI envelope
221
+ // (`{ data: [{ id, ... }] }`), so the same extractor handles both.
222
+ // Chat picker: drop media-generation rows. AIHubMix's `?type=llm` matches any
223
+ // model whose `types` merely contains `llm`, so dual-tagged image models
224
+ // (e.g. gpt-image-2 -> "image_generation,llm") would otherwise leak in. Those
225
+ // belong to the dedicated image/video/audio pickers.
226
+ if (protocol === 'aihubmix')
227
+ return parseAIHubMixCatalog(data, { chatOnly: true });
228
+ if (protocol === 'openai' || protocol === 'senseaudio')
229
+ return extractOpenAiModels(data);
230
+ if (protocol === 'anthropic')
231
+ return extractAnthropicModels(data);
232
+ return extractGoogleModels(data);
233
+ }
234
+ /**
235
+ * Fetches the live model catalog for a BYOK provider connection. Validates
236
+ * the base URL (sync + DNS-resolved SSRF guard) before issuing any request,
237
+ * dispatches per-protocol (a static seed for Bedrock, an explicit
238
+ * "unsupported" response for Azure), and normalizes every provider's
239
+ * response envelope into a de-duplicated, alphabetized `{ id, label }[]`.
240
+ */
241
+ export async function listProviderModels(input) {
242
+ const start = Date.now();
243
+ if (input.protocol === 'azure') {
244
+ return {
245
+ ok: false,
246
+ kind: 'unsupported_protocol',
247
+ latencyMs: Date.now() - start,
248
+ detail: 'Azure OpenAI deployment discovery is not supported from the inference endpoint.',
249
+ };
250
+ }
251
+ const validated = await validateBaseUrlResolved(input.baseUrl, input.dnsLookup ?? defaultDnsLookup);
252
+ if (validated.error || !validated.parsed) {
253
+ return {
254
+ ok: false,
255
+ kind: validated.forbidden ? 'forbidden' : 'invalid_base_url',
256
+ latencyMs: Date.now() - start,
257
+ // Non-null assertion, not a runtime guard: every BaseUrlValidationResult
258
+ // this branch's guard condition can produce sets `error` alongside a
259
+ // missing `parsed` (connection-guard.ts never returns neither/both) —
260
+ // `?? ''` would satisfy the `detail: string` type too, but per this
261
+ // package's coverage-loop policy an assertion is more honest about
262
+ // "TS requires an `undefined` guard here that can't actually occur".
263
+ detail: validated.error,
264
+ };
265
+ }
266
+ if (input.protocol === 'bedrock') {
267
+ return {
268
+ ok: true,
269
+ kind: 'success',
270
+ latencyMs: Date.now() - start,
271
+ models: BEDROCK_MODEL_OPTIONS,
272
+ detail: 'AWS Bedrock uses a static seed until AWS credential-backed discovery is available.',
273
+ };
274
+ }
275
+ let url;
276
+ try {
277
+ url = providerModelsUrl(input.protocol, input.baseUrl, input.apiKey);
278
+ }
279
+ catch (err) {
280
+ return {
281
+ ok: false,
282
+ kind: 'unsupported_protocol',
283
+ latencyMs: Date.now() - start,
284
+ // `providerModelsUrl`'s only throw site is `throw new Error(...)`; the
285
+ // cast (rather than an `instanceof` guard) documents that the
286
+ // non-Error case can't occur here without adding an untestable branch.
287
+ detail: err.message,
288
+ };
289
+ }
290
+ const controller = new AbortController();
291
+ const abortFromParent = () => controller.abort();
292
+ if (input.signal?.aborted) {
293
+ controller.abort();
294
+ }
295
+ else {
296
+ input.signal?.addEventListener('abort', abortFromParent, { once: true });
297
+ }
298
+ const timer = setTimeout(() => controller.abort(), PROVIDER_MODELS_TIMEOUT_MS);
299
+ // `result` + a trailing `return result;` after the try/catch/finally,
300
+ // rather than returning directly from inside `catch` (every return inside
301
+ // `try` stays a direct early return): a v8/istanbul coverage-instrumentation
302
+ // artifact, re-derived empirically for this exact shape (a minimal
303
+ // `try { return A } catch { return B } finally {}` repro reproduces an
304
+ // uncoverable phantom branch at the `finally` clause's own opening brace,
305
+ // regardless of which/how many try/catch paths a test exercises — verified
306
+ // with `success`, `try-throws-then-caught`, and `throw-from-inside-catch`
307
+ // scenarios, all leaving the same phantom branch at 0). Only `catch`
308
+ // needed to change: with `try`'s own returns direct and only `catch`
309
+ // falling through, the phantom branch doesn't appear (also re-derived).
310
+ // TypeScript accepts `result` as definitely assigned at the trailing
311
+ // `return` because every real path through `try` above already returns or
312
+ // throws — the only way to fall through to it is via `catch`, which
313
+ // assigns unconditionally.
314
+ let result;
315
+ try {
316
+ const response = await fetch(url, {
317
+ method: 'GET',
318
+ headers: providerModelsHeaders(input.protocol, input.apiKey),
319
+ ...input.requestInit,
320
+ signal: controller.signal,
321
+ redirect: 'error',
322
+ });
323
+ const latencyMs = Date.now() - start;
324
+ const rawText = await response.text();
325
+ let data = {};
326
+ let parseError;
327
+ try {
328
+ data = rawText ? JSON.parse(rawText) : {};
329
+ }
330
+ catch (err) {
331
+ // JSON.parse only ever throws a SyntaxError (an Error); the cast
332
+ // documents that rather than adding an untestable non-Error branch.
333
+ parseError = err.message;
334
+ }
335
+ if (!response.ok) {
336
+ const detail = parseError
337
+ ? rawText.trim().slice(0, 240) || parseError
338
+ : extractProviderErrorDetail(data, rawText);
339
+ return {
340
+ ok: false,
341
+ kind: statusToKind(response.status),
342
+ latencyMs,
343
+ status: response.status,
344
+ detail: redactSecrets(detail, [input.apiKey]),
345
+ };
346
+ }
347
+ if (parseError) {
348
+ return {
349
+ ok: false,
350
+ kind: 'unknown',
351
+ latencyMs,
352
+ status: response.status,
353
+ detail: redactSecrets(parseError, [input.apiKey]),
354
+ };
355
+ }
356
+ // Safe: `url` above only resolves for the five protocols
357
+ // `ModelListProtocol` covers (providerModelsUrl throws for every other
358
+ // ConnectionTestProtocol, and azure/bedrock already returned above).
359
+ const models = extractModels(input.protocol, data);
360
+ if (models.length === 0) {
361
+ return {
362
+ ok: false,
363
+ kind: 'no_models',
364
+ latencyMs,
365
+ status: response.status,
366
+ detail: 'Provider returned no usable text-generation models.',
367
+ };
368
+ }
369
+ return {
370
+ ok: true,
371
+ kind: 'success',
372
+ latencyMs,
373
+ status: response.status,
374
+ models,
375
+ };
376
+ }
377
+ catch (err) {
378
+ const latencyMs = Date.now() - start;
379
+ const kind = networkErrorToKind(err);
380
+ const message = err instanceof Error ? err.message : String(err);
381
+ result = {
382
+ ok: false,
383
+ kind,
384
+ latencyMs,
385
+ detail: redactSecrets(message, [input.apiKey]),
386
+ };
387
+ }
388
+ finally {
389
+ clearTimeout(timer);
390
+ input.signal?.removeEventListener('abort', abortFromParent);
391
+ }
392
+ return result;
393
+ }
394
+ //# sourceMappingURL=model-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.js","sourceRoot":"","sources":["../../src/providers/model-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export type OAuthCallbackOutcome = {
2
+ kind: 'ok';
3
+ code: string;
4
+ state: string;
5
+ } | {
6
+ kind: 'error';
7
+ error: string;
8
+ state?: string;
9
+ };
10
+ export interface StartOAuthCallbackListenerInput {
11
+ host: string;
12
+ port: number;
13
+ path: string;
14
+ expectedState: string;
15
+ onCallback: (outcome: OAuthCallbackOutcome) => Promise<void> | void;
16
+ timeoutMs?: number;
17
+ }
18
+ export interface OAuthCallbackListener {
19
+ /** Where the listener is actually bound (informational, esp. for tests). */
20
+ readonly address: {
21
+ host: string;
22
+ port: number;
23
+ };
24
+ /** Stops the listener early (e.g. the user cancelled OAuth in the UI). */
25
+ stop(): Promise<void>;
26
+ }
27
+ /**
28
+ * Opens a one-shot HTTP listener for an OAuth redirect callback.
29
+ *
30
+ * Resolves once the listener is bound; callback handling is asynchronous
31
+ * via `onCallback`. The listener self-closes after the first matching
32
+ * callback OR after `timeoutMs` (default 30 min), whichever comes first.
33
+ */
34
+ export declare function startOAuthCallbackListener(input: StartOAuthCallbackListenerInput): Promise<OAuthCallbackListener>;
35
+ //# sourceMappingURL=oauth-callback-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-callback-server.d.ts","sourceRoot":"","sources":["../../src/providers/oauth-callback-server.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,0EAA0E;IAC1E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,qBAAqB,CAAC,CAyKhC"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * @module providers/oauth-callback-server
3
+ *
4
+ * One-shot HTTP listener for an OAuth PKCE redirect callback — opens a
5
+ * loopback listener, accepts a single `GET <path>?code=...&state=...`,
6
+ * validates `state` against the in-flight dance, invokes `onCallback`, then
7
+ * closes itself (or times out after a configurable window).
8
+ *
9
+ * Ported from OD's `integrations/xai-oauth-server.ts`, de-branded: the
10
+ * origin hardcoded xAI's fixed callback port/host/path as module constants
11
+ * and had the origin product's own name baked into the result-page HTML
12
+ * (see `source-map.md` for the exact original strings). Both are now
13
+ * caller-supplied — `host`/`port`/
14
+ * `path` are required input fields instead of defaulted constants (a
15
+ * provider whose OAuth client_id is locked to a specific redirect URI, like
16
+ * xAI's, supplies that provider's fixed port via
17
+ * `oauth-provider.ts`'s preset), and the result page uses generic "the host
18
+ * application" copy with no product name. Listener mechanics are otherwise
19
+ * unchanged.
20
+ */
21
+ import http from 'node:http';
22
+ const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
23
+ /**
24
+ * Opens a one-shot HTTP listener for an OAuth redirect callback.
25
+ *
26
+ * Resolves once the listener is bound; callback handling is asynchronous
27
+ * via `onCallback`. The listener self-closes after the first matching
28
+ * callback OR after `timeoutMs` (default 30 min), whichever comes first.
29
+ */
30
+ export async function startOAuthCallbackListener(input) {
31
+ const { host, port, path: callbackPath } = input;
32
+ const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
33
+ let consumed = false;
34
+ let stopped = false;
35
+ let serverRef = null;
36
+ let timer = null;
37
+ const closeServer = () => new Promise((resolve) => {
38
+ // Non-null: `stop()` (this function's only caller) guards on `stopped`
39
+ // before ever reaching here, so this runs at most once — after
40
+ // `serverRef` was unconditionally set at listener-startup, before this
41
+ // closure's `stop`/`address` are ever handed to a caller.
42
+ const s = serverRef;
43
+ serverRef = null;
44
+ if (timer) {
45
+ clearTimeout(timer);
46
+ timer = null;
47
+ }
48
+ s.close(() => resolve());
49
+ // Force close after a short grace period so lingering keep-alive
50
+ // sockets don't keep the event loop alive in tests.
51
+ const reaper = setTimeout(() => {
52
+ try {
53
+ s.closeAllConnections?.();
54
+ }
55
+ catch {
56
+ // Best-effort cleanup only: node:http's closeAllConnections()
57
+ // doesn't document a throwing case in the supported Node range
58
+ // this package targets — this guard exists for a future/older
59
+ // runtime where it might, not a reachable path today.
60
+ }
61
+ }, 100);
62
+ reaper.unref?.();
63
+ });
64
+ const stop = async () => {
65
+ if (stopped)
66
+ return;
67
+ stopped = true;
68
+ await closeServer();
69
+ };
70
+ const handle = async (req, res) => {
71
+ if (consumed || !req.url) {
72
+ res.statusCode = 410;
73
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
74
+ res.end('Listener already consumed.');
75
+ return;
76
+ }
77
+ let parsed;
78
+ try {
79
+ parsed = new URL(req.url, `http://${host}:${port}`);
80
+ }
81
+ catch {
82
+ res.statusCode = 400;
83
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
84
+ res.end('Bad request.');
85
+ return;
86
+ }
87
+ // Ignore favicon.ico and any other path so the browser's incidental
88
+ // requests don't consume the slot meant for the callback path.
89
+ if (parsed.pathname !== callbackPath) {
90
+ res.statusCode = 404;
91
+ res.setHeader('content-type', 'text/plain; charset=utf-8');
92
+ res.end('Not found.');
93
+ return;
94
+ }
95
+ const code = parsed.searchParams.get('code') ?? '';
96
+ const state = parsed.searchParams.get('state') ?? '';
97
+ const errorParam = parsed.searchParams.get('error') ?? '';
98
+ let outcome;
99
+ if (errorParam) {
100
+ outcome = state
101
+ ? { kind: 'error', error: errorParam, state }
102
+ : { kind: 'error', error: errorParam };
103
+ }
104
+ else if (!code || !state) {
105
+ outcome = { kind: 'error', error: 'missing code or state' };
106
+ }
107
+ else if (state !== input.expectedState) {
108
+ outcome = { kind: 'error', error: 'state mismatch', state };
109
+ }
110
+ else {
111
+ outcome = { kind: 'ok', code, state };
112
+ }
113
+ // Decide whether this hit *consumes* the listener. A stray browser tab
114
+ // replaying an old `?state=...` (or `?error=...&state=...`) would
115
+ // otherwise close a shared fixed-port listener before the real redirect
116
+ // can arrive. Keep the listener open on stale/malformed requests; the
117
+ // real callback will still find it. Consume on:
118
+ // - ok callback (matched state, code present)
119
+ // - explicit ?error= without a state (the server rejected before
120
+ // issuing state, so there's nothing to match against — safe to
121
+ // consume)
122
+ // - explicit ?error= with state matching expectedState (the server
123
+ // told the user the dance failed; propagate now instead of waiting
124
+ // for the timeout)
125
+ // An ?error= with a *mismatched* state is treated like the stale
126
+ // success replay above: 400 the browser, leave the listener live.
127
+ const errorConsumes = Boolean(errorParam) && (!state || state === input.expectedState);
128
+ const consumesListener = outcome.kind === 'ok' || errorConsumes;
129
+ if (consumesListener) {
130
+ consumed = true;
131
+ }
132
+ res.statusCode = outcome.kind === 'ok' ? 200 : 400;
133
+ res.setHeader('content-type', 'text/html; charset=utf-8');
134
+ res.end(renderResultPage(outcome));
135
+ if (!consumesListener) {
136
+ // Stale-tab replay or malformed request — don't surface to the
137
+ // caller and don't tear down the listener. The browser sees the
138
+ // 400 page; the real flow can still complete on a later hit.
139
+ return;
140
+ }
141
+ try {
142
+ await input.onCallback(outcome);
143
+ }
144
+ catch (err) {
145
+ console.error('[oauth-callback-server] onCallback failed:', err);
146
+ }
147
+ finally {
148
+ void stop();
149
+ }
150
+ };
151
+ const server = http.createServer((req, res) => {
152
+ void handle(req, res);
153
+ });
154
+ await new Promise((resolve, reject) => {
155
+ const onError = (err) => {
156
+ if (err.code === 'EADDRINUSE') {
157
+ reject(new Error(`Port ${port} is already in use — close any other process listening on ${host}:${port} (e.g. an in-flight OAuth flow) and try again`));
158
+ }
159
+ else {
160
+ reject(err);
161
+ }
162
+ };
163
+ server.once('error', onError);
164
+ server.listen(port, host, () => {
165
+ server.removeListener('error', onError);
166
+ resolve();
167
+ });
168
+ });
169
+ serverRef = server;
170
+ timer = setTimeout(() => {
171
+ Promise.resolve(input.onCallback({
172
+ kind: 'error',
173
+ error: 'OAuth timed out — sign in again',
174
+ })).catch(() => {
175
+ // already logging in handle(); this branch is best-effort cleanup.
176
+ });
177
+ void stop();
178
+ }, timeoutMs);
179
+ // unref so the timer doesn't keep the event loop alive in tests.
180
+ timer.unref?.();
181
+ const addr = server.address();
182
+ return {
183
+ address: { host: addr.address, port: addr.port },
184
+ stop,
185
+ };
186
+ }
187
+ function renderResultPage(outcome) {
188
+ if (outcome.kind === 'ok') {
189
+ return `<!doctype html>
190
+ <html lang="en"><head><meta charset="utf-8"><title>Authorized</title></head>
191
+ <body style="font:14px system-ui;padding:40px;max-width:480px;margin:auto;text-align:center;color:#222;">
192
+ <h1 style="font-size:18px;margin:0 0 12px;">Authorized!</h1>
193
+ <p style="color:#666;">The host application now has access. You can close this tab and return to it.</p>
194
+ </body></html>`;
195
+ }
196
+ // No `|| 'unknown error'` fallback: every 'error'-kind outcome this file
197
+ // constructs (state/code validation, state mismatch, timeout) always sets
198
+ // a non-empty `error` string, so the field is never falsy in practice —
199
+ // this documents that instead of adding an unreachable fallback branch.
200
+ const reason = escapeHtml(outcome.error);
201
+ return `<!doctype html>
202
+ <html lang="en"><head><meta charset="utf-8"><title>Sign-in failed</title></head>
203
+ <body style="font:14px system-ui;padding:40px;max-width:480px;margin:auto;text-align:center;color:#222;">
204
+ <h1 style="font-size:18px;margin:0 0 12px;">Sign-in failed</h1>
205
+ <p style="color:#c00;">${reason}</p>
206
+ <p style="color:#666;">Close this tab and retry sign-in from the host application.</p>
207
+ </body></html>`;
208
+ }
209
+ function escapeHtml(s) {
210
+ return s
211
+ .replace(/&/g, '&amp;')
212
+ .replace(/</g, '&lt;')
213
+ .replace(/>/g, '&gt;')
214
+ .replace(/"/g, '&quot;')
215
+ .replace(/'/g, '&#39;');
216
+ }
217
+ //# sourceMappingURL=oauth-callback-server.js.map