gemcode 0.3.120__tar.gz → 0.4.0__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.
- {gemcode-0.3.120/src/gemcode.egg-info → gemcode-0.4.0}/PKG-INFO +40 -31
- {gemcode-0.3.120 → gemcode-0.4.0}/README.md +38 -29
- {gemcode-0.3.120 → gemcode-0.4.0}/pyproject.toml +2 -2
- gemcode-0.4.0/src/gemcode/a2a_bridge.py +258 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/agent.py +6 -1
- gemcode-0.4.0/src/gemcode/agent_intelligence.py +259 -0
- gemcode-0.4.0/src/gemcode/agent_mesh.py +536 -0
- gemcode-0.4.0/src/gemcode/agent_triggers.py +332 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/checkpoints.py +18 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/cli.py +38 -2
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/config.py +3 -0
- gemcode-0.4.0/src/gemcode/delegation_learning.py +245 -0
- gemcode-0.4.0/src/gemcode/event_bus.py +201 -0
- gemcode-0.4.0/src/gemcode/fleet_reports.py +350 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/invoke.py +43 -220
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/kaira_client.py +4 -2
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/kaira_daemon.py +70 -7
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/kaira_ipc.py +67 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/repl_slash.py +94 -38
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/__init__.py +52 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/automations_tools.py +3 -3
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/org_tools.py +123 -106
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/subtask.py +29 -10
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tui/scrollback.py +47 -4
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tui/welcome_banner.py +1 -1
- {gemcode-0.3.120 → gemcode-0.4.0/src/gemcode.egg-info}/PKG-INFO +40 -31
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode.egg-info/SOURCES.txt +11 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode.egg-info/requires.txt +1 -1
- gemcode-0.4.0/tests/test_agent_mesh.py +96 -0
- gemcode-0.4.0/tests/test_event_bus.py +151 -0
- gemcode-0.4.0/tests/test_fleet_reports.py +100 -0
- gemcode-0.4.0/tests/test_kaira_ipc_paths.py +39 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/LICENSE +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/MANIFEST.in +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/setup.cfg +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/__main__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/audit.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/autocompact.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/automations.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/autotune.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/callbacks.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/capability_routing.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/compaction.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/computer_use/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/computer_use/browser_computer.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/context_budget.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/context_warning.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/credentials.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/curated_memory.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/dynamic_policy.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/evals/harness.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/hitl_session.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/hooks.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/ide_protocol.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/ide_stdio.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/intent_classifier.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/interactions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/kaira_job_store.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/learning.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/limits.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/live_audio_engine.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/logging_config.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/mcp_loader.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/memory/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/memory/embedding_memory_service.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/memory/file_memory_service.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/modality_tools.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/model_errors.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/model_routing.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/multimodal_input.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/openapi_loader.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/org.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/output_styles.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/paths.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/permissions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/plugins/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/plugins/terminal_hooks_plugin.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/plugins/tool_recovery_plugin.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/policy_profile.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/pricing.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/prompt_suggestions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/config.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/deps.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/engine.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/stop_hooks.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/token_budget.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query/transitions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/query_sanitizer.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/refine.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/repl_commands.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/review_agent.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/rules.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/session_runtime.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/session_store.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/session_summariser.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/skills.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/slash_commands.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/thinking.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tool_prompt_manifest.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tool_registry.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tool_result_store.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/bash.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/browser.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/compress_memory.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/curated_memory.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/edit.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/filesystem.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/notebook.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/notes.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/repo_map.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/search.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/shell.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/shell_gate.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/skills.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/tasks.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/think.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/todo.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/user_choice.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/veomem_tools.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/web.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools/web_search.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tools_inspector.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/trust.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tui/input_handler.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tui/spinner.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/tui/welcome_rich.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/veomem_bridge.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/version.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/vertex.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/wal.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/web/__init__.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/web/sse_adapter.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/web/terminal_repl.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/web/web_sse_compat.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode/workspace_hints.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode.egg-info/dependency_links.txt +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode.egg-info/entry_points.txt +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/src/gemcode.egg-info/top_level.txt +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_add_dir.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_agent_instruction.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_autocompact.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_automations.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_capability_routing.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_checkpoint_diff_command.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_cli_init.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_compress_memory_tool.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_computer_use_permissions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_context_budget.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_context_warning.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_credentials.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_eval_harness_layout.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_ide_stdio_attachments.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_interactive_permission_ask.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_kaira_scheduler.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_modality_tools.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_model_error_retry.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_model_errors.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_model_routing.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_multimodal_input.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_output_styles_and_rules.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_paths.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_permissions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_prompt_suggestions.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_repl_commands.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_repl_slash.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_session_runtime_cache.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_skills.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_slash_commands.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_slash_completion_registry.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_thinking_config.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_token_budget.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_tool_context_circulation.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_tools.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_tools_inspector.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_web_sse_adapter.py +0 -0
- {gemcode-0.3.120 → gemcode-0.4.0}/tests/test_workspace_hints.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemcode
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Local-first coding agent on Google Gemini + ADK
|
|
5
5
|
Author: GemCode Contributors
|
|
6
6
|
License: Apache License
|
|
@@ -175,7 +175,7 @@ Classifier: Topic :: Terminals
|
|
|
175
175
|
Requires-Python: >=3.11
|
|
176
176
|
Description-Content-Type: text/markdown
|
|
177
177
|
License-File: LICENSE
|
|
178
|
-
Requires-Dist: google-adk>=1.0.0
|
|
178
|
+
Requires-Dist: google-adk[a2a]>=1.0.0
|
|
179
179
|
Requires-Dist: google-genai>=1.0.0
|
|
180
180
|
Requires-Dist: python-dotenv>=1.0.0
|
|
181
181
|
Requires-Dist: rich>=13.0.0
|
|
@@ -210,10 +210,12 @@ GemCode is designed for repository-native work rather than copy-paste chat workf
|
|
|
210
210
|
|---|---|
|
|
211
211
|
| One-shot CLI | Single prompt/response runs |
|
|
212
212
|
| REPL | Stateful terminal interaction |
|
|
213
|
-
| TUI |
|
|
213
|
+
| TUI | GemCode terminal UI (scrollback-style; `tui/scrollback.py`) |
|
|
214
214
|
| IDE stdio | Editor integration over JSONL stdin/stdout |
|
|
215
|
-
|
|
|
216
|
-
|
|
|
215
|
+
| Agent Mesh | In-process multi-agent orchestration (automatic) |
|
|
216
|
+
| Kaira daemon | Optional always-on background scheduler |
|
|
217
|
+
| A2A server | Cross-machine agent communication via Google A2A protocol |
|
|
218
|
+
| Live audio (experimental) | Microphone-driven Gemini Live sessions |
|
|
217
219
|
|
|
218
220
|
## Recommended reading order
|
|
219
221
|
|
|
@@ -360,32 +362,25 @@ gemcode -C . --attach ./report.pdf "Summarize this"
|
|
|
360
362
|
gemcode kaira -C .
|
|
361
363
|
```
|
|
362
364
|
|
|
363
|
-
### Orchestration (
|
|
365
|
+
### Orchestration (Agent Mesh + Multi-Agent)
|
|
364
366
|
|
|
365
|
-
|
|
366
|
-
- `../docs/orchestration.md`
|
|
367
|
-
|
|
368
|
-
In one terminal:
|
|
367
|
+
GemCode includes a built-in multi-agent orchestration system that works automatically — no separate daemon required.
|
|
369
368
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
```bash
|
|
377
|
-
gemcode -C .
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
Then in the REPL/TUI:
|
|
369
|
+
**Key features:**
|
|
370
|
+
- **Agent Mesh** — in-process concurrent agent execution with full tool access
|
|
371
|
+
- **Event Bus** — agents communicate via pub/sub (no Unix sockets needed)
|
|
372
|
+
- **Self-Triggering Agents** — agents auto-activate on events (e.g., verifier reviews completed work)
|
|
373
|
+
- **Delegation Learning** — remembers which agents succeed at which tasks
|
|
374
|
+
- **A2A Bridge** — expose/consume agents across machines via Google's A2A protocol
|
|
381
375
|
|
|
376
|
+
Quick example in the REPL:
|
|
382
377
|
```text
|
|
383
|
-
|
|
384
|
-
/org hire verifier "QA / test planner" subagent gemcode "Find risks, propose tests, review plans."
|
|
385
|
-
/org assign verifier "Review the plan and propose tests"
|
|
386
|
-
/kaira jobs
|
|
387
|
-
/kaira follow <job_id_prefix>
|
|
378
|
+
> Analyze the auth module. Delegate security review to the verifier.
|
|
388
379
|
```
|
|
380
|
+
The agent calls `org_delegate("verifier", ...)` → mesh runs a full-power verifier agent → result flows back automatically.
|
|
381
|
+
|
|
382
|
+
Docs:
|
|
383
|
+
- [`../docs/orchestration.md`](../docs/orchestration.md)
|
|
389
384
|
|
|
390
385
|
### Start the IDE bridge
|
|
391
386
|
```bash
|
|
@@ -418,11 +413,21 @@ Status note:
|
|
|
418
413
|
| `/rules` | Inspect active rules |
|
|
419
414
|
| `/diff` | Show current diff/checkpoint diff |
|
|
420
415
|
| `/rewind` | Restore checkpoints |
|
|
421
|
-
| `/review` | Run a review
|
|
416
|
+
| `/review` | Run a parallel code review pipeline |
|
|
422
417
|
| `/eval` | Run evaluation gates |
|
|
423
418
|
| `/kaira` | Show scheduler usage help |
|
|
424
419
|
| `/super` | Super mode: auto-approve tools, no GemCode HITL · `/super off` |
|
|
425
420
|
|
|
421
|
+
## Orchestration commands
|
|
422
|
+
|
|
423
|
+
| Command | Purpose |
|
|
424
|
+
|---|---|
|
|
425
|
+
| `/agent list` | Show all org members |
|
|
426
|
+
| `/agent tree` | Show org hierarchy |
|
|
427
|
+
| `/agent create` | Create a new agent member |
|
|
428
|
+
| `/agent assign <member> <task>` | Delegate work to a member |
|
|
429
|
+
| `/agent improve <member> <lessons>` | Improve a member's skill |
|
|
430
|
+
|
|
426
431
|
Detailed behavior:
|
|
427
432
|
- [`../docs/cli-and-repl.md`](../docs/cli-and-repl.md)
|
|
428
433
|
|
|
@@ -430,11 +435,15 @@ Detailed behavior:
|
|
|
430
435
|
|
|
431
436
|
| Capability | What it adds |
|
|
432
437
|
|---|---|
|
|
433
|
-
|
|
|
434
|
-
|
|
|
435
|
-
|
|
|
438
|
+
| Agent Mesh | In-process multi-agent orchestration (automatic, no daemon needed) |
|
|
439
|
+
| A2A Bridge | Cross-machine agent communication via Google A2A protocol |
|
|
440
|
+
| Self-Triggers | Agents auto-activate on events (verification, failure recovery) |
|
|
441
|
+
| Delegation Learning | Remembers successful patterns, suggests optimal routing |
|
|
442
|
+
| Deep research | Research-focused tool routing and optional dedicated model path |
|
|
443
|
+
| Embeddings | Semantic search and optional embedding-backed memory |
|
|
444
|
+
| Memory | Retrieval-oriented persistent memory |
|
|
436
445
|
| Browser/computer use | Playwright-backed browser automation and inspection |
|
|
437
|
-
| Live audio | Gemini Live microphone sessions |
|
|
446
|
+
| Live audio | Gemini Live microphone sessions (experimental) |
|
|
438
447
|
|
|
439
448
|
Detailed behavior:
|
|
440
449
|
- [`../docs/capabilities.md`](../docs/capabilities.md)
|
|
@@ -18,10 +18,12 @@ GemCode is designed for repository-native work rather than copy-paste chat workf
|
|
|
18
18
|
|---|---|
|
|
19
19
|
| One-shot CLI | Single prompt/response runs |
|
|
20
20
|
| REPL | Stateful terminal interaction |
|
|
21
|
-
| TUI |
|
|
21
|
+
| TUI | GemCode terminal UI (scrollback-style; `tui/scrollback.py`) |
|
|
22
22
|
| IDE stdio | Editor integration over JSONL stdin/stdout |
|
|
23
|
-
|
|
|
24
|
-
|
|
|
23
|
+
| Agent Mesh | In-process multi-agent orchestration (automatic) |
|
|
24
|
+
| Kaira daemon | Optional always-on background scheduler |
|
|
25
|
+
| A2A server | Cross-machine agent communication via Google A2A protocol |
|
|
26
|
+
| Live audio (experimental) | Microphone-driven Gemini Live sessions |
|
|
25
27
|
|
|
26
28
|
## Recommended reading order
|
|
27
29
|
|
|
@@ -168,32 +170,25 @@ gemcode -C . --attach ./report.pdf "Summarize this"
|
|
|
168
170
|
gemcode kaira -C .
|
|
169
171
|
```
|
|
170
172
|
|
|
171
|
-
### Orchestration (
|
|
173
|
+
### Orchestration (Agent Mesh + Multi-Agent)
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
- `../docs/orchestration.md`
|
|
175
|
-
|
|
176
|
-
In one terminal:
|
|
175
|
+
GemCode includes a built-in multi-agent orchestration system that works automatically — no separate daemon required.
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
gemcode -C .
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Then in the REPL/TUI:
|
|
177
|
+
**Key features:**
|
|
178
|
+
- **Agent Mesh** — in-process concurrent agent execution with full tool access
|
|
179
|
+
- **Event Bus** — agents communicate via pub/sub (no Unix sockets needed)
|
|
180
|
+
- **Self-Triggering Agents** — agents auto-activate on events (e.g., verifier reviews completed work)
|
|
181
|
+
- **Delegation Learning** — remembers which agents succeed at which tasks
|
|
182
|
+
- **A2A Bridge** — expose/consume agents across machines via Google's A2A protocol
|
|
189
183
|
|
|
184
|
+
Quick example in the REPL:
|
|
190
185
|
```text
|
|
191
|
-
|
|
192
|
-
/org hire verifier "QA / test planner" subagent gemcode "Find risks, propose tests, review plans."
|
|
193
|
-
/org assign verifier "Review the plan and propose tests"
|
|
194
|
-
/kaira jobs
|
|
195
|
-
/kaira follow <job_id_prefix>
|
|
186
|
+
> Analyze the auth module. Delegate security review to the verifier.
|
|
196
187
|
```
|
|
188
|
+
The agent calls `org_delegate("verifier", ...)` → mesh runs a full-power verifier agent → result flows back automatically.
|
|
189
|
+
|
|
190
|
+
Docs:
|
|
191
|
+
- [`../docs/orchestration.md`](../docs/orchestration.md)
|
|
197
192
|
|
|
198
193
|
### Start the IDE bridge
|
|
199
194
|
```bash
|
|
@@ -226,11 +221,21 @@ Status note:
|
|
|
226
221
|
| `/rules` | Inspect active rules |
|
|
227
222
|
| `/diff` | Show current diff/checkpoint diff |
|
|
228
223
|
| `/rewind` | Restore checkpoints |
|
|
229
|
-
| `/review` | Run a review
|
|
224
|
+
| `/review` | Run a parallel code review pipeline |
|
|
230
225
|
| `/eval` | Run evaluation gates |
|
|
231
226
|
| `/kaira` | Show scheduler usage help |
|
|
232
227
|
| `/super` | Super mode: auto-approve tools, no GemCode HITL · `/super off` |
|
|
233
228
|
|
|
229
|
+
## Orchestration commands
|
|
230
|
+
|
|
231
|
+
| Command | Purpose |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `/agent list` | Show all org members |
|
|
234
|
+
| `/agent tree` | Show org hierarchy |
|
|
235
|
+
| `/agent create` | Create a new agent member |
|
|
236
|
+
| `/agent assign <member> <task>` | Delegate work to a member |
|
|
237
|
+
| `/agent improve <member> <lessons>` | Improve a member's skill |
|
|
238
|
+
|
|
234
239
|
Detailed behavior:
|
|
235
240
|
- [`../docs/cli-and-repl.md`](../docs/cli-and-repl.md)
|
|
236
241
|
|
|
@@ -238,11 +243,15 @@ Detailed behavior:
|
|
|
238
243
|
|
|
239
244
|
| Capability | What it adds |
|
|
240
245
|
|---|---|
|
|
241
|
-
|
|
|
242
|
-
|
|
|
243
|
-
|
|
|
246
|
+
| Agent Mesh | In-process multi-agent orchestration (automatic, no daemon needed) |
|
|
247
|
+
| A2A Bridge | Cross-machine agent communication via Google A2A protocol |
|
|
248
|
+
| Self-Triggers | Agents auto-activate on events (verification, failure recovery) |
|
|
249
|
+
| Delegation Learning | Remembers successful patterns, suggests optimal routing |
|
|
250
|
+
| Deep research | Research-focused tool routing and optional dedicated model path |
|
|
251
|
+
| Embeddings | Semantic search and optional embedding-backed memory |
|
|
252
|
+
| Memory | Retrieval-oriented persistent memory |
|
|
244
253
|
| Browser/computer use | Playwright-backed browser automation and inspection |
|
|
245
|
-
| Live audio | Gemini Live microphone sessions |
|
|
254
|
+
| Live audio | Gemini Live microphone sessions (experimental) |
|
|
246
255
|
|
|
247
256
|
Detailed behavior:
|
|
248
257
|
- [`../docs/capabilities.md`](../docs/capabilities.md)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gemcode"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
description = "Local-first coding agent on Google Gemini + ADK"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -27,7 +27,7 @@ classifiers = [
|
|
|
27
27
|
"Topic :: Terminals",
|
|
28
28
|
]
|
|
29
29
|
dependencies = [
|
|
30
|
-
"google-adk>=1.0.0",
|
|
30
|
+
"google-adk[a2a]>=1.0.0",
|
|
31
31
|
"google-genai>=1.0.0",
|
|
32
32
|
"python-dotenv>=1.0.0",
|
|
33
33
|
"rich>=13.0.0",
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A2A Bridge — Expose and consume GemCode agents via Google's Agent2Agent protocol.
|
|
3
|
+
|
|
4
|
+
This module bridges the org system with ADK's native A2A support:
|
|
5
|
+
- `expose_agent()` — Turn an org member into a network-accessible A2A server
|
|
6
|
+
- `connect_remote_agent()` — Consume a remote A2A agent as an org member
|
|
7
|
+
- Auto-generate agent cards from org.json metadata
|
|
8
|
+
|
|
9
|
+
Requires: google-adk[a2a] (pip install google-adk[a2a])
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from gemcode.config import GemCodeConfig
|
|
19
|
+
from gemcode.org import OrgMember, find_member, resolve_fleet_root
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def a2a_available() -> bool:
|
|
23
|
+
"""Check if A2A support is installed."""
|
|
24
|
+
try:
|
|
25
|
+
from google.adk.a2a.utils.agent_to_a2a import to_a2a # noqa: F401
|
|
26
|
+
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent # noqa: F401
|
|
27
|
+
return True
|
|
28
|
+
except ImportError:
|
|
29
|
+
# Try auto-installing the a2a-sdk dependency
|
|
30
|
+
try:
|
|
31
|
+
import subprocess
|
|
32
|
+
import sys
|
|
33
|
+
subprocess.check_call(
|
|
34
|
+
[sys.executable, "-m", "pip", "install", "a2a-sdk>=0.3.4,<0.4.0", "--quiet"],
|
|
35
|
+
stdout=subprocess.DEVNULL,
|
|
36
|
+
stderr=subprocess.DEVNULL,
|
|
37
|
+
)
|
|
38
|
+
# Retry import after install
|
|
39
|
+
from google.adk.a2a.utils.agent_to_a2a import to_a2a # noqa: F401
|
|
40
|
+
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent # noqa: F401
|
|
41
|
+
return True
|
|
42
|
+
except Exception:
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_agent_card_dict(member: OrgMember, *, base_url: str = "") -> dict[str, Any]:
|
|
47
|
+
"""
|
|
48
|
+
Build an A2A agent card dictionary from an org member.
|
|
49
|
+
|
|
50
|
+
This is the metadata that describes what an agent can do,
|
|
51
|
+
following the A2A protocol specification.
|
|
52
|
+
"""
|
|
53
|
+
skills = []
|
|
54
|
+
|
|
55
|
+
# Primary skill based on the member's role
|
|
56
|
+
skills.append({
|
|
57
|
+
"id": f"{member.name}_primary",
|
|
58
|
+
"name": member.title,
|
|
59
|
+
"description": member.description or f"Agent: {member.name} ({member.title})",
|
|
60
|
+
"tags": [member.kind, "gemcode"],
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
url = base_url or f"http://localhost:0/a2a/{member.name}"
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
"name": member.name,
|
|
67
|
+
"description": member.description or f"{member.name} — {member.title}",
|
|
68
|
+
"version": "1.0.0",
|
|
69
|
+
"url": url,
|
|
70
|
+
"capabilities": {
|
|
71
|
+
"streaming": True,
|
|
72
|
+
"pushNotifications": False,
|
|
73
|
+
},
|
|
74
|
+
"defaultInputModes": ["text/plain"],
|
|
75
|
+
"defaultOutputModes": ["text/plain", "application/json"],
|
|
76
|
+
"skills": skills,
|
|
77
|
+
"supportsAuthenticatedExtendedCard": False,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def expose_member_as_a2a(
|
|
82
|
+
cfg: GemCodeConfig,
|
|
83
|
+
member_name: str,
|
|
84
|
+
*,
|
|
85
|
+
port: int = 0,
|
|
86
|
+
host: str = "localhost",
|
|
87
|
+
) -> Any | None:
|
|
88
|
+
"""
|
|
89
|
+
Expose an org member as an A2A server using ADK's to_a2a().
|
|
90
|
+
|
|
91
|
+
Returns the Starlette app (can be served with uvicorn) or None if A2A unavailable.
|
|
92
|
+
"""
|
|
93
|
+
if not a2a_available():
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
from google.adk.a2a.utils.agent_to_a2a import to_a2a
|
|
97
|
+
|
|
98
|
+
fleet_root = resolve_fleet_root(cfg.project_root)
|
|
99
|
+
m = find_member(fleet_root, member_name)
|
|
100
|
+
if m is None:
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
# Build a real ADK agent for this member
|
|
104
|
+
from gemcode.agent import build_root_agent
|
|
105
|
+
from gemcode.tools import build_function_tools
|
|
106
|
+
|
|
107
|
+
import copy
|
|
108
|
+
agent_cfg = copy.deepcopy(cfg)
|
|
109
|
+
tools = build_function_tools(agent_cfg, include_subtask=False)
|
|
110
|
+
agent = build_root_agent(agent_cfg, _tools=tools)
|
|
111
|
+
|
|
112
|
+
# Generate agent card
|
|
113
|
+
base_url = f"http://{host}:{port}" if port else f"http://{host}"
|
|
114
|
+
card_dict = build_agent_card_dict(m, base_url=base_url)
|
|
115
|
+
|
|
116
|
+
# Create A2A app
|
|
117
|
+
try:
|
|
118
|
+
a2a_app = to_a2a(agent, port=port or 8001, agent_card=card_dict)
|
|
119
|
+
return a2a_app
|
|
120
|
+
except Exception:
|
|
121
|
+
# Fallback: try without custom card
|
|
122
|
+
try:
|
|
123
|
+
a2a_app = to_a2a(agent, port=port or 8001)
|
|
124
|
+
return a2a_app
|
|
125
|
+
except Exception:
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def create_remote_a2a_member(
|
|
130
|
+
*,
|
|
131
|
+
name: str,
|
|
132
|
+
description: str,
|
|
133
|
+
agent_card_url: str,
|
|
134
|
+
use_legacy: bool = False,
|
|
135
|
+
) -> Any | None:
|
|
136
|
+
"""
|
|
137
|
+
Create a RemoteA2aAgent that can be used as a sub-agent.
|
|
138
|
+
|
|
139
|
+
This lets GemCode consume external A2A agents as if they were local org members.
|
|
140
|
+
"""
|
|
141
|
+
if not a2a_available():
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
|
|
146
|
+
|
|
147
|
+
remote_agent = RemoteA2aAgent(
|
|
148
|
+
name=name,
|
|
149
|
+
description=description,
|
|
150
|
+
agent_card=agent_card_url,
|
|
151
|
+
use_legacy=use_legacy,
|
|
152
|
+
)
|
|
153
|
+
return remote_agent
|
|
154
|
+
except Exception:
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def list_exposed_agents(cfg: GemCodeConfig) -> list[dict[str, Any]]:
|
|
159
|
+
"""List all org members that could be exposed via A2A."""
|
|
160
|
+
from gemcode.org import list_members
|
|
161
|
+
|
|
162
|
+
fleet_root = resolve_fleet_root(cfg.project_root)
|
|
163
|
+
members = list_members(fleet_root)
|
|
164
|
+
return [
|
|
165
|
+
{
|
|
166
|
+
"name": m.name,
|
|
167
|
+
"title": m.title,
|
|
168
|
+
"kind": m.kind,
|
|
169
|
+
"description": m.description,
|
|
170
|
+
"a2a_available": a2a_available(),
|
|
171
|
+
"card": build_agent_card_dict(m),
|
|
172
|
+
}
|
|
173
|
+
for m in members
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def make_a2a_tools(cfg: GemCodeConfig) -> list:
|
|
178
|
+
"""Build A2A-related tools for the agent."""
|
|
179
|
+
|
|
180
|
+
def a2a_expose(member: str, port: int = 8001, host: str = "localhost") -> dict:
|
|
181
|
+
"""
|
|
182
|
+
Expose an org member as an A2A server (network-accessible agent).
|
|
183
|
+
|
|
184
|
+
Other GemCode instances or any A2A-compatible agent can then communicate
|
|
185
|
+
with this member over HTTP.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
member: Name or ID of the org member to expose.
|
|
189
|
+
port: Port to serve on (default 8001).
|
|
190
|
+
host: Host to bind to (default localhost).
|
|
191
|
+
"""
|
|
192
|
+
if not a2a_available():
|
|
193
|
+
return {"ok": False, "error": "A2A auto-install failed. Try: pip install a2a-sdk"}
|
|
194
|
+
|
|
195
|
+
app = expose_member_as_a2a(cfg, member, port=port, host=host)
|
|
196
|
+
if app is None:
|
|
197
|
+
return {"ok": False, "error": f"Failed to expose member '{member}'. Check org_list() for available members."}
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
"ok": True,
|
|
201
|
+
"member": member,
|
|
202
|
+
"url": f"http://{host}:{port}",
|
|
203
|
+
"agent_card_url": f"http://{host}:{port}/.well-known/agent-card.json",
|
|
204
|
+
"note": f"Start with: uvicorn ... --host {host} --port {port}",
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
def a2a_connect(name: str, description: str, agent_card_url: str) -> dict:
|
|
208
|
+
"""
|
|
209
|
+
Connect to a remote A2A agent and register it as an org member.
|
|
210
|
+
|
|
211
|
+
This lets you delegate tasks to agents running on other machines or
|
|
212
|
+
in other frameworks (LangGraph, CrewAI, etc.) via the A2A protocol.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
name: Local name for this remote agent.
|
|
216
|
+
description: What this agent does.
|
|
217
|
+
agent_card_url: URL to the agent's card (e.g., http://host:port/.well-known/agent-card.json)
|
|
218
|
+
"""
|
|
219
|
+
if not a2a_available():
|
|
220
|
+
return {"ok": False, "error": "A2A auto-install failed. Try: pip install a2a-sdk"}
|
|
221
|
+
|
|
222
|
+
remote = create_remote_a2a_member(
|
|
223
|
+
name=name,
|
|
224
|
+
description=description,
|
|
225
|
+
agent_card_url=agent_card_url,
|
|
226
|
+
)
|
|
227
|
+
if remote is None:
|
|
228
|
+
return {"ok": False, "error": f"Failed to connect to remote agent at {agent_card_url}"}
|
|
229
|
+
|
|
230
|
+
# Register in org
|
|
231
|
+
from gemcode.org import hire_member
|
|
232
|
+
fleet_root = resolve_fleet_root(cfg.project_root)
|
|
233
|
+
m = hire_member(
|
|
234
|
+
fleet_root,
|
|
235
|
+
name=name,
|
|
236
|
+
title=f"Remote A2A Agent",
|
|
237
|
+
kind="subagent",
|
|
238
|
+
description=f"[A2A] {description} (card: {agent_card_url})",
|
|
239
|
+
reports_to="manager",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
"ok": True,
|
|
244
|
+
"member": m.to_dict() if hasattr(m, "to_dict") else {"name": name},
|
|
245
|
+
"agent_card_url": agent_card_url,
|
|
246
|
+
"note": "Use org_delegate to send tasks to this remote agent.",
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
def a2a_list() -> dict:
|
|
250
|
+
"""List all agents that can be exposed or are connected via A2A."""
|
|
251
|
+
agents = list_exposed_agents(cfg)
|
|
252
|
+
return {"ok": True, "agents": agents, "a2a_installed": a2a_available()}
|
|
253
|
+
|
|
254
|
+
a2a_expose.__name__ = "a2a_expose"
|
|
255
|
+
a2a_connect.__name__ = "a2a_connect"
|
|
256
|
+
a2a_list.__name__ = "a2a_list"
|
|
257
|
+
|
|
258
|
+
return [a2a_expose, a2a_connect, a2a_list]
|
|
@@ -372,7 +372,12 @@ def _build_runtime_facts(cfg: GemCodeConfig) -> str:
|
|
|
372
372
|
"(up to N concurrently). Each job gets `kaira_sleep_ms(ms)` and "
|
|
373
373
|
"`kaira_enqueue_prompt(prompt, priority, session_id)` tools so GemCode can "
|
|
374
374
|
"schedule and trigger follow-up work itself. Useful for: tests/builds, bulk file processing, "
|
|
375
|
-
"periodic automations, and parallelising large independent tasks."
|
|
375
|
+
"periodic automations, and parallelising large independent tasks. "
|
|
376
|
+
"Completed `org.report` / `job.report` / `agent.report` outcomes are also appended to "
|
|
377
|
+
"`.gemcode/fleet_reports.jsonl` and prepended to the next turn (GemCode TUI when `GEMCODE_TUI=1`, and any path using `run_turn`; disable with "
|
|
378
|
+
"`GEMCODE_FLEET_REPORTS_INJECT=0`). Optional hands-off follow-up: "
|
|
379
|
+
"`GEMCODE_FLEET_REPORTS_AUTO_CONTINUE=1` with `GEMCODE_FLEET_REPORTS_AUTO_CONTINUE_MODE=tui|enqueue|both` "
|
|
380
|
+
"(cap via `GEMCODE_FLEET_REPORTS_AUTO_CONTINUE_MAX`, debounce `GEMCODE_FLEET_REPORTS_ENQUEUE_DEBOUNCE_S`)."
|
|
376
381
|
)
|
|
377
382
|
|
|
378
383
|
# ── Git context ───────────────────────────────────────────────────────────
|