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.
- package/.ccw/workflows/cli-templates/schemas/plan-overview-base-schema.json +2 -2
- package/.ccw/workflows/cli-templates/schemas/task-schema.json +14 -7
- package/.claude/agents/action-planning-agent.md +7 -4
- package/.claude/agents/cli-explore-agent.md +77 -63
- package/.claude/agents/cli-lite-planning-agent.md +11 -10
- package/.claude/agents/issue-plan-agent.md +421 -426
- package/.claude/commands/workflow/spec/setup.md +1 -1
- package/.claude/skills/ccw-chain/SKILL.md +119 -0
- package/.claude/skills/ccw-chain/chains/ccw-cycle.json +21 -0
- package/.claude/skills/ccw-chain/chains/ccw-exploration.json +47 -0
- package/.claude/skills/ccw-chain/chains/ccw-issue.json +33 -0
- package/.claude/skills/ccw-chain/chains/ccw-lightweight.json +57 -0
- package/.claude/skills/ccw-chain/chains/ccw-main.json +52 -0
- package/.claude/skills/ccw-chain/chains/ccw-standard.json +39 -0
- package/.claude/skills/ccw-chain/chains/ccw-team.json +10 -0
- package/.claude/skills/ccw-chain/chains/ccw-with-file.json +31 -0
- package/.claude/skills/ccw-chain/phases/analyze-with-file.md +788 -0
- package/.claude/skills/ccw-chain/phases/brainstorm/SKILL.md +408 -0
- package/.claude/skills/ccw-chain/phases/brainstorm/phases/01-mode-routing.md +207 -0
- package/.claude/skills/ccw-chain/phases/brainstorm/phases/02-artifacts.md +567 -0
- package/.claude/skills/ccw-chain/phases/brainstorm/phases/03-role-analysis.md +748 -0
- package/.claude/skills/ccw-chain/phases/brainstorm/phases/04-synthesis.md +827 -0
- package/.claude/skills/ccw-chain/phases/brainstorm-with-file.md +482 -0
- package/.claude/skills/ccw-chain/phases/collaborative-plan-with-file.md +639 -0
- package/.claude/skills/ccw-chain/phases/debug-with-file.md +656 -0
- package/.claude/skills/ccw-chain/phases/integration-test-cycle.md +936 -0
- package/.claude/skills/ccw-chain/phases/issue-convert-to-plan.md +720 -0
- package/.claude/skills/ccw-chain/phases/issue-discover.md +483 -0
- package/.claude/skills/ccw-chain/phases/issue-execute.md +629 -0
- package/.claude/skills/ccw-chain/phases/issue-from-brainstorm.md +382 -0
- package/.claude/skills/ccw-chain/phases/issue-plan.md +343 -0
- package/.claude/skills/ccw-chain/phases/issue-queue.md +464 -0
- package/.claude/skills/ccw-chain/phases/refactor-cycle.md +852 -0
- package/.claude/skills/ccw-chain/phases/review-cycle/SKILL.md +132 -0
- package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-fix.md +760 -0
- package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-module.md +764 -0
- package/.claude/skills/ccw-chain/phases/review-cycle/phases/review-session.md +775 -0
- package/.claude/skills/ccw-chain/phases/roadmap-with-file.md +544 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/SKILL.md +338 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/01-5-requirement-clarification.md +404 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/01-discovery.md +257 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/02-product-brief.md +274 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/03-requirements.md +184 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/04-architecture.md +248 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/05-epics-stories.md +178 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/06-5-auto-fix.md +144 -0
- package/.claude/skills/ccw-chain/phases/spec-generator/phases/06-readiness-check.md +480 -0
- package/.claude/skills/ccw-chain/phases/team-planex.md +123 -0
- package/.claude/skills/ccw-chain/phases/ui-design-explore-auto.md +678 -0
- package/.claude/skills/ccw-chain/phases/unified-execute-with-file.md +870 -0
- package/.claude/skills/ccw-chain/phases/workflow-execute/SKILL.md +625 -0
- package/.claude/skills/ccw-chain/phases/workflow-execute/phases/06-review.md +215 -0
- package/.claude/skills/ccw-chain/phases/workflow-lite-plan.md +616 -0
- package/.claude/skills/ccw-chain/phases/workflow-multi-cli-plan.md +424 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/SKILL.md +466 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/01-session-discovery.md +99 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/02-context-gathering.md +338 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/03-conflict-resolution.md +422 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/04-task-generation.md +440 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/05-plan-verify.md +395 -0
- package/.claude/skills/ccw-chain/phases/workflow-plan/phases/06-replan.md +594 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/SKILL.md +527 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/01-session-discovery.md +57 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/02-context-gathering.md +407 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/03-test-coverage-analysis.md +172 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/04-conflict-resolution.md +426 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/05-tdd-task-generation.md +473 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/06-tdd-structure-validation.md +189 -0
- package/.claude/skills/ccw-chain/phases/workflow-tdd-plan/phases/07-tdd-verify.md +635 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/SKILL.md +482 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/01-session-start.md +60 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/02-test-context-gather.md +493 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/03-test-concept-enhanced.md +150 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/04-test-task-generate.md +346 -0
- package/.claude/skills/ccw-chain/phases/workflow-test-fix/phases/05-test-cycle-execute.md +538 -0
- package/.claude/skills/ccw-chain/specs/auto-mode.md +47 -0
- package/.claude/skills/ccw-chain/specs/intent-patterns.md +60 -0
- package/.claude/skills/chain-loader/SKILL.md +78 -0
- package/.claude/skills/chain-loader/phases/01-analyze-skill.md +53 -0
- package/.claude/skills/chain-loader/phases/02-design-graph.md +73 -0
- package/.claude/skills/chain-loader/phases/03-generate-validate.md +75 -0
- package/.claude/skills/chain-loader/specs/chain-schema.md +99 -0
- package/.claude/skills/chain-loader/specs/design-patterns.md +99 -0
- package/.claude/skills/chain-loader/templates/chain-json.md +63 -0
- package/.claude/skills/review-cycle/phases/review-module.md +764 -764
- package/.claude/skills/review-cycle/phases/review-session.md +775 -775
- package/.claude/skills/workflow-multi-cli-plan/SKILL.md +2 -2
- package/.claude/skills/workflow-plan/phases/03-conflict-resolution.md +422 -422
- package/.claude/skills/workflow-plan/phases/05-plan-verify.md +395 -395
- package/.claude/skills/workflow-tdd-plan/phases/02-context-gathering.md +407 -407
- package/.claude/skills/workflow-tdd-plan/phases/04-conflict-resolution.md +426 -426
- package/.claude/skills/workflow-test-fix/phases/02-test-context-gather.md +493 -493
- package/.codex/skills/brainstorm/SKILL.md +3 -3
- package/.codex/skills/clean/SKILL.md +3 -3
- package/.codex/skills/issue-discover/SKILL.md +13 -13
- package/.codex/skills/issue-discover/phases/02-discover.md +4 -4
- package/.codex/skills/issue-discover/phases/03-discover-by-prompt.md +3 -3
- package/.codex/skills/parallel-dev-cycle/SKILL.md +4 -4
- package/.codex/skills/parallel-dev-cycle/phases/02-agent-execution.md +6 -6
- package/.codex/skills/parallel-dev-cycle/phases/03-result-aggregation.md +10 -10
- package/.codex/skills/review-cycle/SKILL.md +10 -10
- package/.codex/skills/review-cycle/phases/02-parallel-review.md +6 -6
- package/.codex/skills/review-cycle/phases/04-iterative-deep-dive.md +4 -4
- package/.codex/skills/review-cycle/phases/07-fix-parallel-planning.md +4 -4
- package/.codex/skills/review-cycle/phases/08-fix-execution.md +2 -2
- package/.codex/skills/roadmap-with-file/SKILL.md +14 -14
- package/.codex/skills/spec-generator/README.md +1 -1
- package/.codex/skills/spec-generator/SKILL.md +184 -88
- package/.codex/skills/spec-generator/phases/01-5-requirement-clarification.md +4 -7
- package/.codex/skills/spec-generator/phases/01-discovery.md +30 -11
- package/.codex/skills/spec-generator/phases/02-product-brief.md +2 -5
- package/.codex/skills/spec-generator/phases/03-requirements.md +4 -6
- package/.codex/skills/spec-generator/phases/04-architecture.md +4 -6
- package/.codex/skills/spec-generator/phases/05-epics-stories.md +4 -6
- package/.codex/skills/spec-generator/phases/06-5-auto-fix.md +4 -5
- package/.codex/skills/spec-generator/phases/06-readiness-check.md +8 -8
- package/.codex/skills/spec-generator/phases/07-issue-export.md +2 -2
- package/.codex/skills/spec-setup/SKILL.md +4 -4
- package/.codex/skills/workflow-plan/SKILL.md +6 -6
- package/.codex/skills/workflow-tdd-plan/SKILL.md +5 -5
- package/.codex/skills/workflow-test-fix-cycle/SKILL.md +19 -19
- package/.codex/skills/workflow-test-fix-cycle/phases/01-test-fix-gen.md +5 -5
- package/.codex/skills/workflow-test-fix-cycle/phases/02-test-cycle-execute.md +5 -5
- package/README.md +14 -0
- package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/litellm-api-routes.js +0 -23
- package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
- package/ccw/dist/tools/chain-loader.d.ts +10 -0
- package/ccw/dist/tools/chain-loader.d.ts.map +1 -0
- package/ccw/dist/tools/chain-loader.js +642 -0
- package/ccw/dist/tools/chain-loader.js.map +1 -0
- package/ccw/dist/tools/index.d.ts.map +1 -1
- package/ccw/dist/tools/index.js +2 -0
- package/ccw/dist/tools/index.js.map +1 -1
- package/ccw/dist/tools/json-builder.js +20 -0
- package/ccw/dist/tools/json-builder.js.map +1 -1
- package/ccw/dist/types/chain-types.d.ts +72 -0
- package/ccw/dist/types/chain-types.d.ts.map +1 -0
- package/ccw/dist/types/chain-types.js +5 -0
- package/ccw/dist/types/chain-types.js.map +1 -0
- package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js → AlertDialog-exlTDW81.js} +3 -3
- package/ccw/frontend/dist/assets/{AlertDialog-BjP1ydDR.js.map → AlertDialog-exlTDW81.js.map} +1 -1
- package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js → AnalysisPage-cgV9LfAI.js} +2 -2
- package/ccw/frontend/dist/assets/{AnalysisPage-CAX3xqMf.js.map → AnalysisPage-cgV9LfAI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js → ApiSettingsPage-Dk5jJdWt.js} +2 -2
- package/ccw/frontend/dist/assets/{ApiSettingsPage-CtWlmztq.js.map → ApiSettingsPage-Dk5jJdWt.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js → CliModeToggle-Be9xsPiv.js} +2 -2
- package/ccw/frontend/dist/assets/{CliModeToggle-hR4a-eLX.js.map → CliModeToggle-Be9xsPiv.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js → CliSessionSharePage-Bh9jBtPI.js} +2 -2
- package/ccw/frontend/dist/assets/{CliSessionSharePage-DzNPkFN9.js.map → CliSessionSharePage-Bh9jBtPI.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js → CliViewerPage-BrE-oyEq.js} +2 -2
- package/ccw/frontend/dist/assets/{CliViewerPage-BPEGN4TT.js.map → CliViewerPage-BrE-oyEq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js → CodexLensPage-Cd3nrC93.js} +2 -2
- package/ccw/frontend/dist/assets/{CodexLensPage-Cf0r2RHY.js.map → CodexLensPage-Cd3nrC93.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js → Collapsible-DXFl3VKF.js} +2 -2
- package/ccw/frontend/dist/assets/{Collapsible-DEm1rJ4h.js.map → Collapsible-DXFl3VKF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js → CommandsManagerPage-IV8zpjgX.js} +2 -2
- package/ccw/frontend/dist/assets/{CommandsManagerPage-BpeWw8HO.js.map → CommandsManagerPage-IV8zpjgX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js → DeepWikiPage-CpDxtmRX.js} +2 -2
- package/ccw/frontend/dist/assets/{DeepWikiPage-BEsmh2vF.js.map → DeepWikiPage-CpDxtmRX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js → EndpointsPage-BchjWe7s.js} +2 -2
- package/ccw/frontend/dist/assets/{EndpointsPage-B30SFdtU.js.map → EndpointsPage-BchjWe7s.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js → ExplorerPage-CbWvaJ0y.js} +2 -2
- package/ccw/frontend/dist/assets/{ExplorerPage-BVvMpg1O.js.map → ExplorerPage-CbWvaJ0y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js → FixSessionPage-YMjVRiCk.js} +2 -2
- package/ccw/frontend/dist/assets/{FixSessionPage-CL73dHbh.js.map → FixSessionPage-YMjVRiCk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js → FloatingFileBrowser-JW2ehYY_.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingFileBrowser-BL-28lMZ.js.map → FloatingFileBrowser-JW2ehYY_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js → FloatingPanel-BtqzqDVq.js} +2 -2
- package/ccw/frontend/dist/assets/{FloatingPanel-BzZDciHZ.js.map → FloatingPanel-BtqzqDVq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js → GraphExplorerPage-BsJL_W4d.js} +3 -3
- package/ccw/frontend/dist/assets/{GraphExplorerPage-CDp6-d8P.js.map → GraphExplorerPage-BsJL_W4d.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js → HistoryPage-BuWpQ7k5.js} +2 -2
- package/ccw/frontend/dist/assets/{HistoryPage-fZY_7O9n.js.map → HistoryPage-BuWpQ7k5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js → HookManagerPage-D0BtMIWy.js} +2 -2
- package/ccw/frontend/dist/assets/{HookManagerPage-4LJeC9bq.js.map → HookManagerPage-D0BtMIWy.js.map} +1 -1
- package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js → InstallationsPage-C7dwsAKG.js} +2 -2
- package/ccw/frontend/dist/assets/{InstallationsPage-Bpigrbhw.js.map → InstallationsPage-C7dwsAKG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js → IssueHubPage-D0nCNaeB.js} +2 -2
- package/ccw/frontend/dist/assets/{IssueHubPage-BP0zJc1R.js.map → IssueHubPage-D0nCNaeB.js.map} +1 -1
- package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js → LiteTasksPage-B5c2Kb9r.js} +3 -3
- package/ccw/frontend/dist/assets/{LiteTasksPage-CSt2oVKQ.js.map → LiteTasksPage-B5c2Kb9r.js.map} +1 -1
- package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js → McpManagerPage-C-S5CehM.js} +2 -2
- package/ccw/frontend/dist/assets/{McpManagerPage-B-xaMA0w.js.map → McpManagerPage-C-S5CehM.js.map} +1 -1
- package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js → MemoryPage-P_B0JVUQ.js} +2 -2
- package/ccw/frontend/dist/assets/{MemoryPage-CJqo_7DY.js.map → MemoryPage-P_B0JVUQ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js → NotFoundPage-S4Jn9LUE.js} +2 -2
- package/ccw/frontend/dist/assets/{NotFoundPage-ibZeQA-Y.js.map → NotFoundPage-S4Jn9LUE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js → OrchestratorPage-C2Zlr7AC.js} +2 -2
- package/ccw/frontend/dist/assets/{OrchestratorPage-DgJ4ctPQ.js.map → OrchestratorPage-C2Zlr7AC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js → ProjectOverviewPage-CMVfz8s5.js} +2 -2
- package/ccw/frontend/dist/assets/{ProjectOverviewPage-Cit0Yq0D.js.map → ProjectOverviewPage-CMVfz8s5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js → PromptHistoryPage-YEMjFARX.js} +3 -3
- package/ccw/frontend/dist/assets/{PromptHistoryPage-Ce1HDIK0.js.map → PromptHistoryPage-YEMjFARX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js → ReviewSessionPage-DnTm55nG.js} +2 -2
- package/ccw/frontend/dist/assets/{ReviewSessionPage-J1KikNrk.js.map → ReviewSessionPage-DnTm55nG.js.map} +1 -1
- package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js → RulesManagerPage-CUwebtO2.js} +2 -2
- package/ccw/frontend/dist/assets/{RulesManagerPage-CdBjTmth.js.map → RulesManagerPage-CUwebtO2.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js → SessionDetailPage-0qyH1Z5P.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionDetailPage-B9ZK7LvX.js.map → SessionDetailPage-0qyH1Z5P.js.map} +1 -1
- package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js → SessionsPage-BpgP4087.js} +2 -2
- package/ccw/frontend/dist/assets/{SessionsPage-CW_nS5UR.js.map → SessionsPage-BpgP4087.js.map} +1 -1
- package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js +150 -0
- package/ccw/frontend/dist/assets/SettingsPage-C3SJajeT.js.map +1 -0
- package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js +7 -0
- package/ccw/frontend/dist/assets/SkillsManagerPage-vD9PTsmy.js.map +1 -0
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js → SpecsSettingsPage-DT-yTVkD.js} +4 -4
- package/ccw/frontend/dist/assets/{SpecsSettingsPage-DJpi9XQL.js.map → SpecsSettingsPage-DT-yTVkD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js → Switch-CYSPdqWk.js} +2 -2
- package/ccw/frontend/dist/assets/{Switch-Ac6Ov7uy.js.map → Switch-CYSPdqWk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js → TabsNavigation-CPh6Zor1.js} +2 -2
- package/ccw/frontend/dist/assets/{TabsNavigation-DZAAspqR.js.map → TabsNavigation-CPh6Zor1.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js → TaskDrawer-Ds-8830B.js} +2 -2
- package/ccw/frontend/dist/assets/{TaskDrawer-BJkwfhIZ.js.map → TaskDrawer-Ds-8830B.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js → TeamPage-CJODUxBk.js} +2 -2
- package/ccw/frontend/dist/assets/{TeamPage-BJgjxBgb.js.map → TeamPage-CJODUxBk.js.map} +1 -1
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js → TerminalDashboardPage-Cn3fGUuO.js} +3 -3
- package/ccw/frontend/dist/assets/{TerminalDashboardPage-D1WekoOy.js.map → TerminalDashboardPage-Cn3fGUuO.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-DxemgIhF.js → archive-CjwVpw6k.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-DxemgIhF.js.map → archive-CjwVpw6k.js.map} +1 -1
- package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js → archive-restore-2vZa9Ic3.js} +2 -2
- package/ccw/frontend/dist/assets/{archive-restore-CjS83f1V.js.map → archive-restore-2vZa9Ic3.js.map} +1 -1
- package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js → arrow-right-CUU5XDgT.js} +2 -2
- package/ccw/frontend/dist/assets/{arrow-right-B5PUcn8I.js.map → arrow-right-CUU5XDgT.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js → bookmark-plus-Cc3nKRZ5.js} +2 -2
- package/ccw/frontend/dist/assets/{bookmark-plus-DCc9aPbb.js.map → bookmark-plus-Cc3nKRZ5.js.map} +1 -1
- package/ccw/frontend/dist/assets/{bot-DOwFtzak.js → bot-BwpSRDUa.js} +2 -2
- package/ccw/frontend/dist/assets/{bot-DOwFtzak.js.map → bot-BwpSRDUa.js.map} +1 -1
- package/ccw/frontend/dist/assets/{braces-96qH3aFh.js → braces-DBzUW1XC.js} +2 -2
- package/ccw/frontend/dist/assets/{braces-96qH3aFh.js.map → braces-DBzUW1XC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js → circle-stop-CGNNsjvE.js} +2 -2
- package/ccw/frontend/dist/assets/{circle-stop-CCxSuil1.js.map → circle-stop-CGNNsjvE.js.map} +1 -1
- package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js → cpu-D27G86Ul.js} +2 -2
- package/ccw/frontend/dist/assets/{cpu-CZNSJFdq.js.map → cpu-D27G86Ul.js.map} +1 -1
- package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js → ellipsis-vertical-C1Ij47Yz.js} +2 -2
- package/ccw/frontend/dist/assets/{ellipsis-vertical-h8xtvw2_.js.map → ellipsis-vertical-C1Ij47Yz.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js → eye-C6MOB7Au.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-D3NY0bm6.js.map → eye-C6MOB7Au.js.map} +1 -1
- package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js → eye-off-BxfBlZ26.js} +2 -2
- package/ccw/frontend/dist/assets/{eye-off-Cy2vkc8p.js.map → eye-off-BxfBlZ26.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js → file-json-NI237wA-.js} +2 -2
- package/ccw/frontend/dist/assets/{file-json-Bzq3U1Mx.js.map → file-json-NI237wA-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js → file-text-Byn2_2v6.js} +2 -2
- package/ccw/frontend/dist/assets/{file-text-DwuwPDPi.js.map → file-text-Byn2_2v6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{filter-q9g-bknU.js → filter-D-7PhZjx.js} +2 -2
- package/ccw/frontend/dist/assets/{filter-q9g-bknU.js.map → filter-D-7PhZjx.js.map} +1 -1
- package/ccw/frontend/dist/assets/{folder-CL6vb42J.js → folder-BoAsK_FL.js} +2 -2
- package/ccw/frontend/dist/assets/{folder-CL6vb42J.js.map → folder-BoAsK_FL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js → gauge-DCSxJIS4.js} +2 -2
- package/ccw/frontend/dist/assets/{gauge-BkrcQBly.js.map → gauge-DCSxJIS4.js.map} +1 -1
- package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js → globe-CHS3prza.js} +2 -2
- package/ccw/frontend/dist/assets/{globe-BQbwyNeV.js.map → globe-CHS3prza.js.map} +1 -1
- package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js → grid-3x3-D7K35U7S.js} +2 -2
- package/ccw/frontend/dist/assets/{grid-3x3-x5_7DrN7.js.map → grid-3x3-D7K35U7S.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js → hard-drive-eq9xE07G.js} +2 -2
- package/ccw/frontend/dist/assets/{hard-drive-DTyWXwzf.js.map → hard-drive-eq9xE07G.js.map} +1 -1
- package/ccw/frontend/dist/assets/{hash-80O0kJO7.js → hash-C1DMpBua.js} +2 -2
- package/ccw/frontend/dist/assets/{hash-80O0kJO7.js.map → hash-C1DMpBua.js.map} +1 -1
- package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js → history-Di5SBCY-.js} +2 -2
- package/ccw/frontend/dist/assets/{history-DDlN2Bwa.js.map → history-Di5SBCY-.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-mbeo62f8.js → index--_R7COnA.js} +2 -2
- package/ccw/frontend/dist/assets/{index-mbeo62f8.js.map → index--_R7COnA.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-rLgoBCfV.js → index-BUol9HDD.js} +3 -3
- package/ccw/frontend/dist/assets/{index-rLgoBCfV.js.map → index-BUol9HDD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-Bs80iCX0.js → index-CT9oykfw.js} +2 -2
- package/ccw/frontend/dist/assets/{index-Bs80iCX0.js.map → index-CT9oykfw.js.map} +1 -1
- package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js → index-Ddwvf87H.js} +2 -2
- package/ccw/frontend/dist/assets/{index-B9A3Hnrk.js.map → index-Ddwvf87H.js.map} +1 -1
- package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js → layout-grid-LiX0qZbN.js} +2 -2
- package/ccw/frontend/dist/assets/{layout-grid-C1niOWJx.js.map → layout-grid-LiX0qZbN.js.map} +1 -1
- package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js → lightbulb-CL3DVEwb.js} +2 -2
- package/ccw/frontend/dist/assets/{lightbulb-BTmI7SUg.js.map → lightbulb-CL3DVEwb.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js → link-2-CC5cFeq6.js} +2 -2
- package/ccw/frontend/dist/assets/{link-2-CB9HKeuZ.js.map → link-2-CC5cFeq6.js.map} +1 -1
- package/ccw/frontend/dist/assets/{link-koEYiemK.js → link-ngFQ9bs0.js} +2 -2
- package/ccw/frontend/dist/assets/{link-koEYiemK.js.map → link-ngFQ9bs0.js.map} +1 -1
- package/ccw/frontend/dist/assets/{list-v2_GaLdC.js → list-BEU6I0KK.js} +2 -2
- package/ccw/frontend/dist/assets/{list-v2_GaLdC.js.map → list-BEU6I0KK.js.map} +1 -1
- package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js → map-pin-BWZdLA6y.js} +2 -2
- package/ccw/frontend/dist/assets/{map-pin-BQNfAqG_.js.map → map-pin-BWZdLA6y.js.map} +1 -1
- package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js → messages-square-K6_Chm7n.js} +2 -2
- package/ccw/frontend/dist/assets/{messages-square-Dzq5LGg9.js.map → messages-square-K6_Chm7n.js.map} +1 -1
- package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js → minimize-2-CWkphauf.js} +2 -2
- package/ccw/frontend/dist/assets/{minimize-2-CtkoJXcz.js.map → minimize-2-CWkphauf.js.map} +1 -1
- package/ccw/frontend/dist/assets/{package-CH3smL37.js → package-DrNgkamn.js} +2 -2
- package/ccw/frontend/dist/assets/{package-CH3smL37.js.map → package-DrNgkamn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js → plug-CMo3sw5_.js} +2 -2
- package/ccw/frontend/dist/assets/{plug-CZ0aL_yF.js.map → plug-CMo3sw5_.js.map} +1 -1
- package/ccw/frontend/dist/assets/{power-F2A_J4l6.js → power-DppNTW5e.js} +2 -2
- package/ccw/frontend/dist/assets/{power-F2A_J4l6.js.map → power-DppNTW5e.js.map} +1 -1
- package/ccw/frontend/dist/assets/{save-Byxot0YU.js → save-CD8aPMbZ.js} +2 -2
- package/ccw/frontend/dist/assets/{save-Byxot0YU.js.map → save-CD8aPMbZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{send-JjqhUkpw.js → send-B4z90fQD.js} +2 -2
- package/ccw/frontend/dist/assets/{send-JjqhUkpw.js.map → send-B4z90fQD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js → settings-2-CAKRU_QC.js} +2 -2
- package/ccw/frontend/dist/assets/{settings-2--SuN9rAt.js.map → settings-2-CAKRU_QC.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js → square-check-big-KhI3HrzX.js} +2 -2
- package/ccw/frontend/dist/assets/{square-check-big-BbngGB2h.js.map → square-check-big-KhI3HrzX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js → square-pen-BtdGIpuq.js} +2 -2
- package/ccw/frontend/dist/assets/{square-pen-CgrHgZSl.js.map → square-pen-BtdGIpuq.js.map} +1 -1
- package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js → star-ZoBUkXoD.js} +2 -2
- package/ccw/frontend/dist/assets/{star-BU3TQr7Z.js.map → star-ZoBUkXoD.js.map} +1 -1
- package/ccw/frontend/dist/assets/{style-CKs7nnn3.js → style-CltxQP-P.js} +2 -2
- package/ccw/frontend/dist/assets/{style-CKs7nnn3.js.map → style-CltxQP-P.js.map} +1 -1
- package/ccw/frontend/dist/assets/{target-DW5tsDW6.js → target-C32OUSGf.js} +2 -2
- package/ccw/frontend/dist/assets/{target-DW5tsDW6.js.map → target-C32OUSGf.js.map} +1 -1
- package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js → test-tube-0IxoyAVZ.js} +2 -2
- package/ccw/frontend/dist/assets/{test-tube-BHm7w3ON.js.map → test-tube-0IxoyAVZ.js.map} +1 -1
- package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js → upload-4eKCkyBn.js} +2 -2
- package/ccw/frontend/dist/assets/{upload-DYR7PWwt.js.map → upload-4eKCkyBn.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js → useApiSettings-zLTUWqhi.js} +2 -2
- package/ccw/frontend/dist/assets/{useApiSettings-D0TVgQD_.js.map → useApiSettings-zLTUWqhi.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js → useCli-BtN2vpOX.js} +2 -2
- package/ccw/frontend/dist/assets/{useCli-DfY8mAP8.js.map → useCli-BtN2vpOX.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js → useCommands-_spj49qL.js} +2 -2
- package/ccw/frontend/dist/assets/{useCommands-CGusDp0F.js.map → useCommands-_spj49qL.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js → useDebounce-Bm9KFZvd.js} +2 -2
- package/ccw/frontend/dist/assets/{useDebounce-CIwh0fF1.js.map → useDebounce-Bm9KFZvd.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js → useFileExplorer-DOmpm6v9.js} +2 -2
- package/ccw/frontend/dist/assets/{useFileExplorer-FMyFv39K.js.map → useFileExplorer-DOmpm6v9.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js → useLocale-D2rj4rea.js} +2 -2
- package/ccw/frontend/dist/assets/{useLocale-B2qhsoTb.js.map → useLocale-D2rj4rea.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js → useSkills-OskEpomF.js} +3 -3
- package/ccw/frontend/dist/assets/{useSkills-cxKXMBm3.js.map → useSkills-OskEpomF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js → useSystemSettings-BjMgsNSF.js} +2 -2
- package/ccw/frontend/dist/assets/{useSystemSettings-B-xUT_z-.js.map → useSystemSettings-BjMgsNSF.js.map} +1 -1
- package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js → wand-sparkles-CLhyYWa7.js} +2 -2
- package/ccw/frontend/dist/assets/{wand-sparkles-DZV_3lPr.js.map → wand-sparkles-CLhyYWa7.js.map} +1 -1
- package/ccw/frontend/dist/index.html +1 -1
- package/ccw/scripts/prepublish-clean.mjs +0 -1
- package/package.json +1 -3
- package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js +0 -150
- package/ccw/frontend/dist/assets/SettingsPage-B2PYzSoO.js.map +0 -1
- package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js +0 -7
- package/ccw/frontend/dist/assets/SkillsManagerPage-CTnWrrwp.js.map +0 -1
- package/ccw-litellm/README.md +0 -180
- package/ccw-litellm/pyproject.toml +0 -35
- package/ccw-litellm/src/ccw_litellm/__init__.py +0 -47
- package/ccw-litellm/src/ccw_litellm/cli.py +0 -108
- package/ccw-litellm/src/ccw_litellm/clients/__init__.py +0 -12
- package/ccw-litellm/src/ccw_litellm/clients/litellm_embedder.py +0 -270
- package/ccw-litellm/src/ccw_litellm/clients/litellm_llm.py +0 -198
- package/ccw-litellm/src/ccw_litellm/config/__init__.py +0 -22
- package/ccw-litellm/src/ccw_litellm/config/loader.py +0 -343
- package/ccw-litellm/src/ccw_litellm/config/models.py +0 -162
- package/ccw-litellm/src/ccw_litellm/interfaces/__init__.py +0 -14
- package/ccw-litellm/src/ccw_litellm/interfaces/embedder.py +0 -52
- package/ccw-litellm/src/ccw_litellm/interfaces/llm.py +0 -45
package/ccw-litellm/README.md
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
# ccw-litellm
|
|
2
|
-
|
|
3
|
-
Unified LiteLLM interface layer shared by ccw and codex-lens projects.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Unified LLM Interface**: Abstract interface for LLM operations (chat, completion)
|
|
8
|
-
- **Unified Embedding Interface**: Abstract interface for text embeddings
|
|
9
|
-
- **Multi-Provider Support**: OpenAI, Anthropic, Azure, and more via LiteLLM
|
|
10
|
-
- **Configuration Management**: YAML-based configuration with environment variable substitution
|
|
11
|
-
- **Type Safety**: Full type annotations with Pydantic models
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
pip install -e .
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Quick Start
|
|
20
|
-
|
|
21
|
-
### Configuration
|
|
22
|
-
|
|
23
|
-
Create a configuration file at `~/.ccw/config/litellm-config.yaml`:
|
|
24
|
-
|
|
25
|
-
```yaml
|
|
26
|
-
version: 1
|
|
27
|
-
default_provider: openai
|
|
28
|
-
|
|
29
|
-
providers:
|
|
30
|
-
openai:
|
|
31
|
-
api_key: ${OPENAI_API_KEY}
|
|
32
|
-
api_base: https://api.openai.com/v1
|
|
33
|
-
|
|
34
|
-
llm_models:
|
|
35
|
-
default:
|
|
36
|
-
provider: openai
|
|
37
|
-
model: gpt-4
|
|
38
|
-
|
|
39
|
-
embedding_models:
|
|
40
|
-
default:
|
|
41
|
-
provider: openai
|
|
42
|
-
model: text-embedding-3-small
|
|
43
|
-
dimensions: 1536
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Usage
|
|
47
|
-
|
|
48
|
-
#### LLM Client
|
|
49
|
-
|
|
50
|
-
```python
|
|
51
|
-
from ccw_litellm import LiteLLMClient, ChatMessage
|
|
52
|
-
|
|
53
|
-
# Initialize client with default model
|
|
54
|
-
client = LiteLLMClient(model="default")
|
|
55
|
-
|
|
56
|
-
# Chat completion
|
|
57
|
-
messages = [
|
|
58
|
-
ChatMessage(role="user", content="Hello, how are you?")
|
|
59
|
-
]
|
|
60
|
-
response = client.chat(messages)
|
|
61
|
-
print(response.content)
|
|
62
|
-
|
|
63
|
-
# Text completion
|
|
64
|
-
response = client.complete("Once upon a time")
|
|
65
|
-
print(response.content)
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
#### Embedder
|
|
69
|
-
|
|
70
|
-
```python
|
|
71
|
-
from ccw_litellm import LiteLLMEmbedder
|
|
72
|
-
|
|
73
|
-
# Initialize embedder with default model
|
|
74
|
-
embedder = LiteLLMEmbedder(model="default")
|
|
75
|
-
|
|
76
|
-
# Embed single text
|
|
77
|
-
vector = embedder.embed("Hello world")
|
|
78
|
-
print(vector.shape) # (1, 1536)
|
|
79
|
-
|
|
80
|
-
# Embed multiple texts
|
|
81
|
-
vectors = embedder.embed(["Text 1", "Text 2", "Text 3"])
|
|
82
|
-
print(vectors.shape) # (3, 1536)
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
#### Custom Configuration
|
|
86
|
-
|
|
87
|
-
```python
|
|
88
|
-
from ccw_litellm import LiteLLMClient, load_config
|
|
89
|
-
|
|
90
|
-
# Load custom configuration
|
|
91
|
-
config = load_config("/path/to/custom-config.yaml")
|
|
92
|
-
|
|
93
|
-
# Use custom configuration
|
|
94
|
-
client = LiteLLMClient(model="fast", config=config)
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Configuration Reference
|
|
98
|
-
|
|
99
|
-
### Provider Configuration
|
|
100
|
-
|
|
101
|
-
```yaml
|
|
102
|
-
providers:
|
|
103
|
-
<provider_name>:
|
|
104
|
-
api_key: <api_key_or_${ENV_VAR}>
|
|
105
|
-
api_base: <base_url>
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Supported providers: `openai`, `anthropic`, `azure`, `vertex_ai`, `bedrock`, etc.
|
|
109
|
-
|
|
110
|
-
### LLM Model Configuration
|
|
111
|
-
|
|
112
|
-
```yaml
|
|
113
|
-
llm_models:
|
|
114
|
-
<model_name>:
|
|
115
|
-
provider: <provider_name>
|
|
116
|
-
model: <model_identifier>
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Embedding Model Configuration
|
|
120
|
-
|
|
121
|
-
```yaml
|
|
122
|
-
embedding_models:
|
|
123
|
-
<model_name>:
|
|
124
|
-
provider: <provider_name>
|
|
125
|
-
model: <model_identifier>
|
|
126
|
-
dimensions: <embedding_dimensions>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Environment Variables
|
|
130
|
-
|
|
131
|
-
The configuration supports environment variable substitution using the `${VAR}` or `${VAR:-default}` syntax:
|
|
132
|
-
|
|
133
|
-
```yaml
|
|
134
|
-
providers:
|
|
135
|
-
openai:
|
|
136
|
-
api_key: ${OPENAI_API_KEY} # Required
|
|
137
|
-
api_base: ${OPENAI_API_BASE:-https://api.openai.com/v1} # With default
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## API Reference
|
|
141
|
-
|
|
142
|
-
### Interfaces
|
|
143
|
-
|
|
144
|
-
- `AbstractLLMClient`: Abstract base class for LLM clients
|
|
145
|
-
- `AbstractEmbedder`: Abstract base class for embedders
|
|
146
|
-
- `ChatMessage`: Message data class (role, content)
|
|
147
|
-
- `LLMResponse`: Response data class (content, raw)
|
|
148
|
-
|
|
149
|
-
### Implementations
|
|
150
|
-
|
|
151
|
-
- `LiteLLMClient`: LiteLLM implementation of AbstractLLMClient
|
|
152
|
-
- `LiteLLMEmbedder`: LiteLLM implementation of AbstractEmbedder
|
|
153
|
-
|
|
154
|
-
### Configuration
|
|
155
|
-
|
|
156
|
-
- `LiteLLMConfig`: Root configuration model
|
|
157
|
-
- `ProviderConfig`: Provider configuration model
|
|
158
|
-
- `LLMModelConfig`: LLM model configuration model
|
|
159
|
-
- `EmbeddingModelConfig`: Embedding model configuration model
|
|
160
|
-
- `load_config(path)`: Load configuration from YAML file
|
|
161
|
-
- `get_config(path, reload)`: Get global configuration singleton
|
|
162
|
-
- `reset_config()`: Reset global configuration (for testing)
|
|
163
|
-
|
|
164
|
-
## Development
|
|
165
|
-
|
|
166
|
-
### Running Tests
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
pytest tests/ -v
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### Type Checking
|
|
173
|
-
|
|
174
|
-
```bash
|
|
175
|
-
mypy src/ccw_litellm
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## License
|
|
179
|
-
|
|
180
|
-
MIT
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=61.0"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "ccw-litellm"
|
|
7
|
-
version = "0.1.0"
|
|
8
|
-
description = "Unified LiteLLM interface layer shared by ccw and codex-lens"
|
|
9
|
-
requires-python = ">=3.10"
|
|
10
|
-
authors = [{ name = "ccw-litellm contributors" }]
|
|
11
|
-
dependencies = [
|
|
12
|
-
"litellm>=1.0.0",
|
|
13
|
-
"pyyaml",
|
|
14
|
-
"numpy",
|
|
15
|
-
"pydantic>=2.0",
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
[project.optional-dependencies]
|
|
19
|
-
dev = [
|
|
20
|
-
"pytest>=7.0",
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
[project.scripts]
|
|
24
|
-
ccw-litellm = "ccw_litellm.cli:main"
|
|
25
|
-
|
|
26
|
-
[tool.setuptools]
|
|
27
|
-
package-dir = { "" = "src" }
|
|
28
|
-
|
|
29
|
-
[tool.setuptools.packages.find]
|
|
30
|
-
where = ["src"]
|
|
31
|
-
include = ["ccw_litellm*"]
|
|
32
|
-
|
|
33
|
-
[tool.pytest.ini_options]
|
|
34
|
-
testpaths = ["tests"]
|
|
35
|
-
addopts = "-q"
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"""ccw-litellm package.
|
|
2
|
-
|
|
3
|
-
This package provides a small, stable interface layer around LiteLLM to share
|
|
4
|
-
between the ccw and codex-lens projects.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from .clients import LiteLLMClient, LiteLLMEmbedder
|
|
10
|
-
from .config import (
|
|
11
|
-
EmbeddingModelConfig,
|
|
12
|
-
LiteLLMConfig,
|
|
13
|
-
LLMModelConfig,
|
|
14
|
-
ProviderConfig,
|
|
15
|
-
get_config,
|
|
16
|
-
load_config,
|
|
17
|
-
reset_config,
|
|
18
|
-
)
|
|
19
|
-
from .interfaces import (
|
|
20
|
-
AbstractEmbedder,
|
|
21
|
-
AbstractLLMClient,
|
|
22
|
-
ChatMessage,
|
|
23
|
-
LLMResponse,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
__version__ = "0.1.0"
|
|
27
|
-
|
|
28
|
-
__all__ = [
|
|
29
|
-
"__version__",
|
|
30
|
-
# Abstract interfaces
|
|
31
|
-
"AbstractEmbedder",
|
|
32
|
-
"AbstractLLMClient",
|
|
33
|
-
"ChatMessage",
|
|
34
|
-
"LLMResponse",
|
|
35
|
-
# Client implementations
|
|
36
|
-
"LiteLLMClient",
|
|
37
|
-
"LiteLLMEmbedder",
|
|
38
|
-
# Configuration
|
|
39
|
-
"LiteLLMConfig",
|
|
40
|
-
"ProviderConfig",
|
|
41
|
-
"LLMModelConfig",
|
|
42
|
-
"EmbeddingModelConfig",
|
|
43
|
-
"load_config",
|
|
44
|
-
"get_config",
|
|
45
|
-
"reset_config",
|
|
46
|
-
]
|
|
47
|
-
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"""CLI entry point for ccw-litellm."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import argparse
|
|
6
|
-
import json
|
|
7
|
-
import sys
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def main() -> int:
|
|
12
|
-
"""Main CLI entry point."""
|
|
13
|
-
parser = argparse.ArgumentParser(
|
|
14
|
-
prog="ccw-litellm",
|
|
15
|
-
description="Unified LiteLLM interface for ccw and codex-lens",
|
|
16
|
-
)
|
|
17
|
-
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
18
|
-
|
|
19
|
-
# config command
|
|
20
|
-
config_parser = subparsers.add_parser("config", help="Show configuration")
|
|
21
|
-
config_parser.add_argument(
|
|
22
|
-
"--path",
|
|
23
|
-
type=Path,
|
|
24
|
-
help="Configuration file path",
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
# embed command
|
|
28
|
-
embed_parser = subparsers.add_parser("embed", help="Generate embeddings")
|
|
29
|
-
embed_parser.add_argument("texts", nargs="+", help="Texts to embed")
|
|
30
|
-
embed_parser.add_argument(
|
|
31
|
-
"--model",
|
|
32
|
-
default="default",
|
|
33
|
-
help="Embedding model name (default: default)",
|
|
34
|
-
)
|
|
35
|
-
embed_parser.add_argument(
|
|
36
|
-
"--output",
|
|
37
|
-
choices=["json", "shape"],
|
|
38
|
-
default="shape",
|
|
39
|
-
help="Output format (default: shape)",
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
# chat command
|
|
43
|
-
chat_parser = subparsers.add_parser("chat", help="Chat with LLM")
|
|
44
|
-
chat_parser.add_argument("message", help="Message to send")
|
|
45
|
-
chat_parser.add_argument(
|
|
46
|
-
"--model",
|
|
47
|
-
default="default",
|
|
48
|
-
help="LLM model name (default: default)",
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
# version command
|
|
52
|
-
subparsers.add_parser("version", help="Show version")
|
|
53
|
-
|
|
54
|
-
args = parser.parse_args()
|
|
55
|
-
|
|
56
|
-
if args.command == "version":
|
|
57
|
-
from . import __version__
|
|
58
|
-
|
|
59
|
-
print(f"ccw-litellm {__version__}")
|
|
60
|
-
return 0
|
|
61
|
-
|
|
62
|
-
if args.command == "config":
|
|
63
|
-
from .config import get_config
|
|
64
|
-
|
|
65
|
-
try:
|
|
66
|
-
config = get_config(config_path=args.path if hasattr(args, "path") else None)
|
|
67
|
-
print(config.model_dump_json(indent=2))
|
|
68
|
-
except Exception as e:
|
|
69
|
-
print(f"Error loading config: {e}", file=sys.stderr)
|
|
70
|
-
return 1
|
|
71
|
-
return 0
|
|
72
|
-
|
|
73
|
-
if args.command == "embed":
|
|
74
|
-
from .clients import LiteLLMEmbedder
|
|
75
|
-
|
|
76
|
-
try:
|
|
77
|
-
embedder = LiteLLMEmbedder(model=args.model)
|
|
78
|
-
vectors = embedder.embed(args.texts)
|
|
79
|
-
|
|
80
|
-
if args.output == "json":
|
|
81
|
-
print(json.dumps(vectors.tolist()))
|
|
82
|
-
else:
|
|
83
|
-
print(f"Shape: {vectors.shape}")
|
|
84
|
-
print(f"Dimensions: {embedder.dimensions}")
|
|
85
|
-
except Exception as e:
|
|
86
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
87
|
-
return 1
|
|
88
|
-
return 0
|
|
89
|
-
|
|
90
|
-
if args.command == "chat":
|
|
91
|
-
from .clients import LiteLLMClient
|
|
92
|
-
from .interfaces import ChatMessage
|
|
93
|
-
|
|
94
|
-
try:
|
|
95
|
-
client = LiteLLMClient(model=args.model)
|
|
96
|
-
response = client.chat([ChatMessage(role="user", content=args.message)])
|
|
97
|
-
print(response.content)
|
|
98
|
-
except Exception as e:
|
|
99
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
100
|
-
return 1
|
|
101
|
-
return 0
|
|
102
|
-
|
|
103
|
-
parser.print_help()
|
|
104
|
-
return 0
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if __name__ == "__main__":
|
|
108
|
-
sys.exit(main())
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
"""LiteLLM embedder implementation for text embeddings."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Any, Sequence
|
|
7
|
-
|
|
8
|
-
import litellm
|
|
9
|
-
import numpy as np
|
|
10
|
-
from numpy.typing import NDArray
|
|
11
|
-
|
|
12
|
-
from ..config import LiteLLMConfig, get_config
|
|
13
|
-
from ..interfaces.embedder import AbstractEmbedder
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class LiteLLMEmbedder(AbstractEmbedder):
|
|
19
|
-
"""LiteLLM embedder implementation.
|
|
20
|
-
|
|
21
|
-
Supports multiple embedding providers (OpenAI, etc.) through LiteLLM's unified interface.
|
|
22
|
-
|
|
23
|
-
Example:
|
|
24
|
-
embedder = LiteLLMEmbedder(model="default")
|
|
25
|
-
vectors = embedder.embed(["Hello world", "Another text"])
|
|
26
|
-
print(vectors.shape) # (2, 1536)
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
def __init__(
|
|
30
|
-
self,
|
|
31
|
-
model: str = "default",
|
|
32
|
-
config: LiteLLMConfig | None = None,
|
|
33
|
-
**litellm_kwargs: Any,
|
|
34
|
-
) -> None:
|
|
35
|
-
"""Initialize LiteLLM embedder.
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
model: Model name from configuration (default: "default")
|
|
39
|
-
config: Configuration instance (default: use global config)
|
|
40
|
-
**litellm_kwargs: Additional arguments to pass to litellm.embedding()
|
|
41
|
-
"""
|
|
42
|
-
self._config = config or get_config()
|
|
43
|
-
self._model_name = model
|
|
44
|
-
self._litellm_kwargs = litellm_kwargs
|
|
45
|
-
|
|
46
|
-
# Get embedding model configuration
|
|
47
|
-
try:
|
|
48
|
-
self._model_config = self._config.get_embedding_model(model)
|
|
49
|
-
except ValueError as e:
|
|
50
|
-
logger.error(f"Failed to get embedding model configuration: {e}")
|
|
51
|
-
raise
|
|
52
|
-
|
|
53
|
-
# Get provider configuration
|
|
54
|
-
try:
|
|
55
|
-
self._provider_config = self._config.get_provider(self._model_config.provider)
|
|
56
|
-
except ValueError as e:
|
|
57
|
-
logger.error(f"Failed to get provider configuration: {e}")
|
|
58
|
-
raise
|
|
59
|
-
|
|
60
|
-
# Set up LiteLLM environment
|
|
61
|
-
self._setup_litellm()
|
|
62
|
-
|
|
63
|
-
def _setup_litellm(self) -> None:
|
|
64
|
-
"""Configure LiteLLM with provider settings."""
|
|
65
|
-
provider = self._model_config.provider
|
|
66
|
-
|
|
67
|
-
# Set API key
|
|
68
|
-
if self._provider_config.api_key:
|
|
69
|
-
litellm.api_key = self._provider_config.api_key
|
|
70
|
-
# Also set environment-specific keys
|
|
71
|
-
if provider == "openai":
|
|
72
|
-
litellm.openai_key = self._provider_config.api_key
|
|
73
|
-
elif provider == "anthropic":
|
|
74
|
-
litellm.anthropic_key = self._provider_config.api_key
|
|
75
|
-
|
|
76
|
-
# Set API base
|
|
77
|
-
if self._provider_config.api_base:
|
|
78
|
-
litellm.api_base = self._provider_config.api_base
|
|
79
|
-
|
|
80
|
-
def _format_model_name(self) -> str:
|
|
81
|
-
"""Format model name for LiteLLM.
|
|
82
|
-
|
|
83
|
-
Returns:
|
|
84
|
-
Formatted model name (e.g., "openai/text-embedding-3-small")
|
|
85
|
-
"""
|
|
86
|
-
provider = self._model_config.provider
|
|
87
|
-
model = self._model_config.model
|
|
88
|
-
|
|
89
|
-
# For some providers, LiteLLM expects explicit prefix
|
|
90
|
-
if provider in ["azure", "vertex_ai", "bedrock"]:
|
|
91
|
-
return f"{provider}/{model}"
|
|
92
|
-
|
|
93
|
-
# For providers with custom api_base (OpenAI-compatible endpoints),
|
|
94
|
-
# use openai/ prefix to tell LiteLLM to use OpenAI API format
|
|
95
|
-
if self._provider_config.api_base and provider not in ["openai", "anthropic"]:
|
|
96
|
-
return f"openai/{model}"
|
|
97
|
-
|
|
98
|
-
return model
|
|
99
|
-
|
|
100
|
-
@property
|
|
101
|
-
def dimensions(self) -> int:
|
|
102
|
-
"""Embedding vector size."""
|
|
103
|
-
return self._model_config.dimensions
|
|
104
|
-
|
|
105
|
-
@property
|
|
106
|
-
def max_input_tokens(self) -> int:
|
|
107
|
-
"""Maximum token limit for embeddings.
|
|
108
|
-
|
|
109
|
-
Returns the configured max_input_tokens from model config,
|
|
110
|
-
enabling adaptive batch sizing based on actual model capacity.
|
|
111
|
-
"""
|
|
112
|
-
return self._model_config.max_input_tokens
|
|
113
|
-
|
|
114
|
-
def _estimate_tokens(self, text: str) -> int:
|
|
115
|
-
"""Estimate token count for a text using fast heuristic.
|
|
116
|
-
|
|
117
|
-
Args:
|
|
118
|
-
text: Text to estimate tokens for
|
|
119
|
-
|
|
120
|
-
Returns:
|
|
121
|
-
Estimated token count (len/4 is a reasonable approximation)
|
|
122
|
-
"""
|
|
123
|
-
return len(text) // 4
|
|
124
|
-
|
|
125
|
-
def _create_batches(
|
|
126
|
-
self,
|
|
127
|
-
texts: list[str],
|
|
128
|
-
max_tokens: int = 30000
|
|
129
|
-
) -> list[list[str]]:
|
|
130
|
-
"""Split texts into batches that fit within token limits.
|
|
131
|
-
|
|
132
|
-
Args:
|
|
133
|
-
texts: List of texts to batch
|
|
134
|
-
max_tokens: Maximum tokens per batch (default: 30000, safe margin for 40960 limit)
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
List of text batches
|
|
138
|
-
"""
|
|
139
|
-
batches = []
|
|
140
|
-
current_batch = []
|
|
141
|
-
current_tokens = 0
|
|
142
|
-
|
|
143
|
-
for text in texts:
|
|
144
|
-
text_tokens = self._estimate_tokens(text)
|
|
145
|
-
|
|
146
|
-
# If single text exceeds limit, truncate it
|
|
147
|
-
if text_tokens > max_tokens:
|
|
148
|
-
logger.warning(f"Text with {text_tokens} estimated tokens exceeds limit, truncating")
|
|
149
|
-
# Truncate to fit (rough estimate: 4 chars per token)
|
|
150
|
-
max_chars = max_tokens * 4
|
|
151
|
-
text = text[:max_chars]
|
|
152
|
-
text_tokens = self._estimate_tokens(text)
|
|
153
|
-
|
|
154
|
-
# Start new batch if current would exceed limit
|
|
155
|
-
if current_tokens + text_tokens > max_tokens and current_batch:
|
|
156
|
-
batches.append(current_batch)
|
|
157
|
-
current_batch = []
|
|
158
|
-
current_tokens = 0
|
|
159
|
-
|
|
160
|
-
current_batch.append(text)
|
|
161
|
-
current_tokens += text_tokens
|
|
162
|
-
|
|
163
|
-
# Add final batch
|
|
164
|
-
if current_batch:
|
|
165
|
-
batches.append(current_batch)
|
|
166
|
-
|
|
167
|
-
return batches
|
|
168
|
-
|
|
169
|
-
def embed(
|
|
170
|
-
self,
|
|
171
|
-
texts: str | Sequence[str],
|
|
172
|
-
*,
|
|
173
|
-
batch_size: int | None = None,
|
|
174
|
-
max_tokens_per_batch: int | None = None,
|
|
175
|
-
**kwargs: Any,
|
|
176
|
-
) -> NDArray[np.floating]:
|
|
177
|
-
"""Embed one or more texts.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
texts: Single text or sequence of texts
|
|
181
|
-
batch_size: Batch size for processing (deprecated, use max_tokens_per_batch)
|
|
182
|
-
max_tokens_per_batch: Maximum estimated tokens per API call.
|
|
183
|
-
If None, uses 90% of model's max_input_tokens for safety margin.
|
|
184
|
-
**kwargs: Additional arguments for litellm.embedding()
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
A numpy array of shape (n_texts, dimensions).
|
|
188
|
-
|
|
189
|
-
Raises:
|
|
190
|
-
Exception: If LiteLLM embedding fails
|
|
191
|
-
"""
|
|
192
|
-
# Normalize input to list
|
|
193
|
-
if isinstance(texts, str):
|
|
194
|
-
text_list = [texts]
|
|
195
|
-
else:
|
|
196
|
-
text_list = list(texts)
|
|
197
|
-
|
|
198
|
-
if not text_list:
|
|
199
|
-
# Return empty array with correct shape
|
|
200
|
-
return np.empty((0, self.dimensions), dtype=np.float32)
|
|
201
|
-
|
|
202
|
-
# Merge kwargs
|
|
203
|
-
embedding_kwargs = {**self._litellm_kwargs, **kwargs}
|
|
204
|
-
|
|
205
|
-
# For OpenAI-compatible endpoints, ensure encoding_format is set
|
|
206
|
-
if self._provider_config.api_base and "encoding_format" not in embedding_kwargs:
|
|
207
|
-
embedding_kwargs["encoding_format"] = "float"
|
|
208
|
-
|
|
209
|
-
# Determine adaptive max_tokens_per_batch
|
|
210
|
-
# Use 90% of model's max_input_tokens as safety margin
|
|
211
|
-
if max_tokens_per_batch is None:
|
|
212
|
-
max_tokens_per_batch = int(self.max_input_tokens * 0.9)
|
|
213
|
-
logger.debug(
|
|
214
|
-
f"Using adaptive batch size: {max_tokens_per_batch} tokens "
|
|
215
|
-
f"(90% of {self.max_input_tokens})"
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
# Split into token-aware batches
|
|
219
|
-
batches = self._create_batches(text_list, max_tokens_per_batch)
|
|
220
|
-
|
|
221
|
-
if len(batches) > 1:
|
|
222
|
-
logger.info(f"Split {len(text_list)} texts into {len(batches)} batches for embedding")
|
|
223
|
-
|
|
224
|
-
all_embeddings = []
|
|
225
|
-
|
|
226
|
-
for batch_idx, batch in enumerate(batches):
|
|
227
|
-
try:
|
|
228
|
-
# Build call kwargs with explicit api_base
|
|
229
|
-
call_kwargs = {**embedding_kwargs}
|
|
230
|
-
if self._provider_config.api_base:
|
|
231
|
-
call_kwargs["api_base"] = self._provider_config.api_base
|
|
232
|
-
if self._provider_config.api_key:
|
|
233
|
-
call_kwargs["api_key"] = self._provider_config.api_key
|
|
234
|
-
|
|
235
|
-
# Call LiteLLM embedding for this batch
|
|
236
|
-
response = litellm.embedding(
|
|
237
|
-
model=self._format_model_name(),
|
|
238
|
-
input=batch,
|
|
239
|
-
**call_kwargs,
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
# Extract embeddings
|
|
243
|
-
batch_embeddings = [item["embedding"] for item in response.data]
|
|
244
|
-
all_embeddings.extend(batch_embeddings)
|
|
245
|
-
|
|
246
|
-
except Exception as e:
|
|
247
|
-
logger.error(f"LiteLLM embedding failed for batch {batch_idx + 1}/{len(batches)}: {e}")
|
|
248
|
-
raise
|
|
249
|
-
|
|
250
|
-
# Convert to numpy array
|
|
251
|
-
result = np.array(all_embeddings, dtype=np.float32)
|
|
252
|
-
|
|
253
|
-
# Validate dimensions
|
|
254
|
-
if result.shape[1] != self.dimensions:
|
|
255
|
-
logger.warning(
|
|
256
|
-
f"Expected {self.dimensions} dimensions, got {result.shape[1]}. "
|
|
257
|
-
f"Configuration may be incorrect."
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
return result
|
|
261
|
-
|
|
262
|
-
@property
|
|
263
|
-
def model_name(self) -> str:
|
|
264
|
-
"""Get configured model name."""
|
|
265
|
-
return self._model_name
|
|
266
|
-
|
|
267
|
-
@property
|
|
268
|
-
def provider(self) -> str:
|
|
269
|
-
"""Get configured provider name."""
|
|
270
|
-
return self._model_config.provider
|