free-claude-code 6.2.64__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 (429) hide show
  1. free_claude_code/__init__.py +1 -0
  2. free_claude_code/api/__init__.py +1 -0
  3. free_claude_code/api/admin_cache.py +49 -0
  4. free_claude_code/api/admin_routes.py +501 -0
  5. free_claude_code/api/admin_security.py +67 -0
  6. free_claude_code/api/admin_static/admin.css +980 -0
  7. free_claude_code/api/admin_static/admin.js +1934 -0
  8. free_claude_code/api/admin_static/code_sessions.css +109 -0
  9. free_claude_code/api/admin_static/code_sessions.js +1693 -0
  10. free_claude_code/api/admin_static/form_controls.js +15 -0
  11. free_claude_code/api/admin_static/index.html +201 -0
  12. free_claude_code/api/admin_static/model_combobox.js +194 -0
  13. free_claude_code/api/admin_static/providers/LICENSE-llamacpp.txt +21 -0
  14. free_claude_code/api/admin_static/providers/LICENSE-lobe-icons.txt +21 -0
  15. free_claude_code/api/admin_static/providers/SOURCES.md +56 -0
  16. free_claude_code/api/admin_static/providers/agnesai.svg +1 -0
  17. free_claude_code/api/admin_static/providers/azure-color.svg +1 -0
  18. free_claude_code/api/admin_static/providers/bedrock-color.svg +1 -0
  19. free_claude_code/api/admin_static/providers/cerebras-color.svg +1 -0
  20. free_claude_code/api/admin_static/providers/chutes.png +0 -0
  21. free_claude_code/api/admin_static/providers/cline.svg +1 -0
  22. free_claude_code/api/admin_static/providers/cloudflare-color.svg +1 -0
  23. free_claude_code/api/admin_static/providers/cohere-color.svg +1 -0
  24. free_claude_code/api/admin_static/providers/deepinfra-color.svg +1 -0
  25. free_claude_code/api/admin_static/providers/deepseek-color.svg +1 -0
  26. free_claude_code/api/admin_static/providers/experiential.svg +9 -0
  27. free_claude_code/api/admin_static/providers/featherless-color.svg +1 -0
  28. free_claude_code/api/admin_static/providers/fireworks-color.svg +1 -0
  29. free_claude_code/api/admin_static/providers/gemini-color.svg +1 -0
  30. free_claude_code/api/admin_static/providers/githubcopilot.svg +1 -0
  31. free_claude_code/api/admin_static/providers/groq.svg +1 -0
  32. free_claude_code/api/admin_static/providers/huggingface-color.svg +1 -0
  33. free_claude_code/api/admin_static/providers/kilocode.svg +1 -0
  34. free_claude_code/api/admin_static/providers/kimi-color.svg +1 -0
  35. free_claude_code/api/admin_static/providers/lightning.png +0 -0
  36. free_claude_code/api/admin_static/providers/llamacpp.svg +77 -0
  37. free_claude_code/api/admin_static/providers/llm7.png +0 -0
  38. free_claude_code/api/admin_static/providers/lmstudio.svg +1 -0
  39. free_claude_code/api/admin_static/providers/minimax-color.svg +1 -0
  40. free_claude_code/api/admin_static/providers/mistral-color.svg +1 -0
  41. free_claude_code/api/admin_static/providers/nararoute.png +0 -0
  42. free_claude_code/api/admin_static/providers/nebius.svg +1 -0
  43. free_claude_code/api/admin_static/providers/novita-color.svg +1 -0
  44. free_claude_code/api/admin_static/providers/nvidia-color.svg +1 -0
  45. free_claude_code/api/admin_static/providers/ollama.svg +1 -0
  46. free_claude_code/api/admin_static/providers/openai.svg +1 -0
  47. free_claude_code/api/admin_static/providers/opencode.svg +1 -0
  48. free_claude_code/api/admin_static/providers/openrouter.svg +1 -0
  49. free_claude_code/api/admin_static/providers/poolside-color.svg +1 -0
  50. free_claude_code/api/admin_static/providers/qwen-color.svg +1 -0
  51. free_claude_code/api/admin_static/providers/sambanova-color.svg +1 -0
  52. free_claude_code/api/admin_static/providers/scaleway.svg +11 -0
  53. free_claude_code/api/admin_static/providers/siliconcloud-color.svg +1 -0
  54. free_claude_code/api/admin_static/providers/together-color.svg +1 -0
  55. free_claude_code/api/admin_static/providers/tokenrouter.png +0 -0
  56. free_claude_code/api/admin_static/providers/vercel.svg +1 -0
  57. free_claude_code/api/admin_static/providers/vertexai-color.svg +1 -0
  58. free_claude_code/api/admin_static/providers/wafer.png +0 -0
  59. free_claude_code/api/admin_static/providers/wandb.png +0 -0
  60. free_claude_code/api/admin_static/providers/xai.svg +1 -0
  61. free_claude_code/api/admin_static/providers/zai.svg +1 -0
  62. free_claude_code/api/admin_static/providers/zenmux.svg +1 -0
  63. free_claude_code/api/admin_static/session_layout.css +552 -0
  64. free_claude_code/api/admin_static/session_ui.js +202 -0
  65. free_claude_code/api/app.py +149 -0
  66. free_claude_code/api/code_sessions_routes.py +386 -0
  67. free_claude_code/api/command_utils.py +164 -0
  68. free_claude_code/api/dependencies.py +128 -0
  69. free_claude_code/api/detection.py +185 -0
  70. free_claude_code/api/handlers/__init__.py +7 -0
  71. free_claude_code/api/handlers/classifier_response.py +66 -0
  72. free_claude_code/api/handlers/messages.py +359 -0
  73. free_claude_code/api/handlers/responses.py +163 -0
  74. free_claude_code/api/handlers/token_count.py +87 -0
  75. free_claude_code/api/markdown.py +71 -0
  76. free_claude_code/api/model_catalog.py +282 -0
  77. free_claude_code/api/optimization_handlers.py +162 -0
  78. free_claude_code/api/ports.py +97 -0
  79. free_claude_code/api/request_errors.py +100 -0
  80. free_claude_code/api/request_ids.py +100 -0
  81. free_claude_code/api/request_lifetime.py +130 -0
  82. free_claude_code/api/response_streams.py +422 -0
  83. free_claude_code/api/routes.py +269 -0
  84. free_claude_code/api/validation_log.py +46 -0
  85. free_claude_code/application/__init__.py +1 -0
  86. free_claude_code/application/code_sessions/__init__.py +33 -0
  87. free_claude_code/application/code_sessions/models.py +227 -0
  88. free_claude_code/application/code_sessions/ports.py +197 -0
  89. free_claude_code/application/code_sessions/service.py +1123 -0
  90. free_claude_code/application/code_sessions/state.py +659 -0
  91. free_claude_code/application/connected_accounts.py +96 -0
  92. free_claude_code/application/errors.py +41 -0
  93. free_claude_code/application/execution.py +467 -0
  94. free_claude_code/application/model_catalog.py +95 -0
  95. free_claude_code/application/model_metadata.py +26 -0
  96. free_claude_code/application/ports.py +127 -0
  97. free_claude_code/application/readiness.py +43 -0
  98. free_claude_code/application/reasoning.py +134 -0
  99. free_claude_code/application/routing.py +291 -0
  100. free_claude_code/application/session_events.py +140 -0
  101. free_claude_code/application/web_tools/__init__.py +1 -0
  102. free_claude_code/application/web_tools/ports.py +35 -0
  103. free_claude_code/application/web_tools/request.py +348 -0
  104. free_claude_code/application/web_tools/service.py +481 -0
  105. free_claude_code/assets/app-icon.icns +0 -0
  106. free_claude_code/assets/app-icon.ico +0 -0
  107. free_claude_code/assets/app-icon.png +0 -0
  108. free_claude_code/assets/app-icon.svg +14 -0
  109. free_claude_code/cli/__init__.py +5 -0
  110. free_claude_code/cli/commands.py +379 -0
  111. free_claude_code/cli/desktop.py +156 -0
  112. free_claude_code/cli/desktop_assets.py +31 -0
  113. free_claude_code/cli/desktop_entrypoint.py +29 -0
  114. free_claude_code/cli/desktop_tray.py +67 -0
  115. free_claude_code/cli/entrypoints.py +25 -0
  116. free_claude_code/cli/launchers/__init__.py +1 -0
  117. free_claude_code/cli/launchers/aider.py +53 -0
  118. free_claude_code/cli/launchers/aider_config.py +80 -0
  119. free_claude_code/cli/launchers/catalog_http.py +134 -0
  120. free_claude_code/cli/launchers/claude.py +34 -0
  121. free_claude_code/cli/launchers/cline.py +60 -0
  122. free_claude_code/cli/launchers/cline_config.py +121 -0
  123. free_claude_code/cli/launchers/codex.py +47 -0
  124. free_claude_code/cli/launchers/common.py +103 -0
  125. free_claude_code/cli/launchers/dsh.py +69 -0
  126. free_claude_code/cli/launchers/dsh_config.py +124 -0
  127. free_claude_code/cli/launchers/grok.py +116 -0
  128. free_claude_code/cli/launchers/hermes.py +85 -0
  129. free_claude_code/cli/launchers/hermes_config.py +134 -0
  130. free_claude_code/cli/launchers/muse.py +68 -0
  131. free_claude_code/cli/launchers/opencode.py +83 -0
  132. free_claude_code/cli/launchers/opencode_config.py +107 -0
  133. free_claude_code/cli/launchers/pi.py +70 -0
  134. free_claude_code/cli/launchers/pi_extension.ts +190 -0
  135. free_claude_code/cli/launchers/runner.py +155 -0
  136. free_claude_code/cli/local_http.py +12 -0
  137. free_claude_code/cli/managed/__init__.py +6 -0
  138. free_claude_code/cli/managed/claude.py +225 -0
  139. free_claude_code/cli/managed/diagnostics.py +47 -0
  140. free_claude_code/cli/managed/manager.py +207 -0
  141. free_claude_code/cli/managed/session.py +293 -0
  142. free_claude_code/cli/process_registry.py +76 -0
  143. free_claude_code/cli/server_socket.py +71 -0
  144. free_claude_code/cli/uvicorn_server.py +41 -0
  145. free_claude_code/config/__init__.py +10 -0
  146. free_claude_code/config/admin/__init__.py +1 -0
  147. free_claude_code/config/admin/manifest.py +610 -0
  148. free_claude_code/config/admin/persistence.py +202 -0
  149. free_claude_code/config/admin/provider_manifest.py +443 -0
  150. free_claude_code/config/admin/specs.py +77 -0
  151. free_claude_code/config/admin/state.py +18 -0
  152. free_claude_code/config/admin/status.py +116 -0
  153. free_claude_code/config/admin/validation.py +40 -0
  154. free_claude_code/config/admin/values.py +115 -0
  155. free_claude_code/config/constants.py +9 -0
  156. free_claude_code/config/env_files.py +74 -0
  157. free_claude_code/config/env_migrations.py +457 -0
  158. free_claude_code/config/loader.py +196 -0
  159. free_claude_code/config/logging_config.py +197 -0
  160. free_claude_code/config/model_refs.py +118 -0
  161. free_claude_code/config/nim.py +121 -0
  162. free_claude_code/config/paths.py +104 -0
  163. free_claude_code/config/provider_catalog.py +746 -0
  164. free_claude_code/config/provider_proxies.py +44 -0
  165. free_claude_code/config/reasoning.py +24 -0
  166. free_claude_code/config/server_urls.py +55 -0
  167. free_claude_code/config/settings.py +812 -0
  168. free_claude_code/core/__init__.py +15 -0
  169. free_claude_code/core/anthropic/__init__.py +99 -0
  170. free_claude_code/core/anthropic/content.py +31 -0
  171. free_claude_code/core/anthropic/conversion.py +876 -0
  172. free_claude_code/core/anthropic/errors.py +97 -0
  173. free_claude_code/core/anthropic/image_sources.py +77 -0
  174. free_claude_code/core/anthropic/models.py +193 -0
  175. free_claude_code/core/anthropic/native.py +184 -0
  176. free_claude_code/core/anthropic/native_stream.py +306 -0
  177. free_claude_code/core/anthropic/request_serialization.py +57 -0
  178. free_claude_code/core/anthropic/request_snapshot.py +35 -0
  179. free_claude_code/core/anthropic/server_tool_sse.py +234 -0
  180. free_claude_code/core/anthropic/server_tool_types.py +9 -0
  181. free_claude_code/core/anthropic/sse_aggregation.py +144 -0
  182. free_claude_code/core/anthropic/stream_contracts.py +208 -0
  183. free_claude_code/core/anthropic/streaming/__init__.py +43 -0
  184. free_claude_code/core/anthropic/streaming/decoder.py +49 -0
  185. free_claude_code/core/anthropic/streaming/emitter.py +62 -0
  186. free_claude_code/core/anthropic/streaming/ledger.py +538 -0
  187. free_claude_code/core/anthropic/streaming/recovery.py +211 -0
  188. free_claude_code/core/anthropic/thinking.py +140 -0
  189. free_claude_code/core/anthropic/tokens.py +111 -0
  190. free_claude_code/core/anthropic/tool_results.py +63 -0
  191. free_claude_code/core/anthropic/tool_schema.py +94 -0
  192. free_claude_code/core/anthropic/tools.py +493 -0
  193. free_claude_code/core/anthropic/usage.py +38 -0
  194. free_claude_code/core/anthropic/utils.py +9 -0
  195. free_claude_code/core/async_iterators.py +26 -0
  196. free_claude_code/core/async_tasks.py +26 -0
  197. free_claude_code/core/data/README.md +12 -0
  198. free_claude_code/core/data/TIKTOKEN-LICENSE +21 -0
  199. free_claude_code/core/data/cl100k_base.tiktoken +100256 -0
  200. free_claude_code/core/diagnostics.py +319 -0
  201. free_claude_code/core/failures.py +50 -0
  202. free_claude_code/core/gateway_model_ids.py +73 -0
  203. free_claude_code/core/history_replay.py +561 -0
  204. free_claude_code/core/interprocess_lock.py +90 -0
  205. free_claude_code/core/json_types.py +7 -0
  206. free_claude_code/core/model_capabilities.py +10 -0
  207. free_claude_code/core/openai_chat.py +54 -0
  208. free_claude_code/core/openai_responses/__init__.py +90 -0
  209. free_claude_code/core/openai_responses/chat_request.py +747 -0
  210. free_claude_code/core/openai_responses/errors.py +78 -0
  211. free_claude_code/core/openai_responses/events.py +82 -0
  212. free_claude_code/core/openai_responses/ids.py +32 -0
  213. free_claude_code/core/openai_responses/items.py +35 -0
  214. free_claude_code/core/openai_responses/messages_request.py +624 -0
  215. free_claude_code/core/openai_responses/messages_stream.py +404 -0
  216. free_claude_code/core/openai_responses/models.py +33 -0
  217. free_claude_code/core/openai_responses/native.py +147 -0
  218. free_claude_code/core/openai_responses/provider_input.py +409 -0
  219. free_claude_code/core/openai_responses/provider_stream.py +282 -0
  220. free_claude_code/core/openai_responses/reasoning.py +73 -0
  221. free_claude_code/core/openai_responses/streaming/__init__.py +1 -0
  222. free_claude_code/core/openai_responses/streaming/blocks.py +36 -0
  223. free_claude_code/core/openai_responses/streaming/completion.py +169 -0
  224. free_claude_code/core/openai_responses/streaming/error_mapping.py +28 -0
  225. free_claude_code/core/openai_responses/streaming/event_builders.py +198 -0
  226. free_claude_code/core/openai_responses/streaming/ledger.py +96 -0
  227. free_claude_code/core/openai_responses/tokens.py +133 -0
  228. free_claude_code/core/openai_responses/tool_adaptation.py +828 -0
  229. free_claude_code/core/openai_responses/tool_search.py +204 -0
  230. free_claude_code/core/openai_responses/tools.py +169 -0
  231. free_claude_code/core/openai_tool_names.py +178 -0
  232. free_claude_code/core/rate_limit.py +72 -0
  233. free_claude_code/core/reasoning.py +136 -0
  234. free_claude_code/core/token_estimation.py +76 -0
  235. free_claude_code/core/tool_schema_patterns.py +168 -0
  236. free_claude_code/core/trace.py +197 -0
  237. free_claude_code/core/version.py +15 -0
  238. free_claude_code/core/web_tools.py +17 -0
  239. free_claude_code/core/windows_dpi.py +27 -0
  240. free_claude_code/harnesses/__init__.py +1 -0
  241. free_claude_code/harnesses/claude.py +42 -0
  242. free_claude_code/harnesses/claude_desktop_integration.py +418 -0
  243. free_claude_code/harnesses/claude_integration.py +167 -0
  244. free_claude_code/harnesses/codex.py +94 -0
  245. free_claude_code/harnesses/codex_integration.py +147 -0
  246. free_claude_code/harnesses/codex_model_catalog.py +109 -0
  247. free_claude_code/harnesses/config_file.py +33 -0
  248. free_claude_code/harnesses/environment.py +78 -0
  249. free_claude_code/harnesses/jetbrains_acp_integration.py +242 -0
  250. free_claude_code/harnesses/launch.py +21 -0
  251. free_claude_code/harnesses/resources.py +42 -0
  252. free_claude_code/messaging/__init__.py +16 -0
  253. free_claude_code/messaging/cli_event_constants.py +67 -0
  254. free_claude_code/messaging/command_context.py +99 -0
  255. free_claude_code/messaging/command_dispatcher.py +31 -0
  256. free_claude_code/messaging/commands.py +182 -0
  257. free_claude_code/messaging/event_parser.py +184 -0
  258. free_claude_code/messaging/limiter.py +342 -0
  259. free_claude_code/messaging/managed_protocols.py +35 -0
  260. free_claude_code/messaging/models.py +57 -0
  261. free_claude_code/messaging/node_event_pipeline.py +120 -0
  262. free_claude_code/messaging/node_runner.py +408 -0
  263. free_claude_code/messaging/platforms/__init__.py +20 -0
  264. free_claude_code/messaging/platforms/discord.py +319 -0
  265. free_claude_code/messaging/platforms/discord_inbound.py +112 -0
  266. free_claude_code/messaging/platforms/discord_io.py +167 -0
  267. free_claude_code/messaging/platforms/factory.py +109 -0
  268. free_claude_code/messaging/platforms/outbox.py +143 -0
  269. free_claude_code/messaging/platforms/ports.py +99 -0
  270. free_claude_code/messaging/platforms/telegram.py +300 -0
  271. free_claude_code/messaging/platforms/telegram_inbound.py +133 -0
  272. free_claude_code/messaging/platforms/telegram_io.py +287 -0
  273. free_claude_code/messaging/platforms/voice_flow.py +388 -0
  274. free_claude_code/messaging/rendering/__init__.py +3 -0
  275. free_claude_code/messaging/rendering/discord_markdown.py +318 -0
  276. free_claude_code/messaging/rendering/markdown_tables.py +47 -0
  277. free_claude_code/messaging/rendering/profiles.py +53 -0
  278. free_claude_code/messaging/rendering/telegram_markdown.py +331 -0
  279. free_claude_code/messaging/safe_diagnostics.py +15 -0
  280. free_claude_code/messaging/session/__init__.py +5 -0
  281. free_claude_code/messaging/session/managed_message_log.py +135 -0
  282. free_claude_code/messaging/session/persistence.py +161 -0
  283. free_claude_code/messaging/session/store.py +162 -0
  284. free_claude_code/messaging/transcript/__init__.py +6 -0
  285. free_claude_code/messaging/transcript/buffer.py +220 -0
  286. free_claude_code/messaging/transcript/context.py +18 -0
  287. free_claude_code/messaging/transcript/renderer.py +65 -0
  288. free_claude_code/messaging/transcript/segments.py +176 -0
  289. free_claude_code/messaging/transcript/subagents.py +108 -0
  290. free_claude_code/messaging/transcription.py +132 -0
  291. free_claude_code/messaging/trees/__init__.py +41 -0
  292. free_claude_code/messaging/trees/graph.py +250 -0
  293. free_claude_code/messaging/trees/identity.py +16 -0
  294. free_claude_code/messaging/trees/manager.py +587 -0
  295. free_claude_code/messaging/trees/node.py +56 -0
  296. free_claude_code/messaging/trees/processor.py +272 -0
  297. free_claude_code/messaging/trees/queue.py +47 -0
  298. free_claude_code/messaging/trees/repository.py +135 -0
  299. free_claude_code/messaging/trees/runtime.py +487 -0
  300. free_claude_code/messaging/trees/snapshot.py +221 -0
  301. free_claude_code/messaging/trees/transitions.py +174 -0
  302. free_claude_code/messaging/turn_intake.py +241 -0
  303. free_claude_code/messaging/ui_updates.py +99 -0
  304. free_claude_code/messaging/voice.py +376 -0
  305. free_claude_code/messaging/workflow.py +714 -0
  306. free_claude_code/providers/__init__.py +12 -0
  307. free_claude_code/providers/admission.py +942 -0
  308. free_claude_code/providers/anthropic_messages/__init__.py +1 -0
  309. free_claude_code/providers/anthropic_messages/request_policy.py +162 -0
  310. free_claude_code/providers/anthropic_messages/transport.py +499 -0
  311. free_claude_code/providers/base.py +73 -0
  312. free_claude_code/providers/cloudflare/__init__.py +8 -0
  313. free_claude_code/providers/cloudflare/client.py +166 -0
  314. free_claude_code/providers/credential_validation.py +314 -0
  315. free_claude_code/providers/deepseek/__init__.py +5 -0
  316. free_claude_code/providers/deepseek/client.py +117 -0
  317. free_claude_code/providers/deepseek/compat.py +241 -0
  318. free_claude_code/providers/endpoint.py +21 -0
  319. free_claude_code/providers/endpoint_types.py +21 -0
  320. free_claude_code/providers/failure_policy.py +574 -0
  321. free_claude_code/providers/gemini/__init__.py +5 -0
  322. free_claude_code/providers/gemini/client.py +42 -0
  323. free_claude_code/providers/github_copilot/__init__.py +1 -0
  324. free_claude_code/providers/github_copilot/auth.py +502 -0
  325. free_claude_code/providers/github_copilot/broker.py +248 -0
  326. free_claude_code/providers/github_copilot/lifecycle.py +18 -0
  327. free_claude_code/providers/github_copilot/login.py +112 -0
  328. free_claude_code/providers/github_copilot/native_cli.py +82 -0
  329. free_claude_code/providers/github_copilot/provider.py +367 -0
  330. free_claude_code/providers/github_copilot/request_policy.py +119 -0
  331. free_claude_code/providers/github_copilot/responses_events.py +90 -0
  332. free_claude_code/providers/github_copilot/sdk.py +496 -0
  333. free_claude_code/providers/github_copilot/types.py +67 -0
  334. free_claude_code/providers/google_openai/__init__.py +17 -0
  335. free_claude_code/providers/google_openai/provider.py +73 -0
  336. free_claude_code/providers/google_openai/reasoning.py +150 -0
  337. free_claude_code/providers/google_openai/thought_signatures.py +117 -0
  338. free_claude_code/providers/groq/__init__.py +5 -0
  339. free_claude_code/providers/groq/client.py +342 -0
  340. free_claude_code/providers/groq/tpm.py +114 -0
  341. free_claude_code/providers/history_replay.py +260 -0
  342. free_claude_code/providers/http.py +105 -0
  343. free_claude_code/providers/kilo/__init__.py +5 -0
  344. free_claude_code/providers/kilo/client.py +45 -0
  345. free_claude_code/providers/kilo/models.py +60 -0
  346. free_claude_code/providers/lmstudio/__init__.py +5 -0
  347. free_claude_code/providers/lmstudio/client.py +220 -0
  348. free_claude_code/providers/mistral/__init__.py +5 -0
  349. free_claude_code/providers/mistral/client.py +91 -0
  350. free_claude_code/providers/mistral/reasoning.py +410 -0
  351. free_claude_code/providers/model_listing.py +479 -0
  352. free_claude_code/providers/nvidia_nim/__init__.py +5 -0
  353. free_claude_code/providers/nvidia_nim/client.py +224 -0
  354. free_claude_code/providers/nvidia_nim/native_tool_stream.py +693 -0
  355. free_claude_code/providers/nvidia_nim/request_options.py +141 -0
  356. free_claude_code/providers/nvidia_nim/retry.py +85 -0
  357. free_claude_code/providers/nvidia_nim/tool_schema.py +255 -0
  358. free_claude_code/providers/nvidia_nim/voice.py +107 -0
  359. free_claude_code/providers/open_router/__init__.py +5 -0
  360. free_claude_code/providers/open_router/client.py +113 -0
  361. free_claude_code/providers/openai_api/__init__.py +5 -0
  362. free_claude_code/providers/openai_api/provider.py +150 -0
  363. free_claude_code/providers/openai_chat/__init__.py +72 -0
  364. free_claude_code/providers/openai_chat/base_url.py +7 -0
  365. free_claude_code/providers/openai_chat/behavior.py +133 -0
  366. free_claude_code/providers/openai_chat/client.py +40 -0
  367. free_claude_code/providers/openai_chat/extra_body.py +63 -0
  368. free_claude_code/providers/openai_chat/output_cap.py +161 -0
  369. free_claude_code/providers/openai_chat/profiles.py +778 -0
  370. free_claude_code/providers/openai_chat/provider.py +244 -0
  371. free_claude_code/providers/openai_chat/reasoning.py +169 -0
  372. free_claude_code/providers/openai_chat/reasoning_details.py +128 -0
  373. free_claude_code/providers/openai_chat/request_policy.py +140 -0
  374. free_claude_code/providers/openai_chat/stream_output.py +752 -0
  375. free_claude_code/providers/openai_chat/tool_calls.py +462 -0
  376. free_claude_code/providers/openai_chat/transport.py +1643 -0
  377. free_claude_code/providers/openai_chat/usage.py +117 -0
  378. free_claude_code/providers/openai_client.py +74 -0
  379. free_claude_code/providers/openai_codex/__init__.py +1 -0
  380. free_claude_code/providers/openai_codex/auth.py +626 -0
  381. free_claude_code/providers/openai_codex/endpoint.py +53 -0
  382. free_claude_code/providers/openai_codex/login.py +265 -0
  383. free_claude_code/providers/openai_codex/provider.py +259 -0
  384. free_claude_code/providers/openai_responses/__init__.py +5 -0
  385. free_claude_code/providers/openai_responses/presentation.py +115 -0
  386. free_claude_code/providers/openai_responses/transport.py +621 -0
  387. free_claude_code/providers/openai_stream.py +21 -0
  388. free_claude_code/providers/opencode/__init__.py +5 -0
  389. free_claude_code/providers/opencode/catalog.py +340 -0
  390. free_claude_code/providers/opencode/provider.py +359 -0
  391. free_claude_code/providers/reasoning_compatibility.py +199 -0
  392. free_claude_code/providers/request_recovery.py +122 -0
  393. free_claude_code/providers/runtime/__init__.py +10 -0
  394. free_claude_code/providers/runtime/config.py +91 -0
  395. free_claude_code/providers/runtime/discovery.py +63 -0
  396. free_claude_code/providers/runtime/factory.py +282 -0
  397. free_claude_code/providers/runtime/model_cache.py +93 -0
  398. free_claude_code/providers/runtime/runtime.py +108 -0
  399. free_claude_code/providers/stream_recovery.py +164 -0
  400. free_claude_code/providers/vertex/__init__.py +5 -0
  401. free_claude_code/providers/vertex/auth.py +105 -0
  402. free_claude_code/providers/vertex/client.py +140 -0
  403. free_claude_code/providers/vertex/endpoint.py +50 -0
  404. free_claude_code/providers/vertex/models.py +52 -0
  405. free_claude_code/runtime/__init__.py +1 -0
  406. free_claude_code/runtime/application.py +1121 -0
  407. free_claude_code/runtime/asgi.py +63 -0
  408. free_claude_code/runtime/bootstrap.py +153 -0
  409. free_claude_code/runtime/code_sessions_sqlite.py +785 -0
  410. free_claude_code/runtime/codex_app_server.py +775 -0
  411. free_claude_code/runtime/codex_catalog.py +62 -0
  412. free_claude_code/runtime/codex_protocol.py +662 -0
  413. free_claude_code/runtime/configuration.py +53 -0
  414. free_claude_code/runtime/folder_picker.py +134 -0
  415. free_claude_code/runtime/native_folder_dialog.py +123 -0
  416. free_claude_code/runtime/provider_manager.py +716 -0
  417. free_claude_code/runtime/retired_chat.py +47 -0
  418. free_claude_code/runtime/web_tools/__init__.py +1 -0
  419. free_claude_code/runtime/web_tools/client.py +238 -0
  420. free_claude_code/runtime/web_tools/constants.py +17 -0
  421. free_claude_code/runtime/web_tools/egress.py +89 -0
  422. free_claude_code/runtime/web_tools/parsers.py +78 -0
  423. free_claude_code-6.2.64.data/scripts/fcc-update +4 -0
  424. free_claude_code-6.2.64.data/scripts/fcc-update.cmd +5 -0
  425. free_claude_code-6.2.64.dist-info/METADATA +555 -0
  426. free_claude_code-6.2.64.dist-info/RECORD +429 -0
  427. free_claude_code-6.2.64.dist-info/WHEEL +4 -0
  428. free_claude_code-6.2.64.dist-info/entry_points.txt +15 -0
  429. free_claude_code-6.2.64.dist-info/licenses/LICENSE +239 -0
@@ -0,0 +1,272 @@
1
+ """Task execution for claims returned by messaging tree aggregates."""
2
+
3
+ import asyncio
4
+ import contextlib
5
+ from collections.abc import Awaitable, Callable
6
+ from dataclasses import dataclass
7
+
8
+ from loguru import logger
9
+
10
+ from ..safe_diagnostics import format_exception_for_log
11
+ from .runtime import MessageTree
12
+ from .transitions import CancellationReason, NodeClaim, QueueEntry
13
+
14
+ NodeProcessor = Callable[[NodeClaim], Awaitable[None]]
15
+ QueueUpdateCallback = Callable[[tuple[QueueEntry, ...]], Awaitable[None]]
16
+ NodeStartedCallback = Callable[[NodeClaim], Awaitable[None]]
17
+ ClaimFailureCallback = Callable[[NodeClaim], Awaitable[None]]
18
+ ClaimFinishedCallback = Callable[[MessageTree, NodeClaim], Awaitable[None]]
19
+
20
+
21
+ @dataclass(slots=True)
22
+ class _TaskSlot:
23
+ tree: MessageTree
24
+ claim: NodeClaim
25
+ task: asyncio.Task[None] | None = None
26
+ runner_started: bool = False
27
+ transitioned: bool = False
28
+ recovery_task: asyncio.Task[None] | None = None
29
+ cancellation_requested: bool = False
30
+ cancellation_reason: CancellationReason | None = None
31
+
32
+
33
+ @dataclass(frozen=True, slots=True)
34
+ class CancelledTask:
35
+ """Task handle plus whether the node runner owns cancellation UI."""
36
+
37
+ task: asyncio.Task[None]
38
+ runner_started: bool
39
+
40
+
41
+ class TreeQueueProcessor:
42
+ """Own asyncio tasks while MessageTree owns scheduling state."""
43
+
44
+ def __init__(
45
+ self,
46
+ node_processor: NodeProcessor,
47
+ *,
48
+ claim_failure_callback: ClaimFailureCallback,
49
+ claim_finished_callback: ClaimFinishedCallback,
50
+ queue_update_callback: QueueUpdateCallback | None = None,
51
+ node_started_callback: NodeStartedCallback | None = None,
52
+ log_messaging_error_details: bool = False,
53
+ ) -> None:
54
+ self._node_processor = node_processor
55
+ self._claim_failure_callback = claim_failure_callback
56
+ self._claim_finished_callback = claim_finished_callback
57
+ self._queue_update_callback = queue_update_callback
58
+ self._node_started_callback = node_started_callback
59
+ self._log_messaging_error_details = log_messaging_error_details
60
+ self._tasks: dict[str, _TaskSlot] = {}
61
+ self._completion_failures: list[Exception] = []
62
+ self._idle = asyncio.Event()
63
+ self._idle.set()
64
+
65
+ @staticmethod
66
+ def _key(claim: NodeClaim) -> str:
67
+ return claim.claim_id
68
+
69
+ def launch(
70
+ self,
71
+ tree: MessageTree,
72
+ claim: NodeClaim,
73
+ *,
74
+ announce_started: bool = False,
75
+ queue: tuple[QueueEntry, ...] = (),
76
+ ) -> None:
77
+ """Attach a task synchronously before another coroutine can cancel it."""
78
+ key = self._key(claim)
79
+ if key in self._tasks:
80
+ raise RuntimeError(f"Claim {key} already has a task")
81
+ slot = _TaskSlot(tree=tree, claim=claim)
82
+ self._tasks[key] = slot
83
+ self._idle.clear()
84
+ ownership_ready = asyncio.Event()
85
+ claim_runner = self._run_claim(
86
+ slot,
87
+ ownership_ready=ownership_ready,
88
+ announce_started=announce_started,
89
+ queue=queue,
90
+ )
91
+ try:
92
+ task = asyncio.create_task(
93
+ claim_runner,
94
+ name=(f"messaging-claim-{claim.identity.root_id}-{claim.claim_id[:8]}"),
95
+ )
96
+ except BaseException:
97
+ claim_runner.close()
98
+ if self._tasks.get(key) is slot:
99
+ self._tasks.pop(key)
100
+ if not self._tasks:
101
+ self._idle.set()
102
+ raise
103
+ slot.task = task
104
+ task.add_done_callback(lambda _task, claim_key=key: self._task_done(claim_key))
105
+ ownership_ready.set()
106
+
107
+ def _task_done(self, key: str) -> None:
108
+ """Recover a claim if its task was cancelled before entering its body."""
109
+ slot = self._tasks.get(key)
110
+ if slot is None or slot.transitioned or slot.recovery_task is not None:
111
+ return
112
+ slot.recovery_task = asyncio.create_task(
113
+ self._recover_unentered_task(slot),
114
+ name=f"messaging-claim-recovery-{key[:8]}",
115
+ )
116
+
117
+ async def _recover_unentered_task(self, slot: _TaskSlot) -> None:
118
+ task = slot.task
119
+ if task is not None:
120
+ with contextlib.suppress(asyncio.CancelledError, Exception):
121
+ await task
122
+ if not slot.transitioned:
123
+ await self._finish_and_continue(slot)
124
+
125
+ async def _notify_queue_updated(self, queue: tuple[QueueEntry, ...]) -> None:
126
+ if self._queue_update_callback is None:
127
+ return
128
+ try:
129
+ await self._queue_update_callback(queue)
130
+ except Exception as exc:
131
+ logger.warning(
132
+ "Queue update callback failed: {}",
133
+ format_exception_for_log(
134
+ exc,
135
+ log_full_message=self._log_messaging_error_details,
136
+ ),
137
+ )
138
+
139
+ async def notify_queue_updated(self, queue: tuple[QueueEntry, ...]) -> None:
140
+ """Publish a transition-owned queue snapshot."""
141
+ await self._notify_queue_updated(queue)
142
+
143
+ async def _notify_node_started(self, claim: NodeClaim) -> None:
144
+ if self._node_started_callback is None:
145
+ return
146
+ try:
147
+ await self._node_started_callback(claim)
148
+ except Exception as exc:
149
+ logger.warning(
150
+ "Node started callback failed: {}",
151
+ format_exception_for_log(
152
+ exc,
153
+ log_full_message=self._log_messaging_error_details,
154
+ ),
155
+ )
156
+
157
+ async def _run_claim(
158
+ self,
159
+ slot: _TaskSlot,
160
+ *,
161
+ ownership_ready: asyncio.Event,
162
+ announce_started: bool,
163
+ queue: tuple[QueueEntry, ...],
164
+ ) -> None:
165
+ await ownership_ready.wait()
166
+ claim = slot.claim
167
+ try:
168
+ if announce_started:
169
+ await self._notify_node_started(claim)
170
+ await self._notify_queue_updated(queue)
171
+ if slot.cancellation_requested:
172
+ if slot.cancellation_reason is None:
173
+ raise asyncio.CancelledError
174
+ raise asyncio.CancelledError(slot.cancellation_reason)
175
+ slot.runner_started = True
176
+ await self._node_processor(claim)
177
+ except asyncio.CancelledError:
178
+ logger.info("Task for node {} was cancelled", claim.node.node_id)
179
+ raise
180
+ except Exception as exc:
181
+ logger.error(
182
+ "Error processing node {}: {}",
183
+ claim.node.node_id,
184
+ format_exception_for_log(
185
+ exc,
186
+ log_full_message=self._log_messaging_error_details,
187
+ ),
188
+ )
189
+ await self._claim_failure_callback(claim)
190
+ finally:
191
+ if not slot.transitioned:
192
+ await self._finish_and_continue(slot)
193
+
194
+ async def _finish_and_continue(self, slot: _TaskSlot) -> None:
195
+ current = asyncio.current_task()
196
+ if current is not None:
197
+ while current.cancelling():
198
+ current.uncancel()
199
+ try:
200
+ while True:
201
+ try:
202
+ await self._claim_finished_callback(slot.tree, slot.claim)
203
+ slot.transitioned = True
204
+ break
205
+ except asyncio.CancelledError:
206
+ if current is not None:
207
+ while current.cancelling():
208
+ current.uncancel()
209
+ continue
210
+ except Exception as exc:
211
+ self._completion_failures.append(exc)
212
+ logger.error(
213
+ "Claim completion callback failed for node {}: {}",
214
+ slot.claim.node.node_id,
215
+ format_exception_for_log(
216
+ exc,
217
+ log_full_message=self._log_messaging_error_details,
218
+ ),
219
+ )
220
+ finally:
221
+ key = self._key(slot.claim)
222
+ if self._tasks.get(key) is slot:
223
+ self._tasks.pop(key)
224
+ if not self._tasks:
225
+ self._idle.set()
226
+
227
+ def cancel(
228
+ self,
229
+ claim: NodeClaim,
230
+ reason: CancellationReason | None,
231
+ ) -> CancelledTask | None:
232
+ """Cancel exactly the task bound to one aggregate claim."""
233
+ slot = self._tasks.get(self._key(claim))
234
+ if slot is None:
235
+ return None
236
+ slot.cancellation_requested = True
237
+ slot.cancellation_reason = reason
238
+ task = slot.task
239
+ if task is None or task.done():
240
+ return None
241
+ if reason is None:
242
+ task.cancel()
243
+ else:
244
+ task.cancel(reason)
245
+
246
+ if slot.runner_started:
247
+ return CancelledTask(task=task, runner_started=True)
248
+
249
+ if slot.recovery_task is None:
250
+ slot.recovery_task = asyncio.create_task(
251
+ self._recover_unentered_task(slot),
252
+ name=f"messaging-claim-recovery-{claim.claim_id[:8]}",
253
+ )
254
+ return CancelledTask(task=slot.recovery_task, runner_started=False)
255
+
256
+ def task_count(self) -> int:
257
+ """Return the number of attached claims for observability."""
258
+ return len(self._tasks)
259
+
260
+ async def wait_idle(self) -> None:
261
+ """Wait for every task and hand completion failures to the caller once."""
262
+ await self._idle.wait()
263
+ if not self._completion_failures:
264
+ return
265
+ failures = self._completion_failures
266
+ self._completion_failures = []
267
+ if len(failures) == 1:
268
+ raise failures[0]
269
+ raise ExceptionGroup("Messaging claim completion failures", failures)
270
+
271
+
272
+ __all__ = ["CancelledTask", "TreeQueueProcessor"]
@@ -0,0 +1,47 @@
1
+ """FIFO queue state for one messaging conversation tree."""
2
+
3
+ from collections import deque
4
+
5
+
6
+ class MessageNodeQueue:
7
+ """Queue with snapshot/remove helpers, backed by a deque and a set index."""
8
+
9
+ def __init__(self, items: list[str] | None = None) -> None:
10
+ self._deque: deque[str] = deque()
11
+ self._set: set[str] = set()
12
+ for item in items or []:
13
+ self.put(item)
14
+
15
+ def put(self, item: str) -> bool:
16
+ """Append a unique item and report whether the queue changed."""
17
+ if item in self._set:
18
+ return False
19
+ self._deque.append(item)
20
+ self._set.add(item)
21
+ return True
22
+
23
+ def pop(self) -> str | None:
24
+ if not self._deque:
25
+ return None
26
+ item = self._deque.popleft()
27
+ self._set.discard(item)
28
+ return item
29
+
30
+ def qsize(self) -> int:
31
+ return len(self._deque)
32
+
33
+ def items(self) -> tuple[str, ...]:
34
+ return tuple(self._deque)
35
+
36
+ def remove(self, item: str) -> bool:
37
+ if item not in self._set:
38
+ return False
39
+ self._set.discard(item)
40
+ self._deque = deque(x for x in self._deque if x != item)
41
+ return True
42
+
43
+ def drain(self) -> tuple[str, ...]:
44
+ items = tuple(self._deque)
45
+ self._deque.clear()
46
+ self._set.clear()
47
+ return items
@@ -0,0 +1,135 @@
1
+ """Manager-owned index of messaging tree aggregates."""
2
+
3
+ from loguru import logger
4
+
5
+ from ..models import MessageScope
6
+ from .identity import TreeIdentity
7
+ from .runtime import MessageTree
8
+ from .snapshot import ConversationSnapshot
9
+ from .transitions import NodeUiTarget
10
+
11
+
12
+ class TreeRepository:
13
+ """Store aggregates and map node/status references to their root."""
14
+
15
+ def __init__(self) -> None:
16
+ self._trees: dict[TreeIdentity, MessageTree] = {}
17
+ self._reference_to_tree: dict[tuple[MessageScope, str], TreeIdentity] = {}
18
+
19
+ def get_tree(self, identity: TreeIdentity) -> MessageTree | None:
20
+ return self._trees.get(identity)
21
+
22
+ def get_tree_for_reference(
23
+ self,
24
+ scope: MessageScope,
25
+ reference_id: str,
26
+ ) -> MessageTree | None:
27
+ identity = self._reference_to_tree.get((scope, reference_id))
28
+ return self._trees.get(identity) if identity is not None else None
29
+
30
+ def has_reference(self, scope: MessageScope, reference_id: str) -> bool:
31
+ return (scope, reference_id) in self._reference_to_tree
32
+
33
+ def add_tree(
34
+ self,
35
+ tree: MessageTree,
36
+ *,
37
+ node_id: str,
38
+ status_message_id: str,
39
+ ) -> None:
40
+ identity = tree.identity
41
+ if identity in self._trees:
42
+ raise ValueError(f"Tree {identity} already exists")
43
+ self.register_node(
44
+ identity=identity,
45
+ node_id=node_id,
46
+ status_message_id=status_message_id,
47
+ )
48
+ self._trees[identity] = tree
49
+ logger.debug("TREE_REPO: add_tree identity={}", identity)
50
+
51
+ def register_node(
52
+ self,
53
+ *,
54
+ identity: TreeIdentity,
55
+ node_id: str,
56
+ status_message_id: str,
57
+ ) -> None:
58
+ if self.has_reference(identity.scope, node_id) or self.has_reference(
59
+ identity.scope, status_message_id
60
+ ):
61
+ raise ValueError("Node or status message is already registered")
62
+ self._reference_to_tree[(identity.scope, node_id)] = identity
63
+ self._reference_to_tree[(identity.scope, status_message_id)] = identity
64
+
65
+ def unregister_references(
66
+ self,
67
+ identity: TreeIdentity,
68
+ reference_ids: set[str],
69
+ ) -> None:
70
+ for reference_id in reference_ids:
71
+ key = (identity.scope, reference_id)
72
+ if self._reference_to_tree.get(key) == identity:
73
+ self._reference_to_tree.pop(key)
74
+
75
+ def remove_tree(
76
+ self,
77
+ identity: TreeIdentity,
78
+ ) -> MessageTree | None:
79
+ tree = self._trees.pop(identity, None)
80
+ if tree is None:
81
+ return None
82
+ self._reference_to_tree = {
83
+ key: owner
84
+ for key, owner in self._reference_to_tree.items()
85
+ if owner != identity
86
+ }
87
+ logger.debug("TREE_REPO: remove_tree identity={}", identity)
88
+ return tree
89
+
90
+ def trees(self) -> tuple[MessageTree, ...]:
91
+ return tuple(self._trees.values())
92
+
93
+ def tree_count(self) -> int:
94
+ return len(self._trees)
95
+
96
+ @classmethod
97
+ def from_snapshot(
98
+ cls, snapshot: ConversationSnapshot
99
+ ) -> tuple[
100
+ TreeRepository,
101
+ ConversationSnapshot,
102
+ tuple[NodeUiTarget, ...],
103
+ ]:
104
+ repo = cls()
105
+ normalized = ConversationSnapshot()
106
+ stale_targets: list[NodeUiTarget] = []
107
+ for tree_snapshot in snapshot.trees.values():
108
+ try:
109
+ tree = MessageTree.from_snapshot(tree_snapshot)
110
+ except (KeyError, TypeError, ValueError) as exc:
111
+ logger.warning(
112
+ "Skipping invalid messaging tree snapshot: {}",
113
+ type(exc).__name__,
114
+ )
115
+ continue
116
+ references = tree_snapshot.lookup_ids()
117
+ if tree.identity in repo._trees or any(
118
+ repo.has_reference(tree.identity.scope, reference)
119
+ for reference in references
120
+ ):
121
+ logger.warning("Skipping duplicate messaging tree {}", tree.identity)
122
+ continue
123
+ repo._trees[tree.identity] = tree
124
+ for reference in references:
125
+ repo._reference_to_tree[(tree.identity.scope, reference)] = (
126
+ tree.identity
127
+ )
128
+ stale_targets.extend(tree.restored_stale_targets)
129
+ normalized_tree = tree.restored_snapshot
130
+ if normalized_tree is not None:
131
+ normalized = normalized.with_tree(normalized_tree)
132
+ return repo, normalized, tuple(stale_targets)
133
+
134
+
135
+ __all__ = ["TreeRepository"]