Skip to content

Fix connect mode with jupyter-collaboration#95

Open
andrii-i wants to merge 8 commits into
jupyter-ai-contrib:mainfrom
andrii-i:fix-fileid-jupyter-collaboration
Open

Fix connect mode with jupyter-collaboration#95
andrii-i wants to merge 8 commits into
jupyter-ai-contrib:mainfrom
andrii-i:fix-fileid-jupyter-collaboration

Conversation

@andrii-i

@andrii-i andrii-i commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Fixes #92

Problem

Connect mode only works with jupyter-server-documents (JSD) and fails against jupyter-collaboration in four ways:

  1. File ID retrieval calls POST /api/fileid/index, which only exists in JSD. jupyter-collaboration exposes PUT /api/collaboration/session/{path} instead. Connect mode fails with 404 on any jupyter-collaboration server.

  2. The Y.js WebSocket handshake is rejected with 1003 unknown_session. jupyter-collaboration requires a sessionId query parameter on the room WebSocket URL. nb-cli does not pass it.

  3. Kernel WebSocket messages are not parsed correctly. jupyter-collaboration does not hardcode the v1 kernel protocol the way JSD does. Without negotiating the v1.kernel.websocket.jupyter.org subprotocol, the server falls back to the legacy 4-byte big-endian frame format, which the v1 parser (8-byte little-endian offsets) silently fails to decode.

  4. Cell outputs are never written back to the notebook. JSD writes outputs to the Y.js document server-side (server_side_execution=True). jupyter-collaboration does not. nb-cli relies entirely on reading outputs from the Y.js document after the server writes them, so nb execute returns empty outputs.

Changes

get_file_id() in ydoc.rs tries POST /api/fileid/index first (JSD). On 404, falls back to PUT /api/collaboration/session/{path} (jupyter-collaboration), which returns both fileId and sessionId. The return type is now (String, Option<String>) to carry the optional session ID. build_room_ws_url() uses Url::parse + query_pairs_mut for proper encoding and appends sessionId when present. A server_writes_outputs flag tracks which output path to use (true for JSD where session ID is absent, false for jupyter-collaboration).

KernelWebSocket::connect() in websocket.rs sends Sec-WebSocket-Protocol: v1.kernel.websocket.jupyter.org during the handshake. This makes the server select the v1 binary frame format regardless of which Y.js backend is installed.

When server_writes_outputs is false (jupyter-collaboration path), execute_code in mod.rs collects outputs from kernel iopub messages (stream, execute_result, display_data, error) into a local vec. After the kernel goes idle, it writes them to the Y.js document via update_cell_outputs and update_cell_execution_count, syncs, and the existing read loop picks them up. A fallback path returns collected kernel outputs directly if the Y.js write/sync times out.

Removed #[allow(dead_code)] from update_cell_outputs and update_cell_execution_count in output_conversion.rs since they are now called in the client-write path.

Four files changed, no new dependencies.

Testing

Tested end-to-end against real Jupyter servers in clean venvs:

Command jupyter-collaboration 4.4.1 jupyter-server-documents 0.1.2
nb connect pass pass
nb read pass pass
nb execute (2 cells, stream + execute_result) pass, outputs returned pass, outputs returned
nb output clear pass pass
nb status pass pass

Merge order

Needs to be merged after #91.

@andrii-i andrii-i added the enhancement New feature or request label Jun 8, 2026
@andrii-i andrii-i marked this pull request as ready for review June 8, 2026 22:28
@andrii-i andrii-i force-pushed the fix-fileid-jupyter-collaboration branch from 11f06fe to e297c4c Compare June 9, 2026 08:55
@dlqqq

dlqqq commented Jun 9, 2026

Copy link
Copy Markdown

Was hoping the change would be as simple as duplicating our endpoint in JSD to also cover the /api/fileid/id route -- but the endpoints do different things so that's not possible. I think this is the right change for now.

Hmm, but it seems that JSD's POST /api/fileid/index is pretty close to JCollab's PUT /api/collaboration/session/{path}. Maybe we can do that in JSD and then this would work? Would love to see some research on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connect mode fails with jupyter-collaboration (FileID API mismatch)

2 participants