multi-forge 0.2.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 (311) hide show
  1. forge/__init__.py +3 -0
  2. forge/_extensions/agents/.gitkeep +0 -0
  3. forge/_extensions/commands/.gitkeep +0 -0
  4. forge/_extensions/skills/analyze/SKILL.md +87 -0
  5. forge/_extensions/skills/challenge/SKILL.md +91 -0
  6. forge/_extensions/skills/consensus/SKILL.md +120 -0
  7. forge/_extensions/skills/consensus/resources/code_consensus_evaluation.md +94 -0
  8. forge/_extensions/skills/consensus/resources/consensus_evaluation.md +70 -0
  9. forge/_extensions/skills/consensus/resources/synthesis.md +101 -0
  10. forge/_extensions/skills/debate/SKILL.md +116 -0
  11. forge/_extensions/skills/debate/resources/code_debate_evaluation.md +101 -0
  12. forge/_extensions/skills/debate/resources/debate_evaluation.md +90 -0
  13. forge/_extensions/skills/panel/SKILL.md +141 -0
  14. forge/_extensions/skills/panel/resources/synthesis.md +103 -0
  15. forge/_extensions/skills/qa/SKILL.md +704 -0
  16. forge/_extensions/skills/qa/resources/checklist/0-enable.md +78 -0
  17. forge/_extensions/skills/qa/resources/checklist/1-preflight.md +24 -0
  18. forge/_extensions/skills/qa/resources/checklist/10-resume.md +143 -0
  19. forge/_extensions/skills/qa/resources/checklist/11-config.md +150 -0
  20. forge/_extensions/skills/qa/resources/checklist/12-search.md +58 -0
  21. forge/_extensions/skills/qa/resources/checklist/13-guard.md +237 -0
  22. forge/_extensions/skills/qa/resources/checklist/14-workflow.md +305 -0
  23. forge/_extensions/skills/qa/resources/checklist/15-skills.md +155 -0
  24. forge/_extensions/skills/qa/resources/checklist/16-handoff.md +224 -0
  25. forge/_extensions/skills/qa/resources/checklist/17-info.md +50 -0
  26. forge/_extensions/skills/qa/resources/checklist/18-disable.md +84 -0
  27. forge/_extensions/skills/qa/resources/checklist/19-uninstall.md +146 -0
  28. forge/_extensions/skills/qa/resources/checklist/2-extensions.md +188 -0
  29. forge/_extensions/skills/qa/resources/checklist/20-cleanup.md +36 -0
  30. forge/_extensions/skills/qa/resources/checklist/3-auth.md +234 -0
  31. forge/_extensions/skills/qa/resources/checklist/4-proxy.md +481 -0
  32. forge/_extensions/skills/qa/resources/checklist/5-session.md +541 -0
  33. forge/_extensions/skills/qa/resources/checklist/6-hooks.md +275 -0
  34. forge/_extensions/skills/qa/resources/checklist/7-costs.md +309 -0
  35. forge/_extensions/skills/qa/resources/checklist/8-status-line.md +174 -0
  36. forge/_extensions/skills/qa/resources/checklist/9-direct-commands.md +146 -0
  37. forge/_extensions/skills/qa/resources/checklist.md +103 -0
  38. forge/_extensions/skills/qa/resources/report-template.md +62 -0
  39. forge/_extensions/skills/qa/scripts/start-container.sh +529 -0
  40. forge/_extensions/skills/qa/scripts/walkthrough-state.py +1137 -0
  41. forge/_extensions/skills/review/SKILL.md +125 -0
  42. forge/_extensions/skills/review/references/claude-4.6.md +474 -0
  43. forge/_extensions/skills/review/references/claude-4.7.md +710 -0
  44. forge/_extensions/skills/review/references/gemini-3.1.md +546 -0
  45. forge/_extensions/skills/review/references/gpt-5.5.md +490 -0
  46. forge/_extensions/skills/review/references/skills-writing-guide.md +1588 -0
  47. forge/_extensions/skills/review/resources/code-anthropic.md +160 -0
  48. forge/_extensions/skills/review/resources/code-gemini.md +184 -0
  49. forge/_extensions/skills/review/resources/code-openai.md +203 -0
  50. forge/_extensions/skills/review/resources/code.md +160 -0
  51. forge/_extensions/skills/review-docs/SKILL.md +121 -0
  52. forge/_extensions/skills/review-docs/resources/docs-anthropic.md +170 -0
  53. forge/_extensions/skills/review-docs/resources/docs-gemini.md +204 -0
  54. forge/_extensions/skills/review-docs/resources/docs-openai.md +231 -0
  55. forge/_extensions/skills/review-docs/resources/docs.md +170 -0
  56. forge/_extensions/skills/smoke-test/SKILL.md +27 -0
  57. forge/_extensions/skills/smoke-test/scripts/smoke-test.sh +118 -0
  58. forge/_extensions/skills/understand/SKILL.md +148 -0
  59. forge/_extensions/skills/understand/resources/code-anthropic.md +163 -0
  60. forge/_extensions/skills/understand/resources/code-gemini.md +194 -0
  61. forge/_extensions/skills/understand/resources/code-openai.md +181 -0
  62. forge/_extensions/skills/understand/resources/code.md +163 -0
  63. forge/_extensions/skills/understand/resources/docs-anthropic.md +177 -0
  64. forge/_extensions/skills/understand/resources/docs-gemini.md +202 -0
  65. forge/_extensions/skills/understand/resources/docs-openai.md +191 -0
  66. forge/_extensions/skills/understand/resources/docs.md +177 -0
  67. forge/_extensions/skills/walkthrough/SKILL.md +599 -0
  68. forge/_extensions/skills/walkthrough/resources/checklist.md +765 -0
  69. forge/_extensions/skills/walkthrough/scripts/run-in-repo.sh +118 -0
  70. forge/_extensions/skills/walkthrough/scripts/setup-test-repo.sh +198 -0
  71. forge/_extensions/skills/walkthrough/scripts/walkthrough-state.py +1137 -0
  72. forge/backend/__init__.py +174 -0
  73. forge/backend/adapters/__init__.py +38 -0
  74. forge/backend/adapters/litellm.py +158 -0
  75. forge/backend/creation.py +89 -0
  76. forge/backend/registry.py +178 -0
  77. forge/cli/__init__.py +16 -0
  78. forge/cli/auth.py +483 -0
  79. forge/cli/backend.py +298 -0
  80. forge/cli/claude.py +411 -0
  81. forge/cli/config_cmd.py +303 -0
  82. forge/cli/extensions.py +1001 -0
  83. forge/cli/gc.py +165 -0
  84. forge/cli/guard.py +1018 -0
  85. forge/cli/guards.py +106 -0
  86. forge/cli/handoff.py +110 -0
  87. forge/cli/hooks/__init__.py +36 -0
  88. forge/cli/hooks/_group.py +20 -0
  89. forge/cli/hooks/_helpers.py +149 -0
  90. forge/cli/hooks/commands.py +1677 -0
  91. forge/cli/hooks/direct_commands.py +1304 -0
  92. forge/cli/hooks/install.py +232 -0
  93. forge/cli/hooks/policy.py +151 -0
  94. forge/cli/hooks/read_hygiene.py +74 -0
  95. forge/cli/hooks/verification.py +370 -0
  96. forge/cli/logs.py +406 -0
  97. forge/cli/main.py +292 -0
  98. forge/cli/proxy.py +1821 -0
  99. forge/cli/proxy_costs.py +313 -0
  100. forge/cli/search.py +416 -0
  101. forge/cli/session.py +892 -0
  102. forge/cli/session_addendum.py +81 -0
  103. forge/cli/session_fork.py +750 -0
  104. forge/cli/session_handoff.py +141 -0
  105. forge/cli/session_lifecycle.py +2053 -0
  106. forge/cli/session_manage.py +1336 -0
  107. forge/cli/session_memory.py +201 -0
  108. forge/cli/status_line.py +1398 -0
  109. forge/cli/workflow.py +1964 -0
  110. forge/config/__init__.py +110 -0
  111. forge/config/dataclass_utils.py +88 -0
  112. forge/config/defaults/__init__.py +0 -0
  113. forge/config/defaults/backends/__init__.py +0 -0
  114. forge/config/defaults/backends/litellm.yaml +196 -0
  115. forge/config/defaults/templates/__init__.py +0 -0
  116. forge/config/defaults/templates/litellm-anthropic-local.yaml +33 -0
  117. forge/config/defaults/templates/litellm-anthropic.yaml +24 -0
  118. forge/config/defaults/templates/litellm-gemini-flash-local.yaml +37 -0
  119. forge/config/defaults/templates/litellm-gemini-local.yaml +32 -0
  120. forge/config/defaults/templates/litellm-gemini-test.yaml +34 -0
  121. forge/config/defaults/templates/litellm-gemini.yaml +21 -0
  122. forge/config/defaults/templates/litellm-openai-codex-local.yaml +36 -0
  123. forge/config/defaults/templates/litellm-openai-local.yaml +38 -0
  124. forge/config/defaults/templates/litellm-openai.yaml +28 -0
  125. forge/config/defaults/templates/openrouter-anthropic.yaml +23 -0
  126. forge/config/defaults/templates/openrouter-deepseek.yaml +26 -0
  127. forge/config/defaults/templates/openrouter-gemini-flash.yaml +26 -0
  128. forge/config/defaults/templates/openrouter-gemini.yaml +23 -0
  129. forge/config/defaults/templates/openrouter-glm.yaml +23 -0
  130. forge/config/defaults/templates/openrouter-kimi.yaml +30 -0
  131. forge/config/defaults/templates/openrouter-minimax.yaml +26 -0
  132. forge/config/defaults/templates/openrouter-openai-codex.yaml +23 -0
  133. forge/config/defaults/templates/openrouter-openai.yaml +28 -0
  134. forge/config/defaults/templates/openrouter-qwen.yaml +25 -0
  135. forge/config/loader.py +675 -0
  136. forge/config/schema.py +448 -0
  137. forge/core/__init__.py +5 -0
  138. forge/core/auth/__init__.py +67 -0
  139. forge/core/auth/capabilities.py +219 -0
  140. forge/core/auth/credentials_file.py +244 -0
  141. forge/core/auth/protocols.py +18 -0
  142. forge/core/auth/secrets.py +243 -0
  143. forge/core/auth/template_secrets.py +112 -0
  144. forge/core/data/__init__.py +5 -0
  145. forge/core/data/model_catalog.yaml +1522 -0
  146. forge/core/data/pricing.yaml +140 -0
  147. forge/core/data/system_prompt_addendums/__init__.py +0 -0
  148. forge/core/data/system_prompt_addendums/gemini.md +330 -0
  149. forge/core/data/system_prompt_addendums/openai.md +328 -0
  150. forge/core/llm/__init__.py +231 -0
  151. forge/core/llm/clients/__init__.py +14 -0
  152. forge/core/llm/clients/base.py +115 -0
  153. forge/core/llm/clients/litellm.py +619 -0
  154. forge/core/llm/clients/openai_compat.py +244 -0
  155. forge/core/llm/clients/openrouter.py +234 -0
  156. forge/core/llm/credentials.py +439 -0
  157. forge/core/llm/detection.py +86 -0
  158. forge/core/llm/errors.py +44 -0
  159. forge/core/llm/protocols.py +80 -0
  160. forge/core/llm/types.py +176 -0
  161. forge/core/logging.py +146 -0
  162. forge/core/models/__init__.py +91 -0
  163. forge/core/models/catalog.py +467 -0
  164. forge/core/models/pricing.py +165 -0
  165. forge/core/models/types.py +167 -0
  166. forge/core/naming.py +212 -0
  167. forge/core/ops/__init__.py +73 -0
  168. forge/core/ops/context.py +141 -0
  169. forge/core/ops/gc.py +802 -0
  170. forge/core/ops/proxy.py +146 -0
  171. forge/core/ops/resolution.py +135 -0
  172. forge/core/ops/session.py +344 -0
  173. forge/core/ops/session_context.py +548 -0
  174. forge/core/paths.py +38 -0
  175. forge/core/process.py +54 -0
  176. forge/core/reactive/__init__.py +38 -0
  177. forge/core/reactive/cost_tracking.py +300 -0
  178. forge/core/reactive/env.py +180 -0
  179. forge/core/reactive/proxy.py +78 -0
  180. forge/core/reactive/routing.py +622 -0
  181. forge/core/reactive/session_runner.py +185 -0
  182. forge/core/reactive/structured_output.py +62 -0
  183. forge/core/reactive/tagger.py +94 -0
  184. forge/core/reactive/throttle.py +132 -0
  185. forge/core/state/__init__.py +59 -0
  186. forge/core/state/exceptions.py +59 -0
  187. forge/core/state/io.py +140 -0
  188. forge/core/state/lock.py +99 -0
  189. forge/core/state/timestamps.py +60 -0
  190. forge/core/transcript.py +78 -0
  191. forge/core/typing_helpers.py +24 -0
  192. forge/core/workqueue/__init__.py +67 -0
  193. forge/core/workqueue/queue.py +552 -0
  194. forge/core/workqueue/types.py +63 -0
  195. forge/guard/__init__.py +26 -0
  196. forge/guard/deterministic/__init__.py +26 -0
  197. forge/guard/deterministic/base.py +158 -0
  198. forge/guard/deterministic/coding_standards.py +256 -0
  199. forge/guard/deterministic/registry.py +148 -0
  200. forge/guard/deterministic/tdd.py +171 -0
  201. forge/guard/engine.py +216 -0
  202. forge/guard/protocols.py +91 -0
  203. forge/guard/queries.py +96 -0
  204. forge/guard/semantic/__init__.py +34 -0
  205. forge/guard/semantic/promotion.py +18 -0
  206. forge/guard/semantic/supervisor.py +813 -0
  207. forge/guard/semantic/verdict.py +183 -0
  208. forge/guard/store.py +124 -0
  209. forge/guard/team/__init__.py +6 -0
  210. forge/guard/team/config.py +24 -0
  211. forge/guard/team/handlers.py +209 -0
  212. forge/guard/team/prompts.py +41 -0
  213. forge/guard/types.py +125 -0
  214. forge/guard/workflow/__init__.py +17 -0
  215. forge/guard/workflow/branches.py +67 -0
  216. forge/guard/workflow/config.py +63 -0
  217. forge/guard/workflow/divergence.py +113 -0
  218. forge/guard/workflow/policy.py +87 -0
  219. forge/guard/workflow/stages.py +205 -0
  220. forge/install/__init__.py +55 -0
  221. forge/install/cli.py +281 -0
  222. forge/install/exceptions.py +163 -0
  223. forge/install/hooks.py +109 -0
  224. forge/install/installer.py +1037 -0
  225. forge/install/models.py +321 -0
  226. forge/install/preset.py +272 -0
  227. forge/install/settings_merge.py +831 -0
  228. forge/install/tracking.py +238 -0
  229. forge/install/version.py +141 -0
  230. forge/proxy/__init__.py +0 -0
  231. forge/proxy/base_client.py +181 -0
  232. forge/proxy/client_adapter.py +476 -0
  233. forge/proxy/client_factory.py +531 -0
  234. forge/proxy/converters.py +1206 -0
  235. forge/proxy/cost_logger.py +132 -0
  236. forge/proxy/cost_tracker.py +242 -0
  237. forge/proxy/data_models.py +338 -0
  238. forge/proxy/error_hints.py +92 -0
  239. forge/proxy/metrics.py +222 -0
  240. forge/proxy/model_spec.py +158 -0
  241. forge/proxy/proxies.py +333 -0
  242. forge/proxy/proxy_identity.py +134 -0
  243. forge/proxy/proxy_orchestrator.py +1018 -0
  244. forge/proxy/proxy_startup.py +54 -0
  245. forge/proxy/server.py +1561 -0
  246. forge/proxy/utils.py +537 -0
  247. forge/review/__init__.py +6 -0
  248. forge/review/adversarial.py +111 -0
  249. forge/review/consensus.py +236 -0
  250. forge/review/engine.py +356 -0
  251. forge/review/models.py +437 -0
  252. forge/review/resources/__init__.py +5 -0
  253. forge/review/resources/codereview-performance.md +85 -0
  254. forge/review/resources/codereview-quick.md +75 -0
  255. forge/review/resources/codereview-security.md +92 -0
  256. forge/review/resources/codereview.md +85 -0
  257. forge/review/resources/docreview-quick.md +75 -0
  258. forge/review/resources/docreview.md +86 -0
  259. forge/review/resources/thinkdeep.md +89 -0
  260. forge/review/routing.py +368 -0
  261. forge/review/synthesis.py +73 -0
  262. forge/runtime_config.py +438 -0
  263. forge/search/__init__.py +55 -0
  264. forge/search/bm25_store.py +264 -0
  265. forge/search/content_store.py +197 -0
  266. forge/search/engine.py +352 -0
  267. forge/search/exceptions.py +51 -0
  268. forge/search/extractor.py +234 -0
  269. forge/search/index_state.py +295 -0
  270. forge/search/store.py +215 -0
  271. forge/search/tokenizer.py +24 -0
  272. forge/session/__init__.py +130 -0
  273. forge/session/active.py +339 -0
  274. forge/session/artifacts.py +202 -0
  275. forge/session/claude/__init__.py +50 -0
  276. forge/session/claude/cleanup.py +105 -0
  277. forge/session/claude/invoke.py +236 -0
  278. forge/session/claude/paths.py +200 -0
  279. forge/session/cleanup.py +216 -0
  280. forge/session/config.py +34 -0
  281. forge/session/direct_model.py +107 -0
  282. forge/session/effective.py +169 -0
  283. forge/session/exceptions.py +255 -0
  284. forge/session/handoff.py +881 -0
  285. forge/session/handoff_agent.py +544 -0
  286. forge/session/hooks/__init__.py +35 -0
  287. forge/session/hooks/models.py +73 -0
  288. forge/session/hooks/session_start.py +507 -0
  289. forge/session/identity.py +84 -0
  290. forge/session/index.py +553 -0
  291. forge/session/manager.py +1506 -0
  292. forge/session/models.py +572 -0
  293. forge/session/overrides.py +344 -0
  294. forge/session/plan_resolution.py +286 -0
  295. forge/session/prev_sessions.py +128 -0
  296. forge/session/store.py +431 -0
  297. forge/session/validation.py +47 -0
  298. forge/session/worktree/__init__.py +65 -0
  299. forge/session/worktree/cleanup.py +262 -0
  300. forge/session/worktree/config_copy.py +203 -0
  301. forge/session/worktree/create.py +332 -0
  302. forge/sidecar/__init__.py +29 -0
  303. forge/sidecar/container.py +161 -0
  304. forge/sidecar/docker.py +86 -0
  305. forge/sidecar/secrets.py +19 -0
  306. multi_forge-0.2.0.dist-info/METADATA +242 -0
  307. multi_forge-0.2.0.dist-info/RECORD +311 -0
  308. multi_forge-0.2.0.dist-info/WHEEL +4 -0
  309. multi_forge-0.2.0.dist-info/entry_points.txt +2 -0
  310. multi_forge-0.2.0.dist-info/licenses/LICENSE +203 -0
  311. multi_forge-0.2.0.dist-info/licenses/NOTICE +14 -0
@@ -0,0 +1,110 @@
1
+ """Unified configuration system for Multi-Forge.
2
+
3
+ This module provides a type-safe configuration system with three sources:
4
+
5
+ 1. Proxy file: ~/.forge/proxies/{id}/proxy.yaml (user owns full config)
6
+ 2. Template: defaults/templates/{t}.yaml (for proxy creation only)
7
+ 3. Secrets: .env + env vars (*_API_KEY, *_AUTH_URL, FORGE_HOME)
8
+
9
+ Schema defaults in dataclasses handle missing fields.
10
+
11
+ Usage:
12
+ from forge.config import config
13
+
14
+ # Access configuration
15
+ model = config.proxy.litellm.tiers.opus
16
+ overrides = config.proxy.litellm.tier_overrides.get("opus")
17
+
18
+ # Load with specific proxy
19
+ from forge.config import load_config
20
+ config = load_config(proxy_id="my-proxy")
21
+
22
+ # Load template (for proxy creation)
23
+ config = load_config(template="litellm-gemini")
24
+
25
+ # Reload configuration
26
+ from forge.config import reload
27
+ reload(proxy_id="my-proxy")
28
+ """
29
+
30
+ from forge.config.loader import load_config, reload_config
31
+ from forge.config.schema import (
32
+ OPENAI_MODELS,
33
+ ForgeConfig,
34
+ ProviderConfig,
35
+ ProxyConfig,
36
+ SessionConfig,
37
+ TierModels,
38
+ TierOverride,
39
+ TierOverrides,
40
+ is_openai_model,
41
+ )
42
+
43
+ __all__ = [
44
+ # Main config instance
45
+ "config",
46
+ # Functions
47
+ "load_config",
48
+ "reload",
49
+ "get_config",
50
+ "init_config",
51
+ # Helper functions
52
+ "is_openai_model",
53
+ # Constants
54
+ "OPENAI_MODELS",
55
+ # Schema classes (for type hints)
56
+ "ForgeConfig",
57
+ "ProxyConfig",
58
+ "SessionConfig",
59
+ "ProviderConfig",
60
+ "TierModels",
61
+ "TierOverride",
62
+ "TierOverrides",
63
+ ]
64
+
65
+ # Global config instance (singleton)
66
+ _config: ForgeConfig | None = None
67
+
68
+
69
+ def get_config() -> ForgeConfig:
70
+ """Get the global config instance, loading if necessary."""
71
+ global _config
72
+ if _config is None:
73
+ _config = load_config()
74
+ return _config
75
+
76
+
77
+ def reload(*, template: str | None = None, proxy_id: str | None = None) -> ForgeConfig:
78
+ """Reload configuration from all sources."""
79
+ global _config
80
+ if _config is not None:
81
+ _config = reload_config(_config, template=template, proxy_id=proxy_id)
82
+ else:
83
+ _config = load_config(template=template, proxy_id=proxy_id)
84
+ return _config
85
+
86
+
87
+ def init_config(*, template: str | None = None, proxy_id: str | None = None) -> ForgeConfig:
88
+ """Initialize configuration with optional template/proxy.
89
+
90
+ Call this at application startup to load config with a specific template.
91
+ Subsequent calls to get_config() will return this instance.
92
+ """
93
+ global _config
94
+ _config = load_config(template=template, proxy_id=proxy_id)
95
+ return _config
96
+
97
+
98
+ # Lazy-loaded config property
99
+ class _ConfigProxy:
100
+ """Proxy that lazily loads config on first access."""
101
+
102
+ def __getattr__(self, name: str):
103
+ return getattr(get_config(), name)
104
+
105
+ def __repr__(self) -> str:
106
+ return repr(get_config())
107
+
108
+
109
+ # Export lazy config proxy as 'config'
110
+ config: ForgeConfig = _ConfigProxy() # type: ignore[assignment] # _ConfigProxy delegates to ForgeConfig at runtime
@@ -0,0 +1,88 @@
1
+ """Dict-to-dataclass conversion utilities.
2
+
3
+ Extracted from loader.py to break the loader ↔ schema import cycle (CR-007).
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import types
9
+ from dataclasses import fields, is_dataclass
10
+ from typing import Any, Union, get_args, get_origin
11
+
12
+
13
+ def _is_union_type(origin: Any) -> bool:
14
+ """Check if origin indicates a Union type (typing.Union or types.UnionType)."""
15
+ if origin is Union:
16
+ return True
17
+ # PEP604 union (e.g., int | str, X | None) — Python 3.10+
18
+ if origin is types.UnionType:
19
+ return True
20
+ return False
21
+
22
+
23
+ def _unwrap_optional(field_type: Any) -> tuple[Any, bool]:
24
+ """Unwrap Optional[X] or X | None to X.
25
+
26
+ Returns:
27
+ (unwrapped_type, is_optional): The unwrapped type and whether it was Optional.
28
+ """
29
+ origin = get_origin(field_type)
30
+ if not _is_union_type(origin):
31
+ return field_type, False
32
+
33
+ args = get_args(field_type)
34
+ non_none_args = [a for a in args if a is not type(None)]
35
+
36
+ if type(None) in args and len(non_none_args) == 1:
37
+ return non_none_args[0], True
38
+
39
+ return field_type, False
40
+
41
+
42
+ def dict_to_dataclass(cls: type[Any], data: dict, *, strict: bool = False) -> Any:
43
+ """Convert nested dict to dataclass instance.
44
+
45
+ Recursively converts nested dicts to their corresponding dataclass types.
46
+ Handles Optional types, lists, and primitive types.
47
+
48
+ Args:
49
+ strict: If True, raise ValueError on unknown keys not present in the dataclass.
50
+ """
51
+ if not is_dataclass(cls):
52
+ return data # type: ignore[return-value] # returns raw dict when cls is not a dataclass
53
+
54
+ if strict:
55
+ known = {f.name for f in fields(cls)}
56
+ unknown = set(data.keys()) - known
57
+ if unknown:
58
+ raise ValueError(f"{cls.__name__} has unknown fields: {', '.join(sorted(unknown))}")
59
+
60
+ kwargs: dict[str, Any] = {}
61
+ for f in fields(cls):
62
+ if f.name not in data:
63
+ continue
64
+
65
+ value = data[f.name]
66
+ field_type = f.type
67
+
68
+ unwrapped_type, is_optional = _unwrap_optional(field_type)
69
+
70
+ if value is None and is_optional:
71
+ kwargs[f.name] = value
72
+ continue
73
+
74
+ origin = get_origin(unwrapped_type)
75
+
76
+ if origin is list and isinstance(value, list):
77
+ kwargs[f.name] = value
78
+ elif is_dataclass(unwrapped_type) and isinstance(value, dict):
79
+ if isinstance(unwrapped_type, type):
80
+ kwargs[f.name] = dict_to_dataclass(unwrapped_type, value, strict=strict)
81
+ else:
82
+ kwargs[f.name] = value
83
+ elif _is_union_type(origin):
84
+ kwargs[f.name] = value
85
+ else:
86
+ kwargs[f.name] = value
87
+
88
+ return cls(**kwargs)
File without changes
File without changes
@@ -0,0 +1,196 @@
1
+ # LiteLLM Local Proxy Configuration
2
+ # For use with personal API keys (Gemini and/or OpenAI)
3
+ #
4
+ # Supported models:
5
+ # Gemini (requires GEMINI_API_KEY):
6
+ # - gemini/gemini-3.1-pro-preview (Gemini 3.1 Pro - latest with thinking)
7
+ # - gemini/gemini-3.1-pro-preview-customtools (optimized for custom tools + bash)
8
+ # - gemini/gemini-3-flash-preview (Gemini 3 Flash - fast, cheap)
9
+ # - gemini/gemini-2.5-flash (fast, cheap)
10
+ # - gemini/gemini-2.5-pro (powerful)
11
+ #
12
+ # OpenAI (requires OPENAI_API_KEY):
13
+ # - openai/gpt-5, gpt-5-codex, gpt-5-mini, gpt-5-nano, gpt-5-pro
14
+ # - openai/gpt-5.1, gpt-5.1-codex, gpt-5.1-codex-max, gpt-5.1-codex-mini
15
+ # - openai/gpt-5.2, gpt-5.2-codex, gpt-5.2-pro
16
+ # - openai/gpt-5.3-codex
17
+ # - openai/gpt-5.4, gpt-5.4-pro
18
+ # - openai/gpt-5.5
19
+ #
20
+ # Start with: forge backend start litellm --port 4000
21
+
22
+ model_list:
23
+ # Gemini 3.1 Pro Preview - latest model with thinking support
24
+ - model_name: gemini/gemini-3.1-pro-preview
25
+ litellm_params:
26
+ model: gemini/gemini-3.1-pro-preview
27
+ api_key: os.environ/GEMINI_API_KEY
28
+
29
+ # Gemini 3.1 Pro Preview (Custom Tools) - optimized for agentic workflows with custom tools + bash
30
+ - model_name: gemini/gemini-3.1-pro-preview-customtools
31
+ litellm_params:
32
+ model: gemini/gemini-3.1-pro-preview-customtools
33
+ api_key: os.environ/GEMINI_API_KEY
34
+
35
+ # Gemini 3 Flash Preview - fast and cheap
36
+ - model_name: gemini/gemini-3-flash-preview
37
+ litellm_params:
38
+ model: gemini/gemini-3-flash-preview
39
+ api_key: os.environ/GEMINI_API_KEY
40
+
41
+ # Gemini 2.5 Flash - fast and cheap
42
+ - model_name: gemini/gemini-2.5-flash
43
+ litellm_params:
44
+ model: gemini/gemini-2.5-flash
45
+ api_key: os.environ/GEMINI_API_KEY
46
+
47
+ # Gemini 2.5 Pro - powerful
48
+ - model_name: gemini/gemini-2.5-pro
49
+ litellm_params:
50
+ model: gemini/gemini-2.5-pro
51
+ api_key: os.environ/GEMINI_API_KEY
52
+
53
+ # Aliases for convenience (match config.yaml model names)
54
+ - model_name: gemini-3.1-pro-preview
55
+ litellm_params:
56
+ model: gemini/gemini-3.1-pro-preview
57
+ api_key: os.environ/GEMINI_API_KEY
58
+
59
+ - model_name: gemini-3.1-pro-preview-customtools
60
+ litellm_params:
61
+ model: gemini/gemini-3.1-pro-preview-customtools
62
+ api_key: os.environ/GEMINI_API_KEY
63
+
64
+ - model_name: gemini-3-flash-preview
65
+ litellm_params:
66
+ model: gemini/gemini-3-flash-preview
67
+ api_key: os.environ/GEMINI_API_KEY
68
+
69
+ - model_name: gemini-2.5-flash
70
+ litellm_params:
71
+ model: gemini/gemini-2.5-flash
72
+ api_key: os.environ/GEMINI_API_KEY
73
+
74
+ - model_name: gemini-2.5-pro
75
+ litellm_params:
76
+ model: gemini/gemini-2.5-pro
77
+ api_key: os.environ/GEMINI_API_KEY
78
+
79
+ # =========================================================================
80
+ # OpenAI Models (requires OPENAI_API_KEY)
81
+ # =========================================================================
82
+
83
+ # --- GPT-5 family ---
84
+ - model_name: openai/gpt-5
85
+ litellm_params:
86
+ model: openai/gpt-5
87
+ api_key: os.environ/OPENAI_API_KEY
88
+
89
+ - model_name: openai/gpt-5-codex
90
+ litellm_params:
91
+ model: openai/gpt-5-codex
92
+ api_key: os.environ/OPENAI_API_KEY
93
+
94
+ - model_name: openai/gpt-5-mini
95
+ litellm_params:
96
+ model: openai/gpt-5-mini
97
+ api_key: os.environ/OPENAI_API_KEY
98
+
99
+ - model_name: openai/gpt-5-nano
100
+ litellm_params:
101
+ model: openai/gpt-5-nano
102
+ api_key: os.environ/OPENAI_API_KEY
103
+
104
+ - model_name: openai/gpt-5-pro
105
+ litellm_params:
106
+ model: openai/gpt-5-pro
107
+ api_key: os.environ/OPENAI_API_KEY
108
+
109
+ # --- GPT-5.1 family ---
110
+ - model_name: openai/gpt-5.1
111
+ litellm_params:
112
+ model: openai/gpt-5.1
113
+ api_key: os.environ/OPENAI_API_KEY
114
+
115
+ - model_name: openai/gpt-5.1-codex
116
+ litellm_params:
117
+ model: openai/gpt-5.1-codex
118
+ api_key: os.environ/OPENAI_API_KEY
119
+
120
+ - model_name: openai/gpt-5.1-codex-max
121
+ litellm_params:
122
+ model: openai/gpt-5.1-codex-max
123
+ api_key: os.environ/OPENAI_API_KEY
124
+
125
+ - model_name: openai/gpt-5.1-codex-mini
126
+ litellm_params:
127
+ model: openai/gpt-5.1-codex-mini
128
+ api_key: os.environ/OPENAI_API_KEY
129
+
130
+ # --- GPT-5.2 family ---
131
+ - model_name: openai/gpt-5.2
132
+ litellm_params:
133
+ model: openai/gpt-5.2
134
+ api_key: os.environ/OPENAI_API_KEY
135
+
136
+ - model_name: openai/gpt-5.2-codex
137
+ litellm_params:
138
+ model: openai/gpt-5.2-codex
139
+ api_key: os.environ/OPENAI_API_KEY
140
+
141
+ - model_name: openai/gpt-5.2-pro
142
+ litellm_params:
143
+ model: openai/gpt-5.2-pro
144
+ api_key: os.environ/OPENAI_API_KEY
145
+
146
+ # --- GPT-5.3 family ---
147
+ - model_name: openai/gpt-5.3-codex
148
+ litellm_params:
149
+ model: openai/gpt-5.3-codex
150
+ api_key: os.environ/OPENAI_API_KEY
151
+
152
+ # --- GPT-5.4 family ---
153
+ - model_name: openai/gpt-5.4
154
+ litellm_params:
155
+ model: openai/gpt-5.4
156
+ api_key: os.environ/OPENAI_API_KEY
157
+
158
+ - model_name: openai/gpt-5.4-pro
159
+ litellm_params:
160
+ model: openai/gpt-5.4-pro
161
+ api_key: os.environ/OPENAI_API_KEY
162
+
163
+ - model_name: openai/gpt-5.4-mini
164
+ litellm_params:
165
+ model: openai/gpt-5.4-mini
166
+ api_key: os.environ/OPENAI_API_KEY
167
+
168
+ - model_name: openai/gpt-5.4-nano
169
+ litellm_params:
170
+ model: openai/gpt-5.4-nano
171
+ api_key: os.environ/OPENAI_API_KEY
172
+
173
+ # --- GPT-5.5 ---
174
+ - model_name: openai/gpt-5.5
175
+ litellm_params:
176
+ model: openai/gpt-5.5
177
+ api_key: os.environ/OPENAI_API_KEY
178
+
179
+ litellm_settings:
180
+ # Drop unmapped params instead of erroring
181
+ drop_params: true
182
+
183
+ # Enable detailed logging for debugging
184
+ set_verbose: false
185
+
186
+ # Request timeout
187
+ request_timeout: 600
188
+
189
+ # General settings (optional)
190
+ # general_settings:
191
+ # # Master key for API authentication (optional)
192
+ # # Set via: export LITELLM_MASTER_KEY="sk-your-key"
193
+ # master_key: os.environ/LITELLM_MASTER_KEY
194
+ #
195
+ # # Database for tracking (optional)
196
+ # # database_url: "postgresql://..."
File without changes
@@ -0,0 +1,33 @@
1
+ # Template: litellm-anthropic-local
2
+ # Anthropic Claude via local LiteLLM with personal API key (DEVELOPMENT)
3
+ #
4
+ # Requires:
5
+ # - ANTHROPIC_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4000) starts automatically.
8
+ #
9
+ # Note: If you added ANTHROPIC_API_KEY after the backend started,
10
+ # restart with: forge backend stop litellm-4000
11
+
12
+ proxy:
13
+ family: anthropic
14
+ preferred_provider: litellm
15
+ default_port: 8091
16
+
17
+ # Backend dependency (auto-started when proxy starts)
18
+ backend_dependency:
19
+ adapter: litellm
20
+ port: 4000
21
+ required_env_vars:
22
+ - ANTHROPIC_API_KEY
23
+
24
+ litellm:
25
+ tiers:
26
+ haiku: anthropic/claude-haiku-4-5
27
+ sonnet: anthropic/claude-sonnet-4-6
28
+ opus: anthropic/claude-opus-4-6
29
+ model_alternatives:
30
+ opus:
31
+ claude-opus-4-7: anthropic/claude-opus-4-7
32
+ prompt_caching: passthrough
33
+ error_hints: true
@@ -0,0 +1,24 @@
1
+ # Template: litellm-anthropic
2
+ # Anthropic Claude via remote/shared LiteLLM
3
+ #
4
+ # Access to Claude Opus 4.6/4.7, Sonnet 4.6, and Haiku 4.5.
5
+ # Requires LITELLM_API_KEY and LITELLM_BASE_URL in .env (or environment).
6
+ #
7
+ # Use --model claude-opus-4-7 to select Opus 4.7 instead of the 4.6 default.
8
+ # prompt_caching: passthrough respects Anthropic's 4-breakpoint cache_control limit.
9
+
10
+ proxy:
11
+ family: anthropic
12
+ preferred_provider: litellm
13
+ default_port: 8092
14
+
15
+ litellm:
16
+ tiers:
17
+ haiku: anthropic/claude-haiku-4-5
18
+ sonnet: anthropic/claude-sonnet-4-6
19
+ opus: anthropic/claude-opus-4-6
20
+ model_alternatives:
21
+ opus:
22
+ claude-opus-4-7: anthropic/claude-opus-4-7
23
+ prompt_caching: passthrough
24
+ error_hints: true
@@ -0,0 +1,37 @@
1
+ # Template: litellm-gemini-flash-local
2
+ # Gemini 3 Flash via local LiteLLM (beats Pro on SWE benchmarks!)
3
+ #
4
+ # Requires:
5
+ # - GEMINI_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4000) starts automatically.
8
+ # All tiers use Flash, differentiated by reasoning_effort.
9
+ #
10
+ # Note: If you added GEMINI_API_KEY after the backend started,
11
+ # restart with: forge backend stop litellm-4000
12
+
13
+ proxy:
14
+ family: gemini
15
+ preferred_provider: litellm
16
+ default_port: 8088
17
+
18
+ # Backend dependency (auto-started when proxy starts)
19
+ backend_dependency:
20
+ adapter: litellm
21
+ port: 4000
22
+ required_env_vars:
23
+ - GEMINI_API_KEY
24
+
25
+ litellm:
26
+ tiers:
27
+ haiku: gemini/gemini-3-flash-preview
28
+ sonnet: gemini/gemini-3-flash-preview
29
+ opus: gemini/gemini-3-flash-preview
30
+ # Per-tier overrides: all tiers use same model, differentiate by reasoning
31
+ tier_overrides:
32
+ haiku:
33
+ reasoning_effort: low
34
+ sonnet:
35
+ reasoning_effort: medium
36
+ opus:
37
+ reasoning_effort: high
@@ -0,0 +1,32 @@
1
+ # Template: litellm-gemini-local
2
+ # Gemini models via local LiteLLM proxy with personal API key (DEVELOPMENT)
3
+ #
4
+ # Requires:
5
+ # - GEMINI_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4000) starts automatically.
8
+ # For tests: Use litellm-gemini-test template (port 4001)
9
+
10
+ proxy:
11
+ family: gemini
12
+ preferred_provider: litellm
13
+ default_port: 8086
14
+
15
+ # Backend dependency (auto-started when proxy starts)
16
+ backend_dependency:
17
+ adapter: litellm
18
+ port: 4000
19
+ required_env_vars:
20
+ - GEMINI_API_KEY
21
+
22
+ litellm:
23
+ tiers:
24
+ haiku: gemini/gemini-3-flash-preview
25
+ sonnet: gemini/gemini-3.1-pro-preview
26
+ opus: gemini/gemini-3.1-pro-preview
27
+ # Per-tier overrides to differentiate sonnet/opus (both use same model)
28
+ tier_overrides:
29
+ sonnet:
30
+ reasoning_effort: medium
31
+ opus:
32
+ reasoning_effort: high
@@ -0,0 +1,34 @@
1
+ # Template: litellm-gemini-test
2
+ # Gemini models via local LiteLLM proxy on TEST port (4001)
3
+ #
4
+ # Requires:
5
+ # - GEMINI_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4001) starts automatically for test isolation.
8
+ # Dev port is 4000, test port is 4001 (isolation).
9
+
10
+ internal: true # Hidden from user-facing template listings
11
+
12
+ proxy:
13
+ family: gemini
14
+ preferred_provider: litellm
15
+ default_port: 8087
16
+
17
+ # Backend dependency (auto-started when proxy starts, test port for isolation)
18
+ backend_dependency:
19
+ adapter: litellm
20
+ port: 4001
21
+ required_env_vars:
22
+ - GEMINI_API_KEY
23
+
24
+ litellm:
25
+ tiers:
26
+ haiku: gemini/gemini-3-flash-preview
27
+ sonnet: gemini/gemini-3.1-pro-preview
28
+ opus: gemini/gemini-3.1-pro-preview
29
+ # Per-tier overrides to differentiate sonnet/opus (both use same model)
30
+ tier_overrides:
31
+ sonnet:
32
+ reasoning_effort: medium
33
+ opus:
34
+ reasoning_effort: high
@@ -0,0 +1,21 @@
1
+ # Template: litellm-gemini
2
+ # Gemini models via remote/shared LiteLLM
3
+ #
4
+ # Default template for Gemini access through a shared LiteLLM gateway.
5
+ # Requires LITELLM_API_KEY and LITELLM_BASE_URL in .env (or environment).
6
+
7
+ proxy:
8
+ family: gemini
9
+ preferred_provider: litellm
10
+ default_port: 8084
11
+
12
+ litellm:
13
+ tiers:
14
+ haiku: vertex_ai/gemini-2.5-flash
15
+ sonnet: vertex_ai/gemini-3.1-pro-preview
16
+ opus: vertex_ai/gemini-3.1-pro-preview
17
+ tier_overrides:
18
+ sonnet:
19
+ reasoning_effort: medium
20
+ opus:
21
+ reasoning_effort: high
@@ -0,0 +1,36 @@
1
+ # Template: litellm-openai-codex-local
2
+ # OpenAI Codex models via local LiteLLM with personal API key (DEVELOPMENT)
3
+ #
4
+ # Requires:
5
+ # - OPENAI_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4000) starts automatically.
8
+ #
9
+ # Note: If you added OPENAI_API_KEY after the backend started,
10
+ # restart with: forge backend stop litellm-4000
11
+
12
+ proxy:
13
+ family: openai
14
+ preferred_provider: litellm
15
+ default_port: 8090
16
+
17
+ # Backend dependency (auto-started when proxy starts)
18
+ backend_dependency:
19
+ adapter: litellm
20
+ port: 4000
21
+ required_env_vars:
22
+ - OPENAI_API_KEY
23
+
24
+ litellm:
25
+ tiers:
26
+ haiku: openai/gpt-5.1-codex-mini
27
+ sonnet: openai/gpt-5.3-codex
28
+ opus: openai/gpt-5.5
29
+ tier_overrides:
30
+ sonnet:
31
+ reasoning_effort: medium
32
+ opus:
33
+ reasoning_effort: high
34
+ verbosity: high
35
+ openai_api_mode: auto
36
+ error_hints: true
@@ -0,0 +1,38 @@
1
+ # Template: litellm-openai-local
2
+ # OpenAI models via local LiteLLM with personal API key (DEVELOPMENT)
3
+ #
4
+ # Requires:
5
+ # - OPENAI_API_KEY in .env
6
+ #
7
+ # Backend (LiteLLM on port 4000) starts automatically.
8
+ #
9
+ # Note: If you added OPENAI_API_KEY after the backend started,
10
+ # restart with: forge backend stop litellm-4000
11
+
12
+ proxy:
13
+ family: openai
14
+ preferred_provider: litellm
15
+ default_port: 8089
16
+
17
+ # Backend dependency (auto-started when proxy starts)
18
+ backend_dependency:
19
+ adapter: litellm
20
+ port: 4000
21
+ required_env_vars:
22
+ - OPENAI_API_KEY
23
+
24
+ litellm:
25
+ tiers:
26
+ haiku: openai/gpt-5.4-mini
27
+ sonnet: openai/gpt-5.5
28
+ opus: openai/gpt-5.5
29
+ # Per-tier overrides to differentiate sonnet/opus (both use same model)
30
+ tier_overrides:
31
+ sonnet:
32
+ reasoning_effort: medium
33
+ verbosity: high
34
+ opus:
35
+ reasoning_effort: high
36
+ verbosity: high
37
+ openai_api_mode: auto
38
+ error_hints: true
@@ -0,0 +1,28 @@
1
+ # Template: litellm-openai
2
+ # OpenAI models via remote/shared LiteLLM
3
+ #
4
+ # Access to GPT-4o, GPT-5, and O-series models.
5
+ # Requires LITELLM_API_KEY and LITELLM_BASE_URL in .env (or environment).
6
+ #
7
+ # Haiku uses gpt-5.4-mini; sonnet and opus both use gpt-5.5,
8
+ # differentiated by tier_overrides (reasoning_effort and verbosity).
9
+
10
+ proxy:
11
+ family: openai
12
+ preferred_provider: litellm
13
+ default_port: 8085
14
+
15
+ litellm:
16
+ tiers:
17
+ haiku: openai/gpt-5.4-mini
18
+ sonnet: openai/gpt-5.5
19
+ opus: openai/gpt-5.5
20
+ tier_overrides:
21
+ sonnet:
22
+ reasoning_effort: medium
23
+ verbosity: high
24
+ opus:
25
+ reasoning_effort: high
26
+ verbosity: high
27
+ openai_api_mode: auto
28
+ error_hints: true