fix(telegram): forum topic replies route to root chat + ACP spawn fails from forum topics#56060
Conversation
Greptile SummaryThis PR extends the Telegram thread-bindings adapter to support Key findings:
Confidence Score: 4/5Not safe to merge without fixing the stale test that will cause CI failure. One P1 finding (stale test asserting the superseded BINDING_CAPABILITY_UNSUPPORTED error code) will break the test suite. The implementation logic itself is sound for the common path, but the broken test is a blocking issue that must be resolved before merge. extensions/telegram/src/thread-bindings.test.ts — stale "does not support child placement" test must be updated or removed.
|
| Filename | Overview |
|---|---|
| extensions/telegram/src/thread-bindings.ts | Adds "child" to the adapter's placements capability and wires it to createForumTopicTelegram; group ID resolution contains a silent fallback that may misroute in multi-group configs. |
Comments Outside Diff (1)
-
extensions/telegram/src/thread-bindings.test.ts, line 61-82 (link)Stale test now asserts the wrong error code
This test was written to document that
"child"placement was unsupported, and it expects aBINDING_CAPABILITY_UNSUPPORTEDrejection. Now that"child"is included in the adapter'splacementscapability array, the session-binding service will no longer reject the call at the capability gate. Instead,bindwill be entered and will attempt to callloadConfig()/resolveTelegramToken()/createForumTopicTelegram(), failing with a completely different error (e.g. missing token or network) — notBINDING_CAPABILITY_UNSUPPORTED. The test will fail.This test needs to be updated to either:
- Be removed (if the old "unsupported" contract is no longer relevant), or
- Be replaced with a test that mocks
loadConfig/resolveTelegramToken/createForumTopicTelegramand verifies the new child-binding happy path and failure modes.
Prompt To Fix With AI
This is a comment left during a code review. Path: extensions/telegram/src/thread-bindings.test.ts Line: 61-82 Comment: **Stale test now asserts the wrong error code** This test was written to document that `"child"` placement was unsupported, and it expects a `BINDING_CAPABILITY_UNSUPPORTED` rejection. Now that `"child"` is included in the adapter's `placements` capability array, the session-binding service will no longer reject the call at the capability gate. Instead, `bind` will be entered and will attempt to call `loadConfig()` / `resolveTelegramToken()` / `createForumTopicTelegram()`, failing with a completely different error (e.g. missing token or network) — not `BINDING_CAPABILITY_UNSUPPORTED`. The test will fail. This test needs to be updated to either: - Be removed (if the old "unsupported" contract is no longer relevant), or - Be replaced with a test that mocks `loadConfig`/`resolveTelegramToken`/`createForumTopicTelegram` and verifies the new child-binding happy path and failure modes. How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/telegram/src/thread-bindings.test.ts
Line: 61-82
Comment:
**Stale test now asserts the wrong error code**
This test was written to document that `"child"` placement was unsupported, and it expects a `BINDING_CAPABILITY_UNSUPPORTED` rejection. Now that `"child"` is included in the adapter's `placements` capability array, the session-binding service will no longer reject the call at the capability gate. Instead, `bind` will be entered and will attempt to call `loadConfig()` / `resolveTelegramToken()` / `createForumTopicTelegram()`, failing with a completely different error (e.g. missing token or network) — not `BINDING_CAPABILITY_UNSUPPORTED`. The test will fail.
This test needs to be updated to either:
- Be removed (if the old "unsupported" contract is no longer relevant), or
- Be replaced with a test that mocks `loadConfig`/`resolveTelegramToken`/`createForumTopicTelegram` and verifies the new child-binding happy path and failure modes.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: extensions/telegram/src/thread-bindings.ts
Line: 585-590
Comment:
**First-configured-group fallback is non-deterministic in multi-group setups**
When neither `parentConversationId` nor `conversationId` starts with `"-"` (e.g. a bare topic number like `"77"` is provided), the code silently falls back to `groupIds[0]`:
```ts
const groupIds = Object.keys(cfg?.channels?.telegram?.groups ?? {});
if (groupIds.length > 0) {
chatId = groupIds[0];
}
```
`Object.keys` on a plain object preserves insertion order in modern JS engines, but the insertion order of a parsed JSON config is effectively the order the user wrote their config — which may have no relation to the desired target group. In a deployment with two or more Telegram groups configured, this will silently spawn the child topic in whichever group appears first in the config file, with no log message indicating that a fallback occurred.
Consider either:
1. Logging a warning that a fallback was applied (`logVerbose` is already imported), or
2. Returning `null` when the chat ID cannot be unambiguously resolved, to surface the error clearly to the orchestrator.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(telegram): add child thread-binding..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa95a00f95
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a51db6000
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6eda22c6f7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5525c98eb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
88b27e6 to
091430d
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 091430d429
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
02e564d to
f5525c9
Compare
f5525c9 to
09f930f
Compare
17c62aa to
492f6db
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 492f6dbd34
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c9c411c9b3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
Pushed a small follow-up on the PR branch. Root issue in the last ACP change: Telegram forum-topic spawns were still choosing Fix: remove that special case and derive the canonical Telegram topic conversation ID up front ( Also fixed the stale |
Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414
…ack for bare topic IDs in child bind
…de test
- Simplify bare-topic-ID guards in thread-bindings.ts: split into
separate !chatId and !chatId.startsWith("-") checks, removing
unreachable second condition
- Add regression test confirming explicit turnSourceThreadId overrides
session lastThreadId on same channel
Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches.
extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from.
20d7a19 to
8a47841
Compare
obviyus
left a comment
There was a problem hiding this comment.
Reviewed latest changes; landing now.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a47841572
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| chatId = chatId | ||
| .replace(/:topic:\d+$/i, "") | ||
| .replace(/:\d+$/i, "") | ||
| .trim(); | ||
| if (/^-?\d+$/.test(chatId)) { | ||
| return normalizedThreadId ? `${chatId}:topic:${normalizedThreadId}` : chatId; |
There was a problem hiding this comment.
Preserve topic suffix when deriving Telegram conversation IDs
Do not strip :topic:<id> unconditionally here. In the Telegram branch, the code removes any topic suffix from to/groupId and only adds it back when threadId is separately provided, so a topic-qualified target like telegram:group:-100...:topic:42 with no explicit threadId is downgraded to -100.... In that case thread=true ACP spawns bind to the root chat and follow-up delivery can route outside the intended forum topic instead of staying in the requested topic.
Useful? React with 👍 / 👎.
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
…ne27001) * feat(telegram): add child thread-binding placement via createForumTopic Enable ACP subagent spawn on Telegram by adding "child" placement support to the thread-bindings adapter. When a child binding is requested, the adapter creates a new forum topic via the Telegram Bot API and binds the subagent session to it using the canonical chatId:topic:topicId conversation ID format. When the ACP spawn context provides only a topic ID (not a full group chat ID), the adapter resolves the group from the configured Telegram groups in openclaw.json. This mirrors the Discord adapter's child placement behavior (thread creation + session binding) and unblocks the orchestrator pattern on Telegram forum-enabled groups. Closes openclaw#5737 Ref openclaw#23414 * fix(telegram): return null with warning instead of silent group fallback for bare topic IDs in child bind * telegram: fix ACP child thread spawn with group chat ID from agentGroupId * telegram: scope agentGroupId substitution to telegram channel only * Telegram: fix forum topic replies routing to root chat instead of topic thread * fix: clean up dead guard in child bind + add explicit threadId override test - Simplify bare-topic-ID guards in thread-bindings.ts: split into separate !chatId and !chatId.startsWith("-") checks, removing unreachable second condition - Add regression test confirming explicit turnSourceThreadId overrides session lastThreadId on same channel * fix: guard threadId fallback against shared-session race Codex review P1: when turnSourceTo differs from the session's stored to, the session threadId may belong to a different chat/topic. Only fall back to context.threadId when the destination also matches. * fix(telegram): enable ACP spawn from forum topics without thread binding extractExplicitGroupId returned topic-qualified IDs (-100...:topic:1264) instead of bare group chat IDs, breaking agentGroupId resolution. agentGroupId was also never wired in the inline actions path. For Telegram forum topics, skip thread binding entirely — the delivery plan already routes correctly via requester origin (to + threadId). Creating new forum topics per child session is unnecessary; output goes back to the same topic the user asked from. * fix(acp): bind Telegram forum sessions to current topic * fix: restore Telegram forum-topic routing (openclaw#56060) (thanks @one27001) --------- Co-authored-by: openclaw <[email protected]> Co-authored-by: Ayaan Zaidi <[email protected]>
Fix 1: forum topic replies route to root chat
Regression from #24152. The cross-channel guard set
lastThreadId = turnSourceThreadId, but Telegram never setsturnSourceThreadId— the thread ID lives in session context. All forum topic replies silently lostmessage_thread_idand landed in root chat.Fix: Fall back to session
threadIdwhen turn-source channel + destination match the session. Extratocheck prevents shared-session race (Codex P1,17c62aa).Fix 2: ACP spawn from forum topics fails
sessions_spawn(runtime=acp, thread=true)from a forum topic errored with "Telegram recipient must be a numeric chat ID". Three causes:extractExplicitGroupIdreturned topic-qualified IDs (e.g.-100...:topic:1264)agentGroupIdnever wired in inline tool dispatchFix: Strip
:topic:.*from group IDs, wireagentGroupId, and skip thread binding for Telegram forum topics. The delivery plan already routes correctly viaorigin.to+origin.threadIdwithout binding — child output goes back to the same topic.Tests
extractExplicitGroupId)acp-spawn37/37 passed,group-id9/9 passedtargets.test.tsWhatsApp import failure,thread-bindings.test.ts1 timeoutAI-assisted
codex review --base upstream/main), P1 findings addressed — binding path bypassed for Telegram forum topics