gemcode 0.4.7__tar.gz → 0.4.9__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 (183) hide show
  1. {gemcode-0.4.7/src/gemcode.egg-info → gemcode-0.4.9}/PKG-INFO +1 -1
  2. {gemcode-0.4.7 → gemcode-0.4.9}/pyproject.toml +1 -1
  3. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/agent_mesh.py +37 -1
  4. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/fleet_reports.py +11 -0
  5. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/org_tools.py +17 -113
  6. {gemcode-0.4.7 → gemcode-0.4.9/src/gemcode.egg-info}/PKG-INFO +1 -1
  7. {gemcode-0.4.7 → gemcode-0.4.9}/LICENSE +0 -0
  8. {gemcode-0.4.7 → gemcode-0.4.9}/MANIFEST.in +0 -0
  9. {gemcode-0.4.7 → gemcode-0.4.9}/README.md +0 -0
  10. {gemcode-0.4.7 → gemcode-0.4.9}/setup.cfg +0 -0
  11. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/__init__.py +0 -0
  12. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/__main__.py +0 -0
  13. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/a2a_bridge.py +0 -0
  14. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/agent.py +0 -0
  15. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/agent_habits.py +0 -0
  16. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/agent_intelligence.py +0 -0
  17. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/agent_triggers.py +0 -0
  18. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/audit.py +0 -0
  19. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/autocompact.py +0 -0
  20. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/automations.py +0 -0
  21. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/autotune.py +0 -0
  22. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/callbacks.py +0 -0
  23. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/capability_routing.py +0 -0
  24. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/checkpoints.py +0 -0
  25. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/cli.py +0 -0
  26. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/codebase_awareness.py +0 -0
  27. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/compaction.py +0 -0
  28. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/computer_use/__init__.py +0 -0
  29. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/computer_use/browser_computer.py +0 -0
  30. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/config.py +0 -0
  31. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/context_budget.py +0 -0
  32. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/context_warning.py +0 -0
  33. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/credentials.py +0 -0
  34. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/curated_memory.py +0 -0
  35. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/delegation_learning.py +0 -0
  36. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/dynamic_policy.py +0 -0
  37. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/evals/harness.py +0 -0
  38. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/event_bus.py +0 -0
  39. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/hitl_session.py +0 -0
  40. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/hooks.py +0 -0
  41. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/ide_protocol.py +0 -0
  42. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/ide_stdio.py +0 -0
  43. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/intent_classifier.py +0 -0
  44. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/interactions.py +0 -0
  45. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/invoke.py +0 -0
  46. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/kaira_client.py +0 -0
  47. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/kaira_daemon.py +0 -0
  48. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/kaira_ipc.py +0 -0
  49. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/kaira_job_store.py +0 -0
  50. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/learning.py +0 -0
  51. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/limits.py +0 -0
  52. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/live_audio_engine.py +0 -0
  53. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/logging_config.py +0 -0
  54. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/mcp_loader.py +0 -0
  55. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/memory/__init__.py +0 -0
  56. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/memory/embedding_memory_service.py +0 -0
  57. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/memory/file_memory_service.py +0 -0
  58. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/modality_tools.py +0 -0
  59. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/model_errors.py +0 -0
  60. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/model_routing.py +0 -0
  61. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/multimodal_input.py +0 -0
  62. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/openapi_loader.py +0 -0
  63. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/org.py +0 -0
  64. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/output_styles.py +0 -0
  65. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/paths.py +0 -0
  66. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/permissions.py +0 -0
  67. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/plugins/__init__.py +0 -0
  68. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
  69. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
  70. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/policy_profile.py +0 -0
  71. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/pricing.py +0 -0
  72. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/prompt_suggestions.py +0 -0
  73. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/__init__.py +0 -0
  74. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/config.py +0 -0
  75. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/deps.py +0 -0
  76. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/engine.py +0 -0
  77. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/stop_hooks.py +0 -0
  78. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/token_budget.py +0 -0
  79. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query/transitions.py +0 -0
  80. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/query_sanitizer.py +0 -0
  81. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/refine.py +0 -0
  82. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/repl_commands.py +0 -0
  83. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/repl_slash.py +0 -0
  84. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/review_agent.py +0 -0
  85. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/rules.py +0 -0
  86. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/self_healing.py +0 -0
  87. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/session_runtime.py +0 -0
  88. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/session_store.py +0 -0
  89. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/session_summariser.py +0 -0
  90. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/skills.py +0 -0
  91. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/slash_commands.py +0 -0
  92. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/thinking.py +0 -0
  93. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tool_prompt_manifest.py +0 -0
  94. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tool_registry.py +0 -0
  95. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tool_result_store.py +0 -0
  96. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tool_synthesis.py +0 -0
  97. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/__init__.py +0 -0
  98. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/automations_tools.py +0 -0
  99. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/bash.py +0 -0
  100. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/browser.py +0 -0
  101. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/compress_memory.py +0 -0
  102. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/curated_memory.py +0 -0
  103. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/edit.py +0 -0
  104. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/filesystem.py +0 -0
  105. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/notebook.py +0 -0
  106. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/notes.py +0 -0
  107. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/repo_map.py +0 -0
  108. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/search.py +0 -0
  109. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/shell.py +0 -0
  110. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/shell_gate.py +0 -0
  111. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/skills.py +0 -0
  112. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/subtask.py +0 -0
  113. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/tasks.py +0 -0
  114. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/think.py +0 -0
  115. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/todo.py +0 -0
  116. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/user_choice.py +0 -0
  117. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/veomem_tools.py +0 -0
  118. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/web.py +0 -0
  119. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools/web_search.py +0 -0
  120. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tools_inspector.py +0 -0
  121. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/trust.py +0 -0
  122. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tui/input_handler.py +0 -0
  123. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tui/scrollback.py +0 -0
  124. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tui/spinner.py +0 -0
  125. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tui/welcome_banner.py +0 -0
  126. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/tui/welcome_rich.py +0 -0
  127. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/veomem_bridge.py +0 -0
  128. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/version.py +0 -0
  129. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/vertex.py +0 -0
  130. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/wal.py +0 -0
  131. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/web/__init__.py +0 -0
  132. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/web/sse_adapter.py +0 -0
  133. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/web/terminal_repl.py +0 -0
  134. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/web/web_sse_compat.py +0 -0
  135. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode/workspace_hints.py +0 -0
  136. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode.egg-info/SOURCES.txt +0 -0
  137. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode.egg-info/dependency_links.txt +0 -0
  138. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode.egg-info/entry_points.txt +0 -0
  139. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode.egg-info/requires.txt +0 -0
  140. {gemcode-0.4.7 → gemcode-0.4.9}/src/gemcode.egg-info/top_level.txt +0 -0
  141. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_add_dir.py +0 -0
  142. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_agent_habits.py +0 -0
  143. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_agent_instruction.py +0 -0
  144. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_agent_mesh.py +0 -0
  145. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_autocompact.py +0 -0
  146. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_automations.py +0 -0
  147. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_capability_routing.py +0 -0
  148. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_checkpoint_diff_command.py +0 -0
  149. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_cli_init.py +0 -0
  150. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_compress_memory_tool.py +0 -0
  151. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_computer_use_permissions.py +0 -0
  152. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_context_budget.py +0 -0
  153. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_context_warning.py +0 -0
  154. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_credentials.py +0 -0
  155. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_eval_harness_layout.py +0 -0
  156. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_event_bus.py +0 -0
  157. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_fleet_reports.py +0 -0
  158. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_ide_stdio_attachments.py +0 -0
  159. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_interactive_permission_ask.py +0 -0
  160. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_kaira_ipc_paths.py +0 -0
  161. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_kaira_scheduler.py +0 -0
  162. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_modality_tools.py +0 -0
  163. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_model_error_retry.py +0 -0
  164. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_model_errors.py +0 -0
  165. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_model_routing.py +0 -0
  166. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_multimodal_input.py +0 -0
  167. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_output_styles_and_rules.py +0 -0
  168. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_paths.py +0 -0
  169. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_permissions.py +0 -0
  170. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_prompt_suggestions.py +0 -0
  171. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_repl_commands.py +0 -0
  172. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_repl_slash.py +0 -0
  173. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_session_runtime_cache.py +0 -0
  174. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_skills.py +0 -0
  175. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_slash_commands.py +0 -0
  176. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_slash_completion_registry.py +0 -0
  177. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_thinking_config.py +0 -0
  178. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_token_budget.py +0 -0
  179. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_tool_context_circulation.py +0 -0
  180. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_tools.py +0 -0
  181. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_tools_inspector.py +0 -0
  182. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_web_sse_adapter.py +0 -0
  183. {gemcode-0.4.7 → gemcode-0.4.9}/tests/test_workspace_hints.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.4.7
3
+ Version: 0.4.9
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gemcode"
7
- version = "0.4.7"
7
+ version = "0.4.9"
8
8
  description = "Local-first coding agent on Google Gemini + ADK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -634,11 +634,47 @@ class AgentMesh:
634
634
  )
635
635
  return {"ok": True, "job_id": job_id}
636
636
 
637
+ async def agent_dm(to: str, message: str) -> dict:
638
+ """Send a direct message to another agent via the event bus."""
639
+ from_name = job.member_name or 'anonymous'
640
+ await mesh._bus.publish(BusMessage(
641
+ topic='agent.dm', from_addr=from_name, to_addr=to,
642
+ payload={'from': from_name, 'to': to, 'message': message},
643
+ ))
644
+ try:
645
+ from gemcode.fleet_reports import append_fleet_report
646
+ fleet_root = resolve_fleet_root(mesh.cfg.project_root)
647
+ append_fleet_report(fleet_root, topic='agent.dm', payload={
648
+ 'from': from_name, 'to': to, 'message': message[:4000],
649
+ })
650
+ except Exception:
651
+ pass
652
+ return {'ok': True, 'sent_to': to}
653
+
654
+ async def agent_broadcast(message: str) -> dict:
655
+ """Broadcast a message to all agents and the manager."""
656
+ from_name = job.member_name or 'anonymous'
657
+ await mesh._bus.publish(BusMessage(
658
+ topic='agent.broadcast', from_addr=from_name, to_addr='',
659
+ payload={'from': from_name, 'message': message},
660
+ ))
661
+ try:
662
+ from gemcode.fleet_reports import append_fleet_report
663
+ fleet_root = resolve_fleet_root(mesh.cfg.project_root)
664
+ append_fleet_report(fleet_root, topic='agent.broadcast', payload={
665
+ 'from': from_name, 'message': message[:4000],
666
+ })
667
+ except Exception:
668
+ pass
669
+ return {'ok': True, 'broadcast_from': from_name}
670
+
637
671
  mesh_delegate.__name__ = "mesh_delegate"
638
672
  mesh_report.__name__ = "mesh_report"
639
673
  mesh_enqueue.__name__ = "mesh_enqueue"
674
+ agent_dm.__name__ = "agent_dm"
675
+ agent_broadcast.__name__ = "agent_broadcast"
640
676
 
641
- return [mesh_delegate, mesh_report, mesh_enqueue]
677
+ return [mesh_delegate, mesh_report, mesh_enqueue, agent_dm, agent_broadcast]
642
678
 
643
679
  # ── Status / Introspection ──────────────────────────────────────────────
644
680
 
@@ -273,6 +273,17 @@ def _format_record(rec: dict[str, Any]) -> str:
273
273
  elif isinstance(res, str) and res.strip():
274
274
  lines.append(f" result: {res[:8000]}")
275
275
 
276
+ elif topic == "agent.dm":
277
+ from_name = str(payload.get("from") or "")
278
+ to_name = str(payload.get("to") or "")
279
+ msg = str(payload.get("message") or "").strip()
280
+ lines.append(f"[agent.dm] {from_name} → {to_name}: {msg[:4000]}")
281
+
282
+ elif topic == "agent.broadcast":
283
+ from_name = str(payload.get("from") or "")
284
+ msg = str(payload.get("message") or "").strip()
285
+ lines.append(f"[agent.broadcast] {from_name}: {msg[:4000]}")
286
+
276
287
  return "\n".join(lines)
277
288
 
278
289
 
@@ -152,34 +152,7 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
152
152
  pass
153
153
 
154
154
  # ── Also try IPC if daemon is running (bonus, not required) ───────────
155
- if not _bus_enabled():
156
- return
157
-
158
- from gemcode.kaira_ipc import fleet_manager_ipc_path
159
-
160
- sock = str(fleet_manager_ipc_path(fleet_root))
161
- try:
162
- if not Path(sock).exists():
163
- return # No daemon, but that's fine — bus + fleet reports already handled it
164
- except Exception:
165
- return
166
-
167
- try:
168
- from gemcode.kaira_client import KairaIpcClient
169
-
170
- c = await KairaIpcClient.connect(socket_path=str(sock))
171
- try:
172
- for to_addr in chain:
173
- await c.publish(
174
- topic="org.report",
175
- to=str(to_addr or "manager"),
176
- from_addr=from_addr,
177
- payload=payload,
178
- )
179
- finally:
180
- await c.close()
181
- except Exception:
182
- pass
155
+ # Removed: Kaira IPC is no longer needed. The bus + fleet reports handle everything.
183
156
 
184
157
  def org_list() -> dict:
185
158
  """List available org members (workers)."""
@@ -219,7 +192,7 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
219
192
  return {"ok": True, "tree": org_tree(root)}
220
193
 
221
194
  async def org_delegate(member: str, task: str, context: str = "") -> dict:
222
- """Delegate a task to an org member (Kaira worker or subagent)."""
195
+ """Delegate a task to an org member. Uses the mesh — no daemon required."""
223
196
  m = find_member(root, member)
224
197
  if m is None:
225
198
  return {"ok": False, "error": f"unknown member: {member}"}
@@ -229,109 +202,40 @@ def make_org_tools(cfg: GemCodeConfig) -> list:
229
202
  if not task:
230
203
  return {"ok": False, "error": "missing task"}
231
204
 
232
- # ── Strategy 1: In-process Agent Mesh (always available) ──────────────
233
- # The mesh runs real ADK agents in-process with their own sessions.
234
- # This is the PRIMARY path — no daemon required.
205
+ # Primary path: Agent Mesh (always available, runs in background thread)
235
206
  mesh = _get_mesh(cfg)
236
207
  if mesh is not None:
237
208
  try:
238
- # For kaira_workers, run async (non-blocking) by default
239
- # For subagents, run sync (blocking) to return result immediately
240
209
  wait = (m.kind != "kaira_worker")
241
210
  result = await mesh.delegate_to_member(
242
- member=m,
243
- task=task,
244
- context=ctx,
245
- priority=0,
246
- wait=wait,
211
+ member=m, task=task, context=ctx, priority=0, wait=wait,
247
212
  )
248
213
  if result.get("ok"):
249
214
  return {"ok": True, "delegated_to": m.to_dict(), **result}
250
- # If mesh delegation failed, fall through to other strategies
251
215
  except Exception:
252
216
  pass
253
217
 
254
- # ── Strategy 2: Kaira Daemon IPC (if running) ─────────────────────────
255
- if m.kind == "kaira_worker":
256
- try:
257
- from gemcode.kaira_client import KairaIpcClient
258
- fleet_root = resolve_fleet_root(getattr(cfg, "project_root", Path.cwd()))
259
- from gemcode.kaira_ipc import fleet_manager_ipc_path
260
-
261
- sock_s = str(fleet_manager_ipc_path(fleet_root))
262
- if Path(sock_s).exists():
263
- client = await KairaIpcClient.connect(socket_path=sock_s)
264
- try:
265
- session_id = str(getattr(cfg, "_active_session_id", "") or "")
266
- notify_chain = _ancestor_addresses_for(m)
267
- header = (
268
- f"You are {m.name} ({m.title}).\n"
269
- f"Role description: {m.description or '(none)'}\n\n"
270
- "Do the assigned task. Keep outputs concise and actionable.\n"
271
- )
272
- prompt = header + "\nTask:\n" + task
273
- if ctx:
274
- prompt += "\n\nContext:\n" + ctx
275
- meta = {
276
- "org": {
277
- "member": (m.to_dict() if hasattr(m, "to_dict") else {}),
278
- "capabilities": {
279
- "kind": getattr(m, "kind", ""),
280
- "address": getattr(m, "address", "") or getattr(m, "name", ""),
281
- "workspace_rel": getattr(m, "workspace_rel", "") or "",
282
- "reports_to": getattr(m, "reports_to", "") or "",
283
- },
284
- "task": task,
285
- "context": ctx,
286
- "notify_chain": notify_chain,
287
- }
288
- }
289
- res = await client.request(
290
- action="enqueue",
291
- prompt=prompt,
292
- priority=0,
293
- session_id=session_id,
294
- meta=meta,
295
- )
296
- if res.get("ok"):
297
- job_id = str(res.get("job_id") or "")
298
- await _publish_org_report(
299
- m=m, status="delegated", task=task, context=ctx, job_id=job_id,
300
- result={"kind": "kaira_worker", "job_id": job_id},
301
- )
302
- return {"ok": True, "delegated_to": m.to_dict(), "job_id": job_id}
303
- finally:
304
- await client.close()
305
- except Exception:
306
- pass
307
-
308
- # ── Strategy 3: In-process subtask fallback ───────────────────────────
309
- header = (
310
- f"You are {m.name} ({m.title}).\n"
311
- f"Role description: {m.description or '(none)'}\n\n"
312
- "Before acting, load and follow your role skill if available.\n"
313
- f"- If a GemSkill exists: call load_skill(\"{m.skill_name or 'member-' + m.name.lower()}\")\n\n"
314
- "Do the assigned task. Keep outputs concise and actionable.\n"
315
- )
316
- prompt = header + "\nTask:\n" + task
317
- if ctx:
318
- prompt += "\n\nContext:\n" + ctx
319
-
218
+ # Fallback: in-process subtask (blocking but guaranteed to work)
320
219
  try:
321
220
  from gemcode.tools.subtask import make_run_subtask_tool
322
221
 
222
+ header = (
223
+ f"You are {m.name} ({m.title}).\n"
224
+ f"Role: {m.description or '(none)'}\n\n"
225
+ "Do the assigned task. Keep outputs concise and actionable.\n"
226
+ )
227
+ prompt = header + "\nTask:\n" + task
228
+ if ctx:
229
+ prompt += "\n\nContext:\n" + ctx
230
+
323
231
  run_subtask = make_run_subtask_tool(cfg)
324
232
  out = await run_subtask(prompt, "")
325
233
  result = out.get("result") if isinstance(out, dict) else out
326
- await _publish_org_report(
327
- m=m, status="finished", task=task, context=ctx, result=result,
328
- )
234
+ await _publish_org_report(m=m, status="finished", task=task, context=ctx, result=result)
329
235
  return {"ok": True, "delegated_to": m.to_dict(), "result": result}
330
236
  except Exception as e:
331
- await _publish_org_report(
332
- m=m, status="failed", task=task, context=ctx,
333
- error=f"all_strategies_failed: {type(e).__name__}: {e}",
334
- )
237
+ await _publish_org_report(m=m, status="failed", task=task, context=ctx,
238
+ error=f"delegation_failed: {type(e).__name__}: {e}")
335
239
  return {"ok": False, "error": f"delegation_failed: {type(e).__name__}: {e}"}
336
240
 
337
241
  async def org_spawn(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemcode
3
- Version: 0.4.7
3
+ Version: 0.4.9
4
4
  Summary: Local-first coding agent on Google Gemini + ADK
5
5
  Author: GemCode Contributors
6
6
  License: Apache License
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes