SessionApi

works.iterative.claude.ui.transcript.SessionApi
object SessionApi

What a host that lets a page reach a session must answer, described once.

These are descriptions, not servers: a consumer attaches its own logic with serverLogic and interprets the result with whichever Tapir server matches the effect system it already runs — ZIO, cats-effect, Future, sync. That is why Tapir sits on this side of the module and not in the cross-built sources: the element reaches the same address with the browser's own fetch, so the browser bundle carries none of this.

The address is taken from SessionEndpoint, the one place a session's addresses are written down, so the description and the URL the element builds cannot drift apart.

The reading operations refuse with a TranscriptFailure and the writing ones with a SessionFailure, because they fail at different things: a transcript that cannot be read is not a session that will not take what was typed.

Who may ask is the host's to decide. Nothing here authenticates, and the writing operations start an agent, hand it what somebody typed, and stop it — so a host that answers them anywhere but its own machine's loopback must put its own authentication in front of them, and one that answers a browser must also refuse a request whose Origin is not its own, or any page open in that browser can start and drive a session on it.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
SessionApi.type

Members list

Value members

Concrete methods

def follow[S](streams: Streams[S]): PublicEndpoint[String, TranscriptFailure, streams.BinaryStream, S]

Follows one session for as long as it is being written.

Follows one session for as long as it is being written.

The answer is a stream of server-sent events, one per stretch the agent writes, each carrying a TranscriptTail: how many of the rows the page holds are still what the transcript renders, and the markup for the rest. A page therefore replaces only what moved, and the conversation it already has stays where it is.

The stream type is the consumer's: a host passes the Streams of whatever effect system it runs, and writes the events with that system's own server-sent-events support. This module describes the address, the question, and what the answer means; how bytes are put on a socket is the host's, exactly as it is for the other three.

A refusal answers before the stream starts, in the same JSON history refuses with. A browser following this with EventSource never reads that body — it is told only that the connection failed, and tries again — but a consumer that asks with an ordinary client gets the reason.

Attributes

Concrete fields

val artifact: PublicEndpoint[(String, String, Int), TranscriptFailure, (Array[Byte], String), Any]

Reads one picture a call came back with.

Reads one picture a call came back with.

A transcript names its pictures rather than carrying them, so this is where a page fetches one: the session, the call it answered, and which part of that answer it is. Only the picture formats the contract shows are served, and the answer says what it is rather than leaving a browser to work it out from the bytes — which is what makes an artifact safe to show in a page that is not ours.

Attributes

val history: PublicEndpoint[String, TranscriptFailure, Transcript, Any]

Reads one session's transcript: the newest page of the conversation, in the shape this contract owns.

Reads one session's transcript: the newest page of the conversation, in the shape this contract owns.

A refusal answers with the status the failure itself carries, so every host reports a missing session the same way without deciding it again.

Attributes

val interrupt: PublicEndpoint[String, SessionFailure, Unit, Any]

Stops the turn a session is running.

Stops the turn a session is running.

This is the vendor's own control channel, not the page letting go: letting go of the transcript would stop us watching while the agent went on working. The turn it stops ends the way any turn ends — with a result, on the transcript — so a page learns that it stopped by following, as it learns everything else.

Attributes

val markup: PublicEndpoint[String, TranscriptTrouble, String, Any]

Reads one session's transcript, already rendered as the cc-* markup a page inserts as-is.

Reads one session's transcript, already rendered as the cc-* markup a page inserts as-is.

This is the address CC-D3 gives the browser: a transcript's rows have one producer, on the JVM, so the element fetches this instead of drawing rows from the JSON history carries. A refusal answers in the same vocabulary — TranscriptMarkup.trouble, written as HTML — so the element has one thing to do with either answer: insert what came back.

A refusal is typed as what the wire carries — a TranscriptTrouble: the status, and the page the host rendered. It is not typed as a TranscriptFailure, because a status and a page of HTML do not say which case produced them, and a client told a case that was never sent would be told something untrue. A consumer that wants the failure as data reads it off history, whose refusals stay JSON.

Attributes

val send: PublicEndpoint[(String, String), SessionFailure, Unit, Any]

Says something to a session.

Says something to a session.

What comes of it is not the answer to this request. The agent may take a while, and may do several things; everything it does reaches the transcript, so a page that has sent something watches follow for what happens, exactly as it watches a session it has sent nothing to.

Attributes

val start: PublicEndpoint[Unit, SessionFailure, SessionStarted, Any]

Starts a session for a page that asked for one.

Starts a session for a page that asked for one.

A page cannot talk to a session somebody else's terminal started: what is written to is a process this host holds, so this is where one begins. The answer is the name the CLI gave it, which is every other address this page will ask for.

What the session is allowed to do is the host's, not the page's: nothing here says which tools it may reach or what it may touch, so a page cannot ask for more than the host decided.

Attributes