Description
openab set thread.name "..." --thread <id> always fails with:
✗ unknown thread (use --thread or register via message dispatch)
…for every thread, with or without --thread. The thread.name control command can never succeed in the current code.
Root cause: RuntimeHandler::handle_set resolves the target thread through an in-memory thread_id → platform registry, but that registry is never populated.
resolve() requires a registry hit even when --thread is supplied:
|
async fn resolve(&self, thread_id: Option<&str>) -> Option<(Arc<dyn ChatAdapter>, String)> { |
|
let tid = thread_id?; |
|
let platform = self.registry.read().await.get(tid).cloned()?; |
|
let adapter = self.adapters.get(&platform)?.clone(); |
|
Some((adapter, tid.to_string())) |
|
} |
|
} |
The only function that writes to the registry, register_thread, is dead code — marked #[allow(dead_code)] with zero call sites anywhere in src/ or crates/:
|
#[allow(dead_code)] |
|
pub async fn register_thread(registry: &ThreadRegistry, thread_id: &str, platform: &str) { |
|
registry.write().await.insert(thread_id.to_string(), platform.to_string()); |
|
} |
In main.rs the registry is created and handed only to the reader side (RuntimeHandler::new), never to the dispatch/adapter side that would record thread_id → platform. The comment even claims it is "Populated on message dispatch", but that wiring was never implemented:
|
// Thread registry: thread_id → platform. Populated on message dispatch. |
|
let ctl_registry = ctl::new_registry(); |
So self.registry is always empty → resolve() returns None → unknown thread.
Not a regression. The feature was incomplete from the start: ctl.rs was added in #1147 ("openab set/get — Unix socket IPC (Phase 1: thread.name)") and register_thread shipped as dead code then. There is no prior working state.
Architectural note: the registry lives in the openab bin (src/ctl.rs), but message dispatch lives in openab-core, so populating it requires threading the registry (or a register callback) from the bin into the core dispatcher — which is why "Phase 2" was deferred and never landed.
Steps to Reproduce
- Run any bot (
openab run) with at least one adapter (e.g. Discord).
- From inside the container, run:
openab set thread.name "test thread name" --thread <any-thread-id>
- Observe:
✗ unknown thread (use --thread or register via message dispatch) — even though --thread was provided and the bot is actively handling that thread.
(get thread.name is likewise unusable.)
Expected Behavior
openab set thread.name --thread <id> should rename the thread for any thread the bot is handling.
Proposed fix:
- Wire
register_thread into the dispatch path — when the bot dispatches a message in a thread, record thread_id → platform in the ctl registry. This requires passing the registry (or a registration hook) from main.rs into the openab-core dispatcher. Then --thread <id> resolves for any thread seen during the current process lifetime.
- Single-adapter fallback (quick win): if exactly one adapter is configured,
resolve() should fall back to it even without a registry hit — making set/get work immediately for single-platform bots (e.g. Discord-only) without depending on prior dispatch.
- Fix the misleading error message / the
register via message dispatch wording once registration actually works.
Note the registry is in-memory and per-process, so even after the fix it is expected to be empty immediately after a restart until the bot handles a message in the thread (the single-adapter fallback avoids this for single-platform bots).
Description
openab set thread.name "..." --thread <id>always fails with:…for every thread, with or without
--thread. Thethread.namecontrol command can never succeed in the current code.Root cause:
RuntimeHandler::handle_setresolves the target thread through an in-memorythread_id → platformregistry, but that registry is never populated.resolve()requires a registry hit even when--threadis supplied:openab/src/ctl.rs
Lines 176 to 182 in 00ec0e0
The only function that writes to the registry,
register_thread, is dead code — marked#[allow(dead_code)]with zero call sites anywhere insrc/orcrates/:openab/src/ctl.rs
Lines 145 to 148 in 00ec0e0
In
main.rsthe registry is created and handed only to the reader side (RuntimeHandler::new), never to the dispatch/adapter side that would recordthread_id → platform. The comment even claims it is "Populated on message dispatch", but that wiring was never implemented:openab/src/main.rs
Lines 314 to 315 in 00ec0e0
So
self.registryis always empty →resolve()returnsNone→unknown thread.Not a regression. The feature was incomplete from the start:
ctl.rswas added in #1147 ("openab set/get — Unix socket IPC (Phase 1: thread.name)") andregister_threadshipped as dead code then. There is no prior working state.Architectural note: the registry lives in the
openabbin (src/ctl.rs), but message dispatch lives inopenab-core, so populating it requires threading the registry (or a register callback) from the bin into the core dispatcher — which is why "Phase 2" was deferred and never landed.Steps to Reproduce
openab run) with at least one adapter (e.g. Discord).✗ unknown thread (use --thread or register via message dispatch)— even though--threadwas provided and the bot is actively handling that thread.(
get thread.nameis likewise unusable.)Expected Behavior
openab set thread.name --thread <id>should rename the thread for any thread the bot is handling.Proposed fix:
register_threadinto the dispatch path — when the bot dispatches a message in a thread, recordthread_id → platformin the ctl registry. This requires passing the registry (or a registration hook) frommain.rsinto theopenab-coredispatcher. Then--thread <id>resolves for any thread seen during the current process lifetime.resolve()should fall back to it even without a registry hit — makingset/getwork immediately for single-platform bots (e.g. Discord-only) without depending on prior dispatch.register via message dispatchwording once registration actually works.Note the registry is in-memory and per-process, so even after the fix it is expected to be empty immediately after a restart until the bot handles a message in the thread (the single-adapter fallback avoids this for single-platform bots).