feat(orchestration): nested contacts → sessions with create + session send#4475
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (22)
✅ Files skipped from review due to trivial changes (10)
🚧 Files skipped from review as they are similar to previous changes (12)
📝 WalkthroughWalkthroughAdds backend support for creating orchestration sessions and sending session-threaded master messages, exposes these via frontend client/hook APIs, reworks the TinyPlace orchestration tab UI to group sessions under resolved contact addresses with handle display and nested session creation, and adds i18n strings and tests. ChangesSession creation and threading
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d457e2c824
ℹ️ 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".
| const acceptedContactList = useMemo( | ||
| () => | ||
| (pairingSnapshot?.contacts.contacts ?? []).filter(contact => contact.status === 'accepted'), |
There was a problem hiding this comment.
Gate session creation on local pairings
When /contacts contains an accepted contact that is not also in the local orchestration pairing store (for example, accepted in TinyPlace or on another device), this list still exposes the new-session flow. That session can send outbound, but replies from that peer are discarded by ingest_one because it only decrypts senders returned by linked_agent_ids from the local pairings file (src/openhuman/orchestration/ingest.rs:158-162). Filter these contacts against pairingSnapshot.records or persist a linked pairing before enabling session creation.
Useful? React with 👍 / 👎.
| }, | ||
| label: None, | ||
| workspace: None, | ||
| last_seq: 0, |
There was a problem hiding this comment.
Keep manual sends out of ingest health
When sessionId is present, this mirrors an owner-authored message into a non-pinned session and advances last_message_at; orchestration_status reports ingestLastMessageAt as MAX(last_message_at) over every non-pinned session, so a user sending to a session makes the ingest pipeline look fresh even if no inbound relay messages are being ingested. Empty sessions created above also set this timestamp, so please keep a separate last-ingested timestamp or exclude user-created/owner-only activity from that health query.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src/components/intelligence/TinyPlaceOrchestrationTab.tsx`:
- Around line 576-599: The contact disclosure button in
TinyPlaceOrchestrationTab toggles nested sessions but doesn’t expose its open
state to assistive tech. Update the button in the contact row to include
aria-expanded, wired to the existing isOpen state used by toggleContact, so
screen readers can announce whether the session list is expanded or collapsed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 89fefbc6-e42e-4b95-ac85-653a5c210b6a
📒 Files selected for processing (20)
app/src/components/intelligence/TinyPlaceOrchestrationTab.test.tsxapp/src/components/intelligence/TinyPlaceOrchestrationTab.tsxapp/src/lib/i18n/ar.tsapp/src/lib/i18n/bn.tsapp/src/lib/i18n/de.tsapp/src/lib/i18n/en.tsapp/src/lib/i18n/es.tsapp/src/lib/i18n/fr.tsapp/src/lib/i18n/hi.tsapp/src/lib/i18n/id.tsapp/src/lib/i18n/it.tsapp/src/lib/i18n/ko.tsapp/src/lib/i18n/pl.tsapp/src/lib/i18n/pt.tsapp/src/lib/i18n/ru.tsapp/src/lib/i18n/zh-CN.tsapp/src/lib/orchestration/orchestrationClient.tsapp/src/lib/orchestration/useOrchestrationChats.tssrc/openhuman/orchestration/schemas.rssrc/openhuman/orchestration/store.rs
Unrelated CI unblock: tinyhumansai#4446 (Privacy Mode) registered `config_get_privacy_mode` / `config_set_privacy_mode` unconditionally (src/openhuman/config/schemas/controllers.rs) but did not update the `worker_a_controller_schemas_are_fully_exposed` golden in tests/config_auth_app_state_connectivity_e2e.rs, so that test fails on main for every PR that doesn't carry the fix. Add the two methods at their sorted positions (same fix as tinyhumansai#4475) so this PR's Rust E2E / coverage jobs go green. Claude-Session: https://claude.ai/code/session_01KcmdqJVpjmnH31HqTHRLwG
… send - Contacts sidebar is now expandable: each accepted contact expands to reveal its sessions (by sessionId) plus a "New session" action; sessions with no known contact peer fall into an "Other sessions" bucket. - New orchestration_sessions_create RPC mints a per-contact session (fresh uuid harness id, source "user_created"); the composer now sends under a selected session too, not only Master. - send_master_message gains an optional sessionId: the body is wrapped in a v1 session envelope stamped with that id (so a compliant peer threads the reply) and mirrored into the session window. - Fix: resolve a contact's address from contact.requester/addressee when the relay omits the top-level agentId — previously the address rendered blank and the request cards had undefined React keys. - Fix: orchestration_messages_list schema now declares `limit`; every message load was being rejected by param-validation. - i18n keys (contacts/noContacts/newSession/otherSessions) across all 14 locales.
…n envelope The wake-graph's send_dm sent replies as plain DMs, so a reply into a real harness session was not stamped with the session id and a strict peer would classify it as a non-session (Master) DM — breaking return-path threading. - Centralize the outgoing-envelope builder as SessionEnvelopeV1::outgoing() and reuse it from the RPC send path and the graph send path. - send_dm now wraps a reply into a real session in a v1 envelope (plain for the pinned Master/subconscious windows) via a testable session_send_plaintext.
…tton Addresses CodeRabbit: the contact row toggles nested sessions but only signalled state via the ▾/▸ glyph. Add aria-expanded for assistive tech, asserted in the create-session test.
9636641 to
4e77740
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
Summary
sessionId), with a "New session" action per contact. Sessions with no known contact peer land in an "Other sessions" bucket so nothing disappears.orchestration_sessions_create(agentId, label?)RPC mints a per-contact session (fresh uuid harness id,source: "user_created") and returns its summary.orchestration_send_master_messagegains an optionalsessionId: when present the body is wrapped in a v1SessionEnvelopeV1stamped with that id (so a compliant peer threads its reply) and mirrored into the session window. The composer now sends under a selected session, not only Master.contact.requester/contact.addresseewhen the relay omits the top-levelagentId— previously the address rendered blank and request cards hadundefinedReact keys.orchestration_messages_listschema now declareslimit; every message load was being rejected by param-validation.contacts/noContacts/newSession/otherSessions) added across all 14 locales.send_dmnow wraps a reply into a real harness session in a v1 session envelope too (previously plain), so the agent's own replies thread back under the same session — via a sharedSessionEnvelopeV1::outgoing()builder reused by both send paths.configschema-catalog golden inworker_a_controller_schemas_are_fully_exposedwith theconfig_get/set_privacy_modecontrollers that feat(privacy): Privacy Mode + local-only inference enforcement (#4435) #4446 registered but never added — this test fails on every PR that runs the Rust E2E lane.Problem
The orchestration surface listed contacts only as a flat, non-interactive list, and accepted contacts had nowhere to live until a peer happened to message you (sessions are minted only by Stage-3 ingest). There was no way to see a contact's sessions or start a new one. Two latent bugs made it worse: incoming-contact addresses rendered blank whenever the relay left
agentIdempty (the address is in the underlying contact record), andmessages_listrejected every call because the handler read alimitparam the schema never declared.Solution
contactAddress(view)resolver (used for keys, display,@handlelookup, actions) falls back tocontact.requester/addresseeby direction.useOrchestrationChatsgainscreateSession()(creates + selects) and a chat-awaresendMessage(chat, body)that threads under a session (recipient= peer,sessionId) or falls back to the Master path.sessions_createcontroller + asession_agent_idstore lookup, and wraps outgoing session sends in a v1 envelope.upsert_session's conflict clause preserves an existing session'ssource, so a user-created session keeps its origin when a send mirrors into it.orchestration_sessions_create -> ok,orchestration_messages_list -> ok(the param-validation rejections are gone).Submission Checklist
TinyPlaceOrchestrationTab: 12 cases incl. create-session, session-send, address fallback) + Rust (orchestration::schemas: envelope roundtrip, session persist/resolve). CI enforces the merged gate.## Related).uuid/chrono/serde_jsonalready present).docs/RELEASE-MANUAL-SMOKE.md.Closes #NNN.Impact
messages_listnow acceptslimit(previously silently rejected). No security or compatibility implications — session sends reuse the existing signal-send path.Related
AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
feat/orchestration-contact-sessionsd457e2c82408a7cc0f8f5947707e8c4077ae96fdValidation Run
pnpm --filter openhuman-app format:check— Prettier applied clean to changed files.pnpm typecheck— clean.TinyPlaceOrchestrationTab.test.tsx(12/12);cargo test orchestration::schemas(6/6).cargo fmtapplied;cargo check --libclean.app/src-tauricode changed.Validation Blocked
command:N/Aerror:N/Aimpact:N/ABehavior Changes
Summary by CodeRabbit
New Features
Bug Fixes
@handlewhen available).Documentation / Localization