feat(relay): centralize route action safety#49
Merged
Conversation
447c0a1 to
31e91bd
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR centralizes “route-action safety” in extensions/relay/core/route-actions.ts by introducing typed action outcomes, coherent availability probing, and shared prompt/control/media helpers, then migrates Telegram/Discord/Slack runtimes and the broker to use these helpers to avoid stale-context races and ensure consistent rollback behavior.
Changes:
- Introduces typed
RouteActionOutcome+RouteUnavailableError, and shared helpers for prompt delivery, abort/compact, workspace/media access, and availability probing. - Migrates adapter runtimes (Telegram/Discord/Slack) and broker operations to use shared helpers and display-safe outcome messaging.
- Adds unit/boundary tests and documentation clarifying route-action safety vs binding authority.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/slack-runtime.test.ts | Updates Slack runtime expectations for typed “unavailable” errors and idle abort behavior. |
| tests/runtime.test.ts | Updates Telegram runtime tests to use routeUnavailableError() instead of string-matched errors. |
| tests/relay/route-actions.test.ts | Adds focused unit coverage for typed outcomes, unavailable detection, rollback/commit hooks, and coherent probes. |
| tests/relay/route-action-boundary.test.ts | Adds boundary tests to prevent raw route.actions.context usage in long-lived runtimes and ensure helpers stay centralized. |
| tests/relay-core.test.ts | Updates core route snapshot tests to validate new coherent probe behavior under stale model lookup. |
| tests/discord-runtime.test.ts | Updates Discord runtime test to throw typed route-unavailable errors. |
| openspec/changes/relay-route-action-safety/tasks.md | Marks the OpenSpec task list as completed. |
| openspec/changes/relay-route-action-safety/inventory.md | Adds a detailed inventory and rationale for migrated call sites and remaining direct usages. |
| extensions/relay/runtime/extension-runtime.ts | Switches extension route action implementations to throw routeUnavailableError() for stale/unavailable contexts. |
| extensions/relay/core/route-actions.ts | Adds typed outcomes, typed unavailable errors, coherent probe, and shared prompt/control/media/workspace safety helpers. |
| extensions/relay/core/relay-core.ts | Updates route snapshot/state construction to use the coherent probe instead of independent model/idle checks. |
| extensions/relay/broker/tunnel-runtime.ts | Migrates broker prompt/control/media/workspace operations to shared safety helpers and typed display messaging. |
| extensions/relay/adapters/telegram/runtime.ts | Migrates Telegram prompt/control/media/workspace paths to shared helpers and typed display messaging. |
| extensions/relay/adapters/slack/runtime.ts | Migrates Slack prompt/control/media/workspace paths to shared helpers and typed display messaging with rollback hooks. |
| extensions/relay/adapters/discord/runtime.ts | Migrates Discord prompt/control/media/workspace paths to shared helpers and typed display messaging. |
| docs/adapters.md | Documents route-action safety vs binding authority responsibilities. |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
extensions/relay/adapters/telegram/runtime.ts:1276
telegramRequester()setsmessageId: String(message.messageId), butmessageIdis optional for callback flows now. Whenmessage.messageIdisundefined, this stores the literal string "undefined" instead of omitting the field. Consider only settingmessageIdwhen the value is present, otherwise leave itundefined.
private telegramRequester(route: SessionRoute, message: Pick<TelegramInboundMessage, "chat" | "user"> & { messageId?: number }): RelayFileDeliveryRequester {
return {
channel: "telegram",
instanceId: "default",
conversationId: String(message.chat.id),
userId: String(message.user.id),
sessionKey: route.sessionKey,
safeLabel: `Telegram ${getTelegramUserLabel(message.user)}`,
messageId: String(message.messageId),
conversationKind: message.chat.type,
createdAt: Date.now(),
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.
Summary
relay-route-action-safetytasksValidation