fix(rpc): classic --mode rpc applies set_client_info capabilities
Fixes #4006
Part of sisyphuslabs/omo-desktop-app#4042
Problem
In classic --mode rpc (one client over stdio), set_client_info capabilities were accepted (success: true) and then ignored. The handler assigned the declared set only inside the shared-host clientInfo branch, and a classic handler has no clientInfo. A client that declared question therefore still got one select per question; the #4002 real-CLI QA run found this. It contradicts docs/rpc.md "Client information".
Change (connection-handler.ts only)
- Classic
set_client_infotakes effect. On a connection withoutclientInfo, aset_client_infothat carriescapabilitiesreplaces the handler's set. This happens after the senpi#3811 role check, so a refused declaration changes nothing. - Width-only calls keep the set. A
set_client_infowithoutcapabilitieschanges nothing, and the launch-timeSENPI_RPC_CLIENT_CAPABILITIESstays the initial value. extension_eventsfollows the declaration. Whenextension_eventscomes or goes, the handler re-subscribes extension events. The existing subscription code moved intosubscribeExtensionEventsunchanged, andrebindSessioncalls it as before.- Shared hosts are untouched. That branch keeps exactly what it did. Per-connection shared-host behaviour is #4000's, which is stacked on #3814; this PR is independent of it and based on main.
- Size: the handler grows by 14 net lines (+23/−9). The logic needs the handler's closure state (the set, the session and the event output), so it stays in the file as two small closures rather than a new module.
Evidence (exact head 6a04f92d04 on main 4dd6f3c135, Mini)
RED on main, with test/suite/regressions/issue-4006-classic-set-client-info-capabilities.test.ts and the source unchanged:
FAIL classic --mode rpc over stdio > a client that declares question gets the structured question frame expected 'select' to be 'question'
FAIL classic --mode rpc over stdio > a width-only set_client_info keeps the declared question expected 'select' to be 'question'
FAIL classic handler extension_events > declaring extension_events subscribes, and declaring without it unsubscribes expected +0 to be 1
FAIL classic handler extension_events > the launch capabilities are the initial set, which a declaration then replaces expected 1 to be +0
Tests 4 failed | 1 passed (5)
The test has two layers:
- The two question cases spawn the real CLI in
--mode rpcover stdio, with an extension that asks a question. - The
extension_eventscases run a classic handler on the faux harness: subscribe, resize (still subscribed), withdraw (unsubscribed), launch default replaced, and a role-refused declaration that changes nothing.
GREEN at 6a04f92d04 with the workspace rebuilt:
- The new file plus the RPC capability/attach/host suites present on main: 18 files, 107 tests pass.
- Every
rpc-*test undertest/andtest/suite/, plus the rpc, issue-3811, issue-2951 and issue-4006 regressions, withCI=1:
Test Files 240 passed | 1 skipped (241)
Tests 1464 passed | 9 skipped (1473)
tsc --noEmit -p tsconfig.json: exit 0.biome checkon the changed files: clean.node scripts/check-pr-changelog.mjs --base 4dd6f3c135:changelog-gate: PASS.
Coordination
#4000 also edits the set_client_info case and the extension-event subscription in connection-handler.ts. Whichever lands second rebases. The two changes agree: in #4000 a classic handler keeps no clientInfo, so this branch is still the classic path there.
Summary by cubic
Fixes #4006, part of sisyphuslabs/omo-desktop-app#4042. In classic --mode rpc, a client's set_client_info capabilities were accepted but ignored, so a client declaring question still got single select dialogs. The classic handler now applies the declaration after the connection-role check, cancels pending structured questions when question is withdrawn, and re-subscribes extension events when extension_events comes or goes.
- Extracted
subscribeExtensionEventsand addedreplaceClientCapabilitiesfor the classic path; the shared-host branch is unchanged. - A
set_client_infowithoutcapabilitieskeeps the set;SENPI_RPC_CLIENT_CAPABILITIESis only the initial value. - Withdrawing
questionsettles each pending structured question once asquestion_resolvedwith outcomecancelled, matching shared hosts. - Added regression tests in
test/suite/regressions/issue-4006-classic-set-client-info-capabilities.test.tsand documented the behavior indocs/rpc.md.