feat: concurrent multi-tool daemon support (#12)#22
Open
don-petry wants to merge 4 commits intoJoaolfelicio:mainfrom
Open
feat: concurrent multi-tool daemon support (#12)#22don-petry wants to merge 4 commits intoJoaolfelicio:mainfrom
don-petry wants to merge 4 commits intoJoaolfelicio:mainfrom
Conversation
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>
There was a problem hiding this comment.
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_REGISTRYand_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 sharedasyncio.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>
7 tasks
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>
There was a problem hiding this comment.
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
--toolsCLI option to run multiple providers concurrently in a single daemon (e.g.--tools gemini-cli,claude,copilot)asyncio.create_task, feeding interactions into a shared boundedasyncio.Queue(maxsize=1000)[tool_name]--tool(single) still works for backward compatibilityCloses #12
Testing evidence (live, Python 3.12 + mcp, claude + copilot CLIs)
--tools claude,copilotaccepted by CLI--tools invalid_toolrejected with error--tools claude,claude,copilotdeduplicates--tools ,,,(empty) rejected--tool claudebackward compat worksIssues found and fixed during testing
test_daemons.py:TOOL_REGISTRYholds import-time class refs → fixed to patch_create_providers_watch_provider:KeyboardInterruptnot caught (not subclass of Exception) → added to except clause🤖 Generated with Claude Code