Skip to content

feat(protocol)!: narrow the supported scope to sixteen events - #3

Merged
a7vinx merged 1 commit into
mainfrom
feat/narrow-scope
Aug 12, 2026
Merged

feat(protocol)!: narrow the supported scope to sixteen events#3
a7vinx merged 1 commit into
mainfrom
feat/narrow-scope

Conversation

@a7vinx

@a7vinx a7vinx commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Three events leave the supported protocol scope: session:input_state, session:required_action and session:task_ready. The supported surface goes from nineteen events to sixteen.

All three continue to be emitted by the server and to reach callers unchanged. What changes is that the SDK no longer models them and makes no compatibility commitment about them — the same treatment every other unsupported event receives.

Why each one leaves

session:input_state described whether the composer accepts input, and served as the SDK's signal that a turn had ended. Recording a live session showed the signal does not hold: the event arrives twice at the very start of a turn, before the agent has produced anything.

input_state    waiting_input      <- turn begins here
message_status received
state          chat
input_state    waiting_input
llm_thinking   going
…
text_part      "Working on it..."  <- the reply starts here

A turn that ends on this event ends before the reply. The exit path that depended on it is removed with it.

session:required_action restated in a dedicated event what other events already carry. Nothing in the SDK consumed it.

session:task_ready reports what a task will cost in credits. The server computes confirmed from the account balance and, when the balance is sufficient, starts the task itself. The event asks nothing of a client.

What a client keeps

A session stopped on its credit balance remains visible. session:state is in scope, and its values include credits_exhausted and task_paused.

Condition Reported by
Insufficient credit balance session:statecredits_exhausted, task_paused
Account restriction session:restriction
Server-reported failure session:error
Session awaiting a form session:form_to_user
Expired session is_stale, over REST
Outstanding phone verification Nothing

The exception is phone verification, a provisioning prerequisite that has no in-session remedy and now no in-session signal. The README states this rather than leaving it implicit.

Removed from the public API

InputState, InputStateCode, RequiredActionData and TaskReadyData, along with the three S2CEvent members. Callers that need these payloads can still read them off the raw event.

session:task_ready was also counted towards the SDK's judgement that an agent had responded, which governs how long a turn waits between events. Removing it narrows that set — an accurate narrowing, since a cost estimate is not a reply.

Verification

  • 85 offline tests pass; ruff check clean; python -m build and twine check pass.
  • 7 live tests pass against a local backend at PINE_BASE_URL=http://…:9513. The outbound-call test was deselected: it places a real call and spends credits.
  • The event ordering quoted above is from a recording of that local session, not from reading the server.

Note on 0.4.0

0.4.0 is unreleased — PyPI is on 0.3.3 — so these changes fold into its changelog entry rather than opening a new version.

🤖 Generated with Claude Code

`session:input_state`, `session:required_action` and `session:task_ready` leave
the supported surface. All three continue to be emitted by the server and to
reach callers unchanged; the SDK no longer models them and makes no commitment
about them.

## Why each one goes

`session:input_state` described whether the composer accepts input. It was also
the SDK's signal that a turn had ended, and recording a live session showed why
that does not hold: the event arrives twice at the very start of a turn, before
the agent has said anything. A turn ending on it truncates the reply.

`session:required_action` restated in a dedicated event what other events
already carry.

`session:task_ready` reports what a task will cost. The server computes
`confirmed` from the balance and, when it is sufficient, starts the task itself
— so the event asks nothing of a client and its absence costs a client nothing.

## What a client keeps

A session stopped on its credit balance is still visible: `session:state` is in
scope and its values include `credits_exhausted` and `task_paused`. Together
with `session:restriction` and `session:error` — and `is_stale` over REST for an
expired session — every condition that halts a session remains reportable except
one.

The exception is an outstanding phone verification, which is a provisioning
prerequisite with no in-session remedy and now no in-session signal. The README
says so rather than leaving it implicit.

`session:task_ready` was also counted towards the SDK's judgement that an agent
had responded, which governs how long a turn waits between events. Removing it
narrows that set — an accurate narrowing, since a cost estimate is not a reply.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@a7vinx
a7vinx force-pushed the feat/narrow-scope branch from f1f93bd to 88d682e Compare August 12, 2026 15:16
@a7vinx
a7vinx merged commit 145d009 into main Aug 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant