code-agnostic 0.5.0__tar.gz → 0.5.1__tar.gz

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 (171) hide show
  1. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/PKG-INFO +1 -1
  2. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/__init__.py +1 -1
  3. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/claude/service.py +0 -7
  4. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/service.py +1 -1
  5. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/interfaces/service.py +18 -2
  6. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/copilot/service.py +1 -5
  7. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/service.py +1 -3
  8. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/service.py +1 -5
  9. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/PKG-INFO +1 -1
  10. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/pyproject.toml +1 -1
  11. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/LICENSE +0 -0
  12. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/README.md +0 -0
  13. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/__main__.py +0 -0
  14. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/__init__.py +0 -0
  15. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/claude.py +0 -0
  16. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/codex.py +0 -0
  17. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/compilers.py +0 -0
  18. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/copilot.py +0 -0
  19. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/models.py +0 -0
  20. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/opencode.py +0 -0
  21. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/agents/parser.py +0 -0
  22. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/__init__.py +0 -0
  23. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/app_id.py +0 -0
  24. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/apps_service.py +0 -0
  25. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/claude/__init__.py +0 -0
  26. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/claude/config_repository.py +0 -0
  27. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/claude/mapper.py +0 -0
  28. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/__init__.py +0 -0
  29. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/config_repository.py +0 -0
  30. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/mapper.py +0 -0
  31. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/schema.json +0 -0
  32. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/codex/schema_repository.py +0 -0
  33. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/__init__.py +0 -0
  34. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/compiled_planning.py +0 -0
  35. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/framework.py +0 -0
  36. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/interfaces/__init__.py +0 -0
  37. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/interfaces/mapper.py +0 -0
  38. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/interfaces/repositories.py +0 -0
  39. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/loader.py +0 -0
  40. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/models.py +0 -0
  41. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/schema.py +0 -0
  42. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/symlink_planning.py +0 -0
  43. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/common/utils.py +0 -0
  44. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/copilot/__init__.py +0 -0
  45. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/copilot/config_repository.py +0 -0
  46. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/copilot/mapper.py +0 -0
  47. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/__init__.py +0 -0
  48. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/config_repository.py +0 -0
  49. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/mapper.py +0 -0
  50. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/schema.json +0 -0
  51. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/cursor/schema_repository.py +0 -0
  52. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/__init__.py +0 -0
  53. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/config_repository.py +0 -0
  54. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/mapper.py +0 -0
  55. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/schema.json +0 -0
  56. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/apps/opencode/schema_repository.py +0 -0
  57. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/__init__.py +0 -0
  58. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/aliases.py +0 -0
  59. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/__init__.py +0 -0
  60. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/agents.py +0 -0
  61. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/apply.py +0 -0
  62. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/apps.py +0 -0
  63. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/explain_lossiness.py +0 -0
  64. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/import_.py +0 -0
  65. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/mcp.py +0 -0
  66. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/plan.py +0 -0
  67. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/projects.py +0 -0
  68. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/restore.py +0 -0
  69. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/rules.py +0 -0
  70. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/skills.py +0 -0
  71. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/status.py +0 -0
  72. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/validate.py +0 -0
  73. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/commands/workspaces.py +0 -0
  74. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/helpers.py +0 -0
  75. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/cli/options.py +0 -0
  76. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/constants.py +0 -0
  77. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/core/__init__.py +0 -0
  78. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/core/project_repository.py +0 -0
  79. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/core/repository.py +0 -0
  80. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/core/workspace_repository.py +0 -0
  81. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/errors.py +0 -0
  82. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/executor.py +0 -0
  83. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/generated_artifacts.py +0 -0
  84. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/git_exclude_service.py +0 -0
  85. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/imports/__init__.py +0 -0
  86. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/imports/adapters.py +0 -0
  87. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/imports/filesystem.py +0 -0
  88. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/imports/models.py +0 -0
  89. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/imports/service.py +0 -0
  90. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/lossiness.py +0 -0
  91. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/mcp_service.py +0 -0
  92. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/models.py +0 -0
  93. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/planner.py +0 -0
  94. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/project_artifacts.py +0 -0
  95. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/rules/__init__.py +0 -0
  96. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/rules/compilers.py +0 -0
  97. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/rules/models.py +0 -0
  98. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/rules/parser.py +0 -0
  99. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/rules/repository.py +0 -0
  100. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/skills/__init__.py +0 -0
  101. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/skills/compilers.py +0 -0
  102. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/skills/install_sources.py +0 -0
  103. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/skills/models.py +0 -0
  104. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/skills/parser.py +0 -0
  105. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/__init__.py +0 -0
  106. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/loaders.py +0 -0
  107. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/schemas/agent.v1.schema.json +0 -0
  108. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/schemas/mcp.base.schema.json +0 -0
  109. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/schemas/mcp.v1.schema.json +0 -0
  110. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/schemas/rule.v1.schema.json +0 -0
  111. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/spec/schemas/skill.v1.schema.json +0 -0
  112. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/status.py +0 -0
  113. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/__init__.py +0 -0
  114. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/enums.py +0 -0
  115. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/import_selector.py +0 -0
  116. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/renderers.py +0 -0
  117. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/sections.py +0 -0
  118. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/tui/tables.py +0 -0
  119. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/utils.py +0 -0
  120. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/validation.py +0 -0
  121. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/workspace_artifacts.py +0 -0
  122. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic/workspaces.py +0 -0
  123. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/SOURCES.txt +0 -0
  124. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/dependency_links.txt +0 -0
  125. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/entry_points.txt +0 -0
  126. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/requires.txt +0 -0
  127. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/code_agnostic.egg-info/top_level.txt +0 -0
  128. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/setup.cfg +0 -0
  129. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_agents.py +0 -0
  130. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_aliases.py +0 -0
  131. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apply_apps.py +0 -0
  132. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apply_codex.py +0 -0
  133. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apply_cursor.py +0 -0
  134. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apply_mcp_cleanup.py +0 -0
  135. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apply_target.py +0 -0
  136. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_apps.py +0 -0
  137. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_disable_cleanup.py +0 -0
  138. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_explain_lossiness.py +0 -0
  139. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_flags.py +0 -0
  140. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_git_exclude.py +0 -0
  141. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_import.py +0 -0
  142. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_import_interactive.py +0 -0
  143. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_mcp.py +0 -0
  144. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_module_organization.py +0 -0
  145. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_plan.py +0 -0
  146. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_projects.py +0 -0
  147. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_restore.py +0 -0
  148. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_rules.py +0 -0
  149. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_skills.py +0 -0
  150. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_status.py +0 -0
  151. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_validate.py +0 -0
  152. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_workspace_resolution.py +0 -0
  153. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_cli_workspaces.py +0 -0
  154. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_common_mcp_to_dto.py +0 -0
  155. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_common_repository.py +0 -0
  156. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_compiled_planning.py +0 -0
  157. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_dto_to_common_mcp.py +0 -0
  158. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_git_exclude_service.py +0 -0
  159. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_mcp_service.py +0 -0
  160. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_planner_executor.py +0 -0
  161. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_planner_rules.py +0 -0
  162. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_project_config_sync.py +0 -0
  163. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_skill_install_sources.py +0 -0
  164. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_symlink_planning.py +0 -0
  165. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_sync_plan_model.py +0 -0
  166. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_transactional_executor.py +0 -0
  167. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_utils.py +0 -0
  168. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_version.py +0 -0
  169. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_workspace_config_sync.py +0 -0
  170. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_workspace_repo_status.py +0 -0
  171. {code_agnostic-0.5.0 → code_agnostic-0.5.1}/tests/test_workspaces.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-agnostic
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Centralized hub for LLM coding config: MCP, skills, rules, and agents.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.5.0"
3
+ __version__ = "0.5.1"
@@ -12,7 +12,6 @@ from code_agnostic.apps.common.framework import RegisteredAppConfigService
12
12
  from code_agnostic.apps.common.interfaces.mapper import IAppMCPMapper
13
13
  from code_agnostic.apps.common.interfaces.repositories import IAppConfigRepository
14
14
  from code_agnostic.apps.common.models import MCPServerDTO
15
- from code_agnostic.errors import InvalidConfigSchemaError
16
15
  from code_agnostic.models import Action, ActionKind, ActionStatus
17
16
  from code_agnostic.skills.compilers import ClaudeSkillCompiler
18
17
  from code_agnostic.skills.parser import parse_skill
@@ -57,12 +56,6 @@ class ClaudeConfigService(RegisteredAppConfigService):
57
56
  def mcp_config_key(self) -> str:
58
57
  return "mcpServers"
59
58
 
60
- def validate_config(self, payload: Any) -> None:
61
- if not isinstance(payload, dict):
62
- raise InvalidConfigSchemaError(
63
- self.repository.config_path, "must be a JSON object"
64
- )
65
-
66
59
  def build_action_payload(self, payload: dict[str, Any]) -> Any:
67
60
  return payload
68
61
 
@@ -88,7 +88,7 @@ class CodexConfigService(RegisteredAppConfigService):
88
88
  def mcp_config_key(self) -> str:
89
89
  return "mcp_servers"
90
90
 
91
- def validate_config(self, payload: Any) -> None:
91
+ def _validate_schema(self, payload: dict[str, Any]) -> None:
92
92
  error = next(iter(self._validator.iter_errors(payload)), None)
93
93
  if error is not None:
94
94
  raise InvalidConfigSchemaError(
@@ -12,6 +12,7 @@ from code_agnostic.apps.common.interfaces.repositories import IAppConfigReposito
12
12
  from code_agnostic.apps.common.interfaces.repositories import ISourceRepository
13
13
  from code_agnostic.apps.common.models import MCPServerDTO
14
14
  from code_agnostic.apps.common.utils import apply_mcp_servers
15
+ from code_agnostic.errors import InvalidConfigSchemaError
15
16
  from code_agnostic.apps.common.symlink_planning import (
16
17
  load_state_links,
17
18
  load_state_paths,
@@ -59,9 +60,24 @@ class IAppConfigService(ABC):
59
60
  """Native config key that holds the MCP server map for this editor."""
60
61
  raise NotImplementedError
61
62
 
62
- @abstractmethod
63
63
  def validate_config(self, payload: Any) -> None:
64
- raise NotImplementedError
64
+ """Single validation contract for every editor config.
65
+
66
+ Empty/absent config is always valid; anything present must be a JSON
67
+ object; schema-backed editors add their own checks via
68
+ ``_validate_schema``.
69
+ """
70
+ if payload is None or payload == {}:
71
+ return
72
+ if not isinstance(payload, dict):
73
+ raise InvalidConfigSchemaError(
74
+ self.repository.config_path, "must be a JSON object"
75
+ )
76
+ self._validate_schema(payload)
77
+
78
+ def _validate_schema(self, payload: dict[str, Any]) -> None:
79
+ """Editor-specific validation hook. Default: no schema."""
80
+ return
65
81
 
66
82
  @abstractmethod
67
83
  def build_action_payload(self, payload: dict[str, Any]) -> Any:
@@ -55,11 +55,7 @@ class CopilotConfigService(RegisteredAppConfigService):
55
55
  def mcp_config_key(self) -> str:
56
56
  return "mcpServers"
57
57
 
58
- def validate_config(self, payload: Any) -> None:
59
- if not isinstance(payload, dict):
60
- raise InvalidConfigSchemaError(
61
- self.repository.config_path, "must be a JSON object"
62
- )
58
+ def _validate_schema(self, payload: dict[str, Any]) -> None:
63
59
  mcp_servers = payload.get("mcpServers")
64
60
  if mcp_servers is not None and not isinstance(mcp_servers, dict):
65
61
  raise InvalidConfigSchemaError(
@@ -68,9 +68,7 @@ class CursorConfigService(RegisteredAppConfigService):
68
68
  def mcp_config_key(self) -> str:
69
69
  return "mcpServers"
70
70
 
71
- def validate_config(self, payload: Any) -> None:
72
- if payload == {}:
73
- return
71
+ def _validate_schema(self, payload: dict[str, Any]) -> None:
74
72
  error = next(iter(self._validator.iter_errors(payload)), None)
75
73
  if error is not None:
76
74
  raise InvalidConfigSchemaError(
@@ -104,11 +104,7 @@ class OpenCodeConfigService(RegisteredAppConfigService):
104
104
  def mcp_config_key(self) -> str:
105
105
  return "mcp"
106
106
 
107
- def validate_config(self, payload: Any) -> None:
108
- if not isinstance(payload, dict):
109
- raise InvalidConfigSchemaError(
110
- self.repository.config_path, "must be a JSON object"
111
- )
107
+ def _validate_schema(self, payload: dict[str, Any]) -> None:
112
108
  for error in self._validator.iter_errors(payload):
113
109
  if _is_unknown_provider_model_enum_error(error):
114
110
  continue
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-agnostic
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Centralized hub for LLM coding config: MCP, skills, rules, and agents.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "code-agnostic"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Centralized hub for LLM coding config: MCP, skills, rules, and agents."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes