@tonyclaw/agent-inspector 2.0.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 (400) hide show
  1. package/.output/cli.js +1611 -0
  2. package/.output/nitro.json +17 -0
  3. package/.output/public/assets/CompareDrawer-CU5ZrWcL.js +1 -0
  4. package/.output/public/assets/ProxyViewerContainer-pEBqVp1d.js +101 -0
  5. package/.output/public/assets/ReplayDialog-F58yNg5j.js +1 -0
  6. package/.output/public/assets/RequestAnatomy-C9lT0qE_.js +1 -0
  7. package/.output/public/assets/ResponseView-DHJq6bnz.js +1 -0
  8. package/.output/public/assets/StreamingChunkSequence-BTgfpFUT.js +1 -0
  9. package/.output/public/assets/_sessionId-DsNRbnNm.js +1 -0
  10. package/.output/public/assets/alibaba-TTwafVwX.svg +1 -0
  11. package/.output/public/assets/index-CpWG2hFn.css +1 -0
  12. package/.output/public/assets/index-DmBV8Gve.js +1 -0
  13. package/.output/public/assets/json-viewer-CZVYLR8j.js +14 -0
  14. package/.output/public/assets/main-DHs7FBK3.js +18 -0
  15. package/.output/public/assets/minimax-BPMzvuL-.jpeg +0 -0
  16. package/.output/public/assets/qwen-CONDcHqt.png +0 -0
  17. package/.output/public/assets/zhipuai-BPNAnxo-.svg +219 -0
  18. package/.output/server/_chunks/ssr-renderer.mjs +22 -0
  19. package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +1 -0
  20. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +210 -0
  21. package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +2 -0
  22. package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +2 -0
  23. package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +2 -0
  24. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +11 -0
  25. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +69 -0
  26. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +1 -0
  27. package/.output/server/_libs/@radix-ui/react-use-escape-keydown+[...].mjs +17 -0
  28. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +1 -0
  29. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +6 -0
  30. package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +34 -0
  31. package/.output/server/_libs/ajv-formats.mjs +330 -0
  32. package/.output/server/_libs/ajv.mjs +11444 -0
  33. package/.output/server/_libs/aria-hidden.mjs +122 -0
  34. package/.output/server/_libs/atomically.mjs +152 -0
  35. package/.output/server/_libs/bail.mjs +8 -0
  36. package/.output/server/_libs/cfworker__json-schema.mjs +1 -0
  37. package/.output/server/_libs/character-entities.mjs +2130 -0
  38. package/.output/server/_libs/class-variance-authority.mjs +44 -0
  39. package/.output/server/_libs/clsx.mjs +16 -0
  40. package/.output/server/_libs/comma-separated-tokens.mjs +10 -0
  41. package/.output/server/_libs/conf.mjs +635 -0
  42. package/.output/server/_libs/cookie-es.mjs +58 -0
  43. package/.output/server/_libs/core-util-is.mjs +75 -0
  44. package/.output/server/_libs/croner.mjs +1 -0
  45. package/.output/server/_libs/crossws.mjs +1 -0
  46. package/.output/server/_libs/debounce-fn.mjs +69 -0
  47. package/.output/server/_libs/decode-named-character-reference+[...].mjs +8 -0
  48. package/.output/server/_libs/dequal.mjs +27 -0
  49. package/.output/server/_libs/detect-node-es.mjs +1 -0
  50. package/.output/server/_libs/devlop.mjs +8 -0
  51. package/.output/server/_libs/diff.mjs +320 -0
  52. package/.output/server/_libs/dot-prop.mjs +265 -0
  53. package/.output/server/_libs/env-paths.mjs +57 -0
  54. package/.output/server/_libs/estree-util-is-identifier-name.mjs +11 -0
  55. package/.output/server/_libs/extend.mjs +97 -0
  56. package/.output/server/_libs/fast-deep-equal.mjs +38 -0
  57. package/.output/server/_libs/fast-uri.mjs +812 -0
  58. package/.output/server/_libs/floating-ui__core.mjs +725 -0
  59. package/.output/server/_libs/floating-ui__dom.mjs +622 -0
  60. package/.output/server/_libs/floating-ui__react-dom.mjs +292 -0
  61. package/.output/server/_libs/floating-ui__utils.mjs +320 -0
  62. package/.output/server/_libs/get-nonce.mjs +9 -0
  63. package/.output/server/_libs/h3-v2.mjs +276 -0
  64. package/.output/server/_libs/h3.mjs +408 -0
  65. package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +388 -0
  66. package/.output/server/_libs/hast-util-whitespace.mjs +10 -0
  67. package/.output/server/_libs/hookable.mjs +1 -0
  68. package/.output/server/_libs/html-url-attributes.mjs +26 -0
  69. package/.output/server/_libs/immediate.mjs +74 -0
  70. package/.output/server/_libs/inherits.mjs +50 -0
  71. package/.output/server/_libs/inline-style-parser.mjs +142 -0
  72. package/.output/server/_libs/is-plain-obj.mjs +10 -0
  73. package/.output/server/_libs/isarray.mjs +14 -0
  74. package/.output/server/_libs/isbot.mjs +20 -0
  75. package/.output/server/_libs/json-schema-traverse.mjs +180 -0
  76. package/.output/server/_libs/jszip.mjs +3051 -0
  77. package/.output/server/_libs/lie.mjs +273 -0
  78. package/.output/server/_libs/lucide-react.mjs +492 -0
  79. package/.output/server/_libs/mdast-util-from-markdown.mjs +717 -0
  80. package/.output/server/_libs/mdast-util-to-hast.mjs +710 -0
  81. package/.output/server/_libs/mdast-util-to-string.mjs +38 -0
  82. package/.output/server/_libs/micromark-core-commonmark.mjs +2259 -0
  83. package/.output/server/_libs/micromark-factory-destination.mjs +94 -0
  84. package/.output/server/_libs/micromark-factory-label.mjs +63 -0
  85. package/.output/server/_libs/micromark-factory-space.mjs +24 -0
  86. package/.output/server/_libs/micromark-factory-title.mjs +65 -0
  87. package/.output/server/_libs/micromark-factory-whitespace.mjs +22 -0
  88. package/.output/server/_libs/micromark-util-character.mjs +44 -0
  89. package/.output/server/_libs/micromark-util-chunked.mjs +36 -0
  90. package/.output/server/_libs/micromark-util-classify-character+[...].mjs +12 -0
  91. package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +41 -0
  92. package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +19 -0
  93. package/.output/server/_libs/micromark-util-decode-string.mjs +21 -0
  94. package/.output/server/_libs/micromark-util-encode.mjs +1 -0
  95. package/.output/server/_libs/micromark-util-html-tag-name.mjs +69 -0
  96. package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +6 -0
  97. package/.output/server/_libs/micromark-util-resolve-all.mjs +15 -0
  98. package/.output/server/_libs/micromark-util-sanitize-uri.mjs +41 -0
  99. package/.output/server/_libs/micromark-util-subtokenize.mjs +346 -0
  100. package/.output/server/_libs/micromark.mjs +906 -0
  101. package/.output/server/_libs/mimic-function.mjs +47 -0
  102. package/.output/server/_libs/modelcontextprotocol__server.mjs +9738 -0
  103. package/.output/server/_libs/ocache.mjs +1 -0
  104. package/.output/server/_libs/ohash.mjs +1 -0
  105. package/.output/server/_libs/pako.mjs +4223 -0
  106. package/.output/server/_libs/process-nextick-args.mjs +48 -0
  107. package/.output/server/_libs/property-information.mjs +1209 -0
  108. package/.output/server/_libs/radix-ui.mjs +1 -0
  109. package/.output/server/_libs/radix-ui__number.mjs +6 -0
  110. package/.output/server/_libs/radix-ui__primitive.mjs +11 -0
  111. package/.output/server/_libs/radix-ui__react-accordion.mjs +1 -0
  112. package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +1 -0
  113. package/.output/server/_libs/radix-ui__react-arrow.mjs +23 -0
  114. package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +1 -0
  115. package/.output/server/_libs/radix-ui__react-avatar.mjs +1 -0
  116. package/.output/server/_libs/radix-ui__react-checkbox.mjs +1 -0
  117. package/.output/server/_libs/radix-ui__react-collapsible.mjs +144 -0
  118. package/.output/server/_libs/radix-ui__react-collection.mjs +69 -0
  119. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +39 -0
  120. package/.output/server/_libs/radix-ui__react-context-menu.mjs +1 -0
  121. package/.output/server/_libs/radix-ui__react-context.mjs +78 -0
  122. package/.output/server/_libs/radix-ui__react-dialog.mjs +325 -0
  123. package/.output/server/_libs/radix-ui__react-direction.mjs +9 -0
  124. package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +1 -0
  125. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +29 -0
  126. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +206 -0
  127. package/.output/server/_libs/radix-ui__react-form.mjs +1 -0
  128. package/.output/server/_libs/radix-ui__react-hover-card.mjs +1 -0
  129. package/.output/server/_libs/radix-ui__react-id.mjs +14 -0
  130. package/.output/server/_libs/radix-ui__react-label.mjs +1 -0
  131. package/.output/server/_libs/radix-ui__react-menu.mjs +1 -0
  132. package/.output/server/_libs/radix-ui__react-menubar.mjs +1 -0
  133. package/.output/server/_libs/radix-ui__react-popover.mjs +1 -0
  134. package/.output/server/_libs/radix-ui__react-popper.mjs +286 -0
  135. package/.output/server/_libs/radix-ui__react-portal.mjs +16 -0
  136. package/.output/server/_libs/radix-ui__react-presence.mjs +128 -0
  137. package/.output/server/_libs/radix-ui__react-primitive.mjs +42 -0
  138. package/.output/server/_libs/radix-ui__react-progress.mjs +1 -0
  139. package/.output/server/_libs/radix-ui__react-radio-group.mjs +1 -0
  140. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +224 -0
  141. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +721 -0
  142. package/.output/server/_libs/radix-ui__react-select.mjs +1163 -0
  143. package/.output/server/_libs/radix-ui__react-separator.mjs +28 -0
  144. package/.output/server/_libs/radix-ui__react-slider.mjs +1 -0
  145. package/.output/server/_libs/radix-ui__react-slot.mjs +99 -0
  146. package/.output/server/_libs/radix-ui__react-switch.mjs +1 -0
  147. package/.output/server/_libs/radix-ui__react-tabs.mjs +189 -0
  148. package/.output/server/_libs/radix-ui__react-toast.mjs +2 -0
  149. package/.output/server/_libs/radix-ui__react-toggle-group.mjs +1 -0
  150. package/.output/server/_libs/radix-ui__react-toggle.mjs +1 -0
  151. package/.output/server/_libs/radix-ui__react-toolbar.mjs +1 -0
  152. package/.output/server/_libs/radix-ui__react-tooltip.mjs +495 -0
  153. package/.output/server/_libs/radix-ui__react-use-previous.mjs +14 -0
  154. package/.output/server/_libs/radix-ui__react-use-size.mjs +39 -0
  155. package/.output/server/_libs/react-dom.mjs +10781 -0
  156. package/.output/server/_libs/react-markdown.mjs +147 -0
  157. package/.output/server/_libs/react-remove-scroll-bar.mjs +82 -0
  158. package/.output/server/_libs/react-remove-scroll.mjs +328 -0
  159. package/.output/server/_libs/react-style-singleton.mjs +69 -0
  160. package/.output/server/_libs/react.mjs +515 -0
  161. package/.output/server/_libs/readable-stream.mjs +1518 -0
  162. package/.output/server/_libs/remark-parse.mjs +19 -0
  163. package/.output/server/_libs/remark-rehype.mjs +21 -0
  164. package/.output/server/_libs/rou3.mjs +14 -0
  165. package/.output/server/_libs/safe-buffer.mjs +64 -0
  166. package/.output/server/_libs/semver.mjs +1938 -0
  167. package/.output/server/_libs/seroval-plugins.mjs +58 -0
  168. package/.output/server/_libs/seroval.mjs +1765 -0
  169. package/.output/server/_libs/setimmediate.mjs +152 -0
  170. package/.output/server/_libs/space-separated-tokens.mjs +6 -0
  171. package/.output/server/_libs/srvx.mjs +1029 -0
  172. package/.output/server/_libs/stubborn-fs.mjs +91 -0
  173. package/.output/server/_libs/stubborn-utils.mjs +66 -0
  174. package/.output/server/_libs/style-to-js.mjs +72 -0
  175. package/.output/server/_libs/style-to-object.mjs +38 -0
  176. package/.output/server/_libs/swr.mjs +939 -0
  177. package/.output/server/_libs/tailwind-merge.mjs +3010 -0
  178. package/.output/server/_libs/tanstack__history.mjs +217 -0
  179. package/.output/server/_libs/tanstack__react-router.mjs +1480 -0
  180. package/.output/server/_libs/tanstack__react-store.mjs +1 -0
  181. package/.output/server/_libs/tanstack__react-virtual.mjs +44 -0
  182. package/.output/server/_libs/tanstack__router-core.mjs +4827 -0
  183. package/.output/server/_libs/tanstack__store.mjs +1 -0
  184. package/.output/server/_libs/tanstack__virtual-core.mjs +1225 -0
  185. package/.output/server/_libs/tiny-invariant.mjs +12 -0
  186. package/.output/server/_libs/tiny-warning.mjs +5 -0
  187. package/.output/server/_libs/trim-lines.mjs +41 -0
  188. package/.output/server/_libs/trough.mjs +85 -0
  189. package/.output/server/_libs/tslib.mjs +1 -0
  190. package/.output/server/_libs/ufo.mjs +54 -0
  191. package/.output/server/_libs/uint8array-extras.mjs +69 -0
  192. package/.output/server/_libs/ungap__structured-clone.mjs +212 -0
  193. package/.output/server/_libs/unified.mjs +661 -0
  194. package/.output/server/_libs/unist-util-is.mjs +100 -0
  195. package/.output/server/_libs/unist-util-position.mjs +27 -0
  196. package/.output/server/_libs/unist-util-stringify-position.mjs +27 -0
  197. package/.output/server/_libs/unist-util-visit-parents.mjs +82 -0
  198. package/.output/server/_libs/unist-util-visit.mjs +24 -0
  199. package/.output/server/_libs/unstorage.mjs +1 -0
  200. package/.output/server/_libs/use-callback-ref.mjs +66 -0
  201. package/.output/server/_libs/use-sidecar.mjs +106 -0
  202. package/.output/server/_libs/use-sync-external-store.mjs +64 -0
  203. package/.output/server/_libs/util-deprecate.mjs +12 -0
  204. package/.output/server/_libs/vfile-message.mjs +138 -0
  205. package/.output/server/_libs/vfile.mjs +467 -0
  206. package/.output/server/_libs/when-exit.mjs +53 -0
  207. package/.output/server/_libs/zod.mjs +4524 -0
  208. package/.output/server/_sessionId-wMLPvC5g.mjs +123 -0
  209. package/.output/server/_ssr/CompareDrawer-BU4V0uVf.mjs +1041 -0
  210. package/.output/server/_ssr/ProxyViewerContainer-BnRwFEnn.mjs +5972 -0
  211. package/.output/server/_ssr/ReplayDialog-C7dn9pd_.mjs +322 -0
  212. package/.output/server/_ssr/RequestAnatomy-C1rWpe9-.mjs +353 -0
  213. package/.output/server/_ssr/ResponseView-hGpPaYsf.mjs +602 -0
  214. package/.output/server/_ssr/StreamingChunkSequence-BRWI1r_G.mjs +302 -0
  215. package/.output/server/_ssr/index-BKURLVPz.mjs +118 -0
  216. package/.output/server/_ssr/index.mjs +1184 -0
  217. package/.output/server/_ssr/json-viewer-BBd2DtQP.mjs +515 -0
  218. package/.output/server/_ssr/router-BcZ0D6AB.mjs +6317 -0
  219. package/.output/server/_ssr/start-HYkvq4Ni.mjs +4 -0
  220. package/.output/server/_tanstack-start-manifest_v-1y8ZVxRI.mjs +4 -0
  221. package/.output/server/index.mjs +436 -0
  222. package/.output/server/node_modules/tslib/modules/index.js +70 -0
  223. package/.output/server/node_modules/tslib/modules/package.json +3 -0
  224. package/.output/server/node_modules/tslib/package.json +47 -0
  225. package/.output/server/node_modules/tslib/tslib.js +484 -0
  226. package/.output/server/package.json +9 -0
  227. package/LICENSE +21 -0
  228. package/README.md +52 -0
  229. package/package.json +110 -0
  230. package/src/assets/favicon.svg +31 -0
  231. package/src/assets/logos/alibaba.svg +1 -0
  232. package/src/assets/logos/anthropic.svg +1 -0
  233. package/src/assets/logos/claude-code.svg +4 -0
  234. package/src/assets/logos/deepseek.svg +1 -0
  235. package/src/assets/logos/mcp.png +0 -0
  236. package/src/assets/logos/minimax.jpeg +0 -0
  237. package/src/assets/logos/openai.svg +1 -0
  238. package/src/assets/logos/opencode.svg +4 -0
  239. package/src/assets/logos/qwen.png +0 -0
  240. package/src/assets/logos/zhipuai.svg +219 -0
  241. package/src/cli/detect-tools.ts +147 -0
  242. package/src/cli/doctor.ts +521 -0
  243. package/src/cli/onboard.ts +224 -0
  244. package/src/cli/templates/command-onboard.ts +17 -0
  245. package/src/cli/templates/skill-onboard.ts +547 -0
  246. package/src/cli.ts +345 -0
  247. package/src/components/OnboardingBanner.tsx +67 -0
  248. package/src/components/ProxyViewer.tsx +545 -0
  249. package/src/components/ProxyViewerContainer.tsx +363 -0
  250. package/src/components/providers/ImportWizardDialog.tsx +349 -0
  251. package/src/components/providers/ProviderCard.tsx +474 -0
  252. package/src/components/providers/ProviderForm.tsx +494 -0
  253. package/src/components/providers/ProviderLogo.tsx +117 -0
  254. package/src/components/providers/ProvidersPanel.tsx +619 -0
  255. package/src/components/providers/SettingsDialog.tsx +202 -0
  256. package/src/components/proxy-viewer/CompareDrawer.tsx +893 -0
  257. package/src/components/proxy-viewer/ConversationGroup.tsx +107 -0
  258. package/src/components/proxy-viewer/ConversationHeader.tsx +300 -0
  259. package/src/components/proxy-viewer/LogEntry.tsx +543 -0
  260. package/src/components/proxy-viewer/LogEntryHeader.tsx +501 -0
  261. package/src/components/proxy-viewer/ReplayDialog.tsx +218 -0
  262. package/src/components/proxy-viewer/ResponseView.tsx +171 -0
  263. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +188 -0
  264. package/src/components/proxy-viewer/ThreadConnector.tsx +136 -0
  265. package/src/components/proxy-viewer/TurnGroup.tsx +337 -0
  266. package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +98 -0
  267. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +196 -0
  268. package/src/components/proxy-viewer/anatomy/tokenEstimate.ts +53 -0
  269. package/src/components/proxy-viewer/anatomy/types.ts +39 -0
  270. package/src/components/proxy-viewer/anatomy/useAnatomyJump.ts +114 -0
  271. package/src/components/proxy-viewer/cacheTrend.ts +50 -0
  272. package/src/components/proxy-viewer/diff/DiffView.tsx +321 -0
  273. package/src/components/proxy-viewer/diff/computeDiff.ts +178 -0
  274. package/src/components/proxy-viewer/diff/index.ts +3 -0
  275. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +157 -0
  276. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +66 -0
  277. package/src/components/proxy-viewer/formats/anthropic/thinkingExtract.ts +21 -0
  278. package/src/components/proxy-viewer/formats/index.tsx +33 -0
  279. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +170 -0
  280. package/src/components/proxy-viewer/index.ts +9 -0
  281. package/src/components/proxy-viewer/lazy.ts +37 -0
  282. package/src/components/proxy-viewer/log-formats/anthropic.ts +194 -0
  283. package/src/components/proxy-viewer/log-formats/index.ts +23 -0
  284. package/src/components/proxy-viewer/log-formats/openai.ts +167 -0
  285. package/src/components/proxy-viewer/log-formats/types.ts +40 -0
  286. package/src/components/proxy-viewer/log-formats/unknown.ts +18 -0
  287. package/src/components/proxy-viewer/logEntryVisibility.ts +39 -0
  288. package/src/components/proxy-viewer/requestDiff.ts +277 -0
  289. package/src/components/proxy-viewer/useCopyFeedback.ts +36 -0
  290. package/src/components/proxy-viewer/useKeyboardNavigation.ts +190 -0
  291. package/src/components/proxy-viewer/viewerState.ts +66 -0
  292. package/src/components/ui/badge.tsx +47 -0
  293. package/src/components/ui/button.tsx +47 -0
  294. package/src/components/ui/collapsible.tsx +21 -0
  295. package/src/components/ui/confirm-dialog.tsx +51 -0
  296. package/src/components/ui/crab-logo.tsx +95 -0
  297. package/src/components/ui/crab-variants.tsx +467 -0
  298. package/src/components/ui/dialog.tsx +129 -0
  299. package/src/components/ui/json-expansion-button.tsx +56 -0
  300. package/src/components/ui/json-viewer-bulk.ts +97 -0
  301. package/src/components/ui/json-viewer.tsx +494 -0
  302. package/src/components/ui/mcp-logo.tsx +20 -0
  303. package/src/components/ui/scroll-area.tsx +54 -0
  304. package/src/components/ui/select.tsx +178 -0
  305. package/src/components/ui/separator.tsx +28 -0
  306. package/src/components/ui/tabs.tsx +88 -0
  307. package/src/components/ui/tooltip.tsx +51 -0
  308. package/src/index.css +11 -0
  309. package/src/knowledge/candidateStore.ts +63 -0
  310. package/src/knowledge/distiller.ts +98 -0
  311. package/src/knowledge/openclawClient.ts +118 -0
  312. package/src/knowledge/redactor.ts +80 -0
  313. package/src/knowledge/types.ts +84 -0
  314. package/src/lib/apiClient.ts +49 -0
  315. package/src/lib/export-logs.ts +51 -0
  316. package/src/lib/mask.ts +4 -0
  317. package/src/lib/objectUtils.ts +22 -0
  318. package/src/lib/providerContract.ts +26 -0
  319. package/src/lib/providerTestContract.ts +107 -0
  320. package/src/lib/runtimeConfig.ts +25 -0
  321. package/src/lib/serverPort.ts +41 -0
  322. package/src/lib/sessionUrl.ts +44 -0
  323. package/src/lib/stopReason.ts +58 -0
  324. package/src/lib/useOnboarding.ts +80 -0
  325. package/src/lib/useProviders.ts +30 -0
  326. package/src/lib/useStripConfig.ts +108 -0
  327. package/src/lib/utils.ts +21 -0
  328. package/src/mcp/loopback.ts +76 -0
  329. package/src/mcp/previewExtractor.ts +166 -0
  330. package/src/mcp/server.ts +396 -0
  331. package/src/mcp/toolHandlers.ts +341 -0
  332. package/src/proxy/chunkStorage.ts +112 -0
  333. package/src/proxy/claudeCodeStrip.ts +99 -0
  334. package/src/proxy/config.ts +172 -0
  335. package/src/proxy/constants.ts +47 -0
  336. package/src/proxy/dataDir.ts +86 -0
  337. package/src/proxy/formats/anthropic/anthropicProvider.ts +75 -0
  338. package/src/proxy/formats/anthropic/handler.ts +71 -0
  339. package/src/proxy/formats/anthropic/index.ts +14 -0
  340. package/src/proxy/formats/anthropic/register.ts +4 -0
  341. package/src/proxy/formats/anthropic/schemas.ts +237 -0
  342. package/src/proxy/formats/anthropic/stream.ts +205 -0
  343. package/src/proxy/formats/handler.ts +46 -0
  344. package/src/proxy/formats/index.ts +12 -0
  345. package/src/proxy/formats/jsonSchema.ts +36 -0
  346. package/src/proxy/formats/openai/alibabaProvider.ts +38 -0
  347. package/src/proxy/formats/openai/handler.ts +96 -0
  348. package/src/proxy/formats/openai/index.ts +25 -0
  349. package/src/proxy/formats/openai/provider.ts +50 -0
  350. package/src/proxy/formats/openai/register.ts +4 -0
  351. package/src/proxy/formats/openai/schemas.ts +187 -0
  352. package/src/proxy/formats/openai/stream.ts +206 -0
  353. package/src/proxy/formats/protocol.ts +50 -0
  354. package/src/proxy/formats/providerRegistry.ts +51 -0
  355. package/src/proxy/formats/providers/index.ts +3 -0
  356. package/src/proxy/formats/registry.ts +66 -0
  357. package/src/proxy/handler.ts +334 -0
  358. package/src/proxy/logFinalizer.ts +305 -0
  359. package/src/proxy/logFinalizer.worker.ts +24 -0
  360. package/src/proxy/logIndex.ts +268 -0
  361. package/src/proxy/logger.ts +179 -0
  362. package/src/proxy/openaiOrphanToolStrip.ts +142 -0
  363. package/src/proxy/providerImporters.ts +491 -0
  364. package/src/proxy/providers.ts +613 -0
  365. package/src/proxy/schemas.ts +209 -0
  366. package/src/proxy/sessionProcess.ts +140 -0
  367. package/src/proxy/sessionRuntime.ts +85 -0
  368. package/src/proxy/sessionSupervisor.ts +283 -0
  369. package/src/proxy/sessionWorkerEntry.ts +26 -0
  370. package/src/proxy/socketTracker.ts +255 -0
  371. package/src/proxy/store.ts +412 -0
  372. package/src/proxy/upstream.ts +90 -0
  373. package/src/router.tsx +16 -0
  374. package/src/routes/__root.tsx +45 -0
  375. package/src/routes/api/config.paths.ts +14 -0
  376. package/src/routes/api/config.ts +53 -0
  377. package/src/routes/api/health.ts +15 -0
  378. package/src/routes/api/knowledge.candidates.$candidateId.promote.ts +32 -0
  379. package/src/routes/api/knowledge.candidates.ts +10 -0
  380. package/src/routes/api/knowledge.project-context.ts +18 -0
  381. package/src/routes/api/knowledge.search.ts +31 -0
  382. package/src/routes/api/knowledge.sessions.$sessionId.candidates.ts +16 -0
  383. package/src/routes/api/logs.$id.chunks.ts +36 -0
  384. package/src/routes/api/logs.$id.replay.ts +191 -0
  385. package/src/routes/api/logs.$id.ts +22 -0
  386. package/src/routes/api/logs.stream.ts +74 -0
  387. package/src/routes/api/logs.ts +59 -0
  388. package/src/routes/api/mcp.ts +25 -0
  389. package/src/routes/api/models.ts +10 -0
  390. package/src/routes/api/providers.$providerId.test.log.ts +293 -0
  391. package/src/routes/api/providers.$providerId.ts +50 -0
  392. package/src/routes/api/providers.export.ts +26 -0
  393. package/src/routes/api/providers.import.ts +47 -0
  394. package/src/routes/api/providers.scan.ts +23 -0
  395. package/src/routes/api/providers.ts +45 -0
  396. package/src/routes/api/sessions.ts +17 -0
  397. package/src/routes/index.tsx +6 -0
  398. package/src/routes/proxy/$.ts +15 -0
  399. package/src/routes/session/$sessionId.tsx +23 -0
  400. package/styles/globals.css +188 -0
@@ -0,0 +1,237 @@
1
+ import { z } from "zod";
2
+ import { JsonValueSchema } from "../jsonSchema";
3
+
4
+ const CacheControl = z.object({
5
+ type: z.string(),
6
+ ttl: z.string().optional(),
7
+ scope: z.string().optional(),
8
+ });
9
+
10
+ const TextContentBlock = z.object({
11
+ type: z.literal("text"),
12
+ text: z.string(),
13
+ cache_control: CacheControl.optional(),
14
+ });
15
+
16
+ const ThinkingContentBlock = z.object({
17
+ type: z.literal("thinking"),
18
+ thinking: z.string(),
19
+ signature: z.string().optional(),
20
+ });
21
+
22
+ const ThinkContentBlock = z.object({
23
+ type: z.literal("think"),
24
+ thinking: z.string(),
25
+ signature: z.string().optional(),
26
+ });
27
+
28
+ const ImageSourceBlock = z.object({
29
+ type: z.literal("base64"),
30
+ media_type: z.string(),
31
+ data: z.string(),
32
+ });
33
+
34
+ const ImageContentBlock = z.object({
35
+ type: z.literal("image"),
36
+ source: ImageSourceBlock,
37
+ });
38
+
39
+ const ToolUseContentBlock = z.object({
40
+ type: z.literal("tool_use"),
41
+ id: z.string(),
42
+ name: z.string(),
43
+ input: z.record(z.string(), JsonValueSchema),
44
+ });
45
+
46
+ const ToolResultContentItem = z.discriminatedUnion("type", [TextContentBlock, ImageContentBlock]);
47
+
48
+ const ToolResultContentBlock = z.object({
49
+ type: z.literal("tool_result"),
50
+ tool_use_id: z.string().optional(),
51
+ content: z.union([z.string(), z.array(ToolResultContentItem)]),
52
+ is_error: z.boolean().optional(),
53
+ });
54
+
55
+ const ContentBlock = z.discriminatedUnion("type", [
56
+ TextContentBlock,
57
+ ThinkingContentBlock,
58
+ ImageContentBlock,
59
+ ToolUseContentBlock,
60
+ ToolResultContentBlock,
61
+ ]);
62
+
63
+ const MessageContent = z.union([z.string(), z.array(ContentBlock)]);
64
+
65
+ const Message = z.object({
66
+ role: z.enum(["user", "assistant"]),
67
+ content: MessageContent,
68
+ });
69
+
70
+ const SystemBlock = z.object({
71
+ type: z.literal("text"),
72
+ text: z.string(),
73
+ cache_control: CacheControl.optional(),
74
+ });
75
+
76
+ const InputSchema = z.object({
77
+ type: z.string(),
78
+ properties: z.record(z.string(), z.record(z.string(), JsonValueSchema)).optional(),
79
+ required: z.array(z.string()).optional(),
80
+ additionalProperties: z.boolean().optional(),
81
+ $schema: z.string().optional(),
82
+ });
83
+
84
+ const ToolDefinition = z.object({
85
+ name: z.string(),
86
+ description: z.string().optional(),
87
+ input_schema: InputSchema.optional(),
88
+ cache_control: CacheControl.optional(),
89
+ });
90
+
91
+ const ThinkingConfig = z.discriminatedUnion("type", [
92
+ z.object({ type: z.literal("enabled"), budget_tokens: z.number() }),
93
+ z.object({ type: z.literal("disabled") }),
94
+ z.object({ type: z.literal("adaptive") }),
95
+ ]);
96
+
97
+ export const AnthropicRequestSchema = z.object({
98
+ model: z.string(),
99
+ messages: z.array(Message),
100
+ system: z.array(SystemBlock).optional(),
101
+ tools: z.array(ToolDefinition).optional(),
102
+ max_tokens: z.number().optional(),
103
+ temperature: z.number().optional(),
104
+ stream: z.boolean().optional(),
105
+ thinking: ThinkingConfig.optional(),
106
+ metadata: z
107
+ .object({
108
+ user_id: z.string().optional(),
109
+ })
110
+ .optional(),
111
+ });
112
+
113
+ const ResponseContentBlock = z.discriminatedUnion("type", [
114
+ TextContentBlock,
115
+ ThinkingContentBlock,
116
+ ThinkContentBlock,
117
+ ToolUseContentBlock,
118
+ ]);
119
+
120
+ const ResponseUsageSchema = z
121
+ .object({
122
+ input_tokens: z.number().nullable().optional(),
123
+ output_tokens: z.number().nullable().optional(),
124
+ cache_creation_input_tokens: z.number().nullable().optional(),
125
+ cache_read_input_tokens: z.number().nullable().optional(),
126
+ })
127
+ .passthrough(); // Allow extra fields from different providers
128
+
129
+ export const AnthropicResponseSchema = z
130
+ .object({
131
+ id: z.string(),
132
+ type: z.literal("message"),
133
+ model: z.string(),
134
+ role: z.literal("assistant"),
135
+ content: z.array(ResponseContentBlock),
136
+ stop_reason: z.string().nullable(),
137
+ stop_sequence: z.string().nullable().optional(),
138
+ usage: ResponseUsageSchema,
139
+ })
140
+ .passthrough(); // Allow extra unknown fields
141
+
142
+ const SseMessageStartEvent = z.object({
143
+ type: z.literal("message_start"),
144
+ message: z.object({
145
+ id: z.string(),
146
+ type: z.literal("message"),
147
+ model: z.string(),
148
+ role: z.literal("assistant"),
149
+ content: z.array(ResponseContentBlock),
150
+ stop_reason: z.null(),
151
+ stop_sequence: z.null(),
152
+ usage: z
153
+ .object({
154
+ input_tokens: z.number(),
155
+ cache_creation_input_tokens: z.number().optional(),
156
+ cache_read_input_tokens: z.number().optional(),
157
+ })
158
+ .passthrough(),
159
+ }),
160
+ });
161
+
162
+ const SseContentBlockStartEvent = z.object({
163
+ type: z.literal("content_block_start"),
164
+ index: z.number(),
165
+ content_block: ResponseContentBlock,
166
+ });
167
+
168
+ const SseDeltaBlock = z.discriminatedUnion("type", [
169
+ z.object({ type: z.literal("text_delta"), text: z.string() }),
170
+ z.object({ type: z.literal("input_json_delta"), partial_json: z.string() }),
171
+ z.object({ type: z.literal("thinking_delta"), thinking: z.string() }),
172
+ z.object({ type: z.literal("signature_delta"), signature: z.string() }),
173
+ ]);
174
+
175
+ const SseContentBlockDeltaEvent = z.object({
176
+ type: z.literal("content_block_delta"),
177
+ index: z.number(),
178
+ delta: SseDeltaBlock,
179
+ });
180
+
181
+ const SseContentBlockStopEvent = z.object({
182
+ type: z.literal("content_block_stop"),
183
+ index: z.number(),
184
+ });
185
+
186
+ const SseMessageDeltaEvent = z.object({
187
+ type: z.literal("message_delta"),
188
+ delta: z.object({
189
+ stop_reason: z.string().nullable(),
190
+ stop_sequence: z.string().nullable().optional(),
191
+ }),
192
+ usage: z
193
+ .object({
194
+ output_tokens: z.number(),
195
+ input_tokens: z.number().optional(),
196
+ cache_creation_input_tokens: z.number().optional(),
197
+ cache_read_input_tokens: z.number().optional(),
198
+ })
199
+ .passthrough(),
200
+ });
201
+
202
+ const SseMessageStopEvent = z.object({
203
+ type: z.literal("message_stop"),
204
+ });
205
+
206
+ const SsePingEvent = z.object({
207
+ type: z.literal("ping"),
208
+ });
209
+
210
+ const SseErrorEvent = z.object({
211
+ type: z.literal("error"),
212
+ error: z.object({
213
+ type: z.string(),
214
+ message: z.string(),
215
+ }),
216
+ });
217
+
218
+ export const SseEventSchema = z.discriminatedUnion("type", [
219
+ SseMessageStartEvent,
220
+ SseContentBlockStartEvent,
221
+ SseContentBlockDeltaEvent,
222
+ SseContentBlockStopEvent,
223
+ SseMessageDeltaEvent,
224
+ SseMessageStopEvent,
225
+ SsePingEvent,
226
+ SseErrorEvent,
227
+ ]);
228
+
229
+ export type AnthropicRequest = z.infer<typeof AnthropicRequestSchema>;
230
+ export type AnthropicResponse = z.infer<typeof AnthropicResponseSchema>;
231
+ export type ResponseContentBlockType = z.infer<typeof ResponseContentBlock>;
232
+
233
+ // Backward-compatible aliases (originally named Inspector*)
234
+ export const InspectorRequestSchema = AnthropicRequestSchema;
235
+ export const InspectorResponseSchema = AnthropicResponseSchema;
236
+ export type InspectorRequest = AnthropicRequest;
237
+ export type InspectorResponse = AnthropicResponse;
@@ -0,0 +1,205 @@
1
+ import type { CapturedLog, JsonValue } from "../../schemas";
2
+ import { trustAsJsonValue } from "../jsonSchema";
3
+ import { SseEventSchema } from "./schemas";
4
+
5
+ type StreamTextBlock = { type: "text"; text: string };
6
+ type StreamThinkingBlock = { type: "thinking"; thinking: string; signature: string };
7
+ type StreamThinkBlock = { type: "think"; thinking: string; signature: string };
8
+ type StreamToolUseBlock = { type: "tool_use"; id: string; name: string; inputJson: string };
9
+ type StreamBlock = StreamTextBlock | StreamThinkingBlock | StreamThinkBlock | StreamToolUseBlock;
10
+
11
+ function parseInputJson(json: string): Record<string, unknown> {
12
+ if (json === "") return {};
13
+ try {
14
+ const parsed: unknown = JSON.parse(json);
15
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
16
+ return { ...parsed };
17
+ }
18
+ return {};
19
+ } catch {
20
+ return {};
21
+ }
22
+ }
23
+
24
+ function finalizeBlock(block: StreamBlock): Record<string, unknown> {
25
+ switch (block.type) {
26
+ case "text":
27
+ return { type: "text", text: block.text };
28
+ case "thinking": {
29
+ const out: Record<string, unknown> = { type: "thinking", thinking: block.thinking };
30
+ if (block.signature !== "") out.signature = block.signature;
31
+ return out;
32
+ }
33
+ case "think": {
34
+ const out: Record<string, unknown> = { type: "think", thinking: block.thinking };
35
+ if (block.signature !== "") out.signature = block.signature;
36
+ return out;
37
+ }
38
+ case "tool_use":
39
+ return {
40
+ type: "tool_use",
41
+ id: block.id,
42
+ name: block.name,
43
+ input: parseInputJson(block.inputJson),
44
+ };
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Extract Anthropic streaming response and return normalized JSON.
50
+ * Optionally collects SSE chunks into log.streamingChunks for debugging/display.
51
+ */
52
+ export function extractAnthropicStream(
53
+ raw: string,
54
+ log: CapturedLog,
55
+ fallbackModel?: string,
56
+ collectChunks?: boolean,
57
+ ): string {
58
+ const blocks = new Map<number, StreamBlock>();
59
+ let id = "";
60
+ let model = "";
61
+ let stopReason: string | null = null;
62
+ let stopSequence: string | null = null;
63
+ let inputTokens = 0;
64
+ let outputTokens = 0;
65
+
66
+ const MAX_CHUNKS = 1000;
67
+ let chunkIndex = 0;
68
+ let streamStartMs = 0;
69
+ const chunks: Array<{ index: number; timestamp: number; type: string; data: JsonValue }> = [];
70
+
71
+ for (const line of raw.split("\n")) {
72
+ const trimmedLine = line.trim();
73
+ if (!trimmedLine.startsWith("data: ")) continue;
74
+ try {
75
+ const json: unknown = JSON.parse(trimmedLine.slice(6));
76
+ const parsed = SseEventSchema.safeParse(json);
77
+ if (!parsed.success) continue;
78
+ const data = parsed.data;
79
+
80
+ if (chunkIndex === 0) streamStartMs = Date.now();
81
+
82
+ if (collectChunks === true && chunks.length < MAX_CHUNKS) {
83
+ chunks.push({
84
+ index: chunkIndex,
85
+ timestamp: Date.now() - streamStartMs,
86
+ type: data.type,
87
+ // `data` has already been validated by SseEventSchema above; the
88
+ // recursive JsonValue walk is a redundant full-tree zod parse on
89
+ // every SSE event. See trustAsJsonValue for the rationale.
90
+ data: trustAsJsonValue(data),
91
+ });
92
+ }
93
+ chunkIndex++;
94
+
95
+ switch (data.type) {
96
+ case "message_start":
97
+ id = data.message.id;
98
+ model = data.message.model;
99
+ inputTokens = data.message.usage.input_tokens;
100
+ log.inputTokens = inputTokens;
101
+ log.cacheCreationInputTokens = data.message.usage.cache_creation_input_tokens ?? null;
102
+ log.cacheReadInputTokens = data.message.usage.cache_read_input_tokens ?? null;
103
+ if (log.model === null) log.model = model;
104
+ break;
105
+ case "content_block_start": {
106
+ const cb = data.content_block;
107
+ switch (cb.type) {
108
+ case "text":
109
+ blocks.set(data.index, { type: "text", text: cb.text ?? "" });
110
+ break;
111
+ case "thinking":
112
+ blocks.set(data.index, {
113
+ type: "thinking",
114
+ thinking: cb.thinking ?? "",
115
+ signature: cb.signature ?? "",
116
+ });
117
+ break;
118
+ case "think":
119
+ blocks.set(data.index, {
120
+ type: "think",
121
+ thinking: cb.thinking ?? "",
122
+ signature: cb.signature ?? "",
123
+ });
124
+ break;
125
+ case "tool_use":
126
+ blocks.set(data.index, {
127
+ type: "tool_use",
128
+ id: cb.id,
129
+ name: cb.name,
130
+ inputJson: "",
131
+ });
132
+ break;
133
+ }
134
+ break;
135
+ }
136
+ case "content_block_delta": {
137
+ const block = blocks.get(data.index);
138
+ if (block === undefined) break;
139
+ const delta = data.delta;
140
+ if (delta.type === "text_delta" && block.type === "text") {
141
+ block.text += delta.text;
142
+ } else if (
143
+ delta.type === "thinking_delta" &&
144
+ (block.type === "thinking" || block.type === "think")
145
+ ) {
146
+ block.thinking += delta.thinking;
147
+ } else if (
148
+ delta.type === "signature_delta" &&
149
+ (block.type === "thinking" || block.type === "think")
150
+ ) {
151
+ block.signature += delta.signature;
152
+ } else if (delta.type === "input_json_delta" && block.type === "tool_use") {
153
+ block.inputJson += delta.partial_json;
154
+ }
155
+ break;
156
+ }
157
+ case "message_delta":
158
+ stopReason = data.delta.stop_reason;
159
+ stopSequence = data.delta.stop_sequence ?? null;
160
+ outputTokens = data.usage.output_tokens;
161
+ log.outputTokens = outputTokens;
162
+ // Cache tokens may also be present in message_delta usage
163
+ if (data.usage.cache_creation_input_tokens !== undefined) {
164
+ log.cacheCreationInputTokens = data.usage.cache_creation_input_tokens;
165
+ }
166
+ if (data.usage.cache_read_input_tokens !== undefined) {
167
+ log.cacheReadInputTokens = data.usage.cache_read_input_tokens;
168
+ }
169
+ break;
170
+ case "error":
171
+ // Store error info on the log for display
172
+ log.error = data.error.message;
173
+ break;
174
+ case "content_block_stop":
175
+ case "message_stop":
176
+ case "ping":
177
+ break;
178
+ }
179
+ } catch {
180
+ // non-JSON SSE line, skip
181
+ }
182
+ }
183
+
184
+ if (collectChunks === true) {
185
+ log.streamingChunks = {
186
+ chunks,
187
+ truncated: chunkIndex > MAX_CHUNKS,
188
+ };
189
+ }
190
+
191
+ const orderedContent = [...blocks.entries()]
192
+ .sort(([a], [b]) => a - b)
193
+ .map(([, block]) => finalizeBlock(block));
194
+
195
+ return JSON.stringify({
196
+ id,
197
+ type: "message",
198
+ model: model !== "" ? model : (fallbackModel ?? ""),
199
+ role: "assistant",
200
+ content: orderedContent,
201
+ stop_reason: stopReason,
202
+ stop_sequence: stopSequence,
203
+ usage: { input_tokens: inputTokens, output_tokens: outputTokens },
204
+ });
205
+ }
@@ -0,0 +1,46 @@
1
+ import type { CapturedLog, RequestFormat, TokenUsage } from "../schemas";
2
+
3
+ /**
4
+ * Structured result of parsing a raw request body.
5
+ */
6
+ export type ParsedRequest = {
7
+ model: string | null;
8
+ sessionId: string | null;
9
+ };
10
+
11
+ /**
12
+ * FormatHandler defines the contract for all API format implementations.
13
+ *
14
+ * Each API format (Anthropic, OpenAI) provides its own handler that encapsulates
15
+ * request parsing, response parsing, SSE stream extraction, and token extraction.
16
+ * This replaces the scattered if/else format branching previously in handler.ts.
17
+ */
18
+ export type FormatHandler = {
19
+ /** The format identifier */
20
+ readonly format: RequestFormat;
21
+
22
+ /**
23
+ * Parse a raw request body to extract model name and metadata.
24
+ */
25
+ parseRequest(rawBody: string, headers?: Headers): ParsedRequest | null;
26
+
27
+ /**
28
+ * Extract token usage from a non-streaming response body.
29
+ */
30
+ extractTokens(responseBody: string): TokenUsage;
31
+
32
+ /**
33
+ * Extract structured content from a streaming SSE response.
34
+ */
35
+ extractStream(
36
+ raw: string,
37
+ log: CapturedLog,
38
+ fallbackModel?: string,
39
+ collectChunks?: boolean,
40
+ ): string;
41
+
42
+ /**
43
+ * Detect if a raw request body uses this format.
44
+ */
45
+ detectFormat(rawBody: string | null): boolean;
46
+ };
@@ -0,0 +1,12 @@
1
+ // Import submodules to trigger handler registration
2
+ import "./anthropic/index";
3
+ import "./openai/index";
4
+
5
+ // Import providers to trigger self-registration
6
+ import "./anthropic/anthropicProvider";
7
+ import "./openai/provider";
8
+ import "./openai/alibabaProvider";
9
+
10
+ export type { FormatHandler, ParsedRequest } from "./handler";
11
+ export { formatRegistry, formatForPath, requestFormatForPath } from "./registry";
12
+ export { registry } from "./providers";
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Shared JSON value type for streaming chunks.
5
+ * Defined in a separate file to avoid circular dependencies.
6
+ */
7
+ export type JsonValue =
8
+ | string
9
+ | number
10
+ | boolean
11
+ | null
12
+ | JsonValue[]
13
+ | { [key: string]: JsonValue };
14
+
15
+ export const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>
16
+ z.union([
17
+ z.string(),
18
+ z.number(),
19
+ z.boolean(),
20
+ z.null(),
21
+ z.array(JsonValueSchema),
22
+ z.record(z.string(), JsonValueSchema),
23
+ ]),
24
+ );
25
+
26
+ /**
27
+ * Re-types a value as `JsonValue` without re-walking it. Use this ONLY when
28
+ * the value has already been validated (e.g., via `SseEventSchema.safeParse`)
29
+ * AND originated from `JSON.parse`. Skipping the recursive `JsonValueSchema`
30
+ * walk avoids a second full-tree zod parse on every event of every streaming
31
+ * response. Centralized here so the eslint-disable is one site, not two.
32
+ */
33
+ export function trustAsJsonValue<T>(value: T): JsonValue {
34
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
35
+ return value as unknown as JsonValue;
36
+ }
@@ -0,0 +1,38 @@
1
+ import type { CapturedLog } from "../../schemas";
2
+ import type { ProviderProtocol } from "../protocol";
3
+ import { registry } from "../providers";
4
+ import { extractOpenAIStream } from "./stream";
5
+
6
+ const DEFAULT_ALIBABA_UPSTREAM = "https://dashscope.aliyuncs.com/compatible-mode/v1";
7
+
8
+ /**
9
+ * Alibaba Provider Implementation (DashScope)
10
+ */
11
+ export const alibabaProvider: ProviderProtocol = {
12
+ name: "alibaba",
13
+
14
+ matches(model: string): boolean {
15
+ // Normalize: lowercase, replace whitespace with hyphens
16
+ const m = model.toLowerCase().replace(/\s+/g, "-");
17
+ // Match glm-5* and glm-5.1* models
18
+ if (m.startsWith("glm-5")) {
19
+ return true;
20
+ }
21
+ // Match qwen models (qwen3.6-plus, qwen3.7-max, Qwen3.6 Plus, etc.)
22
+ if (m.startsWith("qwen")) {
23
+ return true;
24
+ }
25
+ return false;
26
+ },
27
+
28
+ getUpstreamBase(_isChatCompletions: boolean, _providerConfig?: { baseUrl?: string }): string {
29
+ return DEFAULT_ALIBABA_UPSTREAM;
30
+ },
31
+
32
+ extractStream(raw: string, log: CapturedLog, fallbackModel?: string): string {
33
+ return extractOpenAIStream(raw, log, fallbackModel);
34
+ },
35
+ };
36
+
37
+ // Register the provider
38
+ registry.register(alibabaProvider);
@@ -0,0 +1,96 @@
1
+ import type { FormatHandler, ParsedRequest } from "../handler";
2
+ import type { CapturedLog, TokenUsage } from "../../schemas";
3
+ import { OpenAIRequestSchema, OpenAIResponseSchema, parseOpenAIResponse } from "./schemas";
4
+ import { extractOpenAIStream } from "./stream";
5
+
6
+ export const OpenAIFormatHandler: FormatHandler = {
7
+ format: "openai",
8
+
9
+ parseRequest(rawBody: string, headers?: Headers): ParsedRequest | null {
10
+ try {
11
+ const json: unknown = JSON.parse(rawBody);
12
+ const result = OpenAIRequestSchema.safeParse(json);
13
+ if (result.success) {
14
+ return {
15
+ model: result.data.model,
16
+ sessionId: headers?.get("x-session-affinity") ?? null,
17
+ };
18
+ }
19
+ return null;
20
+ } catch {
21
+ return null;
22
+ }
23
+ },
24
+
25
+ extractTokens(responseBody: string): TokenUsage {
26
+ const parsed = parseOpenAIResponse(responseBody);
27
+ if (parsed) {
28
+ // OpenAI puts cached_tokens in usage.prompt_tokens_details (passthrough field)
29
+ let cacheReadInputTokens: number | null = null;
30
+ try {
31
+ const raw: unknown = JSON.parse(responseBody);
32
+ if (raw !== null && typeof raw === "object" && !Array.isArray(raw)) {
33
+ const usageDesc = Object.getOwnPropertyDescriptor(raw, "usage");
34
+ if (
35
+ usageDesc !== undefined &&
36
+ typeof usageDesc.value === "object" &&
37
+ usageDesc.value !== null
38
+ ) {
39
+ const detailsDesc = Object.getOwnPropertyDescriptor(
40
+ usageDesc.value,
41
+ "prompt_tokens_details",
42
+ );
43
+ if (
44
+ detailsDesc !== undefined &&
45
+ typeof detailsDesc.value === "object" &&
46
+ detailsDesc.value !== null
47
+ ) {
48
+ const cacheDesc = Object.getOwnPropertyDescriptor(detailsDesc.value, "cached_tokens");
49
+ if (cacheDesc !== undefined && typeof cacheDesc.value === "number") {
50
+ cacheReadInputTokens = cacheDesc.value;
51
+ }
52
+ }
53
+ }
54
+ }
55
+ } catch {
56
+ // ignore parse errors
57
+ }
58
+ return {
59
+ inputTokens: parsed.usage.prompt_tokens ?? null,
60
+ outputTokens: parsed.usage.completion_tokens ?? null,
61
+ cacheCreationInputTokens: null,
62
+ cacheReadInputTokens,
63
+ };
64
+ }
65
+ return {
66
+ inputTokens: null,
67
+ outputTokens: null,
68
+ cacheCreationInputTokens: null,
69
+ cacheReadInputTokens: null,
70
+ };
71
+ },
72
+
73
+ extractStream(
74
+ raw: string,
75
+ log: CapturedLog,
76
+ fallbackModel?: string,
77
+ collectChunks?: boolean,
78
+ ): string {
79
+ return extractOpenAIStream(raw, log, fallbackModel, collectChunks);
80
+ },
81
+
82
+ detectFormat(rawBody: string | null): boolean {
83
+ if (rawBody === null) return false;
84
+ try {
85
+ const json: unknown = JSON.parse(rawBody);
86
+ if (typeof json === "object" && json !== null && !Array.isArray(json)) {
87
+ const keys = Object.keys(json);
88
+ // OpenAI has `model` and `messages` at the top level, but NOT `system`
89
+ return keys.includes("model") && keys.includes("messages") && !keys.includes("system");
90
+ }
91
+ return false;
92
+ } catch {
93
+ return false;
94
+ }
95
+ },
96
+ };
@@ -0,0 +1,25 @@
1
+ // Register format handler
2
+ import "./register";
3
+
4
+ // Schemas
5
+ export {
6
+ OpenAIRequestSchema,
7
+ OpenAIResponseSchema,
8
+ OpenAISSERawChunkSchema,
9
+ OpenAIMessage,
10
+ OpenAIMessageContent,
11
+ OpenAIToolDefinition,
12
+ OpenAIChoice,
13
+ OpenAIChoiceDelta,
14
+ parseOpenAIResponse,
15
+ } from "./schemas";
16
+
17
+ // Handler
18
+ export { OpenAIFormatHandler } from "./handler";
19
+
20
+ // Stream extraction
21
+ export { extractOpenAIStream } from "./stream";
22
+
23
+ // Providers
24
+ export { openaiProvider } from "./provider";
25
+ export { alibabaProvider } from "./alibabaProvider";