claude-code-workflow 7.2.28 → 7.2.30

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 (348) hide show
  1. package/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json +2 -2
  2. package/.ccw/workflows/cli-templates/schemas/task-schema.json +14 -7
  3. package/.claude/agents/action-planning-agent.md +7 -4
  4. package/.claude/agents/cli-explore-agent.md +77 -63
  5. package/.claude/agents/cli-lite-planning-agent.md +11 -10
  6. package/.claude/agents/issue-plan-agent.md +421 -426
  7. package/.claude/commands/workflow/spec/setup.md +1 -1
  8. package/.claude/skills/ccw-chain/SKILL.md +119 -0
  9. package/.claude/skills/ccw-chain/chains/ccw-cycle.json +21 -0
  10. package/.claude/skills/ccw-chain/chains/ccw-exploration.json +47 -0
  11. package/.claude/skills/ccw-chain/chains/ccw-issue.json +33 -0
  12. package/.claude/skills/ccw-chain/chains/ccw-lightweight.json +57 -0
  13. package/.claude/skills/ccw-chain/chains/ccw-main.json +52 -0
  14. package/.claude/skills/ccw-chain/chains/ccw-standard.json +39 -0
  15. package/.claude/skills/ccw-chain/chains/ccw-team.json +10 -0
  16. package/.claude/skills/ccw-chain/chains/ccw-with-file.json +31 -0
  17. package/.claude/skills/ccw-chain/phases/analyze-with-file.md +788 -0
  18. package/.claude/skills/ccw-chain/phases/brainstorm/SKILL.md +408 -0
  19. package/.claude/skills/ccw-chain/phases/brainstorm/phases/01-mode-routing.md +207 -0
  20. package/.claude/skills/ccw-chain/phases/brainstorm/phases/02-artifacts.md +567 -0
  21. package/.claude/skills/ccw-chain/phases/brainstorm/phases/03-role-analysis.md +748 -0
  22. package/.claude/skills/ccw-chain/phases/brainstorm/phases/04-synthesis.md +827 -0
  23. package/.claude/skills/ccw-chain/phases/brainstorm-with-file.md +482 -0
  24. package/.claude/skills/ccw-chain/phases/collaborative-plan-with-file.md +639 -0
  25. package/.claude/skills/ccw-chain/phases/debug-with-file.md +656 -0
  26. package/.claude/skills/ccw-chain/phases/integration-test-cycle.md +936 -0
  27. package/.claude/skills/ccw-chain/phases/issue-convert-to-plan.md +720 -0
  28. package/.claude/skills/ccw-chain/phases/issue-discover.md +483 -0
  29. package/.claude/skills/ccw-chain/phases/issue-execute.md +629 -0
  30. package/.claude/skills/ccw-chain/phases/issue-from-brainstorm.md +382 -0
  31. package/.claude/skills/ccw-chain/phases/issue-plan.md +343 -0
  32. package/.claude/skills/ccw-chain/phases/issue-queue.md +464 -0
  33. package/.claude/skills/ccw-chain/phases/refactor-cycle.md +852 -0
  34. package/.claude/skills/ccw-chain/phases/review-cycle/SKILL.md +132 -0
  35. package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-fix.md +760 -0
  36. package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-module.md +764 -0
  37. package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-session.md +775 -0
  38. package/.claude/skills/ccw-chain/phases/roadmap-with-file.md +544 -0
  39. package/.claude/skills/ccw-chain/phases/spec-generator/SKILL.md +338 -0
  40. package/.claude/skills/ccw-chain/phases/spec-generator/phases/01-5-requirement-clarification.md +404 -0
  41. package/.claude/skills/ccw-chain/phases/spec-generator/phases/01-discovery.md +257 -0
  42. package/.claude/skills/ccw-chain/phases/spec-generator/phases/02-product-brief.md +274 -0
  43. package/.claude/skills/ccw-chain/phases/spec-generator/phases/03-requirements.md +184 -0
  44. package/.claude/skills/ccw-chain/phases/spec-generator/phases/04-architecture.md +248 -0
  45. package/.claude/skills/ccw-chain/phases/spec-generator/phases/05-epics-stories.md +178 -0
  46. package/.claude/skills/ccw-chain/phases/spec-generator/phases/06-5-auto-fix.md +144 -0
  47. package/.claude/skills/ccw-chain/phases/spec-generator/phases/06-readiness-check.md +480 -0
  48. package/.claude/skills/ccw-chain/phases/team-planex.md +123 -0
  49. package/.claude/skills/ccw-chain/phases/ui-design-explore-auto.md +678 -0
  50. package/.claude/skills/ccw-chain/phases/unified-execute-with-file.md +870 -0
  51. package/.claude/skills/ccw-chain/phases/workflow-execute/SKILL.md +625 -0
  52. package/.claude/skills/ccw-chain/phases/workflow-execute/phases/06-review.md +215 -0
  53. package/.claude/skills/ccw-chain/phases/workflow-lite-plan.md +616 -0
  54. package/.claude/skills/ccw-chain/phases/workflow-multi-cli-plan.md +424 -0
  55. package/.claude/skills/ccw-chain/phases/workflow-plan/SKILL.md +466 -0
  56. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/01-session-discovery.md +99 -0
  57. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/02-context-gathering.md +338 -0
  58. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/03-conflict-resolution.md +422 -0
  59. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/04-task-generation.md +440 -0
  60. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/05-plan-verify.md +395 -0
  61. package/.claude/skills/ccw-chain/phases/workflow-plan/phases/06-replan.md +594 -0
  62. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/SKILL.md +527 -0
  63. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/01-session-discovery.md +57 -0
  64. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/02-context-gathering.md +407 -0
  65. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/03-test-coverage-analysis.md +172 -0
  66. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/04-conflict-resolution.md +426 -0
  67. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/05-tdd-task-generation.md +473 -0
  68. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/06-tdd-structure-validation.md +189 -0
  69. package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/07-tdd-verify.md +635 -0
  70. package/.claude/skills/ccw-chain/phases/workflow-test-fix/SKILL.md +482 -0
  71. package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/01-session-start.md +60 -0
  72. package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/02-test-context-gather.md +493 -0
  73. package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/03-test-concept-enhanced.md +150 -0
  74. package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/04-test-task-generate.md +346 -0
  75. package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/05-test-cycle-execute.md +538 -0
  76. package/.claude/skills/ccw-chain/specs/auto-mode.md +47 -0
  77. package/.claude/skills/ccw-chain/specs/intent-patterns.md +60 -0
  78. package/.claude/skills/chain-loader/SKILL.md +78 -0
  79. package/.claude/skills/chain-loader/phases/01-analyze-skill.md +53 -0
  80. package/.claude/skills/chain-loader/phases/02-design-graph.md +73 -0
  81. package/.claude/skills/chain-loader/phases/03-generate-validate.md +75 -0
  82. package/.claude/skills/chain-loader/specs/chain-schema.md +99 -0
  83. package/.claude/skills/chain-loader/specs/design-patterns.md +99 -0
  84. package/.claude/skills/chain-loader/templates/chain-json.md +63 -0
  85. package/.claude/skills/review-cycle/phases/review-module.md +764 -764
  86. package/.claude/skills/review-cycle/phases/review-session.md +775 -775
  87. package/.claude/skills/workflow-multi-cli-plan/SKILL.md +2 -2
  88. package/.claude/skills/workflow-plan/phases/03-conflict-resolution.md +422 -422
  89. package/.claude/skills/workflow-plan/phases/05-plan-verify.md +395 -395
  90. package/.claude/skills/workflow-tdd-plan/phases/02-context-gathering.md +407 -407
  91. package/.claude/skills/workflow-tdd-plan/phases/04-conflict-resolution.md +426 -426
  92. package/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md +493 -493
  93. package/.codex/skills/brainstorm/SKILL.md +3 -3
  94. package/.codex/skills/clean/SKILL.md +3 -3
  95. package/.codex/skills/issue-discover/SKILL.md +13 -13
  96. package/.codex/skills/issue-discover/phases/02-discover.md +4 -4
  97. package/.codex/skills/issue-discover/phases/03-discover-by-prompt.md +3 -3
  98. package/.codex/skills/parallel-dev-cycle/SKILL.md +4 -4
  99. package/.codex/skills/parallel-dev-cycle/phases/02-agent-execution.md +6 -6
  100. package/.codex/skills/parallel-dev-cycle/phases/03-result-aggregation.md +10 -10
  101. package/.codex/skills/review-cycle/SKILL.md +10 -10
  102. package/.codex/skills/review-cycle/phases/02-parallel-review.md +6 -6
  103. package/.codex/skills/review-cycle/phases/04-iterative-deep-dive.md +4 -4
  104. package/.codex/skills/review-cycle/phases/07-fix-parallel-planning.md +4 -4
  105. package/.codex/skills/review-cycle/phases/08-fix-execution.md +2 -2
  106. package/.codex/skills/roadmap-with-file/SKILL.md +14 -14
  107. package/.codex/skills/spec-generator/README.md +1 -1
  108. package/.codex/skills/spec-generator/SKILL.md +184 -88
  109. package/.codex/skills/spec-generator/phases/01-5-requirement-clarification.md +4 -7
  110. package/.codex/skills/spec-generator/phases/01-discovery.md +30 -11
  111. package/.codex/skills/spec-generator/phases/02-product-brief.md +2 -5
  112. package/.codex/skills/spec-generator/phases/03-requirements.md +4 -6
  113. package/.codex/skills/spec-generator/phases/04-architecture.md +4 -6
  114. package/.codex/skills/spec-generator/phases/05-epics-stories.md +4 -6
  115. package/.codex/skills/spec-generator/phases/06-5-auto-fix.md +4 -5
  116. package/.codex/skills/spec-generator/phases/06-readiness-check.md +8 -8
  117. package/.codex/skills/spec-generator/phases/07-issue-export.md +2 -2
  118. package/.codex/skills/spec-setup/SKILL.md +4 -4
  119. package/.codex/skills/workflow-plan/SKILL.md +6 -6
  120. package/.codex/skills/workflow-tdd-plan/SKILL.md +5 -5
  121. package/.codex/skills/workflow-test-fix-cycle/SKILL.md +19 -19
  122. package/.codex/skills/workflow-test-fix-cycle/phases/01-test-fix-gen.md +5 -5
  123. package/.codex/skills/workflow-test-fix-cycle/phases/02-test-cycle-execute.md +5 -5
  124. package/README.md +14 -0
  125. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
  126. package/ccw/dist/core/routes/litellm-api-routes.js +0 -23
  127. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
  128. package/ccw/dist/tools/chain-loader.d.ts +10 -0
  129. package/ccw/dist/tools/chain-loader.d.ts.map +1 -0
  130. package/ccw/dist/tools/chain-loader.js +642 -0
  131. package/ccw/dist/tools/chain-loader.js.map +1 -0
  132. package/ccw/dist/tools/index.d.ts.map +1 -1
  133. package/ccw/dist/tools/index.js +2 -0
  134. package/ccw/dist/tools/index.js.map +1 -1
  135. package/ccw/dist/tools/json-builder.js +20 -0
  136. package/ccw/dist/tools/json-builder.js.map +1 -1
  137. package/ccw/dist/types/chain-types.d.ts +72 -0
  138. package/ccw/dist/types/chain-types.d.ts.map +1 -0
  139. package/ccw/dist/types/chain-types.js +5 -0
  140. package/ccw/dist/types/chain-types.js.map +1 -0
  141. package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js → AlertDialog-exlTDW81.js} +3 -3
  142. package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js.map → AlertDialog-exlTDW81.js.map} +1 -1
  143. package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js → AnalysisPage-cgV9LfAI.js} +2 -2
  144. package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js.map → AnalysisPage-cgV9LfAI.js.map} +1 -1
  145. package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js → ApiSettingsPage-Dk5jJdWt.js} +2 -2
  146. package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js.map → ApiSettingsPage-Dk5jJdWt.js.map} +1 -1
  147. package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js → CliModeToggle-Be9xsPiv.js} +2 -2
  148. package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js.map → CliModeToggle-Be9xsPiv.js.map} +1 -1
  149. package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js → CliSessionSharePage-Bh9jBtPI.js} +2 -2
  150. package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js.map → CliSessionSharePage-Bh9jBtPI.js.map} +1 -1
  151. package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js → CliViewerPage-BrE-oyEq.js} +2 -2
  152. package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js.map → CliViewerPage-BrE-oyEq.js.map} +1 -1
  153. package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js → CodexLensPage-Cd3nrC93.js} +2 -2
  154. package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js.map → CodexLensPage-Cd3nrC93.js.map} +1 -1
  155. package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js → Collapsible-DXFl3VKF.js} +2 -2
  156. package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js.map → Collapsible-DXFl3VKF.js.map} +1 -1
  157. package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js → CommandsManagerPage-IV8zpjgX.js} +2 -2
  158. package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js.map → CommandsManagerPage-IV8zpjgX.js.map} +1 -1
  159. package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js → DeepWikiPage-CpDxtmRX.js} +2 -2
  160. package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js.map → DeepWikiPage-CpDxtmRX.js.map} +1 -1
  161. package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js → EndpointsPage-BchjWe7s.js} +2 -2
  162. package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js.map → EndpointsPage-BchjWe7s.js.map} +1 -1
  163. package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js → ExplorerPage-CbWvaJ0y.js} +2 -2
  164. package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js.map → ExplorerPage-CbWvaJ0y.js.map} +1 -1
  165. package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js → FixSessionPage-YMjVRiCk.js} +2 -2
  166. package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js.map → FixSessionPage-YMjVRiCk.js.map} +1 -1
  167. package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js → FloatingFileBrowser-JW2ehYY_.js} +2 -2
  168. package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js.map → FloatingFileBrowser-JW2ehYY_.js.map} +1 -1
  169. package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js → FloatingPanel-BtqzqDVq.js} +2 -2
  170. package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js.map → FloatingPanel-BtqzqDVq.js.map} +1 -1
  171. package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js → GraphExplorerPage-BsJL_W4d.js} +3 -3
  172. package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js.map → GraphExplorerPage-BsJL_W4d.js.map} +1 -1
  173. package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js → HistoryPage-BuWpQ7k5.js} +2 -2
  174. package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js.map → HistoryPage-BuWpQ7k5.js.map} +1 -1
  175. package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js → HookManagerPage-D0BtMIWy.js} +2 -2
  176. package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js.map → HookManagerPage-D0BtMIWy.js.map} +1 -1
  177. package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js → InstallationsPage-C7dwsAKG.js} +2 -2
  178. package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js.map → InstallationsPage-C7dwsAKG.js.map} +1 -1
  179. package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js → IssueHubPage-D0nCNaeB.js} +2 -2
  180. package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js.map → IssueHubPage-D0nCNaeB.js.map} +1 -1
  181. package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js → LiteTasksPage-B5c2Kb9r.js} +3 -3
  182. package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js.map → LiteTasksPage-B5c2Kb9r.js.map} +1 -1
  183. package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js → McpManagerPage-C-S5CehM.js} +2 -2
  184. package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js.map → McpManagerPage-C-S5CehM.js.map} +1 -1
  185. package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js → MemoryPage-P_B0JVUQ.js} +2 -2
  186. package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js.map → MemoryPage-P_B0JVUQ.js.map} +1 -1
  187. package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js → NotFoundPage-S4Jn9LUE.js} +2 -2
  188. package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js.map → NotFoundPage-S4Jn9LUE.js.map} +1 -1
  189. package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js → OrchestratorPage-C2Zlr7AC.js} +2 -2
  190. package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js.map → OrchestratorPage-C2Zlr7AC.js.map} +1 -1
  191. package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js → ProjectOverviewPage-CMVfz8s5.js} +2 -2
  192. package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js.map → ProjectOverviewPage-CMVfz8s5.js.map} +1 -1
  193. package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js → PromptHistoryPage-YEMjFARX.js} +3 -3
  194. package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js.map → PromptHistoryPage-YEMjFARX.js.map} +1 -1
  195. package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js → ReviewSessionPage-DnTm55nG.js} +2 -2
  196. package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js.map → ReviewSessionPage-DnTm55nG.js.map} +1 -1
  197. package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js → RulesManagerPage-CUwebtO2.js} +2 -2
  198. package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js.map → RulesManagerPage-CUwebtO2.js.map} +1 -1
  199. package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js → SessionDetailPage-0qyH1Z5P.js} +2 -2
  200. package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js.map → SessionDetailPage-0qyH1Z5P.js.map} +1 -1
  201. package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js → SessionsPage-BpgP4087.js} +2 -2
  202. package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js.map → SessionsPage-BpgP4087.js.map} +1 -1
  203. package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js +150 -0
  204. package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js.map +1 -0
  205. package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js +7 -0
  206. package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js.map +1 -0
  207. package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js → SpecsSettingsPage-DT-yTVkD.js} +4 -4
  208. package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js.map → SpecsSettingsPage-DT-yTVkD.js.map} +1 -1
  209. package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js → Switch-CYSPdqWk.js} +2 -2
  210. package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js.map → Switch-CYSPdqWk.js.map} +1 -1
  211. package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js → TabsNavigation-CPh6Zor1.js} +2 -2
  212. package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js.map → TabsNavigation-CPh6Zor1.js.map} +1 -1
  213. package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js → TaskDrawer-Ds-8830B.js} +2 -2
  214. package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js.map → TaskDrawer-Ds-8830B.js.map} +1 -1
  215. package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js → TeamPage-CJODUxBk.js} +2 -2
  216. package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js.map → TeamPage-CJODUxBk.js.map} +1 -1
  217. package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js → TerminalDashboardPage-Cn3fGUuO.js} +3 -3
  218. package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js.map → TerminalDashboardPage-Cn3fGUuO.js.map} +1 -1
  219. package/ccw/frontend/dist/assets/{archive-DxemgIhF.js → archive-CjwVpw6k.js} +2 -2
  220. package/ccw/frontend/dist/assets/{archive-DxemgIhF.js.map → archive-CjwVpw6k.js.map} +1 -1
  221. package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js → archive-restore-2vZa9Ic3.js} +2 -2
  222. package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js.map → archive-restore-2vZa9Ic3.js.map} +1 -1
  223. package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js → arrow-right-CUU5XDgT.js} +2 -2
  224. package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js.map → arrow-right-CUU5XDgT.js.map} +1 -1
  225. package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js → bookmark-plus-Cc3nKRZ5.js} +2 -2
  226. package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js.map → bookmark-plus-Cc3nKRZ5.js.map} +1 -1
  227. package/ccw/frontend/dist/assets/{bot-DOwFtzak.js → bot-BwpSRDUa.js} +2 -2
  228. package/ccw/frontend/dist/assets/{bot-DOwFtzak.js.map → bot-BwpSRDUa.js.map} +1 -1
  229. package/ccw/frontend/dist/assets/{braces-96qH3aFh.js → braces-DBzUW1XC.js} +2 -2
  230. package/ccw/frontend/dist/assets/{braces-96qH3aFh.js.map → braces-DBzUW1XC.js.map} +1 -1
  231. package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js → circle-stop-CGNNsjvE.js} +2 -2
  232. package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js.map → circle-stop-CGNNsjvE.js.map} +1 -1
  233. package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js → cpu-D27G86Ul.js} +2 -2
  234. package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js.map → cpu-D27G86Ul.js.map} +1 -1
  235. package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js → ellipsis-vertical-C1Ij47Yz.js} +2 -2
  236. package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js.map → ellipsis-vertical-C1Ij47Yz.js.map} +1 -1
  237. package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js → eye-C6MOB7Au.js} +2 -2
  238. package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js.map → eye-C6MOB7Au.js.map} +1 -1
  239. package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js → eye-off-BxfBlZ26.js} +2 -2
  240. package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js.map → eye-off-BxfBlZ26.js.map} +1 -1
  241. package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js → file-json-NI237wA-.js} +2 -2
  242. package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js.map → file-json-NI237wA-.js.map} +1 -1
  243. package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js → file-text-Byn2_2v6.js} +2 -2
  244. package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js.map → file-text-Byn2_2v6.js.map} +1 -1
  245. package/ccw/frontend/dist/assets/{filter-q9g-bknU.js → filter-D-7PhZjx.js} +2 -2
  246. package/ccw/frontend/dist/assets/{filter-q9g-bknU.js.map → filter-D-7PhZjx.js.map} +1 -1
  247. package/ccw/frontend/dist/assets/{folder-CL6vb42J.js → folder-BoAsK_FL.js} +2 -2
  248. package/ccw/frontend/dist/assets/{folder-CL6vb42J.js.map → folder-BoAsK_FL.js.map} +1 -1
  249. package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js → gauge-DCSxJIS4.js} +2 -2
  250. package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js.map → gauge-DCSxJIS4.js.map} +1 -1
  251. package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js → globe-CHS3prza.js} +2 -2
  252. package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js.map → globe-CHS3prza.js.map} +1 -1
  253. package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js → grid-3x3-D7K35U7S.js} +2 -2
  254. package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js.map → grid-3x3-D7K35U7S.js.map} +1 -1
  255. package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js → hard-drive-eq9xE07G.js} +2 -2
  256. package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js.map → hard-drive-eq9xE07G.js.map} +1 -1
  257. package/ccw/frontend/dist/assets/{hash-80O0kJO7.js → hash-C1DMpBua.js} +2 -2
  258. package/ccw/frontend/dist/assets/{hash-80O0kJO7.js.map → hash-C1DMpBua.js.map} +1 -1
  259. package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js → history-Di5SBCY-.js} +2 -2
  260. package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js.map → history-Di5SBCY-.js.map} +1 -1
  261. package/ccw/frontend/dist/assets/{index-mbeo62f8.js → index--_R7COnA.js} +2 -2
  262. package/ccw/frontend/dist/assets/{index-mbeo62f8.js.map → index--_R7COnA.js.map} +1 -1
  263. package/ccw/frontend/dist/assets/{index-rLgoBCfV.js → index-BUol9HDD.js} +3 -3
  264. package/ccw/frontend/dist/assets/{index-rLgoBCfV.js.map → index-BUol9HDD.js.map} +1 -1
  265. package/ccw/frontend/dist/assets/{index-Bs80iCX0.js → index-CT9oykfw.js} +2 -2
  266. package/ccw/frontend/dist/assets/{index-Bs80iCX0.js.map → index-CT9oykfw.js.map} +1 -1
  267. package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js → index-Ddwvf87H.js} +2 -2
  268. package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js.map → index-Ddwvf87H.js.map} +1 -1
  269. package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js → layout-grid-LiX0qZbN.js} +2 -2
  270. package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js.map → layout-grid-LiX0qZbN.js.map} +1 -1
  271. package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js → lightbulb-CL3DVEwb.js} +2 -2
  272. package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js.map → lightbulb-CL3DVEwb.js.map} +1 -1
  273. package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js → link-2-CC5cFeq6.js} +2 -2
  274. package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js.map → link-2-CC5cFeq6.js.map} +1 -1
  275. package/ccw/frontend/dist/assets/{link-koEYiemK.js → link-ngFQ9bs0.js} +2 -2
  276. package/ccw/frontend/dist/assets/{link-koEYiemK.js.map → link-ngFQ9bs0.js.map} +1 -1
  277. package/ccw/frontend/dist/assets/{list-v2_GaLdC.js → list-BEU6I0KK.js} +2 -2
  278. package/ccw/frontend/dist/assets/{list-v2_GaLdC.js.map → list-BEU6I0KK.js.map} +1 -1
  279. package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js → map-pin-BWZdLA6y.js} +2 -2
  280. package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js.map → map-pin-BWZdLA6y.js.map} +1 -1
  281. package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js → messages-square-K6_Chm7n.js} +2 -2
  282. package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js.map → messages-square-K6_Chm7n.js.map} +1 -1
  283. package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js → minimize-2-CWkphauf.js} +2 -2
  284. package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js.map → minimize-2-CWkphauf.js.map} +1 -1
  285. package/ccw/frontend/dist/assets/{package-CH3smL37.js → package-DrNgkamn.js} +2 -2
  286. package/ccw/frontend/dist/assets/{package-CH3smL37.js.map → package-DrNgkamn.js.map} +1 -1
  287. package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js → plug-CMo3sw5_.js} +2 -2
  288. package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js.map → plug-CMo3sw5_.js.map} +1 -1
  289. package/ccw/frontend/dist/assets/{power-F2A_J4l6.js → power-DppNTW5e.js} +2 -2
  290. package/ccw/frontend/dist/assets/{power-F2A_J4l6.js.map → power-DppNTW5e.js.map} +1 -1
  291. package/ccw/frontend/dist/assets/{save-Byxot0YU.js → save-CD8aPMbZ.js} +2 -2
  292. package/ccw/frontend/dist/assets/{save-Byxot0YU.js.map → save-CD8aPMbZ.js.map} +1 -1
  293. package/ccw/frontend/dist/assets/{send-JjqhUkpw.js → send-B4z90fQD.js} +2 -2
  294. package/ccw/frontend/dist/assets/{send-JjqhUkpw.js.map → send-B4z90fQD.js.map} +1 -1
  295. package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js → settings-2-CAKRU_QC.js} +2 -2
  296. package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js.map → settings-2-CAKRU_QC.js.map} +1 -1
  297. package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js → square-check-big-KhI3HrzX.js} +2 -2
  298. package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js.map → square-check-big-KhI3HrzX.js.map} +1 -1
  299. package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js → square-pen-BtdGIpuq.js} +2 -2
  300. package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js.map → square-pen-BtdGIpuq.js.map} +1 -1
  301. package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js → star-ZoBUkXoD.js} +2 -2
  302. package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js.map → star-ZoBUkXoD.js.map} +1 -1
  303. package/ccw/frontend/dist/assets/{style-CKs7nnn3.js → style-CltxQP-P.js} +2 -2
  304. package/ccw/frontend/dist/assets/{style-CKs7nnn3.js.map → style-CltxQP-P.js.map} +1 -1
  305. package/ccw/frontend/dist/assets/{target-DW5tsDW6.js → target-C32OUSGf.js} +2 -2
  306. package/ccw/frontend/dist/assets/{target-DW5tsDW6.js.map → target-C32OUSGf.js.map} +1 -1
  307. package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js → test-tube-0IxoyAVZ.js} +2 -2
  308. package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js.map → test-tube-0IxoyAVZ.js.map} +1 -1
  309. package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js → upload-4eKCkyBn.js} +2 -2
  310. package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js.map → upload-4eKCkyBn.js.map} +1 -1
  311. package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js → useApiSettings-zLTUWqhi.js} +2 -2
  312. package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js.map → useApiSettings-zLTUWqhi.js.map} +1 -1
  313. package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js → useCli-BtN2vpOX.js} +2 -2
  314. package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js.map → useCli-BtN2vpOX.js.map} +1 -1
  315. package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js → useCommands-_spj49qL.js} +2 -2
  316. package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js.map → useCommands-_spj49qL.js.map} +1 -1
  317. package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js → useDebounce-Bm9KFZvd.js} +2 -2
  318. package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js.map → useDebounce-Bm9KFZvd.js.map} +1 -1
  319. package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js → useFileExplorer-DOmpm6v9.js} +2 -2
  320. package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js.map → useFileExplorer-DOmpm6v9.js.map} +1 -1
  321. package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js → useLocale-D2rj4rea.js} +2 -2
  322. package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js.map → useLocale-D2rj4rea.js.map} +1 -1
  323. package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js → useSkills-OskEpomF.js} +3 -3
  324. package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js.map → useSkills-OskEpomF.js.map} +1 -1
  325. package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js → useSystemSettings-BjMgsNSF.js} +2 -2
  326. package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js.map → useSystemSettings-BjMgsNSF.js.map} +1 -1
  327. package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js → wand-sparkles-CLhyYWa7.js} +2 -2
  328. package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js.map → wand-sparkles-CLhyYWa7.js.map} +1 -1
  329. package/ccw/frontend/dist/index.html +1 -1
  330. package/ccw/scripts/prepublish-clean.mjs +0 -1
  331. package/package.json +1 -3
  332. package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js +0 -150
  333. package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js.map +0 -1
  334. package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js +0 -7
  335. package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js.map +0 -1
  336. package/ccw-litellm/README.md +0 -180
  337. package/ccw-litellm/pyproject.toml +0 -35
  338. package/ccw-litellm/src/ccw_litellm/__init__.py +0 -47
  339. package/ccw-litellm/src/ccw_litellm/cli.py +0 -108
  340. package/ccw-litellm/src/ccw_litellm/clients/__init__.py +0 -12
  341. package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +0 -270
  342. package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +0 -198
  343. package/ccw-litellm/src/ccw_litellm/config/__init__.py +0 -22
  344. package/ccw-litellm/src/ccw_litellm/config/loader.py +0 -343
  345. package/ccw-litellm/src/ccw_litellm/config/models.py +0 -162
  346. package/ccw-litellm/src/ccw_litellm/interfaces/__init__.py +0 -14
  347. package/ccw-litellm/src/ccw_litellm/interfaces/embedder.py +0 -52
  348. package/ccw-litellm/src/ccw_litellm/interfaces/llm.py +0 -45
@@ -1,198 +0,0 @@
1
- """LiteLLM client implementation for LLM operations."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import logging
7
- import os
8
- from typing import Any, Sequence
9
-
10
- import litellm
11
-
12
- from ..config import LiteLLMConfig, get_config
13
- from ..interfaces.llm import AbstractLLMClient, ChatMessage, LLMResponse
14
-
15
- logger = logging.getLogger(__name__)
16
-
17
-
18
- class LiteLLMClient(AbstractLLMClient):
19
- """LiteLLM client implementation.
20
-
21
- Supports multiple providers (OpenAI, Anthropic, etc.) through LiteLLM's unified interface.
22
-
23
- Example:
24
- client = LiteLLMClient(model="default")
25
- response = client.chat([
26
- ChatMessage(role="user", content="Hello!")
27
- ])
28
- print(response.content)
29
- """
30
-
31
- def __init__(
32
- self,
33
- model: str = "default",
34
- config: LiteLLMConfig | None = None,
35
- **litellm_kwargs: Any,
36
- ) -> None:
37
- """Initialize LiteLLM client.
38
-
39
- Args:
40
- model: Model name from configuration (default: "default")
41
- config: Configuration instance (default: use global config)
42
- **litellm_kwargs: Additional arguments to pass to litellm.completion()
43
- """
44
- self._config = config or get_config()
45
- self._model_name = model
46
- self._litellm_kwargs = litellm_kwargs
47
-
48
- # Get model configuration
49
- try:
50
- self._model_config = self._config.get_llm_model(model)
51
- except ValueError as e:
52
- logger.error(f"Failed to get model configuration: {e}")
53
- raise
54
-
55
- # Get provider configuration
56
- try:
57
- self._provider_config = self._config.get_provider(self._model_config.provider)
58
- except ValueError as e:
59
- logger.error(f"Failed to get provider configuration: {e}")
60
- raise
61
-
62
- # Set up LiteLLM environment
63
- self._setup_litellm()
64
-
65
- def _setup_litellm(self) -> None:
66
- """Configure LiteLLM with provider settings."""
67
- provider = self._model_config.provider
68
-
69
- # Set API key
70
- if self._provider_config.api_key:
71
- env_var = f"{provider.upper()}_API_KEY"
72
- litellm.api_key = self._provider_config.api_key
73
- # Also set environment-specific keys
74
- if provider == "openai":
75
- litellm.openai_key = self._provider_config.api_key
76
- elif provider == "anthropic":
77
- litellm.anthropic_key = self._provider_config.api_key
78
-
79
- # Set API base
80
- if self._provider_config.api_base:
81
- litellm.api_base = self._provider_config.api_base
82
-
83
- def _format_model_name(self) -> str:
84
- """Format model name for LiteLLM.
85
-
86
- Returns:
87
- Formatted model name (e.g., "gpt-4", "claude-3-opus-20240229")
88
- """
89
- # LiteLLM expects model names in format: "provider/model" or just "model"
90
- # If provider is explicit, use provider/model format
91
- provider = self._model_config.provider
92
- model = self._model_config.model
93
-
94
- # For some providers, LiteLLM expects explicit prefix
95
- if provider in ["anthropic", "azure", "vertex_ai", "bedrock"]:
96
- return f"{provider}/{model}"
97
-
98
- # If there's a custom api_base, use openai/ prefix to force OpenAI-compatible routing
99
- # This prevents LiteLLM from auto-detecting model provider from name
100
- # (e.g., "gemini-2.5-pro" would otherwise trigger Vertex AI auth)
101
- if self._provider_config.api_base:
102
- # Check if it's not the default OpenAI endpoint
103
- default_openai_bases = [
104
- "https://api.openai.com/v1",
105
- "https://api.openai.com",
106
- ]
107
- if self._provider_config.api_base not in default_openai_bases:
108
- return f"openai/{model}"
109
-
110
- return model
111
-
112
- def chat(
113
- self,
114
- messages: Sequence[ChatMessage],
115
- **kwargs: Any,
116
- ) -> LLMResponse:
117
- """Chat completion for a sequence of messages.
118
-
119
- Args:
120
- messages: Sequence of chat messages
121
- **kwargs: Additional arguments for litellm.completion()
122
-
123
- Returns:
124
- LLM response with content and raw response
125
-
126
- Raises:
127
- Exception: If LiteLLM completion fails
128
- """
129
- # Convert messages to LiteLLM format
130
- litellm_messages = [
131
- {"role": msg.role, "content": msg.content} for msg in messages
132
- ]
133
-
134
- # Merge kwargs
135
- completion_kwargs = {**self._litellm_kwargs, **kwargs}
136
-
137
- # Build extra_headers from multiple sources
138
- if "extra_headers" not in completion_kwargs:
139
- completion_kwargs["extra_headers"] = {}
140
-
141
- # 1. Load custom headers from environment variable (set by CCW)
142
- env_headers = os.environ.get("CCW_LITELLM_EXTRA_HEADERS")
143
- if env_headers:
144
- try:
145
- custom_headers = json.loads(env_headers)
146
- completion_kwargs["extra_headers"].update(custom_headers)
147
- except json.JSONDecodeError:
148
- logger.warning(f"Invalid JSON in CCW_LITELLM_EXTRA_HEADERS: {env_headers}")
149
-
150
- # 2. Override User-Agent to avoid being blocked by some API proxies
151
- # that detect and block OpenAI SDK's default User-Agent
152
- # This is a fallback - user can override via custom headers
153
- if "User-Agent" not in completion_kwargs["extra_headers"]:
154
- completion_kwargs["extra_headers"]["User-Agent"] = "python-httpx/0.27"
155
-
156
- try:
157
- # Call LiteLLM
158
- response = litellm.completion(
159
- model=self._format_model_name(),
160
- messages=litellm_messages,
161
- **completion_kwargs,
162
- )
163
-
164
- # Extract content
165
- content = response.choices[0].message.content or ""
166
-
167
- return LLMResponse(content=content, raw=response)
168
-
169
- except Exception as e:
170
- logger.error(f"LiteLLM completion failed: {e}")
171
- raise
172
-
173
- def complete(self, prompt: str, **kwargs: Any) -> LLMResponse:
174
- """Text completion for a prompt.
175
-
176
- Args:
177
- prompt: Input prompt
178
- **kwargs: Additional arguments for litellm.completion()
179
-
180
- Returns:
181
- LLM response with content and raw response
182
-
183
- Raises:
184
- Exception: If LiteLLM completion fails
185
- """
186
- # Convert to chat format (most modern models use chat interface)
187
- messages = [ChatMessage(role="user", content=prompt)]
188
- return self.chat(messages, **kwargs)
189
-
190
- @property
191
- def model_name(self) -> str:
192
- """Get configured model name."""
193
- return self._model_name
194
-
195
- @property
196
- def provider(self) -> str:
197
- """Get configured provider name."""
198
- return self._model_config.provider
@@ -1,22 +0,0 @@
1
- """Configuration management for LiteLLM integration."""
2
-
3
- from __future__ import annotations
4
-
5
- from .loader import get_config, load_config, reset_config
6
- from .models import (
7
- EmbeddingModelConfig,
8
- LiteLLMConfig,
9
- LLMModelConfig,
10
- ProviderConfig,
11
- )
12
-
13
- __all__ = [
14
- "LiteLLMConfig",
15
- "ProviderConfig",
16
- "LLMModelConfig",
17
- "EmbeddingModelConfig",
18
- "load_config",
19
- "get_config",
20
- "reset_config",
21
- ]
22
-
@@ -1,343 +0,0 @@
1
- """Configuration loader with environment variable substitution."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import os
7
- import re
8
- from pathlib import Path
9
- from typing import Any
10
-
11
- import yaml
12
-
13
- from .models import LiteLLMConfig
14
-
15
- # Default configuration paths
16
- # JSON format (UI config) takes priority over YAML format
17
- DEFAULT_JSON_CONFIG_PATH = Path.home() / ".ccw" / "config" / "litellm-api-config.json"
18
- DEFAULT_YAML_CONFIG_PATH = Path.home() / ".ccw" / "config" / "litellm-config.yaml"
19
- # Keep backward compatibility
20
- DEFAULT_CONFIG_PATH = DEFAULT_YAML_CONFIG_PATH
21
-
22
- # Global configuration singleton
23
- _config_instance: LiteLLMConfig | None = None
24
-
25
-
26
- def _substitute_env_vars(value: Any) -> Any:
27
- """Recursively substitute environment variables in configuration values.
28
-
29
- Supports ${ENV_VAR} and ${ENV_VAR:-default} syntax.
30
-
31
- Args:
32
- value: Configuration value (str, dict, list, or primitive)
33
-
34
- Returns:
35
- Value with environment variables substituted
36
- """
37
- if isinstance(value, str):
38
- # Pattern: ${VAR} or ${VAR:-default}
39
- pattern = r"\$\{([^:}]+)(?::-(.*?))?\}"
40
-
41
- def replace_var(match: re.Match) -> str:
42
- var_name = match.group(1)
43
- default_value = match.group(2) if match.group(2) is not None else ""
44
- return os.environ.get(var_name, default_value)
45
-
46
- return re.sub(pattern, replace_var, value)
47
-
48
- if isinstance(value, dict):
49
- return {k: _substitute_env_vars(v) for k, v in value.items()}
50
-
51
- if isinstance(value, list):
52
- return [_substitute_env_vars(item) for item in value]
53
-
54
- return value
55
-
56
-
57
- def _get_default_config() -> dict[str, Any]:
58
- """Get default configuration when no config file exists.
59
-
60
- Returns:
61
- Default configuration dictionary
62
- """
63
- return {
64
- "version": 1,
65
- "default_provider": "openai",
66
- "providers": {
67
- "openai": {
68
- "api_key": "${OPENAI_API_KEY}",
69
- "api_base": "https://api.openai.com/v1",
70
- },
71
- },
72
- "llm_models": {
73
- "default": {
74
- "provider": "openai",
75
- "model": "gpt-4",
76
- },
77
- "fast": {
78
- "provider": "openai",
79
- "model": "gpt-3.5-turbo",
80
- },
81
- },
82
- "embedding_models": {
83
- "default": {
84
- "provider": "openai",
85
- "model": "text-embedding-3-small",
86
- "dimensions": 1536,
87
- },
88
- },
89
- }
90
-
91
-
92
- def _convert_json_to_internal_format(json_config: dict[str, Any]) -> dict[str, Any]:
93
- """Convert UI JSON config format to internal format.
94
-
95
- The UI stores config in a different structure:
96
- - providers: array of {id, name, type, apiKey, apiBase, llmModels[], embeddingModels[]}
97
-
98
- Internal format uses:
99
- - providers: dict of {provider_id: {api_key, api_base}}
100
- - llm_models: dict of {model_id: {provider, model}}
101
- - embedding_models: dict of {model_id: {provider, model, dimensions}}
102
-
103
- Args:
104
- json_config: Configuration in UI JSON format
105
-
106
- Returns:
107
- Configuration in internal format
108
- """
109
- providers: dict[str, Any] = {}
110
- llm_models: dict[str, Any] = {}
111
- embedding_models: dict[str, Any] = {}
112
- reranker_models: dict[str, Any] = {}
113
- default_provider: str | None = None
114
-
115
- for provider in json_config.get("providers", []):
116
- if not provider.get("enabled", True):
117
- continue
118
-
119
- provider_id = provider.get("id", "")
120
- if not provider_id:
121
- continue
122
-
123
- # Set first enabled provider as default
124
- if default_provider is None:
125
- default_provider = provider_id
126
-
127
- # Convert provider with advanced settings
128
- provider_config: dict[str, Any] = {
129
- "api_key": provider.get("apiKey", ""),
130
- "api_base": provider.get("apiBase"),
131
- }
132
-
133
- # Map advanced settings
134
- adv = provider.get("advancedSettings", {})
135
- if adv.get("timeout"):
136
- provider_config["timeout"] = adv["timeout"]
137
- if adv.get("maxRetries"):
138
- provider_config["max_retries"] = adv["maxRetries"]
139
- if adv.get("organization"):
140
- provider_config["organization"] = adv["organization"]
141
- if adv.get("apiVersion"):
142
- provider_config["api_version"] = adv["apiVersion"]
143
- if adv.get("customHeaders"):
144
- provider_config["custom_headers"] = adv["customHeaders"]
145
-
146
- providers[provider_id] = provider_config
147
-
148
- # Convert LLM models
149
- for model in provider.get("llmModels", []):
150
- if not model.get("enabled", True):
151
- continue
152
- model_id = model.get("id", "")
153
- if not model_id:
154
- continue
155
-
156
- llm_model_config: dict[str, Any] = {
157
- "provider": provider_id,
158
- "model": model.get("name", ""),
159
- }
160
- # Add model-specific endpoint settings
161
- endpoint = model.get("endpointSettings", {})
162
- if endpoint.get("baseUrl"):
163
- llm_model_config["api_base"] = endpoint["baseUrl"]
164
- if endpoint.get("timeout"):
165
- llm_model_config["timeout"] = endpoint["timeout"]
166
- if endpoint.get("maxRetries"):
167
- llm_model_config["max_retries"] = endpoint["maxRetries"]
168
-
169
- # Add capabilities
170
- caps = model.get("capabilities", {})
171
- if caps.get("contextWindow"):
172
- llm_model_config["context_window"] = caps["contextWindow"]
173
- if caps.get("maxOutputTokens"):
174
- llm_model_config["max_output_tokens"] = caps["maxOutputTokens"]
175
-
176
- llm_models[model_id] = llm_model_config
177
-
178
- # Convert embedding models
179
- for model in provider.get("embeddingModels", []):
180
- if not model.get("enabled", True):
181
- continue
182
- model_id = model.get("id", "")
183
- if not model_id:
184
- continue
185
-
186
- embedding_model_config: dict[str, Any] = {
187
- "provider": provider_id,
188
- "model": model.get("name", ""),
189
- "dimensions": model.get("capabilities", {}).get("embeddingDimension", 1536),
190
- "max_input_tokens": model.get("capabilities", {}).get("maxInputTokens", 8192),
191
- }
192
- # Add model-specific endpoint settings
193
- endpoint = model.get("endpointSettings", {})
194
- if endpoint.get("baseUrl"):
195
- embedding_model_config["api_base"] = endpoint["baseUrl"]
196
- if endpoint.get("timeout"):
197
- embedding_model_config["timeout"] = endpoint["timeout"]
198
-
199
- embedding_models[model_id] = embedding_model_config
200
-
201
- # Convert reranker models
202
- for model in provider.get("rerankerModels", []):
203
- if not model.get("enabled", True):
204
- continue
205
- model_id = model.get("id", "")
206
- if not model_id:
207
- continue
208
-
209
- reranker_model_config: dict[str, Any] = {
210
- "provider": provider_id,
211
- "model": model.get("name", ""),
212
- "max_input_tokens": model.get("capabilities", {}).get("maxInputTokens", 8192),
213
- "top_k": model.get("capabilities", {}).get("topK", 50),
214
- }
215
- # Add model-specific endpoint settings
216
- endpoint = model.get("endpointSettings", {})
217
- if endpoint.get("baseUrl"):
218
- reranker_model_config["api_base"] = endpoint["baseUrl"]
219
- if endpoint.get("timeout"):
220
- reranker_model_config["timeout"] = endpoint["timeout"]
221
-
222
- reranker_models[model_id] = reranker_model_config
223
-
224
- # Ensure we have defaults if no models found
225
- if not llm_models:
226
- llm_models["default"] = {
227
- "provider": default_provider or "openai",
228
- "model": "gpt-4",
229
- }
230
-
231
- if not embedding_models:
232
- embedding_models["default"] = {
233
- "provider": default_provider or "openai",
234
- "model": "text-embedding-3-small",
235
- "dimensions": 1536,
236
- "max_input_tokens": 8191,
237
- }
238
-
239
- return {
240
- "version": json_config.get("version", 1),
241
- "default_provider": default_provider or "openai",
242
- "providers": providers,
243
- "llm_models": llm_models,
244
- "embedding_models": embedding_models,
245
- "reranker_models": reranker_models,
246
- }
247
-
248
-
249
- def load_config(config_path: Path | str | None = None) -> LiteLLMConfig:
250
- """Load LiteLLM configuration from JSON or YAML file.
251
-
252
- Priority order:
253
- 1. Explicit config_path if provided
254
- 2. JSON config (UI format): ~/.ccw/config/litellm-api-config.json
255
- 3. YAML config: ~/.ccw/config/litellm-config.yaml
256
- 4. Default configuration
257
-
258
- Args:
259
- config_path: Path to configuration file (optional)
260
-
261
- Returns:
262
- Parsed and validated configuration
263
-
264
- Raises:
265
- FileNotFoundError: If config file not found and no default available
266
- ValueError: If configuration is invalid
267
- """
268
- raw_config: dict[str, Any] | None = None
269
- is_json_format = False
270
-
271
- if config_path is not None:
272
- config_path = Path(config_path)
273
- if config_path.exists():
274
- try:
275
- with open(config_path, "r", encoding="utf-8") as f:
276
- if config_path.suffix == ".json":
277
- raw_config = json.load(f)
278
- is_json_format = True
279
- else:
280
- raw_config = yaml.safe_load(f)
281
- except Exception as e:
282
- raise ValueError(f"Failed to load configuration from {config_path}: {e}") from e
283
-
284
- # Check JSON config first (UI format)
285
- if raw_config is None and DEFAULT_JSON_CONFIG_PATH.exists():
286
- try:
287
- with open(DEFAULT_JSON_CONFIG_PATH, "r", encoding="utf-8") as f:
288
- raw_config = json.load(f)
289
- is_json_format = True
290
- except Exception:
291
- pass # Fall through to YAML
292
-
293
- # Check YAML config
294
- if raw_config is None and DEFAULT_YAML_CONFIG_PATH.exists():
295
- try:
296
- with open(DEFAULT_YAML_CONFIG_PATH, "r", encoding="utf-8") as f:
297
- raw_config = yaml.safe_load(f)
298
- except Exception:
299
- pass # Fall through to default
300
-
301
- # Use default configuration
302
- if raw_config is None:
303
- raw_config = _get_default_config()
304
-
305
- # Convert JSON format to internal format if needed
306
- if is_json_format:
307
- raw_config = _convert_json_to_internal_format(raw_config)
308
-
309
- # Substitute environment variables
310
- config_data = _substitute_env_vars(raw_config)
311
-
312
- # Validate and parse with Pydantic
313
- try:
314
- return LiteLLMConfig.model_validate(config_data)
315
- except Exception as e:
316
- raise ValueError(f"Invalid configuration: {e}") from e
317
-
318
-
319
- def get_config(config_path: Path | str | None = None, reload: bool = False) -> LiteLLMConfig:
320
- """Get global configuration singleton.
321
-
322
- Args:
323
- config_path: Path to configuration file (default: ~/.ccw/config/litellm-config.yaml)
324
- reload: Force reload configuration from disk
325
-
326
- Returns:
327
- Global configuration instance
328
- """
329
- global _config_instance
330
-
331
- if _config_instance is None or reload:
332
- _config_instance = load_config(config_path)
333
-
334
- return _config_instance
335
-
336
-
337
- def reset_config() -> None:
338
- """Reset global configuration singleton.
339
-
340
- Useful for testing.
341
- """
342
- global _config_instance
343
- _config_instance = None