feat(workspace): per-topic project roots as CLI working directory#178
Open
minakovd wants to merge 1 commit into
Open
feat(workspace): per-topic project roots as CLI working directory#178minakovd wants to merge 1 commit into
minakovd wants to merge 1 commit into
Conversation
Add a hot-reloadable `project_roots` config mapping a Telegram topic to a
project directory. When a message arrives in a mapped topic, the CLI runs
with that directory as cwd instead of the shared workspace.
- config: new `project_roots: dict[str, str]` on AgentConfig, listed in
_HOT_RELOADABLE so edits apply without restart.
- workspace/project_roots.py: pure resolver with key priority
topic name > "<chat_id>:<topic_id>" > "<topic_id>"; expands ~, skips
(with a warning) entries pointing at non-existent directories.
- cli/service.py: optional per-request working-dir resolver consulted in
_make_cli; skipped entirely in Docker mode because docker_wrap maps cwd
into the container via relative_to() and would fail on external paths.
- orchestrator: wires the resolver; named sessions ("ns:" labels) keep
the default workspace for resume consistency.
- flows: when the override applies, append a short system-prompt note
pointing the agent back at the shared workspace (memory_system/, tools/).
- session/manager.py: public resolve_topic_name() accessor.
Co-Authored-By: Claude Fable 5 <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.
Use case
Forum topics already give each conversation an isolated CLI context, but every topic shares the same
~/.ductor/workspacecwd. With Claude Code in particular that leaves a lot on the table:CLAUDE.md,.claude/agents,.claude/skills, and.mcp.jsonall resolve from the CLI's working directory. If a topic is a project ("Paper X", "MyProject"), starting the CLI in that project's directory makes the agent pick up the project's own instructions, subagents, skills, and MCP servers with zero extra configuration.This PR adds an opt-in
project_rootsconfig map from topic to directory:Keys are matched by topic name first, then by
<chat_id>:<topic_id>, then by bare<topic_id>.Design highlights
CLIService._make_cli. The working-dir override is applied at the single choke point where every CLI instance is built, so--resumestays consistent across all paths that spawn a CLI for the same session — normal messages, memory flush, heartbeat, and injection. Resolving anywhere higher up would risk resuming a session from a different cwd than it was created in.docker_wrapmaps cwd into the container viarelative_to()and would fail on paths outside the workspace.ns:-labelled sessions keep the default workspace so their resume behavior is unchanged.project_rootsis listed in_HOT_RELOADABLE; config edits apply without a restart. Entries pointing at non-existent directories are skipped with a warning.Nonefor every request — behavior is byte-identical to current main.memory_system/,tools/) so bot-level memory conventions keep working.Migration note
Existing sessions in a topic that becomes mapped were created with the old cwd;
--resumekeeps that cwd until the session is reset. Run/resetonce in each newly mapped topic to start a session in the project root.Test coverage
tests/workspace/test_project_roots.py— resolver: key priority,~expansion, missing-directory skip.tests/cli/test_service.py—_make_clioverride plumbing, Docker guard, no-resolver default.tests/test_config_reload.py— hot-reload ofproject_roots.Full suite: 3999 passed; the 21 failures on this machine are identical on current
main(pre-existing, environment-specifictests/workspace/test_init.pyet al.), none introduced by this change.🤖 Generated with Claude Code