mycode-cli 0.1.0__py3-none-any.whl

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 (404) hide show
  1. mycode/__init__.py +1 -0
  2. mycode/cli/__init__.py +1 -0
  3. mycode/cli/chat.py +650 -0
  4. mycode/cli/main.py +245 -0
  5. mycode/cli/render.py +693 -0
  6. mycode/cli/runtime.py +271 -0
  7. mycode/cli/theme.py +109 -0
  8. mycode/core/__init__.py +30 -0
  9. mycode/core/agent.py +515 -0
  10. mycode/core/config.py +551 -0
  11. mycode/core/messages.py +166 -0
  12. mycode/core/models.py +144 -0
  13. mycode/core/models_catalog.json +2090 -0
  14. mycode/core/providers/__init__.py +86 -0
  15. mycode/core/providers/anthropic_like.py +366 -0
  16. mycode/core/providers/base.py +351 -0
  17. mycode/core/providers/gemini.py +321 -0
  18. mycode/core/providers/openai_chat.py +356 -0
  19. mycode/core/providers/openai_responses.py +326 -0
  20. mycode/core/session.py +537 -0
  21. mycode/core/system_prompt.md +10 -0
  22. mycode/core/system_prompt.py +319 -0
  23. mycode/core/tools.py +898 -0
  24. mycode/server/__init__.py +1 -0
  25. mycode/server/app.py +52 -0
  26. mycode/server/deps.py +29 -0
  27. mycode/server/routers/__init__.py +7 -0
  28. mycode/server/routers/chat.py +320 -0
  29. mycode/server/routers/sessions.py +77 -0
  30. mycode/server/routers/workspaces.py +92 -0
  31. mycode/server/run_manager.py +195 -0
  32. mycode/server/schemas.py +66 -0
  33. mycode/server/static/assets/EditDiff-C1ql7kft.js +12 -0
  34. mycode/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  35. mycode/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  36. mycode/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  37. mycode/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  38. mycode/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  39. mycode/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  40. mycode/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  41. mycode/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  42. mycode/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  43. mycode/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  44. mycode/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  45. mycode/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  46. mycode/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  47. mycode/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  48. mycode/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  49. mycode/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  50. mycode/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  51. mycode/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  52. mycode/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  53. mycode/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  54. mycode/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  55. mycode/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  56. mycode/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  57. mycode/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  58. mycode/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  59. mycode/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  60. mycode/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  61. mycode/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  62. mycode/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  63. mycode/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  64. mycode/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  65. mycode/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  66. mycode/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  67. mycode/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  68. mycode/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  69. mycode/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  70. mycode/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  71. mycode/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  72. mycode/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  73. mycode/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  74. mycode/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  75. mycode/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  76. mycode/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  77. mycode/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  78. mycode/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  79. mycode/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  80. mycode/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  81. mycode/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  82. mycode/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  83. mycode/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  84. mycode/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  85. mycode/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  86. mycode/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  87. mycode/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  88. mycode/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  89. mycode/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  90. mycode/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  91. mycode/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  92. mycode/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  93. mycode/server/static/assets/abap-BdImnpbu.js +1 -0
  94. mycode/server/static/assets/actionscript-3-CoDkCxhg.js +1 -0
  95. mycode/server/static/assets/ada-bCR0ucgS.js +1 -0
  96. mycode/server/static/assets/andromeeda-C4gqWexZ.js +1 -0
  97. mycode/server/static/assets/angular-html-DA-rfuFy.js +1 -0
  98. mycode/server/static/assets/angular-ts-BrjP3tb8.js +1 -0
  99. mycode/server/static/assets/apache-Pmp26Uib.js +1 -0
  100. mycode/server/static/assets/apex-D8_7TLub.js +1 -0
  101. mycode/server/static/assets/apl-CORt7UWP.js +1 -0
  102. mycode/server/static/assets/applescript-Co6uUVPk.js +1 -0
  103. mycode/server/static/assets/ara-BRHolxvo.js +1 -0
  104. mycode/server/static/assets/asciidoc-Ve4PFQV2.js +1 -0
  105. mycode/server/static/assets/asm-D_Q5rh1f.js +1 -0
  106. mycode/server/static/assets/astro-HNnZUWAn.js +1 -0
  107. mycode/server/static/assets/aurora-x-D-2ljcwZ.js +1 -0
  108. mycode/server/static/assets/auto-render-xntwXHOX.js +261 -0
  109. mycode/server/static/assets/awk-DMzUqQB5.js +1 -0
  110. mycode/server/static/assets/ayu-dark-DYE7WIF3.js +1 -0
  111. mycode/server/static/assets/ayu-light-BA47KaF1.js +1 -0
  112. mycode/server/static/assets/ayu-mirage-32ctXXKs.js +1 -0
  113. mycode/server/static/assets/ballerina-BFfxhgS-.js +1 -0
  114. mycode/server/static/assets/bat-BkioyH1T.js +1 -0
  115. mycode/server/static/assets/beancount-k_qm7-4y.js +1 -0
  116. mycode/server/static/assets/berry-uYugtg8r.js +1 -0
  117. mycode/server/static/assets/bibtex-CHM0blh-.js +1 -0
  118. mycode/server/static/assets/bicep-Bmn6On1c.js +1 -0
  119. mycode/server/static/assets/bird2-BIv1doCn.js +1 -0
  120. mycode/server/static/assets/blade-BjGOyj-B.js +1 -0
  121. mycode/server/static/assets/bsl-BO_Y6i37.js +1 -0
  122. mycode/server/static/assets/c-BIGW1oBm.js +1 -0
  123. mycode/server/static/assets/c3-eo99z4R2.js +1 -0
  124. mycode/server/static/assets/cadence-Bv_4Rxtq.js +1 -0
  125. mycode/server/static/assets/cairo-KRGpt6FW.js +1 -0
  126. mycode/server/static/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  127. mycode/server/static/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  128. mycode/server/static/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  129. mycode/server/static/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  130. mycode/server/static/assets/clarity-D53aC0YG.js +1 -0
  131. mycode/server/static/assets/clojure-P80f7IUj.js +1 -0
  132. mycode/server/static/assets/cmake-D1j8_8rp.js +1 -0
  133. mycode/server/static/assets/cobol-nBiQ_Alo.js +1 -0
  134. mycode/server/static/assets/codeowners-Bp6g37R7.js +1 -0
  135. mycode/server/static/assets/codeql-DsOJ9woJ.js +1 -0
  136. mycode/server/static/assets/coffee-Ch7k5sss.js +1 -0
  137. mycode/server/static/assets/common-lisp-Cg-RD9OK.js +1 -0
  138. mycode/server/static/assets/coq-DkFqJrB1.js +1 -0
  139. mycode/server/static/assets/cpp-CofmeUqb.js +1 -0
  140. mycode/server/static/assets/crystal-DNxU26gB.js +1 -0
  141. mycode/server/static/assets/csharp-COcwbKMJ.js +1 -0
  142. mycode/server/static/assets/css-CLj8gQPS.js +1 -0
  143. mycode/server/static/assets/csv-fuZLfV_i.js +1 -0
  144. mycode/server/static/assets/cue-D82EKSYY.js +1 -0
  145. mycode/server/static/assets/cypher-COkxafJQ.js +1 -0
  146. mycode/server/static/assets/d-85-TOEBH.js +1 -0
  147. mycode/server/static/assets/dark-plus-C3mMm8J8.js +1 -0
  148. mycode/server/static/assets/dart-bE4Kk8sk.js +1 -0
  149. mycode/server/static/assets/dax-CEL-wOlO.js +1 -0
  150. mycode/server/static/assets/desktop-BmXAJ9_W.js +1 -0
  151. mycode/server/static/assets/diff-D97Zzqfu.js +1 -0
  152. mycode/server/static/assets/docker-BcOcwvcX.js +1 -0
  153. mycode/server/static/assets/dotenv-Da5cRb03.js +1 -0
  154. mycode/server/static/assets/dracula-BzJJZx-M.js +1 -0
  155. mycode/server/static/assets/dracula-soft-BXkSAIEj.js +1 -0
  156. mycode/server/static/assets/dream-maker-BtqSS_iP.js +1 -0
  157. mycode/server/static/assets/edge-FbVlp4U3.js +1 -0
  158. mycode/server/static/assets/elixir-CkH2-t6x.js +1 -0
  159. mycode/server/static/assets/elm-DbKCFpqz.js +1 -0
  160. mycode/server/static/assets/emacs-lisp-CXvaQtF9.js +1 -0
  161. mycode/server/static/assets/erb-BYCe7drp.js +1 -0
  162. mycode/server/static/assets/erlang-DsQrWhSR.js +1 -0
  163. mycode/server/static/assets/everforest-dark-BgDCqdQA.js +1 -0
  164. mycode/server/static/assets/everforest-light-C8M2exoo.js +1 -0
  165. mycode/server/static/assets/fennel-BYunw83y.js +1 -0
  166. mycode/server/static/assets/fish-BvzEVeQv.js +1 -0
  167. mycode/server/static/assets/fluent-C4IJs8-o.js +1 -0
  168. mycode/server/static/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  169. mycode/server/static/assets/fortran-free-form-BxgE0vQu.js +1 -0
  170. mycode/server/static/assets/fsharp-CXgrBDvD.js +1 -0
  171. mycode/server/static/assets/gdresource-BOOCDP_w.js +1 -0
  172. mycode/server/static/assets/gdscript-C5YyOfLZ.js +1 -0
  173. mycode/server/static/assets/gdshader-DkwncUOv.js +1 -0
  174. mycode/server/static/assets/genie-D0YGMca9.js +1 -0
  175. mycode/server/static/assets/gherkin-DyxjwDmM.js +1 -0
  176. mycode/server/static/assets/git-commit-F4YmCXRG.js +1 -0
  177. mycode/server/static/assets/git-rebase-r7XF79zn.js +1 -0
  178. mycode/server/static/assets/github-dark-DHJKELXO.js +1 -0
  179. mycode/server/static/assets/github-dark-default-Cuk6v7N8.js +1 -0
  180. mycode/server/static/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  181. mycode/server/static/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  182. mycode/server/static/assets/github-light-DAi9KRSo.js +1 -0
  183. mycode/server/static/assets/github-light-default-D7oLnXFd.js +1 -0
  184. mycode/server/static/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  185. mycode/server/static/assets/gleam-BspZqrRM.js +1 -0
  186. mycode/server/static/assets/glimmer-js-ByusRIyA.js +1 -0
  187. mycode/server/static/assets/glimmer-ts-BfAWNZQY.js +1 -0
  188. mycode/server/static/assets/glsl-DplSGwfg.js +1 -0
  189. mycode/server/static/assets/gn-n2N0HUVH.js +1 -0
  190. mycode/server/static/assets/gnuplot-DdkO51Og.js +1 -0
  191. mycode/server/static/assets/go-C27-OAKa.js +1 -0
  192. mycode/server/static/assets/graphql-ChdNCCLP.js +1 -0
  193. mycode/server/static/assets/groovy-gcz8RCvz.js +1 -0
  194. mycode/server/static/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  195. mycode/server/static/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  196. mycode/server/static/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  197. mycode/server/static/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  198. mycode/server/static/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  199. mycode/server/static/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  200. mycode/server/static/assets/hack-i7_Ulhet.js +1 -0
  201. mycode/server/static/assets/haml-D5jkg6IW.js +1 -0
  202. mycode/server/static/assets/handlebars-BpdQsYii.js +1 -0
  203. mycode/server/static/assets/haskell-Df6bDoY_.js +1 -0
  204. mycode/server/static/assets/haxe-CzTSHFRz.js +1 -0
  205. mycode/server/static/assets/hcl-BWvSN4gD.js +1 -0
  206. mycode/server/static/assets/hjson-D5-asLiD.js +1 -0
  207. mycode/server/static/assets/hlsl-D3lLCCz7.js +1 -0
  208. mycode/server/static/assets/horizon-BUw7H-hv.js +1 -0
  209. mycode/server/static/assets/horizon-bright-CUuTKBJd.js +1 -0
  210. mycode/server/static/assets/houston-DnULxvSX.js +1 -0
  211. mycode/server/static/assets/html-derivative-DlHx6ybY.js +1 -0
  212. mycode/server/static/assets/html-pp8916En.js +1 -0
  213. mycode/server/static/assets/http-jrhK8wxY.js +1 -0
  214. mycode/server/static/assets/hurl-irOxFIW8.js +1 -0
  215. mycode/server/static/assets/hxml-Bvhsp5Yf.js +1 -0
  216. mycode/server/static/assets/hy-DFXneXwc.js +1 -0
  217. mycode/server/static/assets/imba-DGztddWO.js +1 -0
  218. mycode/server/static/assets/index-B4e4WQPq.css +1 -0
  219. mycode/server/static/assets/index-C2xTNJGd.js +203 -0
  220. mycode/server/static/assets/ini-BEwlwnbL.js +1 -0
  221. mycode/server/static/assets/java-CylS5w8V.js +1 -0
  222. mycode/server/static/assets/javascript-wDzz0qaB.js +1 -0
  223. mycode/server/static/assets/jinja-f2NsQr07.js +1 -0
  224. mycode/server/static/assets/jison-wvAkD_A8.js +1 -0
  225. mycode/server/static/assets/json-Cp-IABpG.js +1 -0
  226. mycode/server/static/assets/json5-C9tS-k6U.js +1 -0
  227. mycode/server/static/assets/jsonc-Des-eS-w.js +1 -0
  228. mycode/server/static/assets/jsonl-DcaNXYhu.js +1 -0
  229. mycode/server/static/assets/jsonnet-DFQXde-d.js +1 -0
  230. mycode/server/static/assets/jssm-C2t-YnRu.js +1 -0
  231. mycode/server/static/assets/jsx-g9-lgVsj.js +1 -0
  232. mycode/server/static/assets/julia-CxzCAyBv.js +1 -0
  233. mycode/server/static/assets/just-VxiPbLrw.js +1 -0
  234. mycode/server/static/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  235. mycode/server/static/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  236. mycode/server/static/assets/kanagawa-wave-DWedfzmr.js +1 -0
  237. mycode/server/static/assets/katex-DnJR2-55.css +1 -0
  238. mycode/server/static/assets/kdl-DV7GczEv.js +1 -0
  239. mycode/server/static/assets/kotlin-BdnUsdx6.js +1 -0
  240. mycode/server/static/assets/kusto-wEQ09or8.js +1 -0
  241. mycode/server/static/assets/laserwave-DUszq2jm.js +1 -0
  242. mycode/server/static/assets/latex-CWtU0Tv5.js +1 -0
  243. mycode/server/static/assets/lean-BZvkOJ9d.js +1 -0
  244. mycode/server/static/assets/less-B1dDrJ26.js +1 -0
  245. mycode/server/static/assets/light-plus-B7mTdjB0.js +1 -0
  246. mycode/server/static/assets/liquid-C0sCDyMI.js +1 -0
  247. mycode/server/static/assets/llvm-DjAJT7YJ.js +1 -0
  248. mycode/server/static/assets/log-2UxHyX5q.js +1 -0
  249. mycode/server/static/assets/logo-BtOb2qkB.js +1 -0
  250. mycode/server/static/assets/lua-BaeVxFsk.js +1 -0
  251. mycode/server/static/assets/luau-C-HG3fhB.js +1 -0
  252. mycode/server/static/assets/make-CHLpvVh8.js +1 -0
  253. mycode/server/static/assets/markdown-Cvjx9yec.js +1 -0
  254. mycode/server/static/assets/marko-DjSrsDqO.js +1 -0
  255. mycode/server/static/assets/material-theme-D5KoaKCx.js +1 -0
  256. mycode/server/static/assets/material-theme-darker-BfHTSMKl.js +1 -0
  257. mycode/server/static/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  258. mycode/server/static/assets/material-theme-ocean-CyktbL80.js +1 -0
  259. mycode/server/static/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  260. mycode/server/static/assets/matlab-D7o27uSR.js +1 -0
  261. mycode/server/static/assets/mdc-DTYItulj.js +1 -0
  262. mycode/server/static/assets/mdx-Cmh6b_Ma.js +1 -0
  263. mycode/server/static/assets/mermaid-mWjccvbQ.js +1 -0
  264. mycode/server/static/assets/min-dark-CafNBF8u.js +1 -0
  265. mycode/server/static/assets/min-light-CTRr51gU.js +1 -0
  266. mycode/server/static/assets/mipsasm-CKIfxQSi.js +1 -0
  267. mycode/server/static/assets/mojo-rZm6bMo-.js +1 -0
  268. mycode/server/static/assets/monokai-D4h5O-jR.js +1 -0
  269. mycode/server/static/assets/moonbit-_H4v1dQx.js +1 -0
  270. mycode/server/static/assets/move-IF9eRakj.js +1 -0
  271. mycode/server/static/assets/narrat-DRg8JJMk.js +1 -0
  272. mycode/server/static/assets/nextflow-C-mBbutL.js +1 -0
  273. mycode/server/static/assets/nextflow-groovy-vE_lwT2v.js +1 -0
  274. mycode/server/static/assets/nginx-BpAMiNFr.js +1 -0
  275. mycode/server/static/assets/night-owl-C39BiMTA.js +1 -0
  276. mycode/server/static/assets/night-owl-light-CMTm3GFP.js +1 -0
  277. mycode/server/static/assets/nim-BIad80T-.js +1 -0
  278. mycode/server/static/assets/nix-CwoSXNpI.js +1 -0
  279. mycode/server/static/assets/nord-Ddv68eIx.js +1 -0
  280. mycode/server/static/assets/nushell-Cz2AlsmD.js +1 -0
  281. mycode/server/static/assets/objective-c-DXmwc3jG.js +1 -0
  282. mycode/server/static/assets/objective-cpp-CLxacb5B.js +1 -0
  283. mycode/server/static/assets/ocaml-C0hk2d4L.js +1 -0
  284. mycode/server/static/assets/odin-BBf5iR-q.js +1 -0
  285. mycode/server/static/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  286. mycode/server/static/assets/one-light-C3Wv6jpd.js +1 -0
  287. mycode/server/static/assets/openscad-C4EeE6gA.js +1 -0
  288. mycode/server/static/assets/pascal-D93ZcfNL.js +1 -0
  289. mycode/server/static/assets/perl-NvoQZIq0.js +1 -0
  290. mycode/server/static/assets/php-R6g_5hLQ.js +1 -0
  291. mycode/server/static/assets/pkl-u5AG7uiY.js +1 -0
  292. mycode/server/static/assets/plastic-3e1v2bzS.js +1 -0
  293. mycode/server/static/assets/plsql-ChMvpjG-.js +1 -0
  294. mycode/server/static/assets/po-BTJTHyun.js +1 -0
  295. mycode/server/static/assets/poimandres-CS3Unz2-.js +1 -0
  296. mycode/server/static/assets/polar-C0HS_06l.js +1 -0
  297. mycode/server/static/assets/postcss-CXtECtnM.js +1 -0
  298. mycode/server/static/assets/powerquery-CEu0bR-o.js +1 -0
  299. mycode/server/static/assets/powershell-Dpen1YoG.js +1 -0
  300. mycode/server/static/assets/prisma-Dd19v3D-.js +1 -0
  301. mycode/server/static/assets/prolog-CbFg5uaA.js +1 -0
  302. mycode/server/static/assets/proto-C7zT0LnQ.js +1 -0
  303. mycode/server/static/assets/pug-DKIMFp6K.js +1 -0
  304. mycode/server/static/assets/puppet-BMWR74SV.js +1 -0
  305. mycode/server/static/assets/purescript-CklMAg4u.js +1 -0
  306. mycode/server/static/assets/python-B6aJPvgy.js +1 -0
  307. mycode/server/static/assets/qml-3beO22l8.js +1 -0
  308. mycode/server/static/assets/qmldir-C8lEn-DE.js +1 -0
  309. mycode/server/static/assets/qss-IeuSbFQv.js +1 -0
  310. mycode/server/static/assets/r-Dspwwk_N.js +1 -0
  311. mycode/server/static/assets/racket-BqYA7rlc.js +1 -0
  312. mycode/server/static/assets/raku-DXvB9xmW.js +1 -0
  313. mycode/server/static/assets/razor-BDqjjVU7.js +1 -0
  314. mycode/server/static/assets/red-bN70gL4F.js +1 -0
  315. mycode/server/static/assets/reg-C-SQnVFl.js +1 -0
  316. mycode/server/static/assets/regexp-CDVJQ6XC.js +1 -0
  317. mycode/server/static/assets/rel-C3B-1QV4.js +1 -0
  318. mycode/server/static/assets/riscv-BM1_JUlF.js +1 -0
  319. mycode/server/static/assets/ron-D8l8udqQ.js +1 -0
  320. mycode/server/static/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  321. mycode/server/static/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  322. mycode/server/static/assets/rose-pine-qdsjHGoJ.js +1 -0
  323. mycode/server/static/assets/rosmsg-BJDFO7_C.js +1 -0
  324. mycode/server/static/assets/rst-CRjBmOyv.js +1 -0
  325. mycode/server/static/assets/ruby-Wjq7vjNf.js +1 -0
  326. mycode/server/static/assets/rust-B1yitclQ.js +1 -0
  327. mycode/server/static/assets/sas-cz2c8ADy.js +1 -0
  328. mycode/server/static/assets/sass-Cj5Yp3dK.js +1 -0
  329. mycode/server/static/assets/scala-C151Ov-r.js +1 -0
  330. mycode/server/static/assets/scheme-C98Dy4si.js +1 -0
  331. mycode/server/static/assets/scss-D5BDwBP9.js +1 -0
  332. mycode/server/static/assets/sdbl-DVxCFoDh.js +1 -0
  333. mycode/server/static/assets/shaderlab-Dg9Lc6iA.js +1 -0
  334. mycode/server/static/assets/shellscript-Yzrsuije.js +1 -0
  335. mycode/server/static/assets/shellsession-BADoaaVG.js +1 -0
  336. mycode/server/static/assets/slack-dark-BthQWCQV.js +1 -0
  337. mycode/server/static/assets/slack-ochin-DqwNpetd.js +1 -0
  338. mycode/server/static/assets/smalltalk-BERRCDM3.js +1 -0
  339. mycode/server/static/assets/snazzy-light-Bw305WKR.js +1 -0
  340. mycode/server/static/assets/solarized-dark-DXbdFlpD.js +1 -0
  341. mycode/server/static/assets/solarized-light-L9t79GZl.js +1 -0
  342. mycode/server/static/assets/solidity-rGO070M0.js +1 -0
  343. mycode/server/static/assets/soy-8wufbnw4.js +1 -0
  344. mycode/server/static/assets/sparql-rVzFXLq3.js +1 -0
  345. mycode/server/static/assets/splunk-BtCnVYZw.js +1 -0
  346. mycode/server/static/assets/sql-BLtJtn59.js +1 -0
  347. mycode/server/static/assets/ssh-config-_ykCGR6B.js +1 -0
  348. mycode/server/static/assets/stata-BH5u7GGu.js +1 -0
  349. mycode/server/static/assets/stylus-BEDo0Tqx.js +1 -0
  350. mycode/server/static/assets/surrealql-Bq5Q-fJD.js +1 -0
  351. mycode/server/static/assets/svelte-Cy7k_4gC.js +1 -0
  352. mycode/server/static/assets/swift-D82vCrfD.js +1 -0
  353. mycode/server/static/assets/synthwave-84-CbfX1IO0.js +1 -0
  354. mycode/server/static/assets/system-verilog-CnnmHF94.js +1 -0
  355. mycode/server/static/assets/systemd-4A_iFExJ.js +1 -0
  356. mycode/server/static/assets/talonscript-CkByrt1z.js +1 -0
  357. mycode/server/static/assets/tasl-QIJgUcNo.js +1 -0
  358. mycode/server/static/assets/tcl-dwOrl1Do.js +1 -0
  359. mycode/server/static/assets/templ-DhtptRzy.js +1 -0
  360. mycode/server/static/assets/terraform-BETggiCN.js +1 -0
  361. mycode/server/static/assets/tex-idrVyKtj.js +1 -0
  362. mycode/server/static/assets/tokyo-night-hegEt444.js +1 -0
  363. mycode/server/static/assets/toml-vGWfd6FD.js +1 -0
  364. mycode/server/static/assets/ts-tags-DQrlYJgV.js +1 -0
  365. mycode/server/static/assets/tsv-B_m7g4N7.js +1 -0
  366. mycode/server/static/assets/tsx-COt5Ahok.js +1 -0
  367. mycode/server/static/assets/turtle-BsS91CYL.js +1 -0
  368. mycode/server/static/assets/twig-xg9kU7Mw.js +1 -0
  369. mycode/server/static/assets/typescript-BPQ3VLAy.js +1 -0
  370. mycode/server/static/assets/typespec-CAFt9gP4.js +1 -0
  371. mycode/server/static/assets/typst-DHCkPAjA.js +1 -0
  372. mycode/server/static/assets/v-BcVCzyr7.js +1 -0
  373. mycode/server/static/assets/vala-CsfeWuGM.js +1 -0
  374. mycode/server/static/assets/vb-D17OF-Vu.js +1 -0
  375. mycode/server/static/assets/verilog-BQ8w6xss.js +1 -0
  376. mycode/server/static/assets/vesper-DU1UobuO.js +1 -0
  377. mycode/server/static/assets/vhdl-CeAyd5Ju.js +1 -0
  378. mycode/server/static/assets/viml-CJc9bBzg.js +1 -0
  379. mycode/server/static/assets/vitesse-black-Bkuqu6BP.js +1 -0
  380. mycode/server/static/assets/vitesse-dark-D0r3Knsf.js +1 -0
  381. mycode/server/static/assets/vitesse-light-CVO1_9PV.js +1 -0
  382. mycode/server/static/assets/vue-D2xRrEX4.js +1 -0
  383. mycode/server/static/assets/vue-html-AaS7Mt5G.js +1 -0
  384. mycode/server/static/assets/vue-vine-BoDAl6tE.js +1 -0
  385. mycode/server/static/assets/vyper-CDx5xZoG.js +1 -0
  386. mycode/server/static/assets/wasm-CG6Dc4jp.js +1 -0
  387. mycode/server/static/assets/wasm-MzD3tlZU.js +1 -0
  388. mycode/server/static/assets/wenyan-BV7otONQ.js +1 -0
  389. mycode/server/static/assets/wgsl-Dx-B1_4e.js +1 -0
  390. mycode/server/static/assets/wikitext-BhOHFoWU.js +1 -0
  391. mycode/server/static/assets/wit-5i3qLPDT.js +1 -0
  392. mycode/server/static/assets/wolfram-lXgVvXCa.js +1 -0
  393. mycode/server/static/assets/xml-sdJ4AIDG.js +1 -0
  394. mycode/server/static/assets/xsl-CtQFsRM5.js +1 -0
  395. mycode/server/static/assets/yaml-Buea-lGh.js +1 -0
  396. mycode/server/static/assets/zenscript-DVFEvuxE.js +1 -0
  397. mycode/server/static/assets/zig-VOosw3JB.js +1 -0
  398. mycode/server/static/favicon_slashes.svg +12 -0
  399. mycode/server/static/index.html +35 -0
  400. mycode_cli-0.1.0.dist-info/METADATA +186 -0
  401. mycode_cli-0.1.0.dist-info/RECORD +404 -0
  402. mycode_cli-0.1.0.dist-info/WHEEL +4 -0
  403. mycode_cli-0.1.0.dist-info/entry_points.txt +2 -0
  404. mycode_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
mycode/core/config.py ADDED
@@ -0,0 +1,551 @@
1
+ """Application configuration and provider resolution.
2
+
3
+ This module keeps runtime config loading intentionally simple:
4
+
5
+ - read the global config, then the workspace config
6
+ - merge provider entries by name
7
+ - resolve one runnable provider from explicit args, config defaults, or env
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import logging
14
+ import os
15
+ import re
16
+ from dataclasses import dataclass, field
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ from mycode.core.models import ModelMetadata, lookup_model_metadata
21
+ from mycode.core.providers import (
22
+ get_provider_adapter,
23
+ is_supported_provider,
24
+ list_env_discoverable_providers,
25
+ list_supported_providers,
26
+ provider_api_key_from_env,
27
+ provider_default_models,
28
+ provider_env_api_key_names,
29
+ )
30
+
31
+ _DEFAULT_MYCODE_HOME = "~/.mycode"
32
+ _API_KEY_ENV_REF_RE = re.compile(r"^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$")
33
+ _VALID_REASONING_EFFORTS = ("none", "low", "medium", "high", "xhigh")
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class ModelConfig:
38
+ context_window: int | None = None
39
+ max_output_tokens: int | None = None
40
+ supports_reasoning: bool | None = None
41
+ supports_image_input: bool | None = None
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class ProviderConfig:
46
+ name: str
47
+ type: str # internal provider adapter id: anthropic | moonshotai | minimax | …
48
+ models: dict[str, ModelConfig]
49
+ api_key: str | None = None
50
+ api_key_env_var: str | None = None
51
+ base_url: str | None = None
52
+ reasoning_effort: str | None = None
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class Settings:
57
+ providers: dict[str, ProviderConfig]
58
+ default_provider: str | None
59
+ default_model: str | None
60
+ port: int
61
+ cwd: str
62
+ workspace_root: str
63
+ default_reasoning_effort: str | None = None
64
+ compact_threshold: float | None = None
65
+ config_paths: list[str] = field(default_factory=list)
66
+
67
+
68
+ @dataclass(frozen=True)
69
+ class ResolvedProvider:
70
+ """Resolved provider ready for Agent construction."""
71
+
72
+ provider: str
73
+ model: str
74
+ api_key: str | None
75
+ api_base: str | None
76
+ reasoning_effort: str | None
77
+ max_tokens: int = 16_384
78
+ context_window: int | None = 128_000
79
+ supports_reasoning: bool | None = None
80
+ supports_image_input: bool | None = None
81
+ provider_name: str | None = None
82
+
83
+ @property
84
+ def provider_type(self) -> str:
85
+ return self.provider
86
+
87
+
88
+ def resolve_mycode_home() -> Path:
89
+ """Resolve the mycode home directory."""
90
+
91
+ raw = os.environ.get("MYCODE_HOME", _DEFAULT_MYCODE_HOME)
92
+ return Path(raw).expanduser().resolve(strict=False)
93
+
94
+
95
+ def resolve_sessions_dir() -> Path:
96
+ """Resolve the default directory used for persisted sessions."""
97
+
98
+ return resolve_mycode_home() / "sessions"
99
+
100
+
101
+ def find_workspace_root(cwd: str) -> Path:
102
+ """Resolve the project/workspace root for the current cwd."""
103
+
104
+ current = Path(cwd).expanduser().resolve(strict=False)
105
+ for parent in [current, *current.parents]:
106
+ if (parent / ".git").exists():
107
+ return parent
108
+ return current
109
+
110
+
111
+ def _load_json(path: Path) -> dict[str, Any] | None:
112
+ if not path.is_file():
113
+ return None
114
+ try:
115
+ data = json.loads(path.read_text(encoding="utf-8"))
116
+ except Exception:
117
+ return None
118
+ return data if isinstance(data, dict) else None
119
+
120
+
121
+ def _normalize_models(value: Any) -> dict[str, ModelConfig]:
122
+ if not isinstance(value, dict):
123
+ return {}
124
+
125
+ models: dict[str, ModelConfig] = {}
126
+ for model, raw in value.items():
127
+ if not isinstance(model, str):
128
+ continue
129
+ model_id = model.strip()
130
+ if not model_id:
131
+ continue
132
+ if isinstance(raw, ModelConfig):
133
+ models[model_id] = raw
134
+ continue
135
+ raw_config = raw if isinstance(raw, dict) else {}
136
+ context_window = raw_config.get("context_window")
137
+ max_output_tokens = raw_config.get("max_output_tokens")
138
+ supports_reasoning = raw_config.get("supports_reasoning")
139
+ supports_image_input = raw_config.get("supports_image_input")
140
+ models[model_id] = ModelConfig(
141
+ context_window=(
142
+ context_window if isinstance(context_window, int) and not isinstance(context_window, bool) else None
143
+ ),
144
+ max_output_tokens=max_output_tokens
145
+ if isinstance(max_output_tokens, int) and not isinstance(max_output_tokens, bool)
146
+ else None,
147
+ supports_reasoning=supports_reasoning if isinstance(supports_reasoning, bool) else None,
148
+ supports_image_input=supports_image_input if isinstance(supports_image_input, bool) else None,
149
+ )
150
+ return models
151
+
152
+
153
+ def _parse_config_api_key(value: Any) -> tuple[str | None, str | None]:
154
+ if not isinstance(value, str):
155
+ return None, None
156
+
157
+ cleaned = value.strip()
158
+ if not cleaned:
159
+ return None, None
160
+
161
+ match = _API_KEY_ENV_REF_RE.fullmatch(cleaned)
162
+ if match:
163
+ return None, match.group(1)
164
+ return cleaned, None
165
+
166
+
167
+ def _parse_compact_threshold(value: Any) -> float | None:
168
+ """Parse compact_threshold from config.
169
+
170
+ Returns ``None`` when the key should keep the current/default value, ``0.0``
171
+ when compaction is explicitly disabled, or a valid float in ``[0, 1]``.
172
+ """
173
+
174
+ if value is None:
175
+ return None
176
+ if value is False:
177
+ return 0.0
178
+
179
+ try:
180
+ threshold = float(value)
181
+ except (TypeError, ValueError):
182
+ return None
183
+
184
+ if threshold < 0 or threshold > 1:
185
+ return None
186
+ return threshold
187
+
188
+
189
+ def normalize_reasoning_effort(value: Any) -> str | None:
190
+ if not isinstance(value, str):
191
+ return None
192
+
193
+ effort = value.strip().lower()
194
+ if effort in {"", "auto", "default"}:
195
+ return None
196
+ if effort in {"off", "disabled"}:
197
+ return "none"
198
+ return effort
199
+
200
+
201
+ def _config_api_key_from_env_var(provider: ProviderConfig, *, require: bool = False) -> str | None:
202
+ env_name = provider.api_key_env_var
203
+ if not env_name:
204
+ return None
205
+
206
+ value = (os.environ.get(env_name) or "").strip()
207
+ if value:
208
+ return value
209
+
210
+ if require:
211
+ raise ValueError(f"missing API key env var {env_name!r} referenced by provider {provider.name!r}")
212
+ return None
213
+
214
+
215
+ def provider_has_api_key(provider: ProviderConfig) -> bool:
216
+ """Return whether a configured provider can authenticate right now."""
217
+
218
+ if provider.api_key_env_var:
219
+ return bool(_config_api_key_from_env_var(provider))
220
+ return bool(provider.api_key or provider_api_key_from_env(provider.type))
221
+
222
+
223
+ def _candidate_config_paths(cwd: str) -> list[Path]:
224
+ workspace_root = find_workspace_root(cwd)
225
+ return [
226
+ resolve_mycode_home() / "config.json",
227
+ workspace_root / ".mycode" / "config.json",
228
+ ]
229
+
230
+
231
+ def _build_providers(raw_providers: dict[str, dict[str, Any]]) -> dict[str, ProviderConfig]:
232
+ providers: dict[str, ProviderConfig] = {}
233
+
234
+ for name, raw in raw_providers.items():
235
+ raw_type = raw.get("type")
236
+ if raw_type:
237
+ provider_type = str(raw_type)
238
+ elif is_supported_provider(name):
239
+ # Built-in providers can be overridden by name without repeating type.
240
+ provider_type = name
241
+ else:
242
+ raise ValueError(f"provider {name!r} must set 'type'")
243
+
244
+ models = _normalize_models(raw.get("models"))
245
+ if not models:
246
+ models = {model: ModelConfig() for model in provider_default_models(provider_type)}
247
+ providers[name] = ProviderConfig(
248
+ name=name,
249
+ type=provider_type,
250
+ models=models,
251
+ api_key=raw.get("api_key") or None,
252
+ api_key_env_var=raw.get("api_key_env_var") or None,
253
+ base_url=raw.get("base_url") or None,
254
+ reasoning_effort=normalize_reasoning_effort(raw.get("reasoning_effort")),
255
+ )
256
+
257
+ return providers
258
+
259
+
260
+ def get_settings(cwd: str | None = None) -> Settings:
261
+ """Load settings from global and workspace config files."""
262
+
263
+ resolved_cwd = str(Path(cwd or os.getcwd()).expanduser().resolve(strict=False))
264
+ workspace_root = find_workspace_root(resolved_cwd)
265
+
266
+ raw_providers: dict[str, dict[str, Any]] = {}
267
+ default_provider: str | None = None
268
+ default_model: str | None = None
269
+ default_reasoning_effort: str | None = None
270
+ compact_threshold: float | None = None
271
+ config_paths: list[str] = []
272
+
273
+ for path in _candidate_config_paths(resolved_cwd):
274
+ data = _load_json(path)
275
+ if data is None:
276
+ continue
277
+
278
+ resolved_path = str(path.resolve(strict=False))
279
+ if resolved_path not in config_paths:
280
+ config_paths.append(resolved_path)
281
+
282
+ for name, raw in (data.get("providers") or {}).items():
283
+ if not isinstance(name, str) or not isinstance(raw, dict):
284
+ continue
285
+
286
+ merged = dict(raw_providers.get(name, {}))
287
+
288
+ if "type" in raw:
289
+ merged["type"] = raw.get("type") or "anthropic"
290
+ if "models" in raw:
291
+ merged["models"] = _normalize_models(raw.get("models"))
292
+ if "api_key" in raw:
293
+ api_key, api_key_env_var = _parse_config_api_key(raw.get("api_key"))
294
+ merged["api_key"] = api_key
295
+ merged["api_key_env_var"] = api_key_env_var
296
+ if "base_url" in raw:
297
+ merged["base_url"] = raw.get("base_url") or None
298
+ if "reasoning_effort" in raw:
299
+ merged["reasoning_effort"] = raw.get("reasoning_effort") or None
300
+
301
+ raw_providers[name] = merged
302
+
303
+ default = data.get("default") if isinstance(data.get("default"), dict) else {}
304
+ if "provider" in default:
305
+ value = default.get("provider")
306
+ default_provider = value if isinstance(value, str) else None
307
+ if "model" in default:
308
+ value = default.get("model")
309
+ default_model = value if isinstance(value, str) else None
310
+ if "reasoning_effort" in default:
311
+ value = default.get("reasoning_effort")
312
+ default_reasoning_effort = value if isinstance(value, str) else None
313
+ if "compact_threshold" in default:
314
+ parsed_threshold = _parse_compact_threshold(default.get("compact_threshold"))
315
+ if parsed_threshold is not None:
316
+ compact_threshold = parsed_threshold
317
+
318
+ return Settings(
319
+ providers=_build_providers(raw_providers),
320
+ default_provider=default_provider,
321
+ default_model=default_model,
322
+ default_reasoning_effort=normalize_reasoning_effort(default_reasoning_effort),
323
+ compact_threshold=compact_threshold,
324
+ port=int(os.environ.get("PORT", "8000")),
325
+ cwd=resolved_cwd,
326
+ workspace_root=str(workspace_root),
327
+ config_paths=config_paths,
328
+ )
329
+
330
+
331
+ def resolve_provider(
332
+ settings: Settings,
333
+ *,
334
+ provider_name: str | None = None,
335
+ model: str | None = None,
336
+ api_key: str | None = None,
337
+ api_base: str | None = None,
338
+ ) -> ResolvedProvider:
339
+ """Resolve provider, model, api_key, and api_base from settings and overrides."""
340
+
341
+ selected_name = (provider_name or settings.default_provider or "").strip()
342
+ if selected_name:
343
+ return _resolve_provider_runtime(
344
+ settings,
345
+ selected_name=selected_name,
346
+ model=model,
347
+ api_key=api_key,
348
+ api_base=api_base,
349
+ )
350
+
351
+ for available_name, _provider in _available_provider_references(settings):
352
+ return _resolve_provider_runtime(
353
+ settings,
354
+ selected_name=available_name,
355
+ model=model,
356
+ api_key=api_key,
357
+ api_base=api_base,
358
+ )
359
+
360
+ env_names: list[str] = []
361
+ for provider_id in list_env_discoverable_providers():
362
+ for env_name in provider_env_api_key_names(provider_id):
363
+ if env_name not in env_names:
364
+ env_names.append(env_name)
365
+ checked = ", ".join(env_names) or "<api key env>"
366
+ raise ValueError(
367
+ "no available providers found; set one of the supported API key env vars "
368
+ f"({checked}) or configure a provider in ~/.mycode/config.json or <workspace>/.mycode/config.json"
369
+ )
370
+
371
+
372
+ def resolve_provider_choices(settings: Settings) -> list[ResolvedProvider]:
373
+ """Return currently selectable providers in stable selection order."""
374
+
375
+ choices: list[ResolvedProvider] = []
376
+ for selected_name, _provider in _available_provider_references(settings):
377
+ try:
378
+ choices.append(_resolve_provider_runtime(settings, selected_name=selected_name))
379
+ except ValueError:
380
+ continue
381
+ return choices
382
+
383
+
384
+ def _available_provider_references(settings: Settings) -> list[tuple[str, ProviderConfig | None]]:
385
+ """Return usable provider references with the configured default first."""
386
+
387
+ available: list[tuple[str, ProviderConfig | None]] = []
388
+ seen: set[str] = set()
389
+ configured_types_with_credentials: set[str] = set()
390
+
391
+ def add(name: str | None) -> None:
392
+ cleaned = (name or "").strip()
393
+ if not cleaned or cleaned in seen:
394
+ return
395
+
396
+ provider_config = settings.providers.get(cleaned)
397
+ provider_type = provider_config.type if provider_config else cleaned
398
+ if not is_supported_provider(provider_type):
399
+ return
400
+
401
+ if provider_config:
402
+ if not provider_has_api_key(provider_config):
403
+ return
404
+ configured_types_with_credentials.add(provider_type)
405
+ elif not provider_api_key_from_env(provider_type):
406
+ return
407
+
408
+ seen.add(cleaned)
409
+ available.append((cleaned, provider_config))
410
+
411
+ add(settings.default_provider)
412
+
413
+ for name, provider in settings.providers.items():
414
+ if provider_has_api_key(provider):
415
+ add(name)
416
+
417
+ for provider_id in list_env_discoverable_providers():
418
+ if provider_id in configured_types_with_credentials or not provider_api_key_from_env(provider_id):
419
+ continue
420
+ add(provider_id)
421
+
422
+ return available
423
+
424
+
425
+ def _resolve_provider_runtime(
426
+ settings: Settings,
427
+ *,
428
+ selected_name: str,
429
+ model: str | None = None,
430
+ api_key: str | None = None,
431
+ api_base: str | None = None,
432
+ ) -> ResolvedProvider:
433
+ """Resolve one configured alias or raw provider id into a runnable config."""
434
+
435
+ provider_config = settings.providers.get(selected_name)
436
+ provider_type = provider_config.type if provider_config else selected_name
437
+
438
+ if not is_supported_provider(provider_type):
439
+ supported = ", ".join(list_supported_providers())
440
+ raise ValueError(f"unsupported provider {provider_type!r}; supported: {supported}")
441
+
442
+ requested_model = (model or "").strip()
443
+ if requested_model:
444
+ resolved_model = requested_model
445
+ elif provider_config and provider_config.models:
446
+ resolved_model = next(iter(provider_config.models))
447
+ elif selected_name == settings.default_provider and (settings.default_model or "").strip():
448
+ resolved_model = str(settings.default_model).strip()
449
+ else:
450
+ defaults = provider_default_models(provider_type)
451
+ if not defaults:
452
+ raise ValueError(f"provider {selected_name!r} does not define any default models")
453
+ resolved_model = defaults[0]
454
+
455
+ resolved_api_base = api_base or (provider_config.base_url if provider_config else None)
456
+ model_metadata = lookup_model_metadata(
457
+ provider_type=provider_type,
458
+ provider_name=selected_name,
459
+ model=resolved_model,
460
+ api_base=resolved_api_base,
461
+ )
462
+ if provider_config:
463
+ model_config = provider_config.models.get(resolved_model)
464
+ if model_config:
465
+ if model_metadata is None:
466
+ model_metadata = ModelMetadata(
467
+ provider=provider_type,
468
+ model=resolved_model,
469
+ context_window=model_config.context_window,
470
+ max_output_tokens=model_config.max_output_tokens,
471
+ supports_reasoning=model_config.supports_reasoning,
472
+ supports_image_input=model_config.supports_image_input,
473
+ )
474
+ else:
475
+ model_metadata = ModelMetadata(
476
+ provider=model_metadata.provider,
477
+ model=model_metadata.model,
478
+ context_window=(
479
+ model_config.context_window
480
+ if model_config.context_window is not None
481
+ else model_metadata.context_window
482
+ ),
483
+ max_output_tokens=(
484
+ model_config.max_output_tokens
485
+ if model_config.max_output_tokens is not None
486
+ else model_metadata.max_output_tokens
487
+ ),
488
+ supports_reasoning=(
489
+ model_config.supports_reasoning
490
+ if model_config.supports_reasoning is not None
491
+ else model_metadata.supports_reasoning
492
+ ),
493
+ supports_image_input=(
494
+ model_config.supports_image_input
495
+ if model_config.supports_image_input is not None
496
+ else model_metadata.supports_image_input
497
+ ),
498
+ )
499
+
500
+ configured_effort = settings.default_reasoning_effort
501
+ if provider_config and provider_config.reasoning_effort is not None:
502
+ configured_effort = provider_config.reasoning_effort
503
+
504
+ if configured_effort is not None and configured_effort not in _VALID_REASONING_EFFORTS:
505
+ supported = ", ".join(_VALID_REASONING_EFFORTS)
506
+ raise ValueError(f"unsupported reasoning_effort {configured_effort!r}; supported: {supported}")
507
+
508
+ supports_reasoning = model_metadata.supports_reasoning if model_metadata else None
509
+ supports_image_input = model_metadata.supports_image_input if model_metadata else None
510
+ adapter = get_provider_adapter(provider_type)
511
+ if (
512
+ configured_effort is None
513
+ or model_metadata is None
514
+ or supports_reasoning is not True
515
+ or not adapter.supports_reasoning_effort
516
+ ):
517
+ reasoning_effort = None
518
+ else:
519
+ reasoning_effort = configured_effort
520
+
521
+ resolved_api_key = api_key
522
+ if not resolved_api_key and provider_config:
523
+ if provider_config.api_key_env_var:
524
+ resolved_api_key = _config_api_key_from_env_var(provider_config, require=True)
525
+ elif provider_config.api_key:
526
+ resolved_api_key = provider_config.api_key
527
+ if not resolved_api_key:
528
+ resolved_api_key = provider_api_key_from_env(provider_type)
529
+
530
+ if not resolved_api_key:
531
+ checked = ", ".join(provider_env_api_key_names(provider_type)) or "<api key env>"
532
+ raise ValueError(f"provider {selected_name!r} is selected but no API key is available; checked: {checked}")
533
+
534
+ return ResolvedProvider(
535
+ provider_name=selected_name,
536
+ provider=provider_type,
537
+ model=resolved_model,
538
+ api_key=resolved_api_key,
539
+ api_base=resolved_api_base,
540
+ reasoning_effort=reasoning_effort,
541
+ max_tokens=model_metadata.max_output_tokens if model_metadata and model_metadata.max_output_tokens else 16_384,
542
+ context_window=model_metadata.context_window if model_metadata and model_metadata.context_window else 128_000,
543
+ supports_reasoning=supports_reasoning,
544
+ supports_image_input=supports_image_input,
545
+ )
546
+
547
+
548
+ def setup_logging() -> None:
549
+ """Configure default logging."""
550
+
551
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")