Files
vocero-client/docs/client/context-injection.md
T
alvaro 4b0108ecf0 feat(vocero): add linked content and TALKFIRST greetings (#2)
Opening a report or podcast link now establishes an authenticated starting reference for the conversation. Users can select other accessible content or compare reports while retaining the original link, and TALKFIRST greetings can name the verified report or podcast.

Release notes:

- Added authenticated report and episode link resolution with bounded lookups and unavailable-content handling
- Added explicit conversation selection without restricting searches or changing the reference during comparisons
- Added contextual TALKFIRST greetings through both voice-proxy and HTTP reasoning paths
- Preserved backend permission checks, conversation isolation, cancellation, and the existing speech protocol

Reviewed-on: AquaPortal/s2s#2
2026-10-08 09:34:16 -04:00

7.9 KiB
Raw Blame History

Context injection

Context reaches the assistant through browser-built instructions, server-patched realtime session instructions, and HTTP reasoning context. The implementation is in the server's context services, realtime proxy, context.ts, and the WebSocket client.

Authenticated MCP context

When S2S_MCP_URL is configured, the browser submits the page's report_id and episode_id during conversation creation. The server resolves them through the authenticated MCP client and keeps compact verified references separately from the current conversational selection. No legacy profile or episode preload is used. TALKFIRST can mention the verified title after this preparation finishes. The link never restricts searches or access to other permitted content.

See tool calling for selection, authorization, timeout, and missing-content behavior. The controls and public episode fetch below describe the legacy path used when MCP is disabled.

Independent controls

S2S_INJECT_PROFILE defaults to false and gates server loading of caller, episode, report and prior-conversation context. It also controls whether the browser appends caller profile text to its realtime instructions.

It is not a master switch for every context source. Operator-supplied RAG text and configured ApiPilot discovery work independently. S2S_INJECT_TODAY defaults to true; date and voice-output guards are built on paths that invoke instruction augmentation or HTTP context assembly. A WebSocket session with no profile/episode/report/summary or ApiPilot block skips proxy augmentation. Direct browser connections bypass server-side WebSocket injection entirely.

Setting Default Effect
S2S_INJECT_PROFILE false Enable server-resolved caller, episode and history context
S2S_INJECT_REPORTS false Allow scheduled-report fetch/injection; also requires the profile gate
S2S_REPORTS_INJECT_MODE minimal minimal: labels/dates; full: scripts; off/none: no report prompt block
S2S_REPORTS_QUICK_HINT_MAX 5 Keep at most this many newest reports, clamped to 1–50
S2S_INJECT_TODAY true Add the current server-local date guard when its context builder runs
S2S_DEBUG_PROMPT false Log complete prompt/context text instead of only summaries

Context sources

Block Trigger and source Size/behavior
Podcast episode episode_id page/query/body value and profile gate Up to 24,000 characters of serialized episode content
Caller profile phoneNumber and VOCERO_USER_PHONE_AUTH_URL Up to 1,600 serialized characters
Scheduled reports S2S_REPORT_LIST, profile gate and report gate Newest N labels/dates by default; full mode includes scripts with a 12,000-character block limit
Latest conversation S2S_LATEST_SUMMARY_TEXT, or S2S_LATEST_SUMMARY with a phone number Up to 1,600 characters; static text overrides HTTP fetch
Custom RAG Operator applies text through the RAG dialog Up to 12,000 characters; appended in browser instructions and HTTP user_context
ApiPilot discovery Configured S2S_APIPILOT_TOOLS_URL Tool names/descriptions/auth requirements and call-marker rules, independent of the profile gate

Episode

The current episode fetch uses the deployment-specific URL:

https://aquachile.azurianlab.com/api/v1/podcast/episodes/{episode_id}

It follows redirects with a 15-second timeout, accepts JSON or plain text, unwraps a result field, and includes arbitrary episode fields. The prompt labels it as the primary reference for the user's current episode. The endpoint is hardcoded in the fetch helper rather than selected through an environment variable.

Caller profile and login

For caller-specific context, the proxy can first post {"phoneNumber":"+56912345678"} to S2S_LOGIN_BY_PHONE, extract a bearer token, and forward it to subsequent profile/history requests. Profile retrieval uses GET VOCERO_USER_PHONE_AUTH_URL?phoneNumber=... with a 10-second timeout and accepts an object, optionally wrapped in result.

Encode the leading plus sign in page links, for example ?phoneNumber=%2B56912345678. Caller information is also fetched through /api/user/phone for the UI. An available profile can update live browser instructions when profile injection is enabled.

Scheduled reports

S2S_INJECT_REPORTS=false skips report fetching and prompt content, including the table of contents. When enabled, the report endpoint may be called with or without a phone number. The resolver keeps dictionary entries, reads sourceScheduleLabel or sourceSchedule.label, reads date or sourceSchedule.date, and optionally keeps podcastScript in full mode.

Entries are sorted newest first using ISO/date/timestamp handling and an ISO-like string fallback. Empty/unparseable dates sort last. The newest-item limit applies before constructing the prompt block. minimal exposes only the labels and dates; full explicitly opts into script content.

Latest conversation summary

S2S_LATEST_SUMMARY_TEXT takes priority over S2S_LATEST_SUMMARY and needs no phone number or network request. Literal \n sequences in the environment value become newlines. Otherwise the proxy fetches S2S_LATEST_SUMMARY?phoneNumber=... and accepts text or JSON with an optional result wrapper. Both sources pass through the same cap and history wrapper.

Custom RAG

The operator can paste reference material and explicitly apply it to the session. The browser appends it to instructions even with profile injection disabled, includes it in HTTP user_context, and updates an open realtime session. This context does not require an external retrieval endpoint.

Application timing and order

At local WebSocket connect, the server resolves enabled context and stores it in session_ctx. Each client session.update then passes through _patch_client_session_update_with_profile(). Other client frame types are not modified by this helper. The broader relay still performs ApiPilot handling and text/audio filtering.

The current augmentation function keeps base instructions first, then appends surviving voice-output guards, date context, episode, profile, reports, and summary blocks. ApiPilot discovery is appended separately. If a block type is already present in the base, deduplication may omit its server candidate. This describes string assembly, not a guarantee of model attention or priority.

Every HTTP reasoning request rebuilds enabled context. Its user_context assembly orders voice guard, date, episode, profile, reports, summary, ApiPilot and browser-provided context, then deduplicates recognized types and strips internal markers. Server instruction augmentation remains separate, so avoid assuming the WebSocket and HTTP prompts have identical ordering.

Context markers support internal deduplication and diagnostics; ordinary profile/report/episode/history sentinels are stripped before final augmentation. ApiPilot call/catalog markers have their own handling. Treat the source helpers as the reference for the exact final payload.

Failure behavior and inspection

Optional context-fetch errors are logged and the affected context is skipped. The speech conversation normally continues without that reference material. This does not mean all API calls ignore errors: missing reasoning configuration, invalid tool arguments and tool authorization can return explicit errors.

Inspect /api/config for active gates, the actual outbound session.update in browser DevTools, and [INJECT-*]/[DEBUG-PROMPT] server logs. Full prompt logging includes caller data and conversation text. See troubleshooting for a step-by-step diagnostic flow.