@oharness/engine 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 (256) hide show
  1. package/dist/agent/agent.d.ts +196 -0
  2. package/dist/agent/agent.js +758 -0
  3. package/dist/agent/agent.js.map +1 -0
  4. package/dist/agent/compaction.d.ts +68 -0
  5. package/dist/agent/compaction.js +179 -0
  6. package/dist/agent/compaction.js.map +1 -0
  7. package/dist/agent/hooks.d.ts +77 -0
  8. package/dist/agent/hooks.js +152 -0
  9. package/dist/agent/hooks.js.map +1 -0
  10. package/dist/agent/memory.d.ts +45 -0
  11. package/dist/agent/memory.js +147 -0
  12. package/dist/agent/memory.js.map +1 -0
  13. package/dist/agent/overflow.d.ts +35 -0
  14. package/dist/agent/overflow.js +69 -0
  15. package/dist/agent/overflow.js.map +1 -0
  16. package/dist/agent/permissions.d.ts +181 -0
  17. package/dist/agent/permissions.js +289 -0
  18. package/dist/agent/permissions.js.map +1 -0
  19. package/dist/agent/prompt.d.ts +25 -0
  20. package/dist/agent/prompt.js +63 -0
  21. package/dist/agent/prompt.js.map +1 -0
  22. package/dist/agent/session.d.ts +108 -0
  23. package/dist/agent/session.js +231 -0
  24. package/dist/agent/session.js.map +1 -0
  25. package/dist/agent/settings.d.ts +37 -0
  26. package/dist/agent/settings.js +113 -0
  27. package/dist/agent/settings.js.map +1 -0
  28. package/dist/agent/skills.d.ts +58 -0
  29. package/dist/agent/skills.js +225 -0
  30. package/dist/agent/skills.js.map +1 -0
  31. package/dist/agent/store.d.ts +308 -0
  32. package/dist/agent/store.js +596 -0
  33. package/dist/agent/store.js.map +1 -0
  34. package/dist/agent/subagent.d.ts +44 -0
  35. package/dist/agent/subagent.js +138 -0
  36. package/dist/agent/subagent.js.map +1 -0
  37. package/dist/agent/titles.d.ts +8 -0
  38. package/dist/agent/titles.js +23 -0
  39. package/dist/agent/titles.js.map +1 -0
  40. package/dist/agent/workspace.d.ts +60 -0
  41. package/dist/agent/workspace.js +156 -0
  42. package/dist/agent/workspace.js.map +1 -0
  43. package/dist/artifacts/publish.d.ts +94 -0
  44. package/dist/artifacts/publish.js +104 -0
  45. package/dist/artifacts/publish.js.map +1 -0
  46. package/dist/artifacts/store.d.ts +324 -0
  47. package/dist/artifacts/store.js +500 -0
  48. package/dist/artifacts/store.js.map +1 -0
  49. package/dist/auth/index.d.ts +13 -0
  50. package/dist/auth/index.js +10 -0
  51. package/dist/auth/index.js.map +1 -0
  52. package/dist/auth/manager.d.ts +83 -0
  53. package/dist/auth/manager.js +266 -0
  54. package/dist/auth/manager.js.map +1 -0
  55. package/dist/auth/oauth.d.ts +83 -0
  56. package/dist/auth/oauth.js +327 -0
  57. package/dist/auth/oauth.js.map +1 -0
  58. package/dist/auth/providers/account.d.ts +59 -0
  59. package/dist/auth/providers/account.js +282 -0
  60. package/dist/auth/providers/account.js.map +1 -0
  61. package/dist/auth/providers/anthropic.d.ts +24 -0
  62. package/dist/auth/providers/anthropic.js +209 -0
  63. package/dist/auth/providers/anthropic.js.map +1 -0
  64. package/dist/auth/providers/generic.d.ts +57 -0
  65. package/dist/auth/providers/generic.js +155 -0
  66. package/dist/auth/providers/generic.js.map +1 -0
  67. package/dist/auth/providers/official.d.ts +3 -0
  68. package/dist/auth/providers/official.js +90 -0
  69. package/dist/auth/providers/official.js.map +1 -0
  70. package/dist/auth/providers/ottoport.d.ts +3 -0
  71. package/dist/auth/providers/ottoport.js +60 -0
  72. package/dist/auth/providers/ottoport.js.map +1 -0
  73. package/dist/auth/store.d.ts +22 -0
  74. package/dist/auth/store.js +138 -0
  75. package/dist/auth/store.js.map +1 -0
  76. package/dist/auth/types.d.ts +167 -0
  77. package/dist/auth/types.js +16 -0
  78. package/dist/auth/types.js.map +1 -0
  79. package/dist/config.d.ts +197 -0
  80. package/dist/config.js +195 -0
  81. package/dist/config.js.map +1 -0
  82. package/dist/core/errors.d.ts +46 -0
  83. package/dist/core/errors.js +83 -0
  84. package/dist/core/errors.js.map +1 -0
  85. package/dist/core/tokens.d.ts +12 -0
  86. package/dist/core/tokens.js +56 -0
  87. package/dist/core/tokens.js.map +1 -0
  88. package/dist/core/types.d.ts +91 -0
  89. package/dist/core/types.js +49 -0
  90. package/dist/core/types.js.map +1 -0
  91. package/dist/harness.d.ts +302 -0
  92. package/dist/harness.js +695 -0
  93. package/dist/harness.js.map +1 -0
  94. package/dist/index.d.ts +32 -0
  95. package/dist/index.js +21 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/mcp/client.d.ts +55 -0
  98. package/dist/mcp/client.js +199 -0
  99. package/dist/mcp/client.js.map +1 -0
  100. package/dist/mcp/index.d.ts +13 -0
  101. package/dist/mcp/index.js +8 -0
  102. package/dist/mcp/index.js.map +1 -0
  103. package/dist/mcp/manager.d.ts +77 -0
  104. package/dist/mcp/manager.js +325 -0
  105. package/dist/mcp/manager.js.map +1 -0
  106. package/dist/mcp/oauth.d.ts +63 -0
  107. package/dist/mcp/oauth.js +302 -0
  108. package/dist/mcp/oauth.js.map +1 -0
  109. package/dist/mcp/protocol.d.ts +130 -0
  110. package/dist/mcp/protocol.js +14 -0
  111. package/dist/mcp/protocol.js.map +1 -0
  112. package/dist/mcp/registry.d.ts +52 -0
  113. package/dist/mcp/registry.js +100 -0
  114. package/dist/mcp/registry.js.map +1 -0
  115. package/dist/mcp/registry.json +293 -0
  116. package/dist/mcp/secrets.d.ts +20 -0
  117. package/dist/mcp/secrets.js +75 -0
  118. package/dist/mcp/secrets.js.map +1 -0
  119. package/dist/mcp/transport.d.ts +51 -0
  120. package/dist/mcp/transport.js +158 -0
  121. package/dist/mcp/transport.js.map +1 -0
  122. package/dist/paths.d.ts +37 -0
  123. package/dist/paths.js +63 -0
  124. package/dist/paths.js.map +1 -0
  125. package/dist/plugins.d.ts +55 -0
  126. package/dist/plugins.js +201 -0
  127. package/dist/plugins.js.map +1 -0
  128. package/dist/providers/builtin.d.ts +23 -0
  129. package/dist/providers/builtin.js +141 -0
  130. package/dist/providers/builtin.js.map +1 -0
  131. package/dist/providers/catalog.d.ts +129 -0
  132. package/dist/providers/catalog.js +254 -0
  133. package/dist/providers/catalog.js.map +1 -0
  134. package/dist/providers/catalog.json +472 -0
  135. package/dist/providers/discovery.d.ts +16 -0
  136. package/dist/providers/discovery.js +161 -0
  137. package/dist/providers/discovery.js.map +1 -0
  138. package/dist/providers/http.d.ts +24 -0
  139. package/dist/providers/http.js +139 -0
  140. package/dist/providers/http.js.map +1 -0
  141. package/dist/providers/index.d.ts +10 -0
  142. package/dist/providers/index.js +8 -0
  143. package/dist/providers/index.js.map +1 -0
  144. package/dist/providers/piai.d.ts +124 -0
  145. package/dist/providers/piai.js +551 -0
  146. package/dist/providers/piai.js.map +1 -0
  147. package/dist/providers/registry.d.ts +65 -0
  148. package/dist/providers/registry.js +195 -0
  149. package/dist/providers/registry.js.map +1 -0
  150. package/dist/providers/resilient.d.ts +46 -0
  151. package/dist/providers/resilient.js +117 -0
  152. package/dist/providers/resilient.js.map +1 -0
  153. package/dist/providers/types.d.ts +182 -0
  154. package/dist/providers/types.js +50 -0
  155. package/dist/providers/types.js.map +1 -0
  156. package/dist/schedule/cron.d.ts +35 -0
  157. package/dist/schedule/cron.js +125 -0
  158. package/dist/schedule/cron.js.map +1 -0
  159. package/dist/schedule/scheduler.d.ts +87 -0
  160. package/dist/schedule/scheduler.js +237 -0
  161. package/dist/schedule/scheduler.js.map +1 -0
  162. package/dist/storage/kv.d.ts +56 -0
  163. package/dist/storage/kv.js +173 -0
  164. package/dist/storage/kv.js.map +1 -0
  165. package/dist/storage/migrate.d.ts +11 -0
  166. package/dist/storage/migrate.js +93 -0
  167. package/dist/storage/migrate.js.map +1 -0
  168. package/dist/storage/project.d.ts +9 -0
  169. package/dist/storage/project.js +57 -0
  170. package/dist/storage/project.js.map +1 -0
  171. package/dist/storage/records.d.ts +32 -0
  172. package/dist/storage/records.js +48 -0
  173. package/dist/storage/records.js.map +1 -0
  174. package/dist/sync/client.d.ts +79 -0
  175. package/dist/sync/client.js +118 -0
  176. package/dist/sync/client.js.map +1 -0
  177. package/dist/sync/mirror.d.ts +85 -0
  178. package/dist/sync/mirror.js +389 -0
  179. package/dist/sync/mirror.js.map +1 -0
  180. package/dist/sync/protocol.d.ts +67 -0
  181. package/dist/sync/protocol.js +16 -0
  182. package/dist/sync/protocol.js.map +1 -0
  183. package/dist/sync/settings.d.ts +56 -0
  184. package/dist/sync/settings.js +60 -0
  185. package/dist/sync/settings.js.map +1 -0
  186. package/dist/tools/builtin/artifact.d.ts +16 -0
  187. package/dist/tools/builtin/artifact.js +134 -0
  188. package/dist/tools/builtin/artifact.js.map +1 -0
  189. package/dist/tools/builtin/bash.d.ts +3 -0
  190. package/dist/tools/builtin/bash.js +142 -0
  191. package/dist/tools/builtin/bash.js.map +1 -0
  192. package/dist/tools/builtin/fs.d.ts +19 -0
  193. package/dist/tools/builtin/fs.js +280 -0
  194. package/dist/tools/builtin/fs.js.map +1 -0
  195. package/dist/tools/builtin/index.d.ts +22 -0
  196. package/dist/tools/builtin/index.js +42 -0
  197. package/dist/tools/builtin/index.js.map +1 -0
  198. package/dist/tools/builtin/mcp-resource.d.ts +3 -0
  199. package/dist/tools/builtin/mcp-resource.js +220 -0
  200. package/dist/tools/builtin/mcp-resource.js.map +1 -0
  201. package/dist/tools/builtin/memory.d.ts +10 -0
  202. package/dist/tools/builtin/memory.js +76 -0
  203. package/dist/tools/builtin/memory.js.map +1 -0
  204. package/dist/tools/builtin/recall.d.ts +13 -0
  205. package/dist/tools/builtin/recall.js +163 -0
  206. package/dist/tools/builtin/recall.js.map +1 -0
  207. package/dist/tools/builtin/search.d.ts +3 -0
  208. package/dist/tools/builtin/search.js +240 -0
  209. package/dist/tools/builtin/search.js.map +1 -0
  210. package/dist/tools/builtin/skill.d.ts +10 -0
  211. package/dist/tools/builtin/skill.js +46 -0
  212. package/dist/tools/builtin/skill.js.map +1 -0
  213. package/dist/tools/builtin/task.d.ts +9 -0
  214. package/dist/tools/builtin/task.js +68 -0
  215. package/dist/tools/builtin/task.js.map +1 -0
  216. package/dist/tools/builtin/todo.d.ts +20 -0
  217. package/dist/tools/builtin/todo.js +63 -0
  218. package/dist/tools/builtin/todo.js.map +1 -0
  219. package/dist/tools/define.d.ts +19 -0
  220. package/dist/tools/define.js +39 -0
  221. package/dist/tools/define.js.map +1 -0
  222. package/dist/tools/index.d.ts +7 -0
  223. package/dist/tools/index.js +5 -0
  224. package/dist/tools/index.js.map +1 -0
  225. package/dist/tools/registry.d.ts +39 -0
  226. package/dist/tools/registry.js +101 -0
  227. package/dist/tools/registry.js.map +1 -0
  228. package/dist/tools/types.d.ts +112 -0
  229. package/dist/tools/types.js +22 -0
  230. package/dist/tools/types.js.map +1 -0
  231. package/dist/util/id.d.ts +9 -0
  232. package/dist/util/id.js +19 -0
  233. package/dist/util/id.js.map +1 -0
  234. package/dist/util/json.d.ts +25 -0
  235. package/dist/util/json.js +100 -0
  236. package/dist/util/json.js.map +1 -0
  237. package/dist/util/jwt.d.ts +74 -0
  238. package/dist/util/jwt.js +177 -0
  239. package/dist/util/jwt.js.map +1 -0
  240. package/dist/util/logger.d.ts +13 -0
  241. package/dist/util/logger.js +59 -0
  242. package/dist/util/logger.js.map +1 -0
  243. package/dist/util/queue.d.ts +26 -0
  244. package/dist/util/queue.js +106 -0
  245. package/dist/util/queue.js.map +1 -0
  246. package/dist/util/schema.d.ts +17 -0
  247. package/dist/util/schema.js +98 -0
  248. package/dist/util/schema.js.map +1 -0
  249. package/dist/util/shell.d.ts +20 -0
  250. package/dist/util/shell.js +24 -0
  251. package/dist/util/shell.js.map +1 -0
  252. package/official.json +4 -0
  253. package/package.json +38 -0
  254. package/skills/artifact-authoring/SKILL.md +81 -0
  255. package/skills/canvas/SKILL.md +85 -0
  256. package/skills/skill-authoring/SKILL.md +85 -0
@@ -0,0 +1,472 @@
1
+ {
2
+ "$comment": [
3
+ "Model catalog. This is DATA, not code — edit it without touching the harness.",
4
+ "",
5
+ "Precedence, later wins:",
6
+ " 1. this bundled file",
7
+ " 2. ~/.oharness/catalog.json",
8
+ " 3. the `catalog` path in your config",
9
+ " 4. `providers` / `models` in your config",
10
+ " 5. `/models refresh` (asks each provider's own API)",
11
+ "",
12
+ "Provider facts (baseUrl, env var, protocol) are stable and worth shipping.",
13
+ "Model ids go stale fast — only entries verified at the `verified` date below",
14
+ "are listed. For everything else run `/models refresh`, which asks the vendor",
15
+ "directly and is always more current than this file."
16
+ ],
17
+ "verified": "2026-08-05",
18
+ "providers": {
19
+ "official": {
20
+ "label": "OHarness",
21
+ "protocol": "openai-chat",
22
+ "baseUrl": "https://api.oharness.ai/api/v1",
23
+ "envVars": [
24
+ "OHARNESS_API_KEY"
25
+ ],
26
+ "discovery": "openai",
27
+ "idempotencyKey": true,
28
+ "maxOutputTokens": 4096,
29
+ "$note": "The official plan: sign in with an OHarness account, or paste an `oh-` key created on the site. Usage is metered against the account balance and the upstream keys are never the subscriber's — which gateway serves the models is an implementation detail, moved by OHARNESS_BASE_URL. This host is our metering gateway, NOT the upstream one: they speak the same paths, so the two are easy to confuse and the mistake is quiet — the model list is public upstream and answers 200, and only the first completion comes back `invalid_api_key`. No docsUrl: the way in is the sign-in, not a key page, so pointing at one would send people the long way round. The two lines above are the upstream gateway's, not any model's: it wants an `Idempotency-Key` on every completion and caps `max_tokens` at its own `GATEWAY_MAX_OUTPUT_TOKENS` — 4096 by default, and nothing in `/models` mentions either, so both have to be stated here. Raise the number in step with the deployment, or a shorter answer is the least of it: over the line is a 400, not a truncation.",
30
+ "popular": true,
31
+ "recommended": true,
32
+ "description": "Official plan — sign in with your OHarness account"
33
+ },
34
+ "openrouter": {
35
+ "label": "OpenRouter",
36
+ "protocol": "openai-chat",
37
+ "baseUrl": "https://openrouter.ai/api/v1",
38
+ "envVars": [
39
+ "OPENROUTER_API_KEY"
40
+ ],
41
+ "discovery": "openrouter",
42
+ "headers": {
43
+ "HTTP-Referer": "https://github.com/oharness",
44
+ "X-Title": "OHarness"
45
+ },
46
+ "docsUrl": "https://openrouter.ai/keys",
47
+ "popular": true,
48
+ "description": "One key, hundreds of models across vendors"
49
+ },
50
+ "anthropic": {
51
+ "label": "Anthropic",
52
+ "protocol": "anthropic-messages",
53
+ "baseUrl": "https://api.anthropic.com",
54
+ "envVars": [
55
+ "ANTHROPIC_API_KEY"
56
+ ],
57
+ "docsUrl": "https://console.anthropic.com/settings/keys",
58
+ "popular": true,
59
+ "description": "Claude models, direct API or ant CLI subscription"
60
+ },
61
+ "ottoport": {
62
+ "label": "OttoPort",
63
+ "protocol": "openai-chat",
64
+ "baseUrl": "https://ottoport.ai/api/v1",
65
+ "envVars": [
66
+ "OTTOPORT_API_KEY"
67
+ ],
68
+ "discovery": "openai",
69
+ "idempotencyKey": true,
70
+ "maxOutputTokens": 4096,
71
+ "docsUrl": "https://ottoport.ai/docs",
72
+ "$note": "Bring-your-own OttoPort account: the user makes an `op-` key in OttoPort's console and is billed there. Not the official plan — that is `official`, which happens to route through this gateway today but never hands the subscriber a key to it. The two lines above are the upstream gateway's, not any model's: it wants an `Idempotency-Key` on every completion and caps `max_tokens` at its own `GATEWAY_MAX_OUTPUT_TOKENS` — 4096 by default, and nothing in `/models` mentions either, so both have to be stated here. Raise the number in step with the deployment, or a shorter answer is the least of it: over the line is a 400, not a truncation.",
73
+ "popular": true,
74
+ "description": "Your own OttoPort key — GPT, Claude and Gemini behind one gateway"
75
+ },
76
+ "openai": {
77
+ "label": "OpenAI",
78
+ "protocol": "openai-responses",
79
+ "baseUrl": "https://api.openai.com/v1",
80
+ "envVars": [
81
+ "OPENAI_API_KEY"
82
+ ],
83
+ "discovery": "openai",
84
+ "$note": "Responses is the API OpenAI's current models are documented against, and some (the pro tiers) are served nowhere else. A proxy that only speaks chat completions needs { \"providers\": { \"openai\": { \"protocol\": \"openai-chat\" } } }.",
85
+ "docsUrl": "https://platform.openai.com/api-keys",
86
+ "popular": true,
87
+ "description": "GPT models, official API"
88
+ },
89
+ "google": {
90
+ "label": "Google Gemini",
91
+ "protocol": "gemini",
92
+ "baseUrl": "https://generativelanguage.googleapis.com/v1beta",
93
+ "envVars": [
94
+ "GEMINI_API_KEY",
95
+ "GOOGLE_API_KEY"
96
+ ],
97
+ "docsUrl": "https://aistudio.google.com/apikey",
98
+ "popular": true,
99
+ "description": "Gemini models, official API"
100
+ },
101
+ "moonshot": {
102
+ "label": "Moonshot (Kimi)",
103
+ "protocol": "openai-chat",
104
+ "baseUrl": "https://api.moonshot.ai/v1",
105
+ "envVars": [
106
+ "MOONSHOT_API_KEY",
107
+ "KIMI_API_KEY"
108
+ ],
109
+ "discovery": "openai",
110
+ "piProvider": "moonshotai",
111
+ "docsUrl": "https://platform.moonshot.ai/console/api-keys",
112
+ "$note": "Mainland China accounts use https://api.moonshot.cn/v1 — override baseUrl.",
113
+ "popular": true,
114
+ "description": "Kimi official API, long context"
115
+ },
116
+ "deepseek": {
117
+ "label": "DeepSeek",
118
+ "protocol": "openai-chat",
119
+ "baseUrl": "https://api.deepseek.com/v1",
120
+ "envVars": [
121
+ "DEEPSEEK_API_KEY"
122
+ ],
123
+ "discovery": "openai",
124
+ "docsUrl": "https://platform.deepseek.com/api_keys",
125
+ "popular": true,
126
+ "description": "DeepSeek official API, low cost"
127
+ },
128
+ "zhipu": {
129
+ "label": "Zhipu (GLM)",
130
+ "protocol": "openai-chat",
131
+ "baseUrl": "https://open.bigmodel.cn/api/paas/v4",
132
+ "envVars": [
133
+ "ZHIPU_API_KEY",
134
+ "GLM_API_KEY"
135
+ ],
136
+ "discovery": "openai",
137
+ "piProvider": "zai-coding-cn",
138
+ "docsUrl": "https://open.bigmodel.cn/usercenter/apikeys",
139
+ "$note": "pi-ai files the mainland GLM models under `zai-coding-cn`; the model ids are the same ones open.bigmodel.cn serves, so only the name needs reconciling — the endpoint above stays this entry's.",
140
+ "popular": true,
141
+ "description": "Zhipu GLM official API"
142
+ },
143
+ "zai": {
144
+ "label": "Z.ai (GLM)",
145
+ "protocol": "openai-chat",
146
+ "baseUrl": "https://api.z.ai/api/paas/v4",
147
+ "envVars": [
148
+ "ZAI_API_KEY",
149
+ "Z_AI_API_KEY"
150
+ ],
151
+ "discovery": "openai",
152
+ "docsUrl": "https://z.ai/manage-apikey/apikey-list",
153
+ "$note": "Zhipu's international arm, a separate host and a separate key from `zhipu`. A GLM Coding Plan subscription is served from https://api.z.ai/api/coding/paas/v4 — override baseUrl for it.",
154
+ "popular": true,
155
+ "description": "GLM models, international endpoint"
156
+ },
157
+ "siliconflow": {
158
+ "label": "SiliconFlow",
159
+ "protocol": "openai-chat",
160
+ "baseUrl": "https://api.siliconflow.cn/v1",
161
+ "envVars": [
162
+ "SILICONFLOW_API_KEY"
163
+ ],
164
+ "discovery": "openai",
165
+ "description": "SiliconFlow, aggregated open models"
166
+ },
167
+ "volcengine": {
168
+ "label": "Volcengine (Doubao)",
169
+ "protocol": "openai-chat",
170
+ "baseUrl": "https://ark.cn-beijing.volces.com/api/v3",
171
+ "envVars": [
172
+ "ARK_API_KEY",
173
+ "VOLCENGINE_API_KEY"
174
+ ],
175
+ "discovery": "openai",
176
+ "popular": true,
177
+ "description": "Volcengine Ark: Doubao and third-party models"
178
+ },
179
+ "xai": {
180
+ "label": "xAI",
181
+ "protocol": "openai-chat",
182
+ "baseUrl": "https://api.x.ai/v1",
183
+ "envVars": [
184
+ "XAI_API_KEY"
185
+ ],
186
+ "discovery": "openai",
187
+ "docsUrl": "https://console.x.ai",
188
+ "description": "Grok models, official API"
189
+ },
190
+ "mistral": {
191
+ "label": "Mistral",
192
+ "protocol": "openai-chat",
193
+ "baseUrl": "https://api.mistral.ai/v1",
194
+ "envVars": [
195
+ "MISTRAL_API_KEY"
196
+ ],
197
+ "discovery": "openai",
198
+ "docsUrl": "https://console.mistral.ai/api-keys",
199
+ "description": "Mistral official API"
200
+ },
201
+ "groq": {
202
+ "label": "Groq",
203
+ "protocol": "openai-chat",
204
+ "baseUrl": "https://api.groq.com/openai/v1",
205
+ "envVars": [
206
+ "GROQ_API_KEY"
207
+ ],
208
+ "discovery": "openai",
209
+ "docsUrl": "https://console.groq.com/keys",
210
+ "description": "Very low latency inference"
211
+ },
212
+ "together": {
213
+ "label": "Together AI",
214
+ "protocol": "openai-chat",
215
+ "baseUrl": "https://api.together.xyz/v1",
216
+ "envVars": [
217
+ "TOGETHER_API_KEY"
218
+ ],
219
+ "discovery": "openai",
220
+ "docsUrl": "https://api.together.xyz/settings/api-keys",
221
+ "description": "Hosted open-model inference"
222
+ },
223
+ "cerebras": {
224
+ "label": "Cerebras",
225
+ "protocol": "openai-chat",
226
+ "baseUrl": "https://api.cerebras.ai/v1",
227
+ "envVars": [
228
+ "CEREBRAS_API_KEY"
229
+ ],
230
+ "discovery": "openai",
231
+ "docsUrl": "https://cloud.cerebras.ai",
232
+ "description": "Wafer-scale hardware, very high throughput"
233
+ },
234
+ "fireworks": {
235
+ "label": "Fireworks",
236
+ "protocol": "openai-chat",
237
+ "baseUrl": "https://api.fireworks.ai/inference/v1",
238
+ "envVars": [
239
+ "FIREWORKS_API_KEY"
240
+ ],
241
+ "discovery": "openai",
242
+ "docsUrl": "https://fireworks.ai/api-keys",
243
+ "description": "Fast open-model inference"
244
+ },
245
+ "deepinfra": {
246
+ "label": "DeepInfra",
247
+ "protocol": "openai-chat",
248
+ "baseUrl": "https://api.deepinfra.com/v1/openai",
249
+ "envVars": [
250
+ "DEEPINFRA_API_KEY"
251
+ ],
252
+ "discovery": "openai",
253
+ "description": "Low-cost open-model inference"
254
+ },
255
+ "ollama": {
256
+ "label": "Ollama",
257
+ "protocol": "openai-chat",
258
+ "baseUrl": "http://localhost:11434/v1",
259
+ "envVars": [],
260
+ "discovery": "openai",
261
+ "includeUsage": false,
262
+ "description": "Runs locally, no key needed"
263
+ },
264
+ "lmstudio": {
265
+ "label": "LM Studio",
266
+ "protocol": "openai-chat",
267
+ "baseUrl": "http://localhost:1234/v1",
268
+ "envVars": [],
269
+ "discovery": "openai",
270
+ "includeUsage": false,
271
+ "description": "Runs locally, no key needed"
272
+ },
273
+ "vllm": {
274
+ "label": "vLLM",
275
+ "protocol": "openai-chat",
276
+ "baseUrl": "http://localhost:8000/v1",
277
+ "envVars": [],
278
+ "discovery": "openai",
279
+ "description": "Your own vLLM server"
280
+ },
281
+ "perplexity": {
282
+ "label": "Perplexity",
283
+ "protocol": "openai-chat",
284
+ "baseUrl": "https://api.perplexity.ai",
285
+ "envVars": [
286
+ "PERPLEXITY_API_KEY"
287
+ ],
288
+ "discovery": "openai",
289
+ "docsUrl": "https://www.perplexity.ai/settings/api",
290
+ "description": "Models with live web search"
291
+ },
292
+ "nvidia": {
293
+ "label": "NVIDIA NIM",
294
+ "protocol": "openai-chat",
295
+ "baseUrl": "https://integrate.api.nvidia.com/v1",
296
+ "envVars": [
297
+ "NVIDIA_API_KEY"
298
+ ],
299
+ "discovery": "openai",
300
+ "docsUrl": "https://build.nvidia.com/",
301
+ "description": "NVIDIA NIM hosted inference"
302
+ },
303
+ "novita": {
304
+ "label": "Novita",
305
+ "protocol": "openai-chat",
306
+ "baseUrl": "https://api.novita.ai/v3/openai",
307
+ "envVars": [
308
+ "NOVITA_API_KEY"
309
+ ],
310
+ "discovery": "openai",
311
+ "docsUrl": "https://novita.ai/settings/key-management",
312
+ "description": "Open-model inference platform"
313
+ },
314
+ "hyperbolic": {
315
+ "label": "Hyperbolic",
316
+ "protocol": "openai-chat",
317
+ "baseUrl": "https://api.hyperbolic.xyz/v1",
318
+ "envVars": [
319
+ "HYPERBOLIC_API_KEY"
320
+ ],
321
+ "discovery": "openai",
322
+ "docsUrl": "https://app.hyperbolic.xyz/settings",
323
+ "description": "Low-cost open-model inference"
324
+ },
325
+ "minimax": {
326
+ "label": "MiniMax",
327
+ "protocol": "openai-chat",
328
+ "baseUrl": "https://api.minimax.chat/v1",
329
+ "envVars": [
330
+ "MINIMAX_API_KEY"
331
+ ],
332
+ "discovery": "openai",
333
+ "docsUrl": "https://platform.minimaxi.com/user-center/basic-information/interface-key",
334
+ "description": "MiniMax official API"
335
+ }
336
+ },
337
+ "models": [
338
+ {
339
+ "$comment": "Anthropic entries are verified against the official model reference. Reasoning config differs per family and sending the wrong shape is a 400, so these flags are load-bearing.",
340
+ "id": "opus",
341
+ "provider": "anthropic",
342
+ "model": "claude-opus-5",
343
+ "displayName": "Claude Opus 5",
344
+ "contextWindow": 1000000,
345
+ "maxOutputTokens": 128000,
346
+ "supportsTools": true,
347
+ "supportsImages": true,
348
+ "supportsParallelToolCalls": true,
349
+ "supportsPromptCache": true,
350
+ "thinkingMode": "adaptive",
351
+ "effortLevels": [
352
+ "low",
353
+ "medium",
354
+ "high",
355
+ "xhigh",
356
+ "max"
357
+ ],
358
+ "maxEffortWithThinkingDisabled": "high",
359
+ "supportsSampling": false,
360
+ "costPer1MInput": 5,
361
+ "costPer1MOutput": 25
362
+ },
363
+ {
364
+ "id": "fable",
365
+ "provider": "anthropic",
366
+ "model": "claude-fable-5",
367
+ "displayName": "Claude Fable 5",
368
+ "contextWindow": 1000000,
369
+ "maxOutputTokens": 128000,
370
+ "supportsTools": true,
371
+ "supportsImages": true,
372
+ "supportsParallelToolCalls": true,
373
+ "supportsPromptCache": true,
374
+ "thinkingMode": "always-on",
375
+ "effortLevels": [
376
+ "low",
377
+ "medium",
378
+ "high",
379
+ "xhigh",
380
+ "max"
381
+ ],
382
+ "supportsSampling": false,
383
+ "costPer1MInput": 10,
384
+ "costPer1MOutput": 50
385
+ },
386
+ {
387
+ "id": "opus-4-8",
388
+ "provider": "anthropic",
389
+ "model": "claude-opus-4-8",
390
+ "displayName": "Claude Opus 4.8",
391
+ "contextWindow": 1000000,
392
+ "maxOutputTokens": 128000,
393
+ "supportsTools": true,
394
+ "supportsImages": true,
395
+ "supportsParallelToolCalls": true,
396
+ "supportsPromptCache": true,
397
+ "thinkingMode": "adaptive",
398
+ "effortLevels": [
399
+ "low",
400
+ "medium",
401
+ "high",
402
+ "xhigh",
403
+ "max"
404
+ ],
405
+ "supportsSampling": false,
406
+ "costPer1MInput": 5,
407
+ "costPer1MOutput": 25
408
+ },
409
+ {
410
+ "id": "sonnet",
411
+ "provider": "anthropic",
412
+ "model": "claude-sonnet-5",
413
+ "displayName": "Claude Sonnet 5",
414
+ "contextWindow": 1000000,
415
+ "maxOutputTokens": 128000,
416
+ "supportsTools": true,
417
+ "supportsImages": true,
418
+ "supportsParallelToolCalls": true,
419
+ "supportsPromptCache": true,
420
+ "thinkingMode": "adaptive",
421
+ "effortLevels": [
422
+ "low",
423
+ "medium",
424
+ "high",
425
+ "xhigh",
426
+ "max"
427
+ ],
428
+ "supportsSampling": false,
429
+ "costPer1MInput": 3,
430
+ "costPer1MOutput": 15
431
+ },
432
+ {
433
+ "id": "sonnet-4-6",
434
+ "provider": "anthropic",
435
+ "model": "claude-sonnet-4-6",
436
+ "displayName": "Claude Sonnet 4.6",
437
+ "contextWindow": 1000000,
438
+ "maxOutputTokens": 128000,
439
+ "supportsTools": true,
440
+ "supportsImages": true,
441
+ "supportsParallelToolCalls": true,
442
+ "supportsPromptCache": true,
443
+ "thinkingMode": "adaptive",
444
+ "effortLevels": [
445
+ "low",
446
+ "medium",
447
+ "high",
448
+ "max"
449
+ ],
450
+ "supportsSampling": true,
451
+ "costPer1MInput": 3,
452
+ "costPer1MOutput": 15
453
+ },
454
+ {
455
+ "id": "haiku",
456
+ "provider": "anthropic",
457
+ "model": "claude-haiku-4-5",
458
+ "displayName": "Claude Haiku 4.5",
459
+ "contextWindow": 200000,
460
+ "maxOutputTokens": 64000,
461
+ "supportsTools": true,
462
+ "supportsImages": true,
463
+ "supportsParallelToolCalls": true,
464
+ "supportsPromptCache": true,
465
+ "thinkingMode": "budget",
466
+ "effortLevels": [],
467
+ "supportsSampling": true,
468
+ "costPer1MInput": 1,
469
+ "costPer1MOutput": 5
470
+ }
471
+ ]
472
+ }
@@ -0,0 +1,16 @@
1
+ import type { AuthResolver } from "../auth/types.ts";
2
+ import type { DiscoveryFormat } from "./catalog.ts";
3
+ import type { ModelSpec } from "./types.ts";
4
+ export interface DiscoveryOptions {
5
+ providerId: string;
6
+ baseUrl: string;
7
+ apiKey?: string;
8
+ headers?: Record<string, string>;
9
+ auth?: AuthResolver;
10
+ /**
11
+ * How to read the payload. OpenRouter publishes capability and pricing
12
+ * metadata worth parsing; most vendors return bare ids.
13
+ */
14
+ format?: DiscoveryFormat;
15
+ }
16
+ export declare function discoverModels(opts: DiscoveryOptions): Promise<ModelSpec[]>;
@@ -0,0 +1,161 @@
1
+ import { ProviderError } from "../core/errors.js";
2
+ import { applyAuthHeaders } from "./types.js";
3
+ /**
4
+ * Model discovery over the `/models` endpoint every OpenAI-compatible vendor
5
+ * implements.
6
+ *
7
+ * This lives outside the wire adapters on purpose. Streaming is pi-ai's job
8
+ * now, but *which models an account may call* is not something a static
9
+ * catalog can answer: aggregators and subscription plans gate models by
10
+ * entitlement, so the roster has to come from the account itself.
11
+ */
12
+ /** How long a `/models` call may take before it is abandoned. */
13
+ const DISCOVERY_TIMEOUT_MS = 15_000;
14
+ /** `modality` values a chat adapter cannot drive, as gateways report them. */
15
+ const NON_CHAT_MODALITIES = new Set([
16
+ "image",
17
+ "video",
18
+ "audio",
19
+ "speech",
20
+ "tts",
21
+ "music",
22
+ "embedding",
23
+ "embeddings",
24
+ "moderation",
25
+ "rerank",
26
+ ]);
27
+ export async function discoverModels(opts) {
28
+ const base = opts.baseUrl.replace(/\/+$/, "");
29
+ const resolved = await opts.auth?.({ providerId: opts.providerId, url: base });
30
+ const headers = applyAuthHeaders({
31
+ ...(opts.apiKey ? { authorization: `Bearer ${opts.apiKey}` } : {}),
32
+ accept: "application/json",
33
+ ...opts.headers,
34
+ }, resolved);
35
+ const response = await fetch(`${resolved?.baseUrl ?? base}/models`, {
36
+ headers,
37
+ // Discovery is a convenience, and a vendor that cannot answer in this long
38
+ // is not going to. Without a deadline a hung connection never rejects, so
39
+ // `catch` never runs and whatever awaited this waits forever — which is
40
+ // exactly how a "saving…" button gets stuck.
41
+ signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS),
42
+ });
43
+ if (!response.ok) {
44
+ throw new ProviderError(opts.providerId, `model listing failed: HTTP ${response.status}`);
45
+ }
46
+ const payload = (await response.json());
47
+ const entries = Array.isArray(payload.data) ? payload.data : [];
48
+ return entries
49
+ .filter((entry) => !!entry && typeof entry === "object")
50
+ .filter((entry) => typeof entry["id"] === "string")
51
+ // Gateways serve image, video and speech models from the same catalog.
52
+ // Registering those as chat models puts entries in `/model` that the chat
53
+ // endpoint can only reject. Named modalities are excluded rather than chat
54
+ // being required: a vendor that calls its chat models something else
55
+ // should lose nothing.
56
+ .filter((entry) => !NON_CHAT_MODALITIES.has(String(entry["modality"] ?? "")))
57
+ .map((entry) => opts.format === "openrouter"
58
+ ? openRouterModel(opts.providerId, entry)
59
+ : bareModel(opts.providerId, entry));
60
+ }
61
+ /**
62
+ * Fallback for vendors whose `/models` returns little more than ids.
63
+ *
64
+ * Optional fields are read when present and ignored when not, so a plain
65
+ * OpenAI-shaped response still lands on the conservative defaults. The one
66
+ * that matters is the context window: assuming 128k for a million-token model
67
+ * makes the harness compact a conversation it never needed to.
68
+ */
69
+ function bareModel(providerId, entry) {
70
+ const id = entry["id"];
71
+ const pricing = asRecord(entry["pricing"]);
72
+ const displayName = entry["display_name"] ?? entry["name"];
73
+ return {
74
+ id: `${providerId}/${id}`,
75
+ provider: providerId,
76
+ model: id,
77
+ displayName: typeof displayName === "string" ? displayName : id,
78
+ contextWindow: asNumber(entry["context_window"] ?? entry["context_length"]) ?? 128_000,
79
+ maxOutputTokens: asNumber(entry["max_output_tokens"]) ?? 8_192,
80
+ supportsTools: true,
81
+ supportsImages: false,
82
+ supportsParallelToolCalls: true,
83
+ supportsPromptCache: false,
84
+ capabilitiesAssumed: true,
85
+ // No capability metadata available, so claim nothing: guessing a reasoning
86
+ // mode here is a 400 waiting to happen.
87
+ thinkingMode: "none",
88
+ effortLevels: [],
89
+ supportsSampling: true,
90
+ // Dollars per million tokens. Distinguished from OpenRouter's
91
+ // dollars-per-token by the key names — `input`/`output` rather than
92
+ // `prompt`/`completion` — since the magnitudes alone would be a guess.
93
+ ...priceFields(asNumber(pricing?.["input"]), asNumber(pricing?.["output"])),
94
+ };
95
+ }
96
+ /**
97
+ * OpenRouter publishes per-model capabilities and pricing, so everything here
98
+ * is derived from the response rather than assumed.
99
+ */
100
+ function openRouterModel(providerId, entry) {
101
+ const id = entry["id"];
102
+ const architecture = asRecord(entry["architecture"]);
103
+ const topProvider = asRecord(entry["top_provider"]);
104
+ const pricing = asRecord(entry["pricing"]);
105
+ const params = Array.isArray(entry["supported_parameters"])
106
+ ? entry["supported_parameters"].filter((p) => typeof p === "string")
107
+ : [];
108
+ const modalities = Array.isArray(architecture?.["input_modalities"])
109
+ ? architecture["input_modalities"]
110
+ : [];
111
+ const supportsReasoning = params.includes("reasoning");
112
+ return {
113
+ id: `${providerId}/${id}`,
114
+ provider: providerId,
115
+ model: id,
116
+ displayName: typeof entry["name"] === "string" ? entry["name"] : id,
117
+ contextWindow: asNumber(topProvider?.["context_length"] ?? entry["context_length"]) ?? 128_000,
118
+ maxOutputTokens: asNumber(topProvider?.["max_completion_tokens"]) ?? 8_192,
119
+ supportsTools: params.includes("tools"),
120
+ supportsImages: modalities.includes("image"),
121
+ // OpenRouter exposes no parallel-call flag; the OpenAI default holds.
122
+ supportsParallelToolCalls: true,
123
+ supportsPromptCache: false,
124
+ thinkingMode: supportsReasoning ? "effort" : "none",
125
+ effortLevels: supportsReasoning ? ["low", "medium", "high"] : [],
126
+ // Absent from supported_parameters means the upstream rejects it.
127
+ supportsSampling: params.includes("temperature"),
128
+ // Pricing is dollars per token, as a string.
129
+ costPer1MInput: perMillion(pricing?.["prompt"]),
130
+ costPer1MOutput: perMillion(pricing?.["completion"]),
131
+ };
132
+ }
133
+ function asRecord(value) {
134
+ return value && typeof value === "object" ? value : undefined;
135
+ }
136
+ function asNumber(value) {
137
+ if (typeof value === "number" && Number.isFinite(value))
138
+ return value;
139
+ if (typeof value === "string") {
140
+ const parsed = Number(value);
141
+ return Number.isFinite(parsed) ? parsed : undefined;
142
+ }
143
+ return undefined;
144
+ }
145
+ /**
146
+ * Only set the cost fields when the vendor actually quoted a price: a spec
147
+ * carrying `costPer1MInput: 0` reads as "free" everywhere downstream, which is
148
+ * a worse answer than "unknown".
149
+ */
150
+ function priceFields(input, output) {
151
+ return {
152
+ ...(input === undefined ? {} : { costPer1MInput: input }),
153
+ ...(output === undefined ? {} : { costPer1MOutput: output }),
154
+ };
155
+ }
156
+ /** Vendors quote per-token dollars; the catalog stores dollars per 1M tokens. */
157
+ function perMillion(value) {
158
+ const parsed = asNumber(value);
159
+ return parsed === undefined ? undefined : parsed * 1_000_000;
160
+ }
161
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/providers/discovery.ts"],"names":[],"mappings":"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"}