sgar 0.1.3__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 (402) hide show
  1. sgar-0.1.3/LICENSE +6 -0
  2. sgar-0.1.3/MANIFEST.in +7 -0
  3. sgar-0.1.3/PKG-INFO +90 -0
  4. sgar-0.1.3/README.md +52 -0
  5. sgar-0.1.3/core/__init__.py +7 -0
  6. sgar-0.1.3/core/cc/__init__.py +119 -0
  7. sgar-0.1.3/core/cc/agents/__init__.py +10 -0
  8. sgar-0.1.3/core/cc/agents/agent_tool.py +320 -0
  9. sgar-0.1.3/core/cc/agents/backends/__init__.py +11 -0
  10. sgar-0.1.3/core/cc/agents/backends/base.py +62 -0
  11. sgar-0.1.3/core/cc/agents/backends/in_process.py +126 -0
  12. sgar-0.1.3/core/cc/agents/backends/local_subprocess.py +332 -0
  13. sgar-0.1.3/core/cc/agents/definitions.py +25 -0
  14. sgar-0.1.3/core/cc/agents/runtime.py +208 -0
  15. sgar-0.1.3/core/cc/agents/runtime_registry.py +88 -0
  16. sgar-0.1.3/core/cc/agents/runtime_transport.py +66 -0
  17. sgar-0.1.3/core/cc/agents/swarm/__init__.py +3 -0
  18. sgar-0.1.3/core/cc/agents/swarm/mailbox.py +310 -0
  19. sgar-0.1.3/core/cc/agents/task_manager.py +101 -0
  20. sgar-0.1.3/core/cc/agents/task_model.py +106 -0
  21. sgar-0.1.3/core/cc/agents/task_state_store.py +149 -0
  22. sgar-0.1.3/core/cc/api.py +413 -0
  23. sgar-0.1.3/core/cc/artifact_state.py +156 -0
  24. sgar-0.1.3/core/cc/audit.py +255 -0
  25. sgar-0.1.3/core/cc/command_runner.py +331 -0
  26. sgar-0.1.3/core/cc/config.py +830 -0
  27. sgar-0.1.3/core/cc/conversation/__init__.py +47 -0
  28. sgar-0.1.3/core/cc/conversation/agent_mode_strategy.py +129 -0
  29. sgar-0.1.3/core/cc/conversation/compact.py +69 -0
  30. sgar-0.1.3/core/cc/conversation/context_assembler.py +142 -0
  31. sgar-0.1.3/core/cc/conversation/llm_adapter.py +410 -0
  32. sgar-0.1.3/core/cc/conversation/message_store.py +98 -0
  33. sgar-0.1.3/core/cc/conversation/middleware.py +288 -0
  34. sgar-0.1.3/core/cc/conversation/mode_strategy.py +280 -0
  35. sgar-0.1.3/core/cc/conversation/models.py +73 -0
  36. sgar-0.1.3/core/cc/conversation/prompt_builder.py +162 -0
  37. sgar-0.1.3/core/cc/conversation/prompt_catalog.py +98 -0
  38. sgar-0.1.3/core/cc/conversation/protocol.py +28 -0
  39. sgar-0.1.3/core/cc/conversation/query_engine.py +483 -0
  40. sgar-0.1.3/core/cc/conversation/query_loop.py +1173 -0
  41. sgar-0.1.3/core/cc/conversation/query_loop_followup.py +105 -0
  42. sgar-0.1.3/core/cc/conversation/query_loop_implementation_sync.py +95 -0
  43. sgar-0.1.3/core/cc/conversation/query_loop_mode_transitions.py +127 -0
  44. sgar-0.1.3/core/cc/conversation/query_loop_tool_events.py +94 -0
  45. sgar-0.1.3/core/cc/conversation/session.py +119 -0
  46. sgar-0.1.3/core/cc/conversation/session_journal.py +70 -0
  47. sgar-0.1.3/core/cc/conversation/strategy_common.py +93 -0
  48. sgar-0.1.3/core/cc/conversation/tool_ledger.py +179 -0
  49. sgar-0.1.3/core/cc/conversation/turn_pipeline.py +315 -0
  50. sgar-0.1.3/core/cc/editing/__init__.py +16 -0
  51. sgar-0.1.3/core/cc/editing/facade.py +288 -0
  52. sgar-0.1.3/core/cc/editing/file_state.py +61 -0
  53. sgar-0.1.3/core/cc/editing/requests.py +76 -0
  54. sgar-0.1.3/core/cc/editing/rollback.py +150 -0
  55. sgar-0.1.3/core/cc/editing/validator.py +107 -0
  56. sgar-0.1.3/core/cc/engine_factory.py +116 -0
  57. sgar-0.1.3/core/cc/errors.py +46 -0
  58. sgar-0.1.3/core/cc/jsonl.py +105 -0
  59. sgar-0.1.3/core/cc/llm.py +112 -0
  60. sgar-0.1.3/core/cc/memory/__init__.py +26 -0
  61. sgar-0.1.3/core/cc/memory/base.py +40 -0
  62. sgar-0.1.3/core/cc/memory/extractor.py +257 -0
  63. sgar-0.1.3/core/cc/memory/models.py +133 -0
  64. sgar-0.1.3/core/cc/memory/noop_provider.py +51 -0
  65. sgar-0.1.3/core/cc/memory/policy.py +70 -0
  66. sgar-0.1.3/core/cc/memory/registry.py +30 -0
  67. sgar-0.1.3/core/cc/memory/runtime.py +289 -0
  68. sgar-0.1.3/core/cc/memory/serializer.py +53 -0
  69. sgar-0.1.3/core/cc/observability.py +54 -0
  70. sgar-0.1.3/core/cc/plan.py +99 -0
  71. sgar-0.1.3/core/cc/prompt_cc_review.md +100 -0
  72. sgar-0.1.3/core/cc/prompts/agents/worker.en.md +3 -0
  73. sgar-0.1.3/core/cc/prompts/agents/worker.zh.md +3 -0
  74. sgar-0.1.3/core/cc/prompts/system/agent_mode.en.md +34 -0
  75. sgar-0.1.3/core/cc/prompts/system/agent_mode.zh.md +34 -0
  76. sgar-0.1.3/core/cc/prompts/system/agent_mode_followup.en.md +8 -0
  77. sgar-0.1.3/core/cc/prompts/system/agent_mode_followup.zh.md +8 -0
  78. sgar-0.1.3/core/cc/prompts/system/ask_mode.en.md +30 -0
  79. sgar-0.1.3/core/cc/prompts/system/ask_mode.zh.md +30 -0
  80. sgar-0.1.3/core/cc/prompts/system/code_build.en.md +36 -0
  81. sgar-0.1.3/core/cc/prompts/system/code_build.zh.md +36 -0
  82. sgar-0.1.3/core/cc/prompts/system/coordinator.en.md +3 -0
  83. sgar-0.1.3/core/cc/prompts/system/coordinator.zh.md +3 -0
  84. sgar-0.1.3/core/cc/prompts/system/default.en.md +36 -0
  85. sgar-0.1.3/core/cc/prompts/system/default.zh.md +36 -0
  86. sgar-0.1.3/core/cc/prompts/system/doc_mode.en.md +37 -0
  87. sgar-0.1.3/core/cc/prompts/system/doc_mode.zh.md +37 -0
  88. sgar-0.1.3/core/cc/prompts/system/implementation_followup.en.md +6 -0
  89. sgar-0.1.3/core/cc/prompts/system/implementation_followup.zh.md +6 -0
  90. sgar-0.1.3/core/cc/prompts/system/implementation_task_sync_followup.en.md +8 -0
  91. sgar-0.1.3/core/cc/prompts/system/implementation_task_sync_followup.zh.md +8 -0
  92. sgar-0.1.3/core/cc/prompts/system/plan_implementation.en.md +32 -0
  93. sgar-0.1.3/core/cc/prompts/system/plan_implementation.zh.md +32 -0
  94. sgar-0.1.3/core/cc/prompts/system/plan_mode.en.md +52 -0
  95. sgar-0.1.3/core/cc/prompts/system/plan_mode.zh.md +52 -0
  96. sgar-0.1.3/core/cc/prompts/system/query_continue.en.md +1 -0
  97. sgar-0.1.3/core/cc/prompts/system/query_continue.zh.md +1 -0
  98. sgar-0.1.3/core/cc/prompts/system/render_followup.en.md +5 -0
  99. sgar-0.1.3/core/cc/prompts/system/render_followup.zh.md +5 -0
  100. sgar-0.1.3/core/cc/prompts/system/spec_mode.en.md +41 -0
  101. sgar-0.1.3/core/cc/prompts/system/spec_mode.zh.md +41 -0
  102. sgar-0.1.3/core/cc/prompts/system/spec_render.en.md +35 -0
  103. sgar-0.1.3/core/cc/prompts/system/spec_render.zh.md +35 -0
  104. sgar-0.1.3/core/cc/prompts/system/swarm_planner.en.md +35 -0
  105. sgar-0.1.3/core/cc/prompts/system/swarm_planner.zh.md +35 -0
  106. sgar-0.1.3/core/cc/prompts/system/tool_followup.en.md +1 -0
  107. sgar-0.1.3/core/cc/prompts/system/tool_followup.zh.md +1 -0
  108. sgar-0.1.3/core/cc/prompts/tools/file_edit.en.md +3 -0
  109. sgar-0.1.3/core/cc/prompts/tools/file_edit.zh.md +3 -0
  110. sgar-0.1.3/core/cc/providers.py +215 -0
  111. sgar-0.1.3/core/cc/runtime.py +29 -0
  112. sgar-0.1.3/core/cc/safety/__init__.py +11 -0
  113. sgar-0.1.3/core/cc/safety/classifier.py +82 -0
  114. sgar-0.1.3/core/cc/safety/command_rules.py +170 -0
  115. sgar-0.1.3/core/cc/safety/decision.py +17 -0
  116. sgar-0.1.3/core/cc/safety/file_rules.py +32 -0
  117. sgar-0.1.3/core/cc/safety/permission_mode.py +35 -0
  118. sgar-0.1.3/core/cc/specs.py +99 -0
  119. sgar-0.1.3/core/cc/structured_flow.py +548 -0
  120. sgar-0.1.3/core/cc/tools/__init__.py +59 -0
  121. sgar-0.1.3/core/cc/tools/base.py +94 -0
  122. sgar-0.1.3/core/cc/tools/builtin.py +80 -0
  123. sgar-0.1.3/core/cc/tools/context.py +73 -0
  124. sgar-0.1.3/core/cc/tools/enter_plan_mode.py +68 -0
  125. sgar-0.1.3/core/cc/tools/enter_spec_mode.py +68 -0
  126. sgar-0.1.3/core/cc/tools/executor.py +107 -0
  127. sgar-0.1.3/core/cc/tools/exit_plan_mode.py +95 -0
  128. sgar-0.1.3/core/cc/tools/exit_spec_mode.py +95 -0
  129. sgar-0.1.3/core/cc/tools/file_edit.py +124 -0
  130. sgar-0.1.3/core/cc/tools/file_read.py +139 -0
  131. sgar-0.1.3/core/cc/tools/file_write.py +105 -0
  132. sgar-0.1.3/core/cc/tools/glob_tool.py +79 -0
  133. sgar-0.1.3/core/cc/tools/grep_tool.py +453 -0
  134. sgar-0.1.3/core/cc/tools/memory.py +145 -0
  135. sgar-0.1.3/core/cc/tools/memory_fact.py +114 -0
  136. sgar-0.1.3/core/cc/tools/memory_search.py +62 -0
  137. sgar-0.1.3/core/cc/tools/memory_status.py +49 -0
  138. sgar-0.1.3/core/cc/tools/memory_store.py +72 -0
  139. sgar-0.1.3/core/cc/tools/orchestrator.py +249 -0
  140. sgar-0.1.3/core/cc/tools/plan_artifact_write.py +210 -0
  141. sgar-0.1.3/core/cc/tools/powershell.py +65 -0
  142. sgar-0.1.3/core/cc/tools/registry.py +29 -0
  143. sgar-0.1.3/core/cc/tools/result_mapper.py +47 -0
  144. sgar-0.1.3/core/cc/tools/run_tests.py +118 -0
  145. sgar-0.1.3/core/cc/tools/send_message.py +87 -0
  146. sgar-0.1.3/core/cc/tools/shell.py +113 -0
  147. sgar-0.1.3/core/cc/tools/spec_artifact_write.py +159 -0
  148. sgar-0.1.3/core/cc/tools/task_stop.py +77 -0
  149. sgar-0.1.3/core/cc/tools/todo_write.py +84 -0
  150. sgar-0.1.3/core/cc/tools/worktree.py +152 -0
  151. sgar-0.1.3/core/cc/usage.md +370 -0
  152. sgar-0.1.3/core/ccx/__init__.py +46 -0
  153. sgar-0.1.3/core/ccx/agents/__init__.py +17 -0
  154. sgar-0.1.3/core/ccx/agents/cc_agent.py +1149 -0
  155. sgar-0.1.3/core/ccx/agents/ccx_research_tool.py +304 -0
  156. sgar-0.1.3/core/ccx/agents/ccx_sgar_tool.py +278 -0
  157. sgar-0.1.3/core/ccx/agents/ccx_spawn_tool.py +357 -0
  158. sgar-0.1.3/core/ccx/agents/ccx_tool.py +571 -0
  159. sgar-0.1.3/core/ccx/agents/ctx_search_tool.py +372 -0
  160. sgar-0.1.3/core/ccx/agents/event_bridge.py +305 -0
  161. sgar-0.1.3/core/ccx/agents/goal_prompts.py +260 -0
  162. sgar-0.1.3/core/ccx/agents/governed_goal.py +1388 -0
  163. sgar-0.1.3/core/ccx/agents/governed_run.py +444 -0
  164. sgar-0.1.3/core/ccx/agents/governed_spawn.py +470 -0
  165. sgar-0.1.3/core/ccx/agents/metadata_inheritance.py +143 -0
  166. sgar-0.1.3/core/ccx/agents/read_only_runner.py +178 -0
  167. sgar-0.1.3/core/ccx/agents/research_runner.py +340 -0
  168. sgar-0.1.3/core/ccx/agents/subagent.py +216 -0
  169. sgar-0.1.3/core/ccx/agents/swarm/__init__.py +18 -0
  170. sgar-0.1.3/core/ccx/agents/swarm/coordinator.py +379 -0
  171. sgar-0.1.3/core/ccx/agents/swarm/mailbox_bridge.py +155 -0
  172. sgar-0.1.3/core/ccx/agents/swarm/team_runtime.py +365 -0
  173. sgar-0.1.3/core/ccx/agents/task_manager.py +402 -0
  174. sgar-0.1.3/core/ccx/api.py +2346 -0
  175. sgar-0.1.3/core/ccx/audit/__init__.py +95 -0
  176. sgar-0.1.3/core/ccx/audit/check_template.py +61 -0
  177. sgar-0.1.3/core/ccx/audit/code_task.py +320 -0
  178. sgar-0.1.3/core/ccx/audit/contract.py +95 -0
  179. sgar-0.1.3/core/ccx/audit/finding_ledger.py +143 -0
  180. sgar-0.1.3/core/ccx/audit/gitdiff.py +208 -0
  181. sgar-0.1.3/core/ccx/audit/ledger.py +92 -0
  182. sgar-0.1.3/core/ccx/audit/mutation.py +258 -0
  183. sgar-0.1.3/core/ccx/audit/regression_capture.py +276 -0
  184. sgar-0.1.3/core/ccx/audit/wiring.py +119 -0
  185. sgar-0.1.3/core/ccx/conversation/__init__.py +15 -0
  186. sgar-0.1.3/core/ccx/llm_monitor.py +1002 -0
  187. sgar-0.1.3/core/ccx/memory/__init__.py +36 -0
  188. sgar-0.1.3/core/ccx/memory/inject.py +32 -0
  189. sgar-0.1.3/core/ccx/memory/models.py +292 -0
  190. sgar-0.1.3/core/ccx/memory/recall.py +146 -0
  191. sgar-0.1.3/core/ccx/memory/store.py +272 -0
  192. sgar-0.1.3/core/ccx/memory/summarizer.py +174 -0
  193. sgar-0.1.3/core/ccx/modes/__init__.py +50 -0
  194. sgar-0.1.3/core/ccx/modes/_goal.py +19 -0
  195. sgar-0.1.3/core/ccx/modes/_paths.py +14 -0
  196. sgar-0.1.3/core/ccx/modes/_sgar_command_helpers.py +611 -0
  197. sgar-0.1.3/core/ccx/modes/_text_masking.py +83 -0
  198. sgar-0.1.3/core/ccx/modes/agent.py +245 -0
  199. sgar-0.1.3/core/ccx/modes/artifacts.py +189 -0
  200. sgar-0.1.3/core/ccx/modes/ask.py +256 -0
  201. sgar-0.1.3/core/ccx/modes/blueprint.py +82 -0
  202. sgar-0.1.3/core/ccx/modes/diagnostics.py +259 -0
  203. sgar-0.1.3/core/ccx/modes/doc.py +4825 -0
  204. sgar-0.1.3/core/ccx/modes/llm_client.py +223 -0
  205. sgar-0.1.3/core/ccx/modes/parsing.py +216 -0
  206. sgar-0.1.3/core/ccx/modes/plan.py +550 -0
  207. sgar-0.1.3/core/ccx/modes/prompts/__init__.py +234 -0
  208. sgar-0.1.3/core/ccx/modes/prompts/agent.toml +13 -0
  209. sgar-0.1.3/core/ccx/modes/prompts/doc_decompose.toml +71 -0
  210. sgar-0.1.3/core/ccx/modes/prompts/doc_investigator.toml +293 -0
  211. sgar-0.1.3/core/ccx/modes/prompts/doc_prose_to_json.toml +85 -0
  212. sgar-0.1.3/core/ccx/modes/prompts/doc_surveyor.toml +103 -0
  213. sgar-0.1.3/core/ccx/modes/prompts/plan.toml +40 -0
  214. sgar-0.1.3/core/ccx/modes/prompts/spec.toml +28 -0
  215. sgar-0.1.3/core/ccx/modes/prompts/watch_analyzer.toml +179 -0
  216. sgar-0.1.3/core/ccx/modes/prompts/watch_fixer.toml +74 -0
  217. sgar-0.1.3/core/ccx/modes/sgarx.py +83 -0
  218. sgar-0.1.3/core/ccx/modes/spec.py +375 -0
  219. sgar-0.1.3/core/ccx/modes/watch.py +2220 -0
  220. sgar-0.1.3/core/ccx/modes/watch_checks.py +786 -0
  221. sgar-0.1.3/core/ccx/mypy.ini +32 -0
  222. sgar-0.1.3/core/ccx/prompt_ccx_self_review.md +103 -0
  223. sgar-0.1.3/core/ccx/prompts.py +42 -0
  224. sgar-0.1.3/core/ccx/report.py +950 -0
  225. sgar-0.1.3/core/ccx/runtime.py +1015 -0
  226. sgar-0.1.3/core/ccx/services/__init__.py +27 -0
  227. sgar-0.1.3/core/ccx/services/cost_events.py +60 -0
  228. sgar-0.1.3/core/ccx/services/findings_collector.py +83 -0
  229. sgar-0.1.3/core/ccx/services/governance_events.py +132 -0
  230. sgar-0.1.3/core/ccx/services/repository_outline.py +152 -0
  231. sgar-0.1.3/core/ccx/services/steer_inbox.py +140 -0
  232. sgar-0.1.3/core/ccx/sgar/__init__.py +53 -0
  233. sgar-0.1.3/core/ccx/sgar/__main__.py +5 -0
  234. sgar-0.1.3/core/ccx/sgar/autobuild.py +189 -0
  235. sgar-0.1.3/core/ccx/sgar/checks.py +302 -0
  236. sgar-0.1.3/core/ccx/sgar/cli.py +325 -0
  237. sgar-0.1.3/core/ccx/sgar/missions.py +474 -0
  238. sgar-0.1.3/core/ccx/sgar/models.py +208 -0
  239. sgar-0.1.3/core/ccx/sgar/runtime.py +906 -0
  240. sgar-0.1.3/core/ccx/sgar/store.py +381 -0
  241. sgar-0.1.3/core/ccx/sgar/tracing.py +212 -0
  242. sgar-0.1.3/core/ccx/sgar/validation.py +247 -0
  243. sgar-0.1.3/core/ccx/sgarx/__init__.py +13 -0
  244. sgar-0.1.3/core/ccx/sgarx/runtime.py +661 -0
  245. sgar-0.1.3/core/ccx/sgarx/store.py +26 -0
  246. sgar-0.1.3/core/ccx/structured_flow.py +346 -0
  247. sgar-0.1.3/core/ccx/templates/report.html.j2 +547 -0
  248. sgar-0.1.3/core/ccx/watch.py +1326 -0
  249. sgar-0.1.3/core/deepstack_v5/__init__.py +66 -0
  250. sgar-0.1.3/core/deepstack_v5/config.py +97 -0
  251. sgar-0.1.3/core/deepstack_v5/control/__init__.py +0 -0
  252. sgar-0.1.3/core/deepstack_v5/control/budget.py +141 -0
  253. sgar-0.1.3/core/deepstack_v5/control/controller.py +159 -0
  254. sgar-0.1.3/core/deepstack_v5/control/escalation.py +109 -0
  255. sgar-0.1.3/core/deepstack_v5/engine.py +1530 -0
  256. sgar-0.1.3/core/deepstack_v5/events.py +164 -0
  257. sgar-0.1.3/core/deepstack_v5/execution/__init__.py +0 -0
  258. sgar-0.1.3/core/deepstack_v5/execution/assignment.py +121 -0
  259. sgar-0.1.3/core/deepstack_v5/execution/dispatch_context.py +94 -0
  260. sgar-0.1.3/core/deepstack_v5/execution/dispatcher.py +764 -0
  261. sgar-0.1.3/core/deepstack_v5/execution/graph.py +346 -0
  262. sgar-0.1.3/core/deepstack_v5/execution/node.py +214 -0
  263. sgar-0.1.3/core/deepstack_v5/execution/toolcall.py +152 -0
  264. sgar-0.1.3/core/deepstack_v5/knowledge/__init__.py +0 -0
  265. sgar-0.1.3/core/deepstack_v5/knowledge/claims.py +254 -0
  266. sgar-0.1.3/core/deepstack_v5/knowledge/compaction.py +209 -0
  267. sgar-0.1.3/core/deepstack_v5/memory/__init__.py +48 -0
  268. sgar-0.1.3/core/deepstack_v5/memory/content_store.py +816 -0
  269. sgar-0.1.3/core/deepstack_v5/memory/priority.py +122 -0
  270. sgar-0.1.3/core/deepstack_v5/memory/resume.py +128 -0
  271. sgar-0.1.3/core/deepstack_v5/memory/snapshot.py +262 -0
  272. sgar-0.1.3/core/deepstack_v5/persistence/__init__.py +31 -0
  273. sgar-0.1.3/core/deepstack_v5/persistence/db.py +436 -0
  274. sgar-0.1.3/core/deepstack_v5/persistence/file_backend.py +512 -0
  275. sgar-0.1.3/core/deepstack_v5/persistence/outbox.py +98 -0
  276. sgar-0.1.3/core/deepstack_v5/persistence/stores.py +1094 -0
  277. sgar-0.1.3/core/deepstack_v5/runtime.py +210 -0
  278. sgar-0.1.3/core/deepstack_v5/types.py +454 -0
  279. sgar-0.1.3/core/llms/__init__.py +1 -0
  280. sgar-0.1.3/core/llms/_deepseek_stream.py +400 -0
  281. sgar-0.1.3/core/llms/_llm_api_client.py +600 -0
  282. sgar-0.1.3/core/llms/ali_deep_seek_client.py +16 -0
  283. sgar-0.1.3/core/llms/ali_deep_seek_r1_client.py +16 -0
  284. sgar-0.1.3/core/llms/ark_client.py +16 -0
  285. sgar-0.1.3/core/llms/aws_deepseek_client.py +18 -0
  286. sgar-0.1.3/core/llms/aws_deepseek_r1_client.py +19 -0
  287. sgar-0.1.3/core/llms/azure_deep_seek_client.py +132 -0
  288. sgar-0.1.3/core/llms/baichuan_client.py +129 -0
  289. sgar-0.1.3/core/llms/bce_deep_seek_client.py +20 -0
  290. sgar-0.1.3/core/llms/bce_deep_seek_r1_client.py +20 -0
  291. sgar-0.1.3/core/llms/claude_aws_client.py +676 -0
  292. sgar-0.1.3/core/llms/claude_client.py +365 -0
  293. sgar-0.1.3/core/llms/deepbricks_client.py +16 -0
  294. sgar-0.1.3/core/llms/doubao_client.py +238 -0
  295. sgar-0.1.3/core/llms/dummy_client.py +32 -0
  296. sgar-0.1.3/core/llms/ernie_client.py +277 -0
  297. sgar-0.1.3/core/llms/fallback_client.py +181 -0
  298. sgar-0.1.3/core/llms/gemini2_client.py +385 -0
  299. sgar-0.1.3/core/llms/gemini_client.py +596 -0
  300. sgar-0.1.3/core/llms/gemini_pro_client.py +18 -0
  301. sgar-0.1.3/core/llms/glm_client.py +469 -0
  302. sgar-0.1.3/core/llms/glm_free_client.py +14 -0
  303. sgar-0.1.3/core/llms/glm_openai_client.py +19 -0
  304. sgar-0.1.3/core/llms/healer_alpha_client.py +16 -0
  305. sgar-0.1.3/core/llms/hunter_alpha_client.py +16 -0
  306. sgar-0.1.3/core/llms/hunyuan_client.py +266 -0
  307. sgar-0.1.3/core/llms/infini_deep_seek_client.py +23 -0
  308. sgar-0.1.3/core/llms/infini_deep_seek_r1_client.py +19 -0
  309. sgar-0.1.3/core/llms/kimi_client.py +21 -0
  310. sgar-0.1.3/core/llms/llm_factory.py +98 -0
  311. sgar-0.1.3/core/llms/mi_client.py +21 -0
  312. sgar-0.1.3/core/llms/mimo_client.py +16 -0
  313. sgar-0.1.3/core/llms/mini_max_client.py +308 -0
  314. sgar-0.1.3/core/llms/mini_max_pro.py +174 -0
  315. sgar-0.1.3/core/llms/mini_max_text_client.py +11 -0
  316. sgar-0.1.3/core/llms/minimax_r1_client.py +19 -0
  317. sgar-0.1.3/core/llms/minmax_m2_client.py +21 -0
  318. sgar-0.1.3/core/llms/moonshot_client.py +359 -0
  319. sgar-0.1.3/core/llms/multi_claude.py +456 -0
  320. sgar-0.1.3/core/llms/ollama_ds32b_client.py +21 -0
  321. sgar-0.1.3/core/llms/open_router_client.py +16 -0
  322. sgar-0.1.3/core/llms/openai_client.py +555 -0
  323. sgar-0.1.3/core/llms/openai_http_client.py +806 -0
  324. sgar-0.1.3/core/llms/ppio_claude_client.py +19 -0
  325. sgar-0.1.3/core/llms/ppio_claude_sonnet_client.py +19 -0
  326. sgar-0.1.3/core/llms/ppio_client.py +18 -0
  327. sgar-0.1.3/core/llms/ppio_cluade_opus_client.py +19 -0
  328. sgar-0.1.3/core/llms/ppio_deep_seek_client.py +18 -0
  329. sgar-0.1.3/core/llms/ppio_deep_seek_r1_cleint.py +19 -0
  330. sgar-0.1.3/core/llms/ppio_gemini_pro_client.py +19 -0
  331. sgar-0.1.3/core/llms/ppio_openai_client.py +19 -0
  332. sgar-0.1.3/core/llms/ppio_r_client.py +19 -0
  333. sgar-0.1.3/core/llms/px_client.py +442 -0
  334. sgar-0.1.3/core/llms/qianwen14_client.py +15 -0
  335. sgar-0.1.3/core/llms/qianwen32_client.py +15 -0
  336. sgar-0.1.3/core/llms/qianwen_client.py +442 -0
  337. sgar-0.1.3/core/llms/qianwen_coder_client.py +16 -0
  338. sgar-0.1.3/core/llms/qianwen_coder_plus_client.py +15 -0
  339. sgar-0.1.3/core/llms/qianwen_coder_turbo_client.py +15 -0
  340. sgar-0.1.3/core/llms/qianwen_plus.py +17 -0
  341. sgar-0.1.3/core/llms/qianwen_qwq_client.py +15 -0
  342. sgar-0.1.3/core/llms/qianwen_turbo.py +26 -0
  343. sgar-0.1.3/core/llms/qiniu_deep_seek_client.py +27 -0
  344. sgar-0.1.3/core/llms/qiniu_deep_seek_r1_client.py +23 -0
  345. sgar-0.1.3/core/llms/qwq_client.py +18 -0
  346. sgar-0.1.3/core/llms/sense_deep_seek_client.py +20 -0
  347. sgar-0.1.3/core/llms/sense_deep_seek_r1_client.py +24 -0
  348. sgar-0.1.3/core/llms/silicon_deep_seek_client.py +18 -0
  349. sgar-0.1.3/core/llms/silicon_deep_seek_r1_client.py +19 -0
  350. sgar-0.1.3/core/llms/simple_azure.py +336 -0
  351. sgar-0.1.3/core/llms/simple_claude.py +389 -0
  352. sgar-0.1.3/core/llms/simple_deep_seek_client.py +846 -0
  353. sgar-0.1.3/core/llms/simple_deep_seek_client_chat.py +116 -0
  354. sgar-0.1.3/core/llms/simple_deep_seek_client_reasoning.py +88 -0
  355. sgar-0.1.3/core/llms/simple_deep_seek_client_speciale.py +20 -0
  356. sgar-0.1.3/core/llms/simple_doubao_client.py +241 -0
  357. sgar-0.1.3/core/llms/spark_client.py +16 -0
  358. sgar-0.1.3/core/llms/tencent_deep_seek_client.py +21 -0
  359. sgar-0.1.3/core/llms/tencent_deep_seek_r1_client.py +23 -0
  360. sgar-0.1.3/core/llms/volc_deep_seek_client.py +19 -0
  361. sgar-0.1.3/core/llms/volc_deep_seek_r1_client.py +19 -0
  362. sgar-0.1.3/core/llms/zero1_improver_client.py +17 -0
  363. sgar-0.1.3/core/utils/CODE_MODIFICATION_TOOLS.md +628 -0
  364. sgar-0.1.3/core/utils/CODE_UPDATE_QUICKSTART.md +409 -0
  365. sgar-0.1.3/core/utils/FEE_READER_USAGE.md +270 -0
  366. sgar-0.1.3/core/utils/FIX_LLM_CLIENT_CHAT_METHOD.md +257 -0
  367. sgar-0.1.3/core/utils/UNIFIED_LOGGER_README.md +278 -0
  368. sgar-0.1.3/core/utils/__init__.py +43 -0
  369. sgar-0.1.3/core/utils/_legacy/llm_ast_editor.md +943 -0
  370. sgar-0.1.3/core/utils/autonomous_code_agent.md +558 -0
  371. sgar-0.1.3/core/utils/code_editor.md +340 -0
  372. sgar-0.1.3/core/utils/common.py +47 -0
  373. sgar-0.1.3/core/utils/config_setting.py +52 -0
  374. sgar-0.1.3/core/utils/editor_fallback.py +84 -0
  375. sgar-0.1.3/core/utils/error_classifier_helper.py +353 -0
  376. sgar-0.1.3/core/utils/handle_max_tokens.py +63 -0
  377. sgar-0.1.3/core/utils/how_to_use_code_editor.md +792 -0
  378. sgar-0.1.3/core/utils/json_from_text.py +694 -0
  379. sgar-0.1.3/core/utils/llm_block_editor.py +3204 -0
  380. sgar-0.1.3/core/utils/llm_block_editor_lnfree.py +1096 -0
  381. sgar-0.1.3/core/utils/llm_code_editor.py +1447 -0
  382. sgar-0.1.3/core/utils/log.py +250 -0
  383. sgar-0.1.3/core/utils/prompt_language.py +81 -0
  384. sgar-0.1.3/core/utils/rate_limit.py +35 -0
  385. sgar-0.1.3/core/utils/retry.py +19 -0
  386. sgar-0.1.3/core/utils/robust_llm_editor.py +1009 -0
  387. sgar-0.1.3/core/utils/single_ton.py +25 -0
  388. sgar-0.1.3/core/utils/smart_llm_editor_v2.py +1565 -0
  389. sgar-0.1.3/core/utils/source_code_manager.py +363 -0
  390. sgar-0.1.3/pyproject.toml +52 -0
  391. sgar-0.1.3/requirements.txt +24 -0
  392. sgar-0.1.3/setting.ini.template +131 -0
  393. sgar-0.1.3/setup.cfg +4 -0
  394. sgar-0.1.3/setup.py +5 -0
  395. sgar-0.1.3/sgar/__init__.py +3 -0
  396. sgar-0.1.3/sgar/__main__.py +5 -0
  397. sgar-0.1.3/sgar.egg-info/PKG-INFO +90 -0
  398. sgar-0.1.3/sgar.egg-info/SOURCES.txt +400 -0
  399. sgar-0.1.3/sgar.egg-info/dependency_links.txt +1 -0
  400. sgar-0.1.3/sgar.egg-info/entry_points.txt +2 -0
  401. sgar-0.1.3/sgar.egg-info/requires.txt +27 -0
  402. sgar-0.1.3/sgar.egg-info/top_level.txt +2 -0
sgar-0.1.3/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ Copyright (c) 2026 wxy2ab. All rights reserved.
2
+
3
+ This software is distributed as a proprietary, internal package ("sgar").
4
+ No license to use, copy, modify, or distribute is granted except by explicit
5
+ written permission of the copyright holder. Replace this file with the license
6
+ of your choice before any external distribution.
sgar-0.1.3/MANIFEST.in ADDED
@@ -0,0 +1,7 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ include setting.ini.template
5
+ recursive-include core *.md *.toml *.j2 *.typed *.ini *.json *.html *.txt *.yaml *.yml
6
+ global-exclude *.py[cod]
7
+ global-exclude __pycache__/*
sgar-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: sgar
3
+ Version: 0.1.3
4
+ Summary: SGAR — ccx 治理化 agent 运行时(自 llm_dealer 导出的独立分发)
5
+ Author: wxy2ab
6
+ License: Proprietary
7
+ Keywords: ccx,sgar,agent,llm,governance
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: anthropic
12
+ Requires-Dist: azure-ai-inference
13
+ Requires-Dist: boto3
14
+ Requires-Dist: colorlog
15
+ Requires-Dist: dashscope
16
+ Requires-Dist: google-generativeai
17
+ Requires-Dist: grep-ast
18
+ Requires-Dist: httpx
19
+ Requires-Dist: matplotlib
20
+ Requires-Dist: numpy
21
+ Requires-Dist: openai
22
+ Requires-Dist: pandas
23
+ Requires-Dist: pillow
24
+ Requires-Dist: rank-bm25
25
+ Requires-Dist: ratelimit
26
+ Requires-Dist: regex
27
+ Requires-Dist: requests
28
+ Requires-Dist: tenacity
29
+ Requires-Dist: tencentcloud-sdk-python
30
+ Requires-Dist: tree-sitter
31
+ Requires-Dist: tree-sitter-python
32
+ Requires-Dist: volcengine-python-sdk[ark]
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest; extra == "dev"
35
+ Requires-Dist: mypy; extra == "dev"
36
+ Requires-Dist: ruff; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # sgar
40
+
41
+ `ccx` 治理化 agent 运行时,从 `llm_dealer` 仓库中按 `core/ccx` 的依赖闭包自动导出的
42
+ 独立、可 pip 安装项目。
43
+
44
+ 本目录由 `task/copy/ccx_out.py` 生成:包含 321 个源文件、61 个运行期资源文件,
45
+ 覆盖子包 `core.cc`, `core.ccx`, `core.deepstack_v5`, `core.llms`, `core.utils`。
46
+
47
+ > 注意:分发名是 `sgar`,但可导入的顶层包是 `core`(保留原命名空间以免改写大量
48
+ > `import core.*`)。
49
+
50
+ ## 安装
51
+
52
+ ```bash
53
+ pip install -e .
54
+ # 或
55
+ pip install .
56
+ ```
57
+
58
+ 需要 Python >=3.12。
59
+
60
+ ## 配置
61
+
62
+ 复制配置模板并填入你的密钥:
63
+
64
+ ```bash
65
+ cp setting.ini.template setting.ini
66
+ $EDITOR setting.ini
67
+ ```
68
+
69
+ 所有键也可以用同名大写的环境变量提供(见 `core/utils/config_setting.py`)。
70
+ `setting.ini` 含密钥,已在 `.gitignore` 中忽略,请勿提交。
71
+
72
+ ## 使用
73
+
74
+ ```bash
75
+ sgar --help # 安装后提供的命令行入口
76
+ python -m sgar --help
77
+ python -m core.ccx.sgar --help
78
+ ```
79
+
80
+ ```python
81
+ from core.ccx.api import AgentRunRequest # 程序化入口
82
+ ```
83
+
84
+ ## 自动发布
85
+
86
+ - 每次 push 到 `main` 后,GitHub Actions 会自动将 `pyproject.toml` 的 patch 版本加 `1`。
87
+ - 版本 bump 成功后,会自动构建并发布到 PyPI。
88
+ - 如需手动发布,可在 GitHub Actions 里运行 `Publish sgar to PyPI`,并选择 `pypi` 或 `testpypi`。
89
+ - 正式发布使用 GitHub Repository Secret `PYPI_API_TOKEN`。
90
+ - 如需手动发布到 TestPyPI,请额外配置 `TEST_PYPI_API_TOKEN`。
sgar-0.1.3/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # sgar
2
+
3
+ `ccx` 治理化 agent 运行时,从 `llm_dealer` 仓库中按 `core/ccx` 的依赖闭包自动导出的
4
+ 独立、可 pip 安装项目。
5
+
6
+ 本目录由 `task/copy/ccx_out.py` 生成:包含 321 个源文件、61 个运行期资源文件,
7
+ 覆盖子包 `core.cc`, `core.ccx`, `core.deepstack_v5`, `core.llms`, `core.utils`。
8
+
9
+ > 注意:分发名是 `sgar`,但可导入的顶层包是 `core`(保留原命名空间以免改写大量
10
+ > `import core.*`)。
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ pip install -e .
16
+ # 或
17
+ pip install .
18
+ ```
19
+
20
+ 需要 Python >=3.12。
21
+
22
+ ## 配置
23
+
24
+ 复制配置模板并填入你的密钥:
25
+
26
+ ```bash
27
+ cp setting.ini.template setting.ini
28
+ $EDITOR setting.ini
29
+ ```
30
+
31
+ 所有键也可以用同名大写的环境变量提供(见 `core/utils/config_setting.py`)。
32
+ `setting.ini` 含密钥,已在 `.gitignore` 中忽略,请勿提交。
33
+
34
+ ## 使用
35
+
36
+ ```bash
37
+ sgar --help # 安装后提供的命令行入口
38
+ python -m sgar --help
39
+ python -m core.ccx.sgar --help
40
+ ```
41
+
42
+ ```python
43
+ from core.ccx.api import AgentRunRequest # 程序化入口
44
+ ```
45
+
46
+ ## 自动发布
47
+
48
+ - 每次 push 到 `main` 后,GitHub Actions 会自动将 `pyproject.toml` 的 patch 版本加 `1`。
49
+ - 版本 bump 成功后,会自动构建并发布到 PyPI。
50
+ - 如需手动发布,可在 GitHub Actions 里运行 `Publish sgar to PyPI`,并选择 `pypi` 或 `testpypi`。
51
+ - 正式发布使用 GitHub Repository Secret `PYPI_API_TOKEN`。
52
+ - 如需手动发布到 TestPyPI,请额外配置 `TEST_PYPI_API_TOKEN`。
@@ -0,0 +1,7 @@
1
+ def str_to_obj(*args, **kwargs):
2
+ from .utils.common import str_to_obj as _str_to_obj
3
+
4
+ return _str_to_obj(*args, **kwargs)
5
+
6
+
7
+ __all__ = ["str_to_obj"]
@@ -0,0 +1,119 @@
1
+ # ---------------------------------------------------------------------------
2
+ # Public API (stable, recommended for external integrations)
3
+ # ---------------------------------------------------------------------------
4
+ from .audit import (
5
+ RuntimeAuditQuery,
6
+ RuntimeAuditSnapshot,
7
+ RuntimeAuditSummary,
8
+ query_runtime_audit,
9
+ read_runtime_audit,
10
+ summarize_runtime_audit,
11
+ )
12
+ from .api import (
13
+ AgentRunRequest,
14
+ AgentRunResult,
15
+ CodeAgent,
16
+ CodeBuildRequest,
17
+ build_code_with_agent,
18
+ run_code_agent,
19
+ )
20
+ from .config import CCConfig, load_cc_config
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # Advanced API (stable but lower-level; for fine-grained session control)
24
+ # ---------------------------------------------------------------------------
25
+ from .llm import DefaultLLMClientProvider, LLMClientProvider
26
+ from .runtime import build_default_query_engine
27
+ from .conversation.query_engine import QueryEngine
28
+ from .conversation.session import QuerySession, SessionFactory
29
+ from .conversation.models import SessionEvent, SessionMessage
30
+
31
+ # ---------------------------------------------------------------------------
32
+ # Middleware pipeline (composable cross-cutting concerns)
33
+ # ---------------------------------------------------------------------------
34
+ from .conversation.middleware import (
35
+ RetryPolicy,
36
+ TurnHooks,
37
+ TurnMiddleware,
38
+ TurnRunner,
39
+ apply as apply_middleware,
40
+ pipe as pipe_middleware,
41
+ with_compaction,
42
+ with_hooks,
43
+ with_persistence,
44
+ with_retry,
45
+ with_turn_tracking,
46
+ )
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # Environment providers (injectable filesystem / shell abstractions)
50
+ # ---------------------------------------------------------------------------
51
+ from .providers import (
52
+ CommandProvider,
53
+ Environment,
54
+ FileSystemProvider,
55
+ LocalCommandProvider,
56
+ LocalFileSystemProvider,
57
+ default_environment,
58
+ )
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # Errors
62
+ # ---------------------------------------------------------------------------
63
+ from .errors import (
64
+ CCError,
65
+ ConfigError,
66
+ ToolExecutionError,
67
+ ToolValidationError,
68
+ )
69
+
70
+ __all__ = [
71
+ # -- Public API --
72
+ "AgentRunRequest",
73
+ "AgentRunResult",
74
+ "CCConfig",
75
+ "CodeAgent",
76
+ "CodeBuildRequest",
77
+ "RuntimeAuditQuery",
78
+ "RuntimeAuditSnapshot",
79
+ "RuntimeAuditSummary",
80
+ "build_code_with_agent",
81
+ "load_cc_config",
82
+ "query_runtime_audit",
83
+ "read_runtime_audit",
84
+ "run_code_agent",
85
+ "summarize_runtime_audit",
86
+ # -- Advanced API --
87
+ "DefaultLLMClientProvider",
88
+ "LLMClientProvider",
89
+ "QueryEngine",
90
+ "QuerySession",
91
+ "SessionEvent",
92
+ "SessionFactory",
93
+ "SessionMessage",
94
+ "build_default_query_engine",
95
+ # -- Middleware pipeline --
96
+ "RetryPolicy",
97
+ "TurnHooks",
98
+ "TurnMiddleware",
99
+ "TurnRunner",
100
+ "apply_middleware",
101
+ "pipe_middleware",
102
+ "with_compaction",
103
+ "with_hooks",
104
+ "with_persistence",
105
+ "with_retry",
106
+ "with_turn_tracking",
107
+ # -- Environment providers --
108
+ "CommandProvider",
109
+ "Environment",
110
+ "FileSystemProvider",
111
+ "LocalCommandProvider",
112
+ "LocalFileSystemProvider",
113
+ "default_environment",
114
+ # -- Errors --
115
+ "CCError",
116
+ "ConfigError",
117
+ "ToolExecutionError",
118
+ "ToolValidationError",
119
+ ]
@@ -0,0 +1,10 @@
1
+ from .definitions import AgentDefinition
2
+ from .task_manager import TaskManager
3
+ from .task_model import AgentTask, AgentTaskStatus
4
+
5
+ __all__ = [
6
+ "AgentDefinition",
7
+ "AgentTask",
8
+ "AgentTaskStatus",
9
+ "TaskManager",
10
+ ]
@@ -0,0 +1,320 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ import logging
5
+ import os
6
+ from typing import Any
7
+ import asyncio
8
+
9
+ from ..agents.backends import InProcessBackend, LocalSubprocessBackend, RuntimeBackend
10
+ from ..config import CCConfig
11
+ from ..conversation.session import QuerySession, SessionFactory
12
+ from ..llm import DefaultLLMClientProvider, LLMClientProvider
13
+ from ..observability import EventRecord, JsonlAuditLogger
14
+ from ..tools.base import BaseTool, ToolCall, ToolResult, ToolSpec, ValidationResult
15
+ from ..tools.context import ToolUseContext
16
+ from .definitions import AgentDefinition
17
+ from .runtime import AgentRuntime
18
+ from .runtime_registry import InProcessRuntimeRegistry, get_in_process_runtime_registry
19
+ from .task_manager import TaskManager
20
+ from .task_model import AgentTask, AgentTaskStatus
21
+
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ # Maximum recursion depth for the ``agent`` tool. With cc_query_loop as the
27
+ # default ccx runner kind, every agent node can call ``agent`` to spawn a
28
+ # child runtime, which itself can call ``agent``, and so on. Each level
29
+ # multiplies the cost by the per-node fan-out, so an unconstrained recursion
30
+ # of depth 4 with fan-out 3 is already 81 leaves. The cap here is the only
31
+ # mechanical (non-prompt) backstop — LLMs can't reliably stay within a
32
+ # nominal budget via prompt instructions, but the runtime can refuse the
33
+ # call.
34
+ #
35
+ # Depth 0 = the top-level cc engine driven by ccx's CcAgentRunner; depth 1
36
+ # = its first helper; depth 2 = a helper-of-helper. The default of 3 keeps
37
+ # room for a real "lead → researcher → reviewer" pattern without permitting
38
+ # unbounded chains. Override via the ``CC_MAX_AGENT_RECURSION_DEPTH``
39
+ # environment variable for unusual workloads.
40
+ _DEFAULT_MAX_AGENT_RECURSION_DEPTH = 3
41
+ _RECURSION_DEPTH_STATE_KEY = "agent_recursion_depth"
42
+ _AGENT_SPAWN_REFUSED_ERROR_CODE = "AT1100"
43
+
44
+
45
+ def _resolve_max_recursion_depth() -> int:
46
+ raw = os.environ.get("CC_MAX_AGENT_RECURSION_DEPTH")
47
+ if not raw:
48
+ return _DEFAULT_MAX_AGENT_RECURSION_DEPTH
49
+ try:
50
+ value = int(raw)
51
+ except ValueError:
52
+ logger.warning(
53
+ "CC_MAX_AGENT_RECURSION_DEPTH=%r is not an int; using default %d",
54
+ raw, _DEFAULT_MAX_AGENT_RECURSION_DEPTH,
55
+ )
56
+ return _DEFAULT_MAX_AGENT_RECURSION_DEPTH
57
+ if value < 0:
58
+ logger.warning(
59
+ "CC_MAX_AGENT_RECURSION_DEPTH=%d is negative; using default %d",
60
+ value, _DEFAULT_MAX_AGENT_RECURSION_DEPTH,
61
+ )
62
+ return _DEFAULT_MAX_AGENT_RECURSION_DEPTH
63
+ return value
64
+
65
+
66
+ @dataclass(slots=True)
67
+ class AgentToolRequest:
68
+ description: str
69
+ prompt: str
70
+ subagent_type: str | None = None
71
+ backend: str | None = None
72
+ model: str | None = None
73
+ run_in_background: bool = False
74
+ name: str | None = None
75
+ team_name: str | None = None
76
+ mode: str | None = None
77
+ isolation: str | None = None
78
+ cwd: str | None = None
79
+
80
+
81
+ class AgentTool(BaseTool):
82
+ def __init__(
83
+ self,
84
+ llm_client_provider: LLMClientProvider | None = None,
85
+ runtime_registry: InProcessRuntimeRegistry | None = None,
86
+ ) -> None:
87
+ super().__init__(
88
+ ToolSpec(
89
+ name="agent",
90
+ description="Spawn a child agent to work on a sub-task and return its result.",
91
+ input_schema={
92
+ "type": "object",
93
+ "properties": {
94
+ "description": {"type": "string"},
95
+ "prompt": {"type": "string"},
96
+ "subagent_type": {"type": "string"},
97
+ "backend": {"type": "string"},
98
+ "run_in_background": {"type": "boolean"},
99
+ "cwd": {"type": "string"},
100
+ },
101
+ "required": ["description", "prompt"],
102
+ },
103
+ )
104
+ )
105
+ self.llm_client_provider = llm_client_provider or DefaultLLMClientProvider()
106
+ self.runtime_registry = runtime_registry
107
+
108
+ def validate_input(self, arguments: dict[str, Any]) -> ValidationResult:
109
+ if not arguments.get("description"):
110
+ return ValidationResult(ok=False, message="description is required.")
111
+ if not arguments.get("prompt"):
112
+ return ValidationResult(ok=False, message="prompt is required.")
113
+ backend = arguments.get("backend")
114
+ if backend and str(backend) not in {"in_process", "local_subprocess"}:
115
+ return ValidationResult(ok=False, message=f"Unsupported backend: {backend}")
116
+ return ValidationResult(ok=True)
117
+
118
+ async def execute(self, tool_call: ToolCall, ctx: ToolUseContext) -> ToolResult:
119
+ request = AgentToolRequest(
120
+ description=str(tool_call.arguments["description"]),
121
+ prompt=str(tool_call.arguments["prompt"]),
122
+ subagent_type=tool_call.arguments.get("subagent_type"),
123
+ backend=tool_call.arguments.get("backend"),
124
+ run_in_background=bool(tool_call.arguments.get("run_in_background", False)),
125
+ cwd=tool_call.arguments.get("cwd"),
126
+ )
127
+ # Recursion depth check (Tier 1 backstop against runaway sub-agent
128
+ # spawning when cc_query_loop is the default ccx runner). Read the
129
+ # parent's depth from session metadata.state, refuse if we'd exceed
130
+ # the cap, and emit an audit event either way so deep chains are
131
+ # debuggable post-hoc.
132
+ parent_session = ctx.metadata.get("session")
133
+ parent_depth = 0
134
+ if parent_session is not None:
135
+ parent_depth = int(
136
+ (parent_session.metadata.state or {}).get(
137
+ _RECURSION_DEPTH_STATE_KEY, 0,
138
+ ) or 0
139
+ )
140
+ max_depth = _resolve_max_recursion_depth()
141
+ runtime_root_for_audit = ctx.config.runtime_root_path(ctx.cwd)
142
+ agent_audit_logger = JsonlAuditLogger(
143
+ runtime_root_for_audit / "audit" / "agent_events.jsonl"
144
+ )
145
+ prospective_child_depth = parent_depth + 1
146
+ if prospective_child_depth > max_depth:
147
+ agent_audit_logger.append(EventRecord(
148
+ event_type="agent_spawn_refused_recursion_cap",
149
+ session_id=getattr(parent_session, "session_id", None),
150
+ tool_name="agent",
151
+ success=False,
152
+ error_code=_AGENT_SPAWN_REFUSED_ERROR_CODE,
153
+ details={
154
+ "parent_depth": parent_depth,
155
+ "prospective_child_depth": prospective_child_depth,
156
+ "max_depth": max_depth,
157
+ "description": (request.description or "")[:200],
158
+ "tool_use_id": tool_call.tool_use_id,
159
+ },
160
+ ))
161
+ logger.warning(
162
+ "agent tool refused: parent_depth=%d would exceed max_depth=%d "
163
+ "(description=%r). Set CC_MAX_AGENT_RECURSION_DEPTH to raise the cap.",
164
+ parent_depth, max_depth, (request.description or "")[:120],
165
+ )
166
+ return ToolResult(
167
+ tool_use_id=tool_call.tool_use_id,
168
+ tool_name=tool_call.tool_name,
169
+ success=False,
170
+ content=(
171
+ f"agent spawn refused: recursion depth {prospective_child_depth} "
172
+ f"would exceed cap {max_depth}. Complete this task with the "
173
+ f"context you already have, or finalize and return."
174
+ ),
175
+ error_code=_AGENT_SPAWN_REFUSED_ERROR_CODE,
176
+ data={
177
+ "parent_depth": parent_depth,
178
+ "max_depth": max_depth,
179
+ "refused": True,
180
+ },
181
+ )
182
+ # Approaching-cap warning (one less than max). Distinct event type
183
+ # so dashboards can flag chains that get close without firing on
184
+ # every spawn.
185
+ if prospective_child_depth == max_depth:
186
+ agent_audit_logger.append(EventRecord(
187
+ event_type="agent_collaboration_depth_warning",
188
+ session_id=getattr(parent_session, "session_id", None),
189
+ tool_name="agent",
190
+ success=None,
191
+ details={
192
+ "parent_depth": parent_depth,
193
+ "child_depth": prospective_child_depth,
194
+ "max_depth": max_depth,
195
+ "description": (request.description or "")[:200],
196
+ "tool_use_id": tool_call.tool_use_id,
197
+ },
198
+ ))
199
+
200
+ definition = self.resolve_agent_definition(request)
201
+ backend_name = self.resolve_backend_name(request, ctx)
202
+ backend = self.resolve_backend(backend_name)
203
+ runtime_root = ctx.config.runtime_root_path(ctx.cwd)
204
+ runtime_registry = self.runtime_registry or get_in_process_runtime_registry(runtime_root)
205
+ task_manager = TaskManager(runtime_root / "tasks")
206
+ task = task_manager.create_task(
207
+ AgentTask.create(
208
+ agent_type=definition.agent_id,
209
+ backend=backend_name,
210
+ prompt_language=ctx.prompt_language,
211
+ title=request.description,
212
+ input_payload={
213
+ "description": request.description,
214
+ "prompt": request.prompt,
215
+ },
216
+ )
217
+ )
218
+ child_session = self.build_child_session(
219
+ parent_session=ctx.metadata["session"],
220
+ task=task,
221
+ agent_definition=definition,
222
+ cwd=request.cwd or ctx.cwd,
223
+ )
224
+ # Stamp the child's depth so its own ``agent`` tool calls see a
225
+ # bumped value and the cap composes across levels.
226
+ child_session.metadata.state[_RECURSION_DEPTH_STATE_KEY] = prospective_child_depth
227
+ from ..runtime import build_default_query_engine
228
+
229
+ runtime = AgentRuntime(
230
+ definition=definition,
231
+ task=task,
232
+ query_engine=build_default_query_engine(
233
+ cwd=child_session.cwd,
234
+ config=child_session.config,
235
+ llm_client_provider=self.llm_client_provider,
236
+ session=child_session,
237
+ ),
238
+ task_manager=task_manager,
239
+ )
240
+ controller = await backend.create_controller(
241
+ runtime=runtime,
242
+ run_in_background=request.run_in_background,
243
+ runtime_root=runtime_root,
244
+ )
245
+ runtime_registry.register(controller)
246
+ if request.run_in_background:
247
+ if backend_name == "in_process":
248
+ task_manager.update_task_status(task.task_id, AgentTaskStatus.RUNNING)
249
+ background_task = asyncio.create_task(controller.start(request.prompt))
250
+ runtime_registry.register_background_task(task.runtime_id, background_task)
251
+ launch_result = {
252
+ "task_id": task.task_id,
253
+ "runtime_id": task.runtime_id,
254
+ "status": task.status.value,
255
+ "background": True,
256
+ "backend": backend_name,
257
+ }
258
+ else:
259
+ launch_result = await controller.start(request.prompt)
260
+ return ToolResult(
261
+ tool_use_id=tool_call.tool_use_id,
262
+ tool_name=tool_call.tool_name,
263
+ success=True,
264
+ content="Agent launched in background mode.",
265
+ data=launch_result,
266
+ )
267
+ result = await controller.start(request.prompt)
268
+ return ToolResult(
269
+ tool_use_id=tool_call.tool_use_id,
270
+ tool_name=tool_call.tool_name,
271
+ success=True,
272
+ content=result["final_text"],
273
+ data=result,
274
+ )
275
+
276
+ def resolve_backend_name(self, request: AgentToolRequest, ctx: ToolUseContext) -> str:
277
+ return str(request.backend or request.mode or ctx.config.default_backend or "in_process")
278
+
279
+ def resolve_backend(self, backend_name: str) -> RuntimeBackend:
280
+ if backend_name == "in_process":
281
+ return InProcessBackend()
282
+ if backend_name == "local_subprocess":
283
+ return LocalSubprocessBackend()
284
+ raise ValueError(f"Unsupported backend: {backend_name}")
285
+
286
+ def resolve_agent_definition(self, request: AgentToolRequest) -> AgentDefinition:
287
+ agent_id = request.subagent_type or "worker"
288
+ return AgentDefinition(
289
+ agent_id=agent_id,
290
+ name=request.name or agent_id,
291
+ description=request.description,
292
+ prompt_key="agents.worker",
293
+ )
294
+
295
+ def build_child_session(
296
+ self,
297
+ *,
298
+ parent_session: QuerySession,
299
+ task: AgentTask,
300
+ agent_definition: AgentDefinition,
301
+ cwd: str,
302
+ ) -> QuerySession:
303
+ child_config = CCConfig.from_mapping(
304
+ {
305
+ **parent_session.config.to_dict(),
306
+ "agent_mode": "",
307
+ }
308
+ )
309
+ child_factory = SessionFactory(child_config)
310
+ child_session = child_factory.create(
311
+ cwd=cwd,
312
+ model_name=parent_session.model_name,
313
+ agent_id=agent_definition.agent_id,
314
+ parent_task_id=task.task_id,
315
+ )
316
+ child_session.prompt_language = parent_session.prompt_language
317
+ child_session.permission_mode = parent_session.permission_mode
318
+ child_session.agent_mode = ""
319
+ child_session.metadata.state["spawned_by_agent_mode"] = parent_session.agent_mode
320
+ return child_session
@@ -0,0 +1,11 @@
1
+ from .base import BackendHandle, RuntimeBackend, RuntimeController
2
+ from .in_process import InProcessBackend
3
+ from .local_subprocess import LocalSubprocessBackend
4
+
5
+ __all__ = [
6
+ "BackendHandle",
7
+ "InProcessBackend",
8
+ "LocalSubprocessBackend",
9
+ "RuntimeBackend",
10
+ "RuntimeController",
11
+ ]
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ from typing import Any, Protocol, TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from ..runtime import AgentMessage, AgentRuntime
9
+ from ..task_model import AgentTask
10
+
11
+
12
+ @dataclass(slots=True)
13
+ class BackendHandle:
14
+ runtime_id: str
15
+ backend_name: str
16
+ process_id: int | None = None
17
+ endpoint: str | None = None
18
+ output_path: str | None = None
19
+
20
+
21
+ class RuntimeController(Protocol):
22
+ task: "AgentTask"
23
+ handle: BackendHandle
24
+
25
+ async def start(self, prompt: str) -> dict[str, Any]:
26
+ ...
27
+
28
+ async def send_message(
29
+ self,
30
+ message: "AgentMessage",
31
+ *,
32
+ timeout_seconds: float | None = None,
33
+ ) -> dict[str, Any]:
34
+ ...
35
+
36
+ async def stop(self, reason: str) -> None:
37
+ ...
38
+
39
+ async def collect_status(self) -> dict[str, Any]:
40
+ ...
41
+
42
+ async def apply_shared_state(
43
+ self,
44
+ *,
45
+ shared_context: dict[str, Any],
46
+ shared_allowed_paths: list[str],
47
+ timeout_seconds: float | None = None,
48
+ ) -> dict[str, Any]:
49
+ ...
50
+
51
+
52
+ class RuntimeBackend(Protocol):
53
+ name: str
54
+
55
+ async def create_controller(
56
+ self,
57
+ *,
58
+ runtime: "AgentRuntime",
59
+ run_in_background: bool,
60
+ runtime_root: Path,
61
+ ) -> RuntimeController:
62
+ ...