Skip to content

feat: concurrent multi-tool daemon support (#12)#22

Open
don-petry wants to merge 4 commits intoJoaolfelicio:mainfrom
don-petry:feat/concurrent-multi-tool
Open

feat: concurrent multi-tool daemon support (#12)#22
don-petry wants to merge 4 commits intoJoaolfelicio:mainfrom
don-petry:feat/concurrent-multi-tool

Conversation

@don-petry
Copy link
Copy Markdown
Collaborator

@don-petry don-petry commented Apr 5, 2026

Why

Users who work across multiple AI tools (Gemini, Claude, Copilot) must currently run separate daemon instances for each one. This is cumbersome to manage and wastes resources — each instance runs its own MCP client connection and evaluator. A single daemon that monitors all tools concurrently with shared infrastructure is simpler to operate and more resource-efficient.

Summary

  • Adds --tools CLI option to run multiple providers concurrently in a single daemon (e.g. --tools gemini-cli,claude,copilot)
  • Each provider watches in its own asyncio.create_task, feeding interactions into a shared bounded asyncio.Queue(maxsize=1000)
  • Shared MCP client and evaluator across all providers
  • Dashboard header shows all active tools; status messages prefixed with [tool_name]
  • --tool (single) still works for backward compatibility

Closes #12

Testing evidence (live, Python 3.12 + mcp, claude + copilot CLIs)

Check Result
Full test suite: 75/75 passed ✅ PASS
Live: create single claude provider ✅ PASS
Live: create multiple providers (claude + copilot) ✅ PASS
Live: unknown tool raises ValueError with available list ✅ PASS
Live: --tools claude,copilot accepted by CLI ✅ PASS
Live: --tools invalid_tool rejected with error ✅ PASS
Live: --tools claude,claude,copilot deduplicates ✅ PASS
Live: --tools ,,, (empty) rejected ✅ PASS
Live: --tool claude backward compat works ✅ PASS
TOOL_REGISTRY has all 3 tools (gemini-cli, copilot, claude) ✅ PASS

Issues found and fixed during testing

  • test_daemons.py: TOOL_REGISTRY holds import-time class refs → fixed to patch _create_providers
  • _watch_provider: KeyboardInterrupt not caught (not subclass of Exception) → added to except clause

🤖 Generated with Claude Code

Adds --tools option to run multiple providers concurrently in a single
daemon process. Each provider watches in its own async task, feeding
interactions into a shared asyncio.Queue for unified processing.

Key changes:
- TOOL_REGISTRY maps tool names to (provider_class, bootstrap_fn) pairs
- _create_providers() bootstraps and instantiates multiple providers
- run_daemon() creates watcher tasks per provider via asyncio.create_task
- Dashboard shows all active tools in header
- --tool still works for single-tool backward compat
- --tools validates tool names and rejects unknowns

Usage: context-scribe --tools gemini-cli,claude,copilot

Closes Joaolfelicio#12

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 5, 2026 03:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for running multiple log providers concurrently within a single context-scribe daemon instance, using a shared evaluator + Memory Bank client and an interaction fan-in queue.

Changes:

  • Introduces a TOOL_REGISTRY and _create_providers() to bootstrap/instantiate providers from tool names.
  • Adds --tools (CSV) CLI option and updates the daemon loop to run one watcher task per provider, feeding a shared asyncio.Queue.
  • Adds new unit tests covering registry population and provider creation behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
context_scribe/main.py Adds registry/provider factory + concurrent watcher tasks + --tools CLI parsing and multi-tool dashboard labeling.
tests/test_multi_tool.py Adds tests for TOOL_REGISTRY and _create_providers() behavior (single/multi/unknown/bootstrap).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- _create_providers() now raises ValueError for unknown tools
- Queue bounded to maxsize=1000 to prevent memory growth
- _watch_provider() catches StopIteration and exceptions gracefully
- watcher_tasks initialized before try to prevent UnboundLocalError
- --tools deduplicates and rejects empty input

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@don-petry
Copy link
Copy Markdown
Collaborator Author

@Joaolfelicio - What do you think about this enhancement idea?

- test_daemons.py: patch _create_providers instead of individual class
  names, since TOOL_REGISTRY captures class refs at import time
- _watch_provider: catch KeyboardInterrupt from mock generators
- Increase test wait timeout for queue-based async pipeline

Found via full test suite run with Python 3.12 + mcp installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 5, 2026 17:32
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Reject empty/whitespace --tools values by checking `tools_csv is not None`
- Fail fast in run_daemon() when tools=[] instead of silent fallback
- Add CLI unit tests for --tools deduplication, invalid, and empty input
- Remove unused provider_class from test_daemons.py parametrize
- Fix misleading docstring in test_multi_tool.py fixture

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Concurrent multi-tool daemon support

2 participants