Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Custom LSP RPC Contracts

Status: Current Last updated: 2026-04-16 21:52 EDT

The extension drives twelve custom workspace/executeCommand endpoints exposed by chatter-lsp. This page is the per-endpoint reference: command identifier, request shape, response shape, TS caller, Rust handler. Everything here is verified against the current source on both sides — if an endpoint’s behavior drifts, update this page in the same commit.

One typical call at runtime

%% Verified against: apps/vscode-extension/src/lsp/executeCommandClient.ts,
%% crates/chatter-lsp/src/backend/requests/execute_command.rs,
%% crates/chatter-lsp/src/backend/execute_commands.rs.
sequenceDiagram
    participant TS as TS feature (e.g. analysis.ts)
    participant Client as TalkbankExecuteCommandClient
    participant LSP as tower-lsp dispatcher
    participant Decoder as ExecuteCommandRequest::parse
    participant Handler as feature handler (Rust)

    TS->>Client: executeStructured("talkbank/analyze", [payload])
    Client->>LSP: workspace/executeCommand JSON-RPC
    LSP->>Decoder: parse(params)
    Decoder-->>LSP: typed ExecuteCommandRequest::Analyze(...)
    LSP->>Handler: handle_analyze(&request)
    Handler-->>LSP: Result<serde_json::Value, LspBackendError>
    LSP-->>Client: JSON response (or stringified error)
    Client->>TS: decoded payload via Effect Schema

Twelve endpoints grouped by handler family.

Documents family

talkbank/showDependencyGraph

Generate a Graphviz DOT dependency graph for the utterance at a cursor position.

Rust requestDocumentPositionRequest { uri: Url, position: Position } in backend/execute_commands.rs
Rust handlergraph::build_dependency_graph_response(utterance, parse_state) in crates/chatter-lsp/src/graph/mod.rs
Rust responseDependencyGraphResponse::Dot { source } | Unavailable { reason }
TS callerexecuteCommandClient.getDependencyGraph (or similar — see graphPanel.ts)
TS response typeDependencyGraphResponse (Effect Schema discriminated union) in lsp/executeCommandPayloads.ts

Request layout: argument position 0 is the document URI, position 1 is the cursor as { line, character }. See the Cross-Tier Alignment and Dependency Graphs pages for user-facing behavior; the DOT output includes a stale baseline header label when the backend is serving a stale-baseline parse (see developer/architecture.md).

talkbank/getAlignmentSidecar

Produce the alignment-sidecar payload for one document — a JSON view of every utterance’s AlignmentSet usable by the extension’s alignment overlays.

Rust requestDocumentUriRequest { uri: Url }
Rust handlerbuild_alignment_sidecar(&uri, text, &chat_file) in backend/requests/alignment_sidecar.rs
Rust responseAlignmentSidecarDocument { schema_version, uri, utterances[] }
TS callerTalkbankExecuteCommandClient.getAlignmentSidecar
TS response typeAlignmentSidecarDocument in lsp/executeCommandPayloads.ts

alignments.wor on each utterance carries synthetic positional pairs {source_index: i, target_index: i} when the backing WorTimingSidecar is Positional, and is empty when it is Drifted or absent. See alignment-indices.md.

Analysis family

talkbank/analyze

Run one CLAN analysis command (freq, mlu, kideval, …) and return JSON.

Rust requestAnalyzeRequest = AnalyzeCommandPayload (shared with clan-core)
Rust handlerhandle_analyze(&request) in backend/analysis.rs
Rust responseserde_json::Value — the analysis command’s native JSON output
TS callerTalkbankExecuteCommandClient.analyze(request)
TS request typeAnalyzeCommandRequest in lsp/executeCommandPayloads.ts

Payload carries command_name, target_uri, and an AnalysisOptions struct with every per-command flag. See the Command Reference page for the command-name catalog.

talkbank/kidevalDatabases · talkbank/evalDatabases

Discover normative databases in a CLAN library directory. Returns the same shape for both; the extension surfaces them in different UIs.

Rust requestDiscoverDatabasesRequest { library_dir: PathBuf }
Rust handlerhandle_discover_databases(&request) in backend/analysis.rs
Rust responseVec<AvailableDatabase>
TS callerTalkbankExecuteCommandClient.kidevalDatabases / .evalDatabases
TS response typeAvailableDatabase[] in lsp/executeCommandPayloads.ts

Participants family

talkbank/getParticipants

Extract @ID participant entries from a document.

Rust requestDocumentUriRequest { uri: Url }
Rust handlerhandle_get_participants(&backend, &request) in backend/participants.rs
Rust responseVec<ParticipantEntry>
TS callerTalkbankExecuteCommandClient.getParticipants
TS response typeParticipantEntry[]

talkbank/formatIdLine

Format one @ID header line from field values. Pure formatting — does not touch a document.

Rust requestIdLineFieldsRequest { language, corpus, speaker, age, sex, group, ses, role, education, custom }
Rust handlerhandle_format_id_line(&request) in backend/participants.rs
Rust response{ formatted: String }
TS callerTalkbankExecuteCommandClient.formatIdLine
TS request typeIdLineFields

ChatOps family

talkbank/getSpeakers

Extract declared speaker metadata from @Participants.

Rust requestDocumentUriRequest { uri: Url }
Rust handlerhandle_get_speakers(&backend, &request) in backend/chat_ops/speakers.rs
Rust responseVec<SpeakerInfo>
TS callerTalkbankExecuteCommandClient.getSpeakers
TS response typeSpeakerInfo[]

talkbank/filterDocument

Filter a document down to selected speakers. Returns the filtered document text for use as a virtual document.

Rust requestFilterDocumentRequest { uri: Url, speakers: Vec<String> }
Rust handlerhandle_filter_document(&backend, &request) in backend/chat_ops/filter_document.rs
Rust response{ text: String }
TS callerTalkbankExecuteCommandClient.filterDocument

talkbank/getUtterances

Return utterance metadata used by coder mode (speaker, text, range).

Rust requestDocumentUriRequest { uri: Url }
Rust handlerhandle_get_utterances(&backend, &request) in backend/chat_ops/utterances.rs
Rust responseVec<UtteranceInfo>
TS callerTalkbankExecuteCommandClient.getUtterances
TS response typeUtteranceInfo[]

talkbank/formatBulletLine

Format one timing-bullet insertion for the transcription mode’s F4 insertion key.

Rust requestFormatBulletLineRequest { prev_ms, current_ms, speaker }
Rust handlerhandle_format_bullet_line(&request) in backend/chat_ops/format_bullet.rs
Rust responseFormattedBulletLine { bullet, new_line }
TS callerTalkbankExecuteCommandClient.formatBulletLine
TS response typeFormattedBulletLine

talkbank/scopedFind

Execute semantically scoped search in one document (main tier only, all tiers, specific dependent tier, with optional regex).

Rust requestScopedFindRequest { uri, query, scope, speakers[], regex }
Rust handlerhandle_scoped_find(&backend, &request) in backend/chat_ops/scoped_find.rs
Rust responseVec<ScopedFindMatch>
TS callerTalkbankExecuteCommandClient.scopedFind
TS request typeScopedFindRequest · TS response type ScopedFindMatch[]

Error contract

All handlers return Result<serde_json::Value, LspBackendError>. The dispatcher in backend/requests/execute_command.rs serializes successes to the JSON-RPC result; failures are returned as a string-valued result (one-field wire format) so the extension can render them inline even when no LSP Diagnostic applies. LspBackendError variants include ArgumentMissing, ArgumentInvalid, InvalidUriParse, UriNotFilePath, DocumentNotFound, LanguageServicesUnavailable(BackendInitError), and the command-agnostic ExternalServiceFailed { service, reason }.

The TS side wraps every call in three typed error classes:

  • ExecuteCommandRequestError — transport failed (disconnected, timeout)
  • ExecuteCommandResponseError — wrong payload shape
  • ExecuteCommandServerError — server returned a string-valued error

See apps/vscode-extension/src/lsp/executeCommandErrors.ts for the tagged error family and Webview Message Contracts for the panel-side decoding patterns.

Advertised command list

The LSP advertises its twelve command names during initialize via ExecuteCommandName::advertised_commands(). A unit test in backend/execute_commands.rs::tests pins the list against the manifest so adding a command without updating the advertisement is a compile-and-test failure.