| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
The SDK modelled 33 server-to-client events selected from roughly 60 the backend emits, with nothing marking which of them carry a compatibility guarantee. The supported scope names 19, and the two sets were not in a containment relationship. ## Protocol surface The modelled surface is now the supported scope and nothing else. Four supported events were absent and are added, with models: `session:llm_thinking`, `session:tool_status`, `session:required_action` and `session:restriction`. Between them they carry what a task is doing and why it stopped. The reasoning stream previously ran on `session:work_log`, which is outside the scope and is a distinct event from `session:llm_thinking` rather than a former name for it. Events outside the scope are unmodelled but still delivered, unchanged and in order. `is_supported_event()` distinguishes the two surfaces and `emit_event()` sends an unmodelled event. This follows the scope's own position: tolerating an unsupported event is required, depending on one is not. ## Requirements Three requirements the scope states as MUST were unmet: - **Recovery.** `session:join` now carries `since_revision` `"0"` and ignores the incremental-synchronisation fields. `rebuild()` pages through history until the cursor is exhausted, on every join and every reconnect. A short or empty page does not indicate exhaustion. - **Deduplication.** Events are keyed on the event identifier together with the message type. Identifiers collide across types, so keying on the identifier alone discards valid events. - **Blocking conditions.** `InputState` exposes the reason from `session:input_state`, including the two conditions the scope calls out. Turn control no longer depends on unsupported events. It previously hinged on `session:ask_for_location`, `session:interactive_auth_confirmation`, `session:three_way_call` and `session:reward`. ## Tests Three layers. `tests/protocol/fixtures` holds one envelope per supported event, with provenance recorded — 14 captured from live sessions, 4 derived from the protocol definition for conditions an ordinary session does not reach. `test_contract.py` validates one envelope at a time. `test_flow.py` drives sequences through the real transport and pins each MUST by name, including that an unrecognised event arrives verbatim without disturbing ordering. `tests/integration` was two overlapping copies of one live script, one of which asserted behaviour the SDK had already dropped. It is now a single suite that also serves as the fixture recorder. It places one call to a number in the range NANP reserves for fiction, which is what makes `session:task_ready`, `session:tool_status` and `session:task_finished` observable. It stays out of CI: it requires a token and consumes credits. CI gains a lint step. `ruff` was configured but never invoked. ## Fixed Sessions joined through `join_session()` were never re-joined after a reconnect. Membership was tracked on the fire-and-forget emit path, while joining is a request/response call. ## Breaking `send_auth_confirmation()`, `send_location_response()` and `send_location_selection()` are removed, along with `NotificationEvent`, the `session:reward` and `session:payment` models, the unsupported event constants, the `action` argument on `chat()`, and `request_work_log` on `get_history()`. Each remains reachable through `emit_event()`. `pine-mcp-server` calls the three removed methods and depends on `pine-assistant>=0.3.2`. It requires a corresponding change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
Summary
The SDK modelled 33 server-to-client events selected from roughly 60 the backend emits, with nothing marking which of them carry a compatibility guarantee. The supported protocol scope names 19, and the two sets were not in a containment relationship.
This aligns the modelled surface with that scope, implements the requirements the scope states as MUST, and adds a test layer that pins both.
Protocol surface
Four supported events were absent and are added, with models:
The reasoning stream previously ran on session:work_log, which is outside the scope. It is a distinct event from session:llm_thinking, not a former name for it.
Events outside the scope are unmodelled but still delivered, unchanged and in order. is_supported_event() distinguishes the two surfaces; emit_event() sends an unmodelled event. This follows the scope's own position: tolerating an unsupported event is required, depending on one is not.
Requirements implemented
Recovery. session:join carries since_revision "0" and ignores the incremental-synchronisation fields. rebuild() pages through history until the cursor is exhausted, on every join and every reconnect. A short or empty page does not indicate exhaustion.
Deduplication. Events are keyed on the event identifier together with the message type. Identifiers collide across types, so keying on the identifier alone discards valid events.
Blocking conditions. InputState exposes the reason from session:input_state, including insufficient credits and outstanding phone verification.
Turn control no longer depends on unsupported events. It previously hinged on session:ask_for_location, session:interactive_auth_confirmation, session:three_way_call and session:reward.
Tests
Three layers, separated because they fail for different reasons.
tests/protocol/fixtures holds one envelope per supported event, with provenance recorded: 14 captured from live sessions, 4 derived from the protocol definition for conditions an ordinary session does not reach. test_contract.py validates one envelope at a time — a failure means a payload shape moved. test_flow.py drives sequences through the real transport and pins each MUST by name, including that an unrecognised event arrives verbatim without disturbing ordering.
tests/integration was two overlapping copies of one live script, one of which asserted behaviour the SDK had already dropped. It is now a single suite that also serves as the fixture recorder. It places one call to a number in the range NANP reserves for fiction, which is what makes session:task_ready, session:tool_status and session:task_finished observable. It remains outside CI: it requires a token and consumes credits.
CI gains a lint step. ruff was configured but never invoked.
Fixed
Sessions joined through join_session() were never re-joined after a reconnect. Membership was tracked on the fire-and-forget emit path, while joining is a request/response call.
Breaking changes
Removed: send_auth_confirmation(), send_location_response(), send_location_selection(), NotificationEvent, the session:reward and session:payment models, the unsupported event constants, the action argument on chat(), and request_work_log on get_history(). Each remains reachable through emit_event().
pine-mcp-server calls the three removed methods and declares pine-assistant>=0.3.2. It requires a corresponding change before this is released.
Verification
🤖 Generated with Claude Code