@armadra/agent 0.0.0-stage → 0.2.1

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 (407) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +426 -2
  4. package/dist/agent/agent.d.ts +56 -0
  5. package/dist/agent/agent.js +129 -0
  6. package/dist/agent/loop.d.ts +51 -0
  7. package/dist/agent/loop.js +158 -0
  8. package/dist/agent/queue.d.ts +25 -0
  9. package/dist/agent/queue.js +55 -0
  10. package/dist/agent/retry.d.ts +22 -0
  11. package/dist/agent/retry.js +92 -0
  12. package/dist/agent/schema.d.ts +27 -0
  13. package/dist/agent/schema.js +186 -0
  14. package/dist/agent/session-cache.d.ts +100 -0
  15. package/dist/agent/session-cache.js +511 -0
  16. package/dist/agent/session-compaction.d.ts +49 -0
  17. package/dist/agent/session-compaction.js +251 -0
  18. package/dist/agent/session-core.d.ts +103 -0
  19. package/dist/agent/session-core.js +7 -0
  20. package/dist/agent/session-run.d.ts +55 -0
  21. package/dist/agent/session-run.js +246 -0
  22. package/dist/agent/session-state.d.ts +39 -0
  23. package/dist/agent/session-state.js +118 -0
  24. package/dist/agent/session-subagent.d.ts +54 -0
  25. package/dist/agent/session-subagent.js +157 -0
  26. package/dist/agent/session-sync.d.ts +20 -0
  27. package/dist/agent/session-sync.js +104 -0
  28. package/dist/agent/session-tools.d.ts +24 -0
  29. package/dist/agent/session-tools.js +277 -0
  30. package/dist/agent/session.d.ts +117 -0
  31. package/dist/agent/session.js +484 -0
  32. package/dist/agent/system-prompt.d.ts +49 -0
  33. package/dist/agent/system-prompt.js +121 -0
  34. package/dist/agent/tool-runner.d.ts +64 -0
  35. package/dist/agent/tool-runner.js +309 -0
  36. package/dist/agent/transform.d.ts +26 -0
  37. package/dist/agent/transform.js +171 -0
  38. package/dist/agent/types.d.ts +378 -0
  39. package/dist/agent/types.js +21 -0
  40. package/dist/ai/apis/anthropic-messages.d.ts +26 -0
  41. package/dist/ai/apis/anthropic-messages.js +214 -0
  42. package/dist/ai/apis/anthropic-request.d.ts +42 -0
  43. package/dist/ai/apis/anthropic-request.js +282 -0
  44. package/dist/ai/apis/api.d.ts +28 -0
  45. package/dist/ai/apis/api.js +102 -0
  46. package/dist/ai/apis/cache-params.d.ts +48 -0
  47. package/dist/ai/apis/cache-params.js +163 -0
  48. package/dist/ai/apis/google-generative-ai.d.ts +32 -0
  49. package/dist/ai/apis/google-generative-ai.js +249 -0
  50. package/dist/ai/apis/google-request.d.ts +40 -0
  51. package/dist/ai/apis/google-request.js +255 -0
  52. package/dist/ai/apis/openai-compat.d.ts +35 -0
  53. package/dist/ai/apis/openai-compat.js +142 -0
  54. package/dist/ai/apis/openai-completions.d.ts +28 -0
  55. package/dist/ai/apis/openai-completions.js +246 -0
  56. package/dist/ai/apis/openai-request.d.ts +35 -0
  57. package/dist/ai/apis/openai-request.js +303 -0
  58. package/dist/ai/apis/openai-responses-request.d.ts +52 -0
  59. package/dist/ai/apis/openai-responses-request.js +266 -0
  60. package/dist/ai/apis/openai-responses.d.ts +28 -0
  61. package/dist/ai/apis/openai-responses.js +303 -0
  62. package/dist/ai/apis/shared.d.ts +56 -0
  63. package/dist/ai/apis/shared.js +179 -0
  64. package/dist/ai/cache/economics.d.ts +24 -0
  65. package/dist/ai/cache/economics.js +69 -0
  66. package/dist/ai/cache/fingerprint.d.ts +17 -0
  67. package/dist/ai/cache/fingerprint.js +39 -0
  68. package/dist/ai/cache/miss.d.ts +49 -0
  69. package/dist/ai/cache/miss.js +96 -0
  70. package/dist/ai/cache/reporting.d.ts +39 -0
  71. package/dist/ai/cache/reporting.js +102 -0
  72. package/dist/ai/cache/types.d.ts +94 -0
  73. package/dist/ai/cache/types.js +19 -0
  74. package/dist/ai/cache/warmer.d.ts +94 -0
  75. package/dist/ai/cache/warmer.js +224 -0
  76. package/dist/ai/context.d.ts +35 -0
  77. package/dist/ai/context.js +114 -0
  78. package/dist/ai/cost.d.ts +21 -0
  79. package/dist/ai/cost.js +60 -0
  80. package/dist/ai/event-stream.d.ts +33 -0
  81. package/dist/ai/event-stream.js +101 -0
  82. package/dist/ai/fake/fake-provider.d.ts +68 -0
  83. package/dist/ai/fake/fake-provider.js +278 -0
  84. package/dist/ai/fake/fake-script.d.ts +69 -0
  85. package/dist/ai/fake/fake-script.js +142 -0
  86. package/dist/ai/http.d.ts +54 -0
  87. package/dist/ai/http.js +212 -0
  88. package/dist/ai/json-partial.d.ts +17 -0
  89. package/dist/ai/json-partial.js +243 -0
  90. package/dist/ai/overflow.d.ts +22 -0
  91. package/dist/ai/overflow.js +61 -0
  92. package/dist/ai/providers/auth.d.ts +71 -0
  93. package/dist/ai/providers/auth.js +202 -0
  94. package/dist/ai/providers/builtin.d.ts +23 -0
  95. package/dist/ai/providers/builtin.js +148 -0
  96. package/dist/ai/providers/catalog-data.d.ts +5 -0
  97. package/dist/ai/providers/catalog-data.js +19 -0
  98. package/dist/ai/providers/catalog.d.ts +28 -0
  99. package/dist/ai/providers/catalog.js +166 -0
  100. package/dist/ai/providers/registry.d.ts +83 -0
  101. package/dist/ai/providers/registry.js +305 -0
  102. package/dist/ai/sse.d.ts +32 -0
  103. package/dist/ai/sse.js +140 -0
  104. package/dist/ai/thinking.d.ts +42 -0
  105. package/dist/ai/thinking.js +101 -0
  106. package/dist/ai/types.d.ts +428 -0
  107. package/dist/ai/types.js +19 -0
  108. package/dist/bundle/ama-sandbox.cjs +324 -0
  109. package/dist/bundle/ama.cjs +25770 -0
  110. package/dist/bundle.d.ts +9 -0
  111. package/dist/bundle.js +15 -0
  112. package/dist/cli/args.d.ts +82 -0
  113. package/dist/cli/args.js +381 -0
  114. package/dist/cli/bootstrap.d.ts +18 -0
  115. package/dist/cli/bootstrap.js +398 -0
  116. package/dist/cli/compose-providers.d.ts +37 -0
  117. package/dist/cli/compose-providers.js +104 -0
  118. package/dist/cli/compose-session.d.ts +69 -0
  119. package/dist/cli/compose-session.js +370 -0
  120. package/dist/cli/compose-store.d.ts +24 -0
  121. package/dist/cli/compose-store.js +125 -0
  122. package/dist/cli/compose.d.ts +106 -0
  123. package/dist/cli/compose.js +206 -0
  124. package/dist/cli/default-model.d.ts +16 -0
  125. package/dist/cli/default-model.js +24 -0
  126. package/dist/cli/deps.d.ts +205 -0
  127. package/dist/cli/deps.js +12 -0
  128. package/dist/cli/exit-codes.d.ts +29 -0
  129. package/dist/cli/exit-codes.js +40 -0
  130. package/dist/cli/main.d.ts +26 -0
  131. package/dist/cli/main.js +165 -0
  132. package/dist/cli/runtime.d.ts +90 -0
  133. package/dist/cli/runtime.js +8 -0
  134. package/dist/cli/startup-screen.d.ts +15 -0
  135. package/dist/cli/startup-screen.js +56 -0
  136. package/dist/cli/startup-steps.d.ts +35 -0
  137. package/dist/cli/startup-steps.js +197 -0
  138. package/dist/cli/subcommands/auth.d.ts +12 -0
  139. package/dist/cli/subcommands/auth.js +91 -0
  140. package/dist/cli/subcommands/config.d.ts +44 -0
  141. package/dist/cli/subcommands/config.js +201 -0
  142. package/dist/cli/subcommands/context.d.ts +21 -0
  143. package/dist/cli/subcommands/context.js +41 -0
  144. package/dist/cli/subcommands/doctor.d.ts +11 -0
  145. package/dist/cli/subcommands/doctor.js +246 -0
  146. package/dist/cli/subcommands/models-cache-probe.d.ts +34 -0
  147. package/dist/cli/subcommands/models-cache-probe.js +190 -0
  148. package/dist/cli/subcommands/models-discover.d.ts +40 -0
  149. package/dist/cli/subcommands/models-discover.js +204 -0
  150. package/dist/cli/subcommands/models.d.ts +40 -0
  151. package/dist/cli/subcommands/models.js +144 -0
  152. package/dist/cli/subcommands/sessions.d.ts +11 -0
  153. package/dist/cli/subcommands/sessions.js +100 -0
  154. package/dist/codemode/capability.d.ts +37 -0
  155. package/dist/codemode/capability.js +55 -0
  156. package/dist/codemode/declarations.d.ts +44 -0
  157. package/dist/codemode/declarations.js +111 -0
  158. package/dist/codemode/host-side.d.ts +59 -0
  159. package/dist/codemode/host-side.js +253 -0
  160. package/dist/codemode/modes.d.ts +23 -0
  161. package/dist/codemode/modes.js +40 -0
  162. package/dist/codemode/protocol.d.ts +91 -0
  163. package/dist/codemode/protocol.js +114 -0
  164. package/dist/codemode/sandbox-entry.d.ts +25 -0
  165. package/dist/codemode/sandbox-entry.js +323 -0
  166. package/dist/codemode/store.d.ts +26 -0
  167. package/dist/codemode/store.js +53 -0
  168. package/dist/codemode/tool.d.ts +105 -0
  169. package/dist/codemode/tool.js +283 -0
  170. package/dist/compaction/branch-summary.d.ts +30 -0
  171. package/dist/compaction/branch-summary.js +79 -0
  172. package/dist/compaction/breaker.d.ts +32 -0
  173. package/dist/compaction/breaker.js +65 -0
  174. package/dist/compaction/cut-point.d.ts +23 -0
  175. package/dist/compaction/cut-point.js +70 -0
  176. package/dist/compaction/estimate.d.ts +30 -0
  177. package/dist/compaction/estimate.js +114 -0
  178. package/dist/compaction/prune-tier.d.ts +31 -0
  179. package/dist/compaction/prune-tier.js +83 -0
  180. package/dist/compaction/serialize.d.ts +20 -0
  181. package/dist/compaction/serialize.js +115 -0
  182. package/dist/compaction/summarize-tier.d.ts +111 -0
  183. package/dist/compaction/summarize-tier.js +305 -0
  184. package/dist/config/auth-file.d.ts +39 -0
  185. package/dist/config/auth-file.js +92 -0
  186. package/dist/config/context-files.d.ts +30 -0
  187. package/dist/config/context-files.js +77 -0
  188. package/dist/config/load.d.ts +45 -0
  189. package/dist/config/load.js +97 -0
  190. package/dist/config/merge.d.ts +73 -0
  191. package/dist/config/merge.js +248 -0
  192. package/dist/config/paths.d.ts +38 -0
  193. package/dist/config/paths.js +108 -0
  194. package/dist/config/profile.d.ts +27 -0
  195. package/dist/config/profile.js +65 -0
  196. package/dist/config/schema.d.ts +34 -0
  197. package/dist/config/schema.js +413 -0
  198. package/dist/config/trust.d.ts +42 -0
  199. package/dist/config/trust.js +122 -0
  200. package/dist/config/types.d.ts +172 -0
  201. package/dist/config/types.js +27 -0
  202. package/dist/config/write.d.ts +10 -0
  203. package/dist/config/write.js +25 -0
  204. package/dist/errors.d.ts +28 -0
  205. package/dist/errors.js +30 -0
  206. package/dist/hooks/config.d.ts +49 -0
  207. package/dist/hooks/config.js +102 -0
  208. package/dist/hooks/dispatcher.d.ts +41 -0
  209. package/dist/hooks/dispatcher.js +104 -0
  210. package/dist/hooks/matcher.d.ts +22 -0
  211. package/dist/hooks/matcher.js +108 -0
  212. package/dist/hooks/protocol.d.ts +33 -0
  213. package/dist/hooks/protocol.js +240 -0
  214. package/dist/hooks/runner.d.ts +30 -0
  215. package/dist/hooks/runner.js +143 -0
  216. package/dist/hooks/types.d.ts +147 -0
  217. package/dist/hooks/types.js +20 -0
  218. package/dist/host/api-impl.d.ts +75 -0
  219. package/dist/host/api-impl.js +173 -0
  220. package/dist/host/loader.d.ts +31 -0
  221. package/dist/host/loader.js +147 -0
  222. package/dist/host/types.d.ts +169 -0
  223. package/dist/host/types.js +14 -0
  224. package/dist/host.d.ts +5 -0
  225. package/dist/host.js +4 -0
  226. package/dist/index.d.ts +41 -0
  227. package/dist/index.js +28 -0
  228. package/dist/modes/commands-core.d.ts +44 -0
  229. package/dist/modes/commands-core.js +171 -0
  230. package/dist/modes/interactive/approval-dialog.d.ts +48 -0
  231. package/dist/modes/interactive/approval-dialog.js +202 -0
  232. package/dist/modes/interactive/commands.d.ts +41 -0
  233. package/dist/modes/interactive/commands.js +202 -0
  234. package/dist/modes/interactive/completion.d.ts +53 -0
  235. package/dist/modes/interactive/completion.js +157 -0
  236. package/dist/modes/interactive/interactive-mode.d.ts +46 -0
  237. package/dist/modes/interactive/interactive-mode.js +487 -0
  238. package/dist/modes/interactive/key-dispatch.d.ts +29 -0
  239. package/dist/modes/interactive/key-dispatch.js +107 -0
  240. package/dist/modes/interactive/line/line-editor.d.ts +50 -0
  241. package/dist/modes/interactive/line/line-editor.js +232 -0
  242. package/dist/modes/interactive/line/line-mode.d.ts +20 -0
  243. package/dist/modes/interactive/line/line-mode.js +216 -0
  244. package/dist/modes/interactive/line/line-render.d.ts +35 -0
  245. package/dist/modes/interactive/line/line-render.js +171 -0
  246. package/dist/modes/interactive/line/paste-state.d.ts +26 -0
  247. package/dist/modes/interactive/line/paste-state.js +72 -0
  248. package/dist/modes/interactive/message-view.d.ts +77 -0
  249. package/dist/modes/interactive/message-view.js +269 -0
  250. package/dist/modes/interactive/pickers.d.ts +42 -0
  251. package/dist/modes/interactive/pickers.js +115 -0
  252. package/dist/modes/interactive/startup-ui.d.ts +28 -0
  253. package/dist/modes/interactive/startup-ui.js +238 -0
  254. package/dist/modes/interactive/status-bar.d.ts +48 -0
  255. package/dist/modes/interactive/status-bar.js +139 -0
  256. package/dist/modes/interactive/tool-view.d.ts +95 -0
  257. package/dist/modes/interactive/tool-view.js +344 -0
  258. package/dist/modes/print/json-event.d.ts +15 -0
  259. package/dist/modes/print/json-event.js +39 -0
  260. package/dist/modes/print/print-mode.d.ts +15 -0
  261. package/dist/modes/print/print-mode.js +96 -0
  262. package/dist/modes/rpc/commands.d.ts +40 -0
  263. package/dist/modes/rpc/commands.js +258 -0
  264. package/dist/modes/rpc/jsonl.d.ts +16 -0
  265. package/dist/modes/rpc/jsonl.js +55 -0
  266. package/dist/modes/rpc/rpc-mode.d.ts +22 -0
  267. package/dist/modes/rpc/rpc-mode.js +153 -0
  268. package/dist/modes/session-report.d.ts +55 -0
  269. package/dist/modes/session-report.js +278 -0
  270. package/dist/modes/shared.d.ts +13 -0
  271. package/dist/modes/shared.js +52 -0
  272. package/dist/modes/startup-ui-text.d.ts +16 -0
  273. package/dist/modes/startup-ui-text.js +103 -0
  274. package/dist/permissions/broker.d.ts +47 -0
  275. package/dist/permissions/broker.js +107 -0
  276. package/dist/permissions/dangerous.d.ts +47 -0
  277. package/dist/permissions/dangerous.js +370 -0
  278. package/dist/permissions/pipeline.d.ts +51 -0
  279. package/dist/permissions/pipeline.js +181 -0
  280. package/dist/permissions/preview.d.ts +43 -0
  281. package/dist/permissions/preview.js +463 -0
  282. package/dist/permissions/rules.d.ts +58 -0
  283. package/dist/permissions/rules.js +249 -0
  284. package/dist/permissions/types.d.ts +100 -0
  285. package/dist/permissions/types.js +18 -0
  286. package/dist/rpc.d.ts +171 -0
  287. package/dist/rpc.js +13 -0
  288. package/dist/sdk.d.ts +98 -0
  289. package/dist/sdk.js +195 -0
  290. package/dist/session/manager.d.ts +70 -0
  291. package/dist/session/manager.js +278 -0
  292. package/dist/session/migrate.d.ts +19 -0
  293. package/dist/session/migrate.js +53 -0
  294. package/dist/session/projection.d.ts +50 -0
  295. package/dist/session/projection.js +180 -0
  296. package/dist/session/store.d.ts +47 -0
  297. package/dist/session/store.js +210 -0
  298. package/dist/session/tree.d.ts +21 -0
  299. package/dist/session/tree.js +88 -0
  300. package/dist/session/types.d.ts +199 -0
  301. package/dist/session/types.js +18 -0
  302. package/dist/skills/discover.d.ts +60 -0
  303. package/dist/skills/discover.js +160 -0
  304. package/dist/skills/expand.d.ts +35 -0
  305. package/dist/skills/expand.js +46 -0
  306. package/dist/skills/frontmatter.d.ts +27 -0
  307. package/dist/skills/frontmatter.js +157 -0
  308. package/dist/skills/index-prompt.d.ts +13 -0
  309. package/dist/skills/index-prompt.js +42 -0
  310. package/dist/skills/templates.d.ts +52 -0
  311. package/dist/skills/templates.js +177 -0
  312. package/dist/tools/bash.d.ts +49 -0
  313. package/dist/tools/bash.js +222 -0
  314. package/dist/tools/edit-fuzzy.d.ts +36 -0
  315. package/dist/tools/edit-fuzzy.js +129 -0
  316. package/dist/tools/edit.d.ts +38 -0
  317. package/dist/tools/edit.js +241 -0
  318. package/dist/tools/file-mutex.d.ts +8 -0
  319. package/dist/tools/file-mutex.js +29 -0
  320. package/dist/tools/glob.d.ts +44 -0
  321. package/dist/tools/glob.js +217 -0
  322. package/dist/tools/grep.d.ts +39 -0
  323. package/dist/tools/grep.js +179 -0
  324. package/dist/tools/ignore.d.ts +40 -0
  325. package/dist/tools/ignore.js +174 -0
  326. package/dist/tools/ls.d.ts +21 -0
  327. package/dist/tools/ls.js +96 -0
  328. package/dist/tools/output-accumulator.d.ts +48 -0
  329. package/dist/tools/output-accumulator.js +106 -0
  330. package/dist/tools/paths.d.ts +20 -0
  331. package/dist/tools/paths.js +58 -0
  332. package/dist/tools/presets.d.ts +71 -0
  333. package/dist/tools/presets.js +128 -0
  334. package/dist/tools/process-tree.d.ts +35 -0
  335. package/dist/tools/process-tree.js +125 -0
  336. package/dist/tools/read.d.ts +28 -0
  337. package/dist/tools/read.js +181 -0
  338. package/dist/tools/registry.d.ts +43 -0
  339. package/dist/tools/registry.js +106 -0
  340. package/dist/tools/shell.d.ts +38 -0
  341. package/dist/tools/shell.js +91 -0
  342. package/dist/tools/task.d.ts +29 -0
  343. package/dist/tools/task.js +107 -0
  344. package/dist/tools/todo.d.ts +28 -0
  345. package/dist/tools/todo.js +107 -0
  346. package/dist/tools/truncate.d.ts +44 -0
  347. package/dist/tools/truncate.js +175 -0
  348. package/dist/tools/types.d.ts +135 -0
  349. package/dist/tools/types.js +19 -0
  350. package/dist/tools/write.d.ts +20 -0
  351. package/dist/tools/write.js +84 -0
  352. package/dist/tui/ansi.d.ts +29 -0
  353. package/dist/tui/ansi.js +420 -0
  354. package/dist/tui/component.d.ts +38 -0
  355. package/dist/tui/component.js +13 -0
  356. package/dist/tui/components/box.d.ts +26 -0
  357. package/dist/tui/components/box.js +65 -0
  358. package/dist/tui/components/container.d.ts +14 -0
  359. package/dist/tui/components/container.js +39 -0
  360. package/dist/tui/components/editor-buffer.d.ts +67 -0
  361. package/dist/tui/components/editor-buffer.js +300 -0
  362. package/dist/tui/components/editor-paste.d.ts +29 -0
  363. package/dist/tui/components/editor-paste.js +64 -0
  364. package/dist/tui/components/editor.d.ts +114 -0
  365. package/dist/tui/components/editor.js +530 -0
  366. package/dist/tui/components/key-value.d.ts +29 -0
  367. package/dist/tui/components/key-value.js +48 -0
  368. package/dist/tui/components/loader.d.ts +35 -0
  369. package/dist/tui/components/loader.js +71 -0
  370. package/dist/tui/components/markdown.d.ts +90 -0
  371. package/dist/tui/components/markdown.js +462 -0
  372. package/dist/tui/components/meter.d.ts +29 -0
  373. package/dist/tui/components/meter.js +47 -0
  374. package/dist/tui/components/overlay.d.ts +24 -0
  375. package/dist/tui/components/overlay.js +52 -0
  376. package/dist/tui/components/select-list.d.ts +57 -0
  377. package/dist/tui/components/select-list.js +179 -0
  378. package/dist/tui/components/spacer.d.ts +11 -0
  379. package/dist/tui/components/spacer.js +16 -0
  380. package/dist/tui/components/text.d.ts +30 -0
  381. package/dist/tui/components/text.js +65 -0
  382. package/dist/tui/keybindings.d.ts +66 -0
  383. package/dist/tui/keybindings.js +120 -0
  384. package/dist/tui/keys.d.ts +38 -0
  385. package/dist/tui/keys.js +275 -0
  386. package/dist/tui/stdin-buffer.d.ts +41 -0
  387. package/dist/tui/stdin-buffer.js +206 -0
  388. package/dist/tui/terminal.d.ts +79 -0
  389. package/dist/tui/terminal.js +153 -0
  390. package/dist/tui/theme.d.ts +31 -0
  391. package/dist/tui/theme.js +199 -0
  392. package/dist/tui/tui.d.ts +103 -0
  393. package/dist/tui/tui.js +363 -0
  394. package/dist/tui/vt-screen.d.ts +46 -0
  395. package/dist/tui/vt-screen.js +251 -0
  396. package/dist/tui.d.ts +30 -0
  397. package/dist/tui.js +31 -0
  398. package/dist/version.d.ts +8 -0
  399. package/dist/version.js +24 -0
  400. package/docs/codemode.md +102 -0
  401. package/docs/hooks.md +196 -0
  402. package/docs/host-api.md +161 -0
  403. package/docs/providers.md +316 -0
  404. package/docs/rpc.md +253 -0
  405. package/docs/session-format.md +119 -0
  406. package/docs/tui.md +168 -0
  407. package/package.json +101 -4
@@ -0,0 +1,142 @@
1
+ /**
2
+ * OpenAI 兼容线的 compat 推断(设计 §3.3)。
3
+ *
4
+ * 顺序:保守缺省 ← 推断表(先按 provider id,再按 baseUrl 子串)← `provider.compat` ←
5
+ * `model.compat`(字段级覆盖,undefined 不覆盖)。显式配置永远胜过推断。
6
+ *
7
+ * 缺省是「最保守的 OpenAI 兼容服务」:`max_tokens`、`system` 角色、不发 `store` /
8
+ * `reasoning_effort` / `strict`。只有 OpenAI 官方端点打开 OpenAI 专有开关。
9
+ * 表里每一项都应对应一个已验证的差异(文档或真实样本);没验证过的不要加。
10
+ */
11
+ export const OPENAI_COMPAT_KEYS = [
12
+ "maxTokensField",
13
+ "supportsDeveloperRole",
14
+ "supportsUsageInStreaming",
15
+ "supportsFinishReason",
16
+ "supportsReasoningEffort",
17
+ "thinkingFormat",
18
+ "thinkingTokenBudgetField",
19
+ "requiresReasoningContentOnAssistantMessages",
20
+ "requiresToolResultName",
21
+ "requiresAssistantAfterToolResult",
22
+ "supportsMidConvoSystemMessages",
23
+ "cacheControlFormat",
24
+ "supportsStrictTools",
25
+ "supportsStore",
26
+ ];
27
+ export const CONSERVATIVE_COMPAT = {
28
+ maxTokensField: "max_tokens",
29
+ supportsDeveloperRole: false,
30
+ supportsUsageInStreaming: true,
31
+ supportsFinishReason: true,
32
+ supportsReasoningEffort: false,
33
+ thinkingFormat: "openai",
34
+ requiresReasoningContentOnAssistantMessages: false,
35
+ requiresToolResultName: false,
36
+ requiresAssistantAfterToolResult: false,
37
+ supportsMidConvoSystemMessages: false,
38
+ cacheControlFormat: "none",
39
+ supportsStrictTools: false,
40
+ supportsStore: false,
41
+ };
42
+ /** 推断表:13 家内置里走 OpenAI 兼容线的 11 家(anthropic / google 不走本协议)。 */
43
+ export const INFERENCE_RULES = [
44
+ {
45
+ provider: "openai",
46
+ baseUrl: "api.openai.com",
47
+ patch: () => ({
48
+ maxTokensField: "max_completion_tokens",
49
+ supportsDeveloperRole: true,
50
+ supportsReasoningEffort: true,
51
+ supportsStrictTools: true,
52
+ supportsStore: true,
53
+ }),
54
+ },
55
+ {
56
+ provider: "deepseek",
57
+ baseUrl: "deepseek.com",
58
+ patch: () => ({
59
+ supportsReasoningEffort: true,
60
+ thinkingFormat: "deepseek",
61
+ requiresReasoningContentOnAssistantMessages: true,
62
+ }),
63
+ },
64
+ {
65
+ provider: "moonshot",
66
+ baseUrl: "moonshot.",
67
+ patch: () => ({ thinkingFormat: "deepseek", supportsMidConvoSystemMessages: true }),
68
+ },
69
+ { provider: "zhipu", baseUrl: "bigmodel.cn", patch: () => ({ thinkingFormat: "zai" }) },
70
+ {
71
+ provider: "dashscope",
72
+ baseUrl: "dashscope",
73
+ patch: () => ({ thinkingFormat: "qwen", thinkingTokenBudgetField: "thinking_budget" }),
74
+ },
75
+ {
76
+ provider: "openrouter",
77
+ baseUrl: "openrouter.ai",
78
+ patch: (modelId) => ({
79
+ maxTokensField: "max_completion_tokens",
80
+ supportsReasoningEffort: true,
81
+ thinkingFormat: "openrouter",
82
+ supportsDeveloperRole: modelId.startsWith("openai/") || modelId.startsWith("anthropic/"),
83
+ cacheControlFormat: modelId.startsWith("anthropic/") ? "anthropic" : "none",
84
+ }),
85
+ },
86
+ {
87
+ provider: "groq",
88
+ baseUrl: "groq.com",
89
+ patch: () => ({
90
+ maxTokensField: "max_completion_tokens",
91
+ supportsDeveloperRole: true,
92
+ supportsReasoningEffort: true,
93
+ }),
94
+ },
95
+ {
96
+ provider: "xai",
97
+ baseUrl: "api.x.ai",
98
+ patch: () => ({ maxTokensField: "max_completion_tokens", supportsReasoningEffort: true }),
99
+ },
100
+ {
101
+ provider: "mistral",
102
+ baseUrl: "mistral.ai",
103
+ patch: () => ({ thinkingFormat: "none", requiresToolResultName: true }),
104
+ },
105
+ { provider: "ollama", baseUrl: ":11434", patch: () => ({}) },
106
+ { provider: "lmstudio", baseUrl: ":1234", patch: () => ({}) },
107
+ ];
108
+ /** 命中的推断规则(先 provider id,后 baseUrl 子串)。 */
109
+ export function findInferenceRule(providerId, baseUrl) {
110
+ return (INFERENCE_RULES.find((rule) => rule.provider === providerId) ??
111
+ INFERENCE_RULES.find((rule) => baseUrl.toLowerCase().includes(rule.baseUrl)));
112
+ }
113
+ /** 从 ProviderCompat 里挑出本协议的字段(undefined 跳过)。 */
114
+ export function pickOpenAICompat(compat) {
115
+ const out = {};
116
+ if (!compat)
117
+ return out;
118
+ for (const key of OPENAI_COMPAT_KEYS) {
119
+ const value = compat[key];
120
+ if (value !== undefined)
121
+ out[key] = value;
122
+ }
123
+ return out;
124
+ }
125
+ /** 推断(不含显式配置)。 */
126
+ export function inferOpenAICompat(providerId, baseUrl, modelId) {
127
+ const rule = findInferenceRule(providerId, baseUrl);
128
+ return { ...CONSERVATIVE_COMPAT, ...(rule ? rule.patch(modelId) : {}) };
129
+ }
130
+ /**
131
+ * 完整 compat:推断 ← provider.compat ← model.compat。`provider` 缺省时只用 model
132
+ * 自带信息(registry 物化后的模型已把 provider.compat 合进 model.compat)。
133
+ */
134
+ export function detectCompat(model, provider) {
135
+ const providerId = provider?.id ?? model.provider;
136
+ const baseUrl = model.baseUrl ?? provider?.baseUrl ?? "";
137
+ return {
138
+ ...inferOpenAICompat(providerId, baseUrl, model.id),
139
+ ...pickOpenAICompat(provider?.compat),
140
+ ...pickOpenAICompat(model.compat),
141
+ };
142
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * openai-completions 协议(设计 §3.1、§3.3):POST `{baseUrl}/chat/completions`(stream),
3
+ * `data:` 块 → 事件,`data: [DONE]` 结束。
4
+ *
5
+ * - 文本:`delta.content`;思考:`delta.reasoning_content` / `reasoning` / `reasoning_text`
6
+ * 取第一个非空字段,字段名记进 `thinkingSignature`(回放时放回同名字段);
7
+ * - 工具调用增量按 `index` 拼接;缺 index 按 `id`;两者都缺则续到最近一个工具调用;
8
+ * - usage 三个位置:`chunk.usage`(标准)、`chunk.x_groq.usage`(Groq)、`choices[0].usage`
9
+ * (Moonshot);缓存命中三种字段:`prompt_tokens_details.cached_tokens`(OpenAI /
10
+ * OpenRouter)、`prompt_cache_hit_tokens`(DeepSeek)、顶层 `cached_tokens`(Moonshot);任一缓存
11
+ * 字段出现(含 0)即 `cacheReported: true`,都没有为 false(第三波 §1.6);
12
+ * - 结束证据是 finish_reason 或 `[DONE]`;两者都没有 → 断流错误。finish_reason 为 stop 但
13
+ * 有工具调用时按 toolUse(部分本地服务如此返回);`supportsFinishReason: false` 时完全按
14
+ * 内容推断。
15
+ */
16
+ import type { ApiImplementation, OpenAICompletionsCompat, Usage } from "../types.js";
17
+ type Json = Record<string, unknown>;
18
+ /** OpenAI 兼容 usage → Usage(input 去掉缓存部分)。 */
19
+ export declare function parseOpenAIUsage(raw: Json): Usage;
20
+ type MappedFinish = {
21
+ reason: "stop" | "length" | "toolUse";
22
+ } | {
23
+ reason: "error";
24
+ message: string;
25
+ };
26
+ export declare function mapFinishReason(raw: string): MappedFinish;
27
+ export declare const openAICompletionsApi: ApiImplementation<OpenAICompletionsCompat>;
28
+ export {};
@@ -0,0 +1,246 @@
1
+ /**
2
+ * openai-completions 协议(设计 §3.1、§3.3):POST `{baseUrl}/chat/completions`(stream),
3
+ * `data:` 块 → 事件,`data: [DONE]` 结束。
4
+ *
5
+ * - 文本:`delta.content`;思考:`delta.reasoning_content` / `reasoning` / `reasoning_text`
6
+ * 取第一个非空字段,字段名记进 `thinkingSignature`(回放时放回同名字段);
7
+ * - 工具调用增量按 `index` 拼接;缺 index 按 `id`;两者都缺则续到最近一个工具调用;
8
+ * - usage 三个位置:`chunk.usage`(标准)、`chunk.x_groq.usage`(Groq)、`choices[0].usage`
9
+ * (Moonshot);缓存命中三种字段:`prompt_tokens_details.cached_tokens`(OpenAI /
10
+ * OpenRouter)、`prompt_cache_hit_tokens`(DeepSeek)、顶层 `cached_tokens`(Moonshot);任一缓存
11
+ * 字段出现(含 0)即 `cacheReported: true`,都没有为 false(第三波 §1.6);
12
+ * - 结束证据是 finish_reason 或 `[DONE]`;两者都没有 → 断流错误。finish_reason 为 stop 但
13
+ * 有工具调用时按 toolUse(部分本地服务如此返回);`supportsFinishReason: false` 时完全按
14
+ * 内容推断。
15
+ */
16
+ import { AssistantEventStreamImpl } from "../event-stream.js";
17
+ import { USER_AGENT, authHeaders, describeErrorJson, joinUrl, mergeHeaders } from "../http.js";
18
+ import { readSseEvents } from "../sse.js";
19
+ import { affinityHeaders, postWithCacheFallback, resolveCacheRetention } from "./cache-params.js";
20
+ import { detectCompat } from "./openai-compat.js";
21
+ import { REASONING_FIELDS, buildOpenAIRequest } from "./openai-request.js";
22
+ import { BlockTracker, STREAM_ENDED_MESSAGE, ProviderStopError, createOutput, finishDone, finishError, requireApiKey, } from "./shared.js";
23
+ function num(value) {
24
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
25
+ }
26
+ function obj(value) {
27
+ return typeof value === "object" && value !== null && !Array.isArray(value)
28
+ ? value
29
+ : undefined;
30
+ }
31
+ function str(value) {
32
+ return typeof value === "string" ? value : undefined;
33
+ }
34
+ /** OpenAI 兼容 usage → Usage(input 去掉缓存部分)。 */
35
+ export function parseOpenAIUsage(raw) {
36
+ const prompt = num(raw["prompt_tokens"]) ?? 0;
37
+ const details = obj(raw["prompt_tokens_details"]);
38
+ const cacheRead = num(details?.["cached_tokens"]) ??
39
+ num(raw["prompt_cache_hit_tokens"]) ??
40
+ num(raw["cached_tokens"]) ??
41
+ 0;
42
+ const cacheWrite = num(details?.["cache_write_tokens"]) ?? 0;
43
+ const output = num(raw["completion_tokens"]) ?? 0;
44
+ const cacheFields = [
45
+ details?.["cached_tokens"],
46
+ details?.["cache_write_tokens"],
47
+ raw["prompt_cache_hit_tokens"],
48
+ raw["prompt_cache_miss_tokens"],
49
+ raw["cached_tokens"],
50
+ ];
51
+ const usage = {
52
+ input: Math.max(0, prompt - cacheRead - cacheWrite),
53
+ output,
54
+ cacheRead,
55
+ cacheWrite,
56
+ totalTokens: 0,
57
+ cacheReported: cacheFields.some((value) => num(value) !== undefined),
58
+ };
59
+ const reasoning = num(obj(raw["completion_tokens_details"])?.["reasoning_tokens"]);
60
+ if (reasoning !== undefined)
61
+ usage.reasoning = reasoning;
62
+ return usage;
63
+ }
64
+ const ERROR_FINISH = new Set([
65
+ "content_filter",
66
+ "network_error",
67
+ "sensitive",
68
+ "model_context_window_exceeded",
69
+ ]);
70
+ export function mapFinishReason(raw) {
71
+ if (raw === "length")
72
+ return { reason: "length" };
73
+ if (raw === "tool_calls" || raw === "function_call")
74
+ return { reason: "toolUse" };
75
+ if (ERROR_FINISH.has(raw))
76
+ return { reason: "error", message: `Provider finish_reason: ${raw}` };
77
+ return { reason: "stop" };
78
+ }
79
+ function closeProse(state, tracker) {
80
+ if (state.text !== undefined)
81
+ tracker.end(state.text);
82
+ if (state.thinking !== undefined)
83
+ tracker.end(state.thinking);
84
+ state.text = undefined;
85
+ state.thinking = undefined;
86
+ }
87
+ function handleToolCalls(calls, state, tracker) {
88
+ closeProse(state, tracker);
89
+ for (const raw of calls) {
90
+ const call = obj(raw);
91
+ if (!call)
92
+ continue;
93
+ const streamIndex = num(call["index"]);
94
+ const id = str(call["id"]) || undefined;
95
+ const fn = obj(call["function"]);
96
+ const name = str(fn?.["name"]) || undefined;
97
+ let target = streamIndex !== undefined ? state.toolsByIndex.get(streamIndex) : undefined;
98
+ if (target === undefined && id)
99
+ target = state.toolsById.get(id);
100
+ if (target === undefined && streamIndex === undefined && !id)
101
+ target = state.lastTool;
102
+ if (target === undefined || !tracker.isOpen(target)) {
103
+ const generated = `call_${tracker.output.content.length}_${Date.now().toString(36)}`;
104
+ target = tracker.startToolCall(id ?? generated, name ?? "");
105
+ }
106
+ const block = tracker.toolCallBlock(target);
107
+ if (block && id && block.id !== id && !state.toolsById.has(block.id))
108
+ block.id = id;
109
+ if (block && name && !block.name)
110
+ block.name = name;
111
+ if (streamIndex !== undefined)
112
+ state.toolsByIndex.set(streamIndex, target);
113
+ if (id)
114
+ state.toolsById.set(id, target);
115
+ state.lastTool = target;
116
+ const args = str(fn?.["arguments"]);
117
+ if (args)
118
+ tracker.appendToolArgs(target, args);
119
+ }
120
+ }
121
+ function handleChunk(chunk, state, tracker) {
122
+ if (chunk["error"] !== undefined) {
123
+ throw new Error(describeErrorJson(chunk) ?? JSON.stringify(chunk["error"]));
124
+ }
125
+ const output = tracker.output;
126
+ const id = str(chunk["id"]);
127
+ if (id && !output.responseId)
128
+ output.responseId = id;
129
+ const choices = Array.isArray(chunk["choices"]) ? chunk["choices"] : [];
130
+ const choice = obj(choices[0]);
131
+ const rawUsage = obj(chunk["usage"]) ?? obj(obj(chunk["x_groq"])?.["usage"]) ?? obj(choice?.["usage"]);
132
+ if (rawUsage)
133
+ output.usage = parseOpenAIUsage(rawUsage);
134
+ if (!choice)
135
+ return;
136
+ const delta = obj(choice["delta"]);
137
+ if (delta) {
138
+ const field = REASONING_FIELDS.find((name) => {
139
+ const value = delta[name];
140
+ return typeof value === "string" && value.length > 0;
141
+ });
142
+ if (field) {
143
+ if (state.text !== undefined) {
144
+ tracker.end(state.text);
145
+ state.text = undefined;
146
+ }
147
+ state.thinking ??= tracker.startThinking("", field);
148
+ tracker.appendThinking(state.thinking, delta[field]);
149
+ }
150
+ const content = str(delta["content"]);
151
+ if (content) {
152
+ if (state.thinking !== undefined) {
153
+ tracker.end(state.thinking);
154
+ state.thinking = undefined;
155
+ }
156
+ state.text ??= tracker.startText();
157
+ tracker.appendText(state.text, content);
158
+ }
159
+ if (Array.isArray(delta["tool_calls"]))
160
+ handleToolCalls(delta["tool_calls"], state, tracker);
161
+ }
162
+ const finish = str(choice["finish_reason"]);
163
+ if (finish) {
164
+ state.finish = finish;
165
+ output.rawStopReason = finish;
166
+ }
167
+ }
168
+ function resolveStop(state, compat, hasToolCalls) {
169
+ const inferred = { reason: hasToolCalls ? "toolUse" : "stop" };
170
+ if (!compat.supportsFinishReason || state.finish === undefined)
171
+ return inferred;
172
+ const mapped = mapFinishReason(state.finish);
173
+ return mapped.reason === "stop" && hasToolCalls ? inferred : mapped;
174
+ }
175
+ function buildHeaders(model, options) {
176
+ return mergeHeaders({ "content-type": "application/json", accept: "text/event-stream", "user-agent": USER_AGENT }, authHeaders(options.apiKey, model.authHeader, "authorization-bearer"), affinityHeaders(model, "openai-completions", options.sessionId, resolveCacheRetention(options.cacheRetention)), model.headers, options.headers);
177
+ }
178
+ async function run(stream, model, context, options) {
179
+ const tracker = new BlockTracker(stream, createOutput(model));
180
+ try {
181
+ const request = buildOpenAIRequest(model, context, options);
182
+ tracker.output.thinkingLevel = request.thinkingLevel;
183
+ if (request.providerThinkingLevel !== undefined) {
184
+ tracker.output.providerThinkingLevel = request.providerThinkingLevel;
185
+ }
186
+ const replaced = options.onPayload?.(request.body);
187
+ const baseUrl = model.baseUrl ?? "https://api.openai.com/v1";
188
+ const response = await postWithCacheFallback(model, joinUrl(baseUrl, "/chat/completions"), {
189
+ headers: buildHeaders(model, options),
190
+ body: replaced === undefined ? request.body : replaced,
191
+ signal: options.signal,
192
+ timeoutMs: options.timeoutMs,
193
+ onResponse: options.onResponse,
194
+ });
195
+ stream.push({ type: "start", partial: tracker.output });
196
+ const state = {
197
+ text: undefined,
198
+ thinking: undefined,
199
+ lastTool: undefined,
200
+ toolsByIndex: new Map(),
201
+ toolsById: new Map(),
202
+ finish: undefined,
203
+ sawDone: false,
204
+ };
205
+ const body = response.body;
206
+ for await (const sse of readSseEvents(body, options.signal)) {
207
+ const data = sse.data.trim();
208
+ if (data === "")
209
+ continue;
210
+ if (data === "[DONE]") {
211
+ state.sawDone = true;
212
+ break;
213
+ }
214
+ let chunk;
215
+ try {
216
+ chunk = obj(JSON.parse(data)) ?? {};
217
+ }
218
+ catch {
219
+ throw new Error(`Malformed SSE data: ${data.slice(0, 200)}`);
220
+ }
221
+ handleChunk(chunk, state, tracker);
222
+ }
223
+ if (options.signal.aborted)
224
+ throw new Error("aborted");
225
+ if (state.finish === undefined && !state.sawDone)
226
+ throw new Error(STREAM_ENDED_MESSAGE);
227
+ const stop = resolveStop(state, request.compat, tracker.hasToolCalls);
228
+ if (stop.reason === "error")
229
+ throw new ProviderStopError(stop.message);
230
+ finishDone(stream, tracker, model, stop.reason);
231
+ }
232
+ catch (error) {
233
+ finishError(stream, tracker, model, error, options.signal);
234
+ }
235
+ }
236
+ function stream(model, context, options) {
237
+ requireApiKey(model, options);
238
+ const events = new AssistantEventStreamImpl();
239
+ void run(events, model, context, options).finally(() => events.end());
240
+ return events;
241
+ }
242
+ export const openAICompletionsApi = {
243
+ id: "openai-completions",
244
+ stream,
245
+ detectCompat,
246
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * openai-completions 请求体(设计 §3.1、§3.3):消息转换、compat 开关、思考字段、缓存。
3
+ *
4
+ * compat 开关在这里生效的位置:
5
+ * - maxTokensField / supportsDeveloperRole / supportsUsageInStreaming(stream_options)/
6
+ * supportsStore(store:false)/ supportsStrictTools(strict:true,仅对严格兼容的 schema);
7
+ * - thinkingFormat:openai → reasoning_effort;openrouter → reasoning.effort;deepseek →
8
+ * thinking.type(+ reasoning_effort);zai → thinking.type(+ reasoning_effort);qwen →
9
+ * enable_thinking(+ thinkingTokenBudgetField 预算);none → 不发;
10
+ * - requiresReasoningContentOnAssistantMessages:推理模型的助手消息一律带 reasoning_content;
11
+ * - requiresToolResultName / requiresAssistantAfterToolResult / supportsMidConvoSystemMessages;
12
+ * - cacheControlFormat "anthropic":system 末、最后一个工具、最后一条 user / tool 消息打
13
+ * cache_control(OpenRouter 上的 anthropic/* 模型)。
14
+ * 缓存(第三波 §1.3):`prompt_cache_key = sessionId` 只在 `sendPromptCacheKey`(官方端点缺省开)时发;
15
+ * `long` 在 `supportsLongCacheRetention` 时发 `prompt_cache_retention: "24h"`,否则降为 short;
16
+ * 保留层级未指定时读 `AMA_CACHE_RETENTION`。`toolChoice: "none"`(有工具时)→ `tool_choice: "none"`。
17
+ */
18
+ import { type InlineSystemUpdate } from "../context.js";
19
+ import type { AssistantMessage, JsonSchema, Model, ModelThinkingLevel, OpenAICompletionsCompat, StreamOptions, ToolResultMessage, TranscriptContext, UserMessage } from "../types.js";
20
+ type Json = Record<string, unknown>;
21
+ type Conversation = UserMessage | AssistantMessage | ToolResultMessage;
22
+ /** 思考文本回放用的字段名;thinkingSignature 记录来源字段,回放时原样放回。 */
23
+ export declare const REASONING_FIELDS: readonly ["reasoning_content", "reasoning", "reasoning_text"];
24
+ export declare const ASSISTANT_BRIDGE_TEXT = "Tool results received.";
25
+ export interface OpenAIRequest {
26
+ body: Json;
27
+ compat: OpenAICompletionsCompat;
28
+ thinkingLevel: ModelThinkingLevel;
29
+ providerThinkingLevel: string | undefined;
30
+ }
31
+ export declare function convertMessages(model: Model, messages: readonly Conversation[], compat: OpenAICompletionsCompat, instructionRole: "system" | "developer", updates?: readonly InlineSystemUpdate[]): Json[];
32
+ /** strict 模式要求:object 关闭 additionalProperties 且全部属性必填(递归)。 */
33
+ export declare function isStrictCompatible(schema: JsonSchema): boolean;
34
+ export declare function buildOpenAIRequest(model: Model, context: TranscriptContext, options: StreamOptions): OpenAIRequest;
35
+ export {};