Add Jitsi bridge with downstream-configurable identity and Azure model updates#52263
Add Jitsi bridge with downstream-configurable identity and Azure model updates#52263quandes wants to merge 2 commits intoopenclaw:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 083982385e
ℹ️ 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".
| ): TelegramInlineButtons { | ||
| if (!hasActiveRoom) { | ||
| return [ | ||
| [{ text: labels.createButton, callback_data: `${TELEGRAM_JITSI_CALLBACK_PREFIX}start` }], |
There was a problem hiding this comment.
Wire Jitsi panel callbacks into Telegram callback handling
This adds inline /meet buttons with callback_data values (for example jitsi:start), but the new callback parser/executor (parseTelegramMeetCallback / handleTelegramMeetCallback) is never invoked anywhere, so button taps do not trigger the intended room actions. In the current Telegram callback flow (src/telegram/bot-handlers.ts), unknown callback payloads fall through to synthetic message processing, so users can end up sending raw jitsi:* text into normal agent handling instead of controlling the meeting panel.
Useful? React with 👍 / 👎.
| const labels = jitsiCfg?.labels; | ||
| const envBridgeUrl = process.env.OPENCLAW_TELEGRAM_JITSI_BRIDGE_URL?.trim(); | ||
| const bridgeUrl = jitsiCfg?.bridgeUrl?.trim() || envBridgeUrl || undefined; | ||
| const enabled = jitsiCfg?.enabled === true || Boolean(bridgeUrl); |
There was a problem hiding this comment.
Respect explicit disabled flag for Telegram Jitsi integration
The enablement check ignores an explicit channels.telegram.jitsi.enabled: false whenever a bridge URL is present, because it uses jitsi.enabled === true || Boolean(bridgeUrl). That makes opt-out impossible for accounts that still have bridgeUrl configured (or inherited from OPENCLAW_TELEGRAM_JITSI_BRIDGE_URL), so /meet and /jitsi remain active even when the config tries to disable them.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR delivers two independent feature commits: a Jitsi realtime bridge service with downstream-configurable identity/prompts, and Azure realtime model forward-compatibility updates for The Azure model compat work ( The Jitsi bridge is a well-structured MVP: token-gated join/enter flow, timing-safe token comparison, process-group signal escalation for joiner stop, and a sensible downstream config merge system. However, several policy violations need to be addressed before landing:
Confidence Score: 3/5
|
| }; | ||
|
|
||
| function asObject(value: unknown): Record<string, unknown> | null { | ||
| return typeof value === "object" && value !== null ? (value as Record<string, unknown>) : null; | ||
| } | ||
|
|
||
| function asString(value: unknown): string | undefined { | ||
| return typeof value === "string" && value.trim() ? value.trim() : undefined; | ||
| } | ||
|
|
||
| function asStringList(value: unknown): string[] | undefined { | ||
| if (!Array.isArray(value)) { | ||
| return undefined; | ||
| } | ||
| const lines = value | ||
| .map((entry) => asString(entry)) | ||
| .filter((entry): entry is string => Boolean(entry)); | ||
| return lines.length > 0 ? lines : undefined; | ||
| } | ||
|
|
||
| function resolveDownstreamConfigPath(): string | undefined { | ||
| const explicit = | ||
| process.env.OPENCLAW_JITSI_CONFIG_PATH?.trim() || | ||
| process.env.JITSI_DOWNSTREAM_CONFIG_PATH?.trim() || | ||
| process.env.OPENCLAW_DOWNSTREAM_CONFIG_PATH?.trim(); | ||
| if (!explicit) { | ||
| return undefined; | ||
| } | ||
| return path.isAbsolute(explicit) ? explicit : path.resolve(process.cwd(), explicit); | ||
| } | ||
|
|
||
| let cachedConfigPath: string | undefined; | ||
| let cachedConfig: JitsiBridgeDownstreamConfig | undefined; | ||
|
|
||
| export function loadJitsiBridgeDownstreamConfig(): JitsiBridgeDownstreamConfig { | ||
| const configPath = resolveDownstreamConfigPath(); | ||
| if (cachedConfig && cachedConfigPath === configPath) { | ||
| return cachedConfig; |
There was a problem hiding this comment.
German strings in default prompt/UI config violate the English-only policy
CLAUDE.md requires: "Written English: use American spelling and grammar in code, comments, docs, and UI strings."
The DEFAULT_JITSI_BRIDGE_DOWNSTREAM_CONFIG has German defaults for every user-facing string — baseInstructions, button labels, hints, and delegation messages. Because downstream deployments override these, the German defaults ship in the published package and appear verbatim for any deployment that doesn't supply a custom config file.
For example:
baseInstructions: [
"Du bist ein technischer Meeting-Assistent in einem Business-Meeting.",
...
]
telegramUi: {
createButton: "Neues Meeting",
emptyPanelText: "Kein aktives Meeting in diesem Chat.",
...
}
All defaults should be English. Downstream operators who want German output can supply a JSON config file that overrides them.
The same issue applies to hardcoded German response strings throughout src/jitsi-bridge/jitsi-command.ts (e.g. "Meeting ${room.id} erstellt.", "Joiner wurde gestartet.", "Briefing für ${room.id} gespeichert.", "Meeting ${room.id} gestoppt. Bot hat den Raum verlassen…", "Aktives Meeting für diesen Chat wurde entfernt.") and to the German HTML page in src/jitsi-bridge/service.ts (lang="de", "Meeting bereit", "Ein Klick startet den Bot-Join…").
These strings also cannot currently be overridden via the downstream config or labels system, so even a downstream deployment that supplies a full config file will still receive German response text from the Telegram command handlers and the join page.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/jitsi-bridge/downstream-config.ts
Line: 88-125
Comment:
**German strings in default prompt/UI config violate the English-only policy**
`CLAUDE.md` requires: *"Written English: use American spelling and grammar in code, comments, docs, and UI strings."*
The `DEFAULT_JITSI_BRIDGE_DOWNSTREAM_CONFIG` has German defaults for every user-facing string — `baseInstructions`, button labels, hints, and delegation messages. Because downstream deployments override these, the German defaults ship in the published package and appear verbatim for any deployment that doesn't supply a custom config file.
For example:
```
baseInstructions: [
"Du bist ein technischer Meeting-Assistent in einem Business-Meeting.",
...
]
telegramUi: {
createButton: "Neues Meeting",
emptyPanelText: "Kein aktives Meeting in diesem Chat.",
...
}
```
All defaults should be English. Downstream operators who want German output can supply a JSON config file that overrides them.
The same issue applies to hardcoded German response strings throughout `src/jitsi-bridge/jitsi-command.ts` (e.g. `"Meeting ${room.id} erstellt."`, `"Joiner wurde gestartet."`, `"Briefing für ${room.id} gespeichert."`, `"Meeting ${room.id} gestoppt. Bot hat den Raum verlassen…"`, `"Aktives Meeting für diesen Chat wurde entfernt."`) and to the German HTML page in `src/jitsi-bridge/service.ts` (`lang="de"`, `"Meeting bereit"`, `"Ein Klick startet den Bot-Join…"`).
These strings also cannot currently be overridden via the downstream config or labels system, so even a downstream deployment that supplies a full config file will still receive German response text from the Telegram command handlers and the join page.
How can I resolve this? If you propose a fix, please make it concise.| # Jitsi Realtime Bridge | ||
|
|
||
| Dieser Prototyp setzt das Zielbild in einer ersten lauffaehigen Form um: | ||
|
|
||
| 1. OpenClaw oder ein Telegram-Workflow kann einen Raum per HTTP anlegen. | ||
| 2. Der Dienst erzeugt eine Jitsi-URL und merkt sich Briefings pro Raum. | ||
| 3. Ein Joiner-Prozess tritt mit konfigurierbarer Bot-Identitaet einem Jitsi-Raum bei. | ||
| 4. Eine Azure-Realtime-Bridge kann pro Raum Antworten mit Persona + Briefing erzeugen. | ||
| 5. Der Joiner schleust Remote-Audio aus Jitsi in Azure Realtime und spielt Antwort-Audio in die lokale Meeting-Mikrofonspur zurück. | ||
|
|
There was a problem hiding this comment.
Documentation file is entirely in German
CLAUDE.md requires English for all docs in this repo. docs/jitsi-realtime-bridge.md is written entirely in German, including headings, body text, and explanations.
Additionally, the env-var example includes a real private-network IP address:
export JITSI_BRIDGE_PUBLIC_BASE_URL="http://192.168.179.3:4318"
Per the docs policy, use a generic placeholder such as http://192.0.2.1:4318 or http://<gateway-host>:4318 instead of a specific private address.
Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/jitsi-realtime-bridge.md
Line: 1-10
Comment:
**Documentation file is entirely in German**
`CLAUDE.md` requires English for all docs in this repo. `docs/jitsi-realtime-bridge.md` is written entirely in German, including headings, body text, and explanations.
Additionally, the env-var example includes a real private-network IP address:
```
export JITSI_BRIDGE_PUBLIC_BASE_URL="http://192.168.179.3:4318"
```
Per the docs policy, use a generic placeholder such as `http://192.0.2.1:4318` or `http://<gateway-host>:4318` instead of a specific private address.
How can I resolve this? If you propose a fix, please make it concise.
Summary
This PR adds two isolated commits that can also be cherry-picked independently:
8a3d6a61-feat(jitsi): add bridge and downstream-configurable identity/jitsiand/meetbridge control integration.channels.telegram.jitsi.08398238-feat(models): add azure realtime and forward-compat updatesWhy
Downstream deployments need to configure identity and custom behavior without source edits, and keep Azure realtime/model support aligned with local runtime requirements.
Validation
pnpm tsgopnpm vitest run src/jitsi-bridge/downstream-config.test.ts src/jitsi-bridge/jitsi-url.test.ts src/jitsi-bridge/room-store.test.ts src/jitsi-bridge/audio.test.tspnpm vitest run src/config/config.secrets-schema.test.tsCherry-pick alternative
If maintainers prefer selective landing, cherry-pick:
8a3d6a6108398238