[feature] an agent can pull recordings from the account's other devices - #334
Merged
Merged
Conversation
call_frontend gave every RPC the same 20s deadline. That is generous for folder bookkeeping, but short for the RPCs that pull a recording's audio down from the cloud: on a slow connection the tool reports failure while the app is still downloading, and the caller retries work that was about to succeed. The deadline now depends on the action — 180s for the two that fetch a whole recording, 20s for everything else. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Parley Cloud already mirrors an account's recordings across its devices, but MCP could not reach that: list_recordings reads local disk only, so an agent on a secondary device was blind to everything recorded elsewhere until someone clicked the card in the library. list_cloud_recordings returns the account's cloud mirror, tagging each entry with where it stands on this device — "cloud" (recorded elsewhere, not here yet), "stale" (the local copy is behind) or "synced". Pass pending: true for exactly the set this device is missing or behind on. download_cloud_recording then pulls one down: transcript, saved analysis, and the audio when the cloud copy has it. Afterwards it is an ordinary local recording — listed, readable, searchable, replayable. Both are RPCs into the app rather than plain Rust, because the account's bearer token lives in the frontend. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
❌ SonarQube Quality Gate ERROR — pathorsAI_parley
0 open issues on this PR. |
3 tasks
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.
What this changes
Two new MCP tools let an agent reach the recordings an account made on its other devices, not just the ones sitting on this one:
list_cloud_recordings— the account's personal cloud mirror, each entry tagged withsync:"cloud"(recorded elsewhere, not on this device yet),"stale"(a local copy exists but the cloud one is newer), or"synced". Passpending: truefor exactly the set this device is missing or behind on. Supports the samequery/since/limitfilters aslist_recordings.download_cloud_recording— pulls one down: transcript, saved analysis, and the audio when the cloud copy has it. Afterwards it is an ordinary local recording — it appears inlist_recordings, reads withget_recording, is searchable withsearch_meetings, and opens in replay. Re-downloading a"stale"entry refreshes the local copy.Both are RPCs into the app rather than plain Rust, because the account's bearer token lives in the frontend.
Why
Parley Cloud already mirrors an account's recordings across its devices — the library grid shows cloud-only entries and downloads them on click. MCP could not reach any of that:
list_recordingsreads local disk only, so an agent on a secondary device was blind to everything recorded elsewhere until a human clicked the card.The motivating shape: many machines record, a few machines analyze. The analyzing machines need to pull work down on their own.
Until now the only agent-drivable path between devices was the org one (
share_recording_to_org->copy_org_recording_to_personal), which requires deliberately publishing each recording into a shared space. For one person's own devices that is the wrong mechanism.Also here: a timeout fix
call_frontendgave every RPC the same 20s deadline. That is generous for folder bookkeeping but short for pulling a meeting's audio down — the tool reports failure while the app is still downloading, and the caller retries work that was about to succeed. The deadline is now per-action: 180s for the two RPCs that fetch a whole recording, 20s for everything else.This is a pre-existing bug that
copy_org_recording_to_personalalready had; it is fixed here too rather than left for the org path to keep hitting. Split into its own commit so it reads independently.How it was verified
bunx tsc --noEmitpassesbunx vitest runpasses (307 tests)cargo test --libpasses (45 tests), 3 new:download_cloud_recordingclassifies as a write (it puts a file on disk, so the activity log must not treat it as a harmless read), download RPCs get a longer deadline than bookkeeping, and every tool name intools()is uniquebun run tauri dev) and exercised the changezh-TWandeninsrc/i18n/messages.tsNot verified end-to-end on two real machines. The type checking, unit tests and wiring are covered; an actual A -> cloud -> B pull has not been exercised on hardware. Worth doing before relying on it.
No new i18n keys: this is MCP surface only, no UI strings. No backend contract changes either —
/recordings,/recordings/:id/metaand/recordings/:id/audiowere already in use by the library grid.Notes for review
list_cloud_recordingsdeliberately callslistCloudRecordings()beforelistMergedHistory(). The latter falls back to local-only when the cloud is unreachable, which would surface as "nothing to download" — the one wrong answer for a caller whose entire purpose is finding what to download. The extra call is there to make a failed fetch throw.list_recordings' description now says explicitly that it is this device only and points at the new tool, so an agent does not conclude a recording is missing when it is merely elsewhere.