The desktop ships cwd_explicit provenance with session.create (#52589), but the wire contract (extra=forbid) rejected the unknown key, so every remote-mode create failed with 'out of sync (different versions)' and the composer never accepted the draft (Desktop core E2E remote-topology). Local-backend lanes never sent it (a bare new chat is detached, no cwd). Regenerate the shared contract TS + OpenRPC from the updated registry.
734 lines
23 KiB
Python
734 lines
23 KiB
Python
"""Session lifecycle contracts (``tui_gateway/methods_session.py``): create / resume / activate /
|
|
close, the live-session snapshot those share, history + compression + undo, mid-turn corrections,
|
|
listing/browsing stored rows, spawn-tree snapshots, event replay and the stateless one-shot LLM call.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import Field
|
|
|
|
from .base import JsonValue, Params, Result, WireEnum
|
|
from .common import (OpenModel, PendingApproval, ProfileParams, SessionLiveInfo, SessionParams, TranscriptMessage,
|
|
Usage)
|
|
from .connectors_operation import ConnectionRequestPayload
|
|
from .registry import method
|
|
|
|
|
|
# ── shared live-session snapshot ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
class OpenRequestEntry(Result):
|
|
"""One unanswered server→client request (``server_requests.Request.snapshot``); the reconnecting
|
|
client re-delivers it to its request handlers."""
|
|
|
|
id: str
|
|
method: str
|
|
params: dict[str, JsonValue]
|
|
|
|
|
|
class InflightTurn(Result):
|
|
"""``session_auto_continue._inflight_snapshot``: the live (or retained failed) turn a reconnecting
|
|
client rebuilds its bubbles from."""
|
|
|
|
assistant: str = ""
|
|
streaming: bool = False
|
|
user: str = ""
|
|
display_kind: str | None = None
|
|
display_metadata: dict[str, JsonValue] | None = None
|
|
corrections: list[str] | None = None
|
|
correction_offsets: list[int] | None = None
|
|
error: str | None = None
|
|
status: str | None = None
|
|
recoverable: bool | None = None
|
|
error_surface: dict[str, JsonValue] | None = None
|
|
|
|
|
|
class QueuedPrompt(Result):
|
|
user: str
|
|
|
|
|
|
class TodoState(Result):
|
|
"""``tool_progress._normalize_todo_state``: the authoritative todo snapshot."""
|
|
|
|
todos: list[dict[str, JsonValue]]
|
|
revision: int
|
|
|
|
|
|
class AutoContinue(Result):
|
|
"""A crash-interrupted turn was scheduled to continue right after this resume."""
|
|
|
|
attempt: int
|
|
interrupted_at: float
|
|
|
|
|
|
class LiveSessionStatus(WireEnum):
|
|
idle = "idle"
|
|
starting = "starting"
|
|
waiting = "waiting"
|
|
working = "working"
|
|
streaming = "streaming" # lazy watch window whose child run is active
|
|
resuming = "resuming" # deferred hydration in flight
|
|
|
|
|
|
class LiveSessionSnapshot(Result):
|
|
"""Union of ``server._live_session_payload``, ``methods_session._resume_response`` and the
|
|
live-unpersisted resume path; keys only some paths produce are optional."""
|
|
|
|
session_id: str
|
|
message_count: int
|
|
messages: list[TranscriptMessage]
|
|
info: SessionLiveInfo
|
|
stored_session_id: str | None = None
|
|
resumed: str | None = None
|
|
session_key: str | None = None
|
|
messages_omitted: bool | None = None
|
|
hydrating: bool | None = None
|
|
running: bool | None = None
|
|
turn_started_at: float | None = None
|
|
started_at: float | None = None
|
|
status: str | None = None # a LiveSessionStatus value
|
|
inflight: InflightTurn | None = None
|
|
queued: QueuedPrompt | None = None
|
|
pending_approval: PendingApproval | None = None
|
|
open_requests: list[OpenRequestEntry] | None = None
|
|
# The open connection operation (``tools/connectors/live.current``) as its ``connection.request``
|
|
# payload: the card restores with the server's deadline after a reconnect or restart.
|
|
pending_connection: ConnectionRequestPayload | None = None
|
|
todo_state: TodoState | None = None
|
|
auto_continue: AutoContinue | None = None
|
|
|
|
|
|
# ── session.create ────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SeedMessage(Params):
|
|
"""One create-time transcript row (``session_history._coerce_seed_history``); ``text`` is the
|
|
legacy alias of ``content``; only ``display_kind: "hidden"`` is accepted from the wire. Clients
|
|
forward stored rows verbatim (``_row_id``, ``timestamp``, …) and the coercer drops what it does
|
|
not use, so the row stays open."""
|
|
|
|
model_config = Params.model_config | {"extra": "allow"}
|
|
|
|
role: str
|
|
content: str | None = None
|
|
text: str | None = None
|
|
display_kind: str | None = None
|
|
|
|
|
|
class SessionCreateParams(ProfileParams):
|
|
cols: int | None = None
|
|
source: str | None = None
|
|
cwd: str | None = None
|
|
# #52589: provenance for ``cwd`` — true only for a deliberate workspace pick;
|
|
# an inherited app-global workspace must yield to a named profile's terminal.cwd.
|
|
cwd_explicit: bool | None = None
|
|
messages: list[SeedMessage] | None = None
|
|
parent_session_id: str | None = None
|
|
title: str | None = None
|
|
model: str | None = None
|
|
provider: str | None = None
|
|
reasoning_effort: str | None = None
|
|
fast: bool | None = None # presence is the contract: omitted inherits, true pins priority, false pins normal
|
|
close_on_disconnect: bool = False
|
|
hidden: bool = False
|
|
room_plumbing: bool = False
|
|
follow_profile_config: bool = False
|
|
|
|
|
|
class SessionCreateResult(Result):
|
|
session_id: str
|
|
stored_session_id: str
|
|
message_count: int
|
|
messages: list[TranscriptMessage]
|
|
info: SessionLiveInfo
|
|
|
|
|
|
method("session.create", params=SessionCreateParams, result=SessionCreateResult,
|
|
doc="Mint a live session (agent builds after the reply); a DB row appears on the first prompt unless seeded.")
|
|
|
|
|
|
class SessionBranchStoredParams(ProfileParams):
|
|
parent_session_id: str = Field(min_length=1)
|
|
cols: int | None = None
|
|
source: str | None = None
|
|
cwd: str | None = None
|
|
|
|
|
|
class SessionBranchStoredResult(Result):
|
|
session_id: str
|
|
stored_session_id: str
|
|
message_count: int
|
|
messages_omitted: bool
|
|
info: SessionLiveInfo
|
|
|
|
|
|
method("session.branch_stored", params=SessionBranchStoredParams, result=SessionBranchStoredResult,
|
|
doc="Whole-session branch of a stored parent: the owning backend reads and copies the transcript, "
|
|
"which never crosses the wire (a separate method so an older gateway fails loudly, not with an empty "
|
|
"branch).")
|
|
|
|
|
|
# ── session.resume / activate ─────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SessionResumeParams(SessionParams):
|
|
"""``session_id`` is the STORED id (or an exact title); the reply's ``session_id`` is the runtime id."""
|
|
|
|
cols: int | None = None
|
|
source: str | None = None
|
|
lazy: bool = False
|
|
defer_history: bool = False
|
|
omit_messages: bool = False
|
|
eager_build: bool = False
|
|
close_on_disconnect: bool = False
|
|
|
|
|
|
class SessionResumeResult(LiveSessionSnapshot):
|
|
pass
|
|
|
|
|
|
method("session.resume", params=SessionResumeParams, result=SessionResumeResult,
|
|
doc="Attach to a stored session: reuse it if live here, else lazy / deferred / cold / eager rebuild.")
|
|
|
|
|
|
class SessionActivateParams(SessionParams):
|
|
cols: int | None = None # sent by the desktop; the handler keeps the session's current width
|
|
omit_messages: bool = False
|
|
|
|
|
|
class SessionActivateResult(LiveSessionSnapshot):
|
|
pass
|
|
|
|
|
|
method("session.activate", params=SessionActivateParams, result=SessionActivateResult,
|
|
doc="Attach the frontend to a live session without closing the previously focused one.")
|
|
|
|
|
|
# ── listing ───────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SessionListParams(ProfileParams):
|
|
title: str | None = None # exact-title lookup (title as identity); windowless
|
|
limit: int | None = None
|
|
include_hidden: bool = False
|
|
|
|
|
|
class SessionListRow(Result):
|
|
"""``methods_session._session_row_summary``; ``resolved_id`` only on a title lookup that followed a
|
|
compression lineage to its tip."""
|
|
|
|
id: str
|
|
resolved_id: str | None = None
|
|
title: str = ""
|
|
preview: str = ""
|
|
started_at: float = 0
|
|
message_count: int = 0
|
|
source: str = ""
|
|
|
|
|
|
class SessionListResult(Result):
|
|
sessions: list[SessionListRow]
|
|
|
|
|
|
method("session.list", params=SessionListParams, result=SessionListResult,
|
|
doc="Human-facing stored sessions, most recent first (sub-agent / kanban sources denied).")
|
|
|
|
|
|
class SessionMostRecentParams(ProfileParams):
|
|
pass
|
|
|
|
|
|
class SessionMostRecentResult(Result):
|
|
session_id: str | None
|
|
title: str | None = None
|
|
started_at: float | None = None
|
|
source: str | None = None
|
|
|
|
|
|
method("session.most_recent", params=SessionMostRecentParams, result=SessionMostRecentResult,
|
|
doc="Most recent human-facing session; errors fold into a null session_id.")
|
|
|
|
|
|
class SessionActiveListParams(ProfileParams):
|
|
current_session_id: str | None = None
|
|
|
|
|
|
class SessionActiveItem(Result):
|
|
"""``server._session_live_item``."""
|
|
|
|
current: bool
|
|
id: str
|
|
last_active: float
|
|
message_count: int
|
|
model: str
|
|
preview: str
|
|
session_key: str
|
|
started_at: float
|
|
status: LiveSessionStatus
|
|
title: str
|
|
|
|
|
|
class SessionActiveListResult(Result):
|
|
sessions: list[SessionActiveItem]
|
|
|
|
|
|
method("session.active_list", params=SessionActiveListParams, result=SessionActiveListResult,
|
|
doc="Live sessions in this process, insertion order (not a DB browser).")
|
|
|
|
|
|
# ── stored-row mutation ───────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SessionDeleteParams(SessionParams):
|
|
"""``session_id`` is the STORED id."""
|
|
|
|
|
|
class SessionDeleteResult(Result):
|
|
deleted: str
|
|
|
|
|
|
method("session.delete", params=SessionDeleteParams, result=SessionDeleteResult,
|
|
doc="Delete a stored session + transcripts; refused while it is live here.")
|
|
|
|
|
|
class SessionTitleParams(SessionParams):
|
|
title: str | None = None # absent: read; present: set (non-empty)
|
|
|
|
|
|
class SessionTitleResult(Result):
|
|
title: str
|
|
session_key: str | None = None
|
|
pending: bool | None = None # True: no row yet, applied on the first turn
|
|
|
|
|
|
method("session.title", params=SessionTitleParams, result=SessionTitleResult,
|
|
doc="Read or set a live session's title; a title set before the row exists is queued.")
|
|
|
|
|
|
class SessionSetHiddenParams(Params):
|
|
"""``session_id`` is a live runtime id first, else a stored id / key / title."""
|
|
|
|
session_id: str
|
|
hidden: bool = True
|
|
profile: str | None = None
|
|
|
|
|
|
class SessionSetHiddenResult(Result):
|
|
hidden: bool
|
|
session_key: str
|
|
|
|
|
|
method("session.set_hidden", params=SessionSetHiddenParams, result=SessionSetHiddenResult,
|
|
doc="Set/clear hidden (out of the default list, still resumable by its owner) on a session + lineage.")
|
|
|
|
|
|
class SessionWorkspaceMoveParams(ProfileParams):
|
|
session_key: str
|
|
cwd: str
|
|
|
|
|
|
class SessionWorkspaceMoveResult(Result):
|
|
cwd: str
|
|
branch: str | None = None
|
|
git_repo_root: str | None = None
|
|
|
|
|
|
method("session.workspace.move", params=SessionWorkspaceMoveParams, result=SessionWorkspaceMoveResult,
|
|
doc="Re-home a stored session's workspace; git identity is replaced and a live agent follows.")
|
|
|
|
|
|
class SessionCwdSetParams(SessionParams):
|
|
cwd: str
|
|
|
|
|
|
class SessionCwdSetResult(SessionLiveInfo):
|
|
"""The refreshed ``session.info`` view (full agent view, or the lazy shape)."""
|
|
|
|
|
|
method("session.cwd.set", params=SessionCwdSetParams, result=SessionCwdSetResult,
|
|
doc="Change a live, idle session's working directory.")
|
|
|
|
|
|
# ── live-session lifecycle ────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SessionCloseParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionCloseResult(Result):
|
|
closed: bool # False when the runtime id was already gone
|
|
|
|
|
|
method("session.close", params=SessionCloseParams, result=SessionCloseResult,
|
|
doc="Tear down a live session (its stored row stays resumable).")
|
|
|
|
|
|
class SessionBranchParams(SessionParams):
|
|
name: str | None = None
|
|
count: int | None = None # keep only the first N rows of the source history
|
|
|
|
|
|
class SessionBranchResult(Result):
|
|
session_id: str
|
|
stored_session_id: str
|
|
title: str
|
|
parent: str
|
|
message_count: int
|
|
messages: list[TranscriptMessage]
|
|
info: SessionLiveInfo
|
|
|
|
|
|
method("session.branch", params=SessionBranchParams, result=SessionBranchResult,
|
|
doc="Fork a live session into a new stored child that shares the parent's history so far.")
|
|
|
|
|
|
class SessionBranchWholeParams(SessionParams):
|
|
name: str | None = None
|
|
|
|
|
|
class SessionBranchWholeResult(Result):
|
|
session_id: str
|
|
stored_session_id: str
|
|
title: str
|
|
parent: str
|
|
message_count: int
|
|
messages_omitted: bool
|
|
info: SessionLiveInfo
|
|
|
|
|
|
method("session.branch_whole", params=SessionBranchWholeParams, result=SessionBranchWholeResult,
|
|
doc="session.branch of the whole history without echoing the copied transcript back.")
|
|
|
|
|
|
class SessionUndoParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionUndoResult(Result):
|
|
removed: int
|
|
|
|
|
|
method("session.undo", params=SessionUndoParams, result=SessionUndoResult,
|
|
doc="Drop the last user turn (and everything after it) from an idle session.")
|
|
|
|
|
|
class SessionSaveParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionSaveResult(Result):
|
|
"""Under turn isolation the compute host's result passes through verbatim."""
|
|
|
|
file: str | None = None
|
|
model_config = Result.model_config | {"extra": "allow"}
|
|
|
|
|
|
method("session.save", params=SessionSaveParams, result=SessionSaveResult,
|
|
doc="Export the transcript to ~/.hermes/sessions/saved (classic /save).")
|
|
|
|
|
|
class SessionStatusParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionStatusResult(Result):
|
|
output: str
|
|
|
|
|
|
method("session.status", params=SessionStatusParams, result=SessionStatusResult,
|
|
doc="Rendered /status text for the session.")
|
|
|
|
|
|
class SessionHistoryParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionHistoryResult(Result):
|
|
count: int
|
|
messages: list[TranscriptMessage]
|
|
|
|
|
|
method("session.history", params=SessionHistoryParams, result=SessionHistoryResult,
|
|
doc="The durable display transcript (ancestors included, row ids attached).")
|
|
|
|
|
|
class SessionUsageParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class SessionUsageResult(Usage):
|
|
credits_lines: list[str] | None = None
|
|
|
|
|
|
method("session.usage", params=SessionUsageParams, result=SessionUsageResult,
|
|
doc="Token / context / cost counters for the session (+ Nous credit lines when available).")
|
|
|
|
|
|
class SessionContextBreakdownParams(SessionParams):
|
|
pass
|
|
|
|
|
|
class ContextCategory(Result):
|
|
color: str
|
|
id: str
|
|
label: str
|
|
tokens: int
|
|
|
|
|
|
class ContextFileSource(Result):
|
|
"""One row of ``agent.context_file_sources.list_context_file_sources``."""
|
|
|
|
label: str
|
|
path: str
|
|
chars: int
|
|
est_tokens: int
|
|
loaded: bool
|
|
status: str
|
|
|
|
|
|
class SessionContextBreakdownResult(Result):
|
|
"""``agent.context_breakdown.compute_session_context_breakdown`` (empty categories before the agent builds)
|
|
plus the per-file context manifest (empty until the agent exists)."""
|
|
|
|
categories: list[ContextCategory]
|
|
context_max: int
|
|
context_percent: int
|
|
context_used: int
|
|
estimated_total: int
|
|
context_estimated: bool
|
|
context_source: str
|
|
model: str
|
|
context_files: list[ContextFileSource] = []
|
|
|
|
|
|
method("session.context_breakdown", params=SessionContextBreakdownParams, result=SessionContextBreakdownResult,
|
|
doc="Cursor-style split of the context window by category.")
|
|
|
|
|
|
# ── compression ───────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class CompressionSummary(OpenModel):
|
|
"""``agent.manual_compression_feedback.summarize_manual_compression``."""
|
|
|
|
noop: bool = False
|
|
aborted: bool = False
|
|
refused_would_grow: bool | None = None
|
|
fallback_used: bool | None = None
|
|
headline: str = ""
|
|
token_line: str = ""
|
|
note: str | None = None
|
|
|
|
|
|
class SessionCompressParams(SessionParams):
|
|
focus_topic: str | None = None
|
|
|
|
|
|
class SessionCompressResult(Result):
|
|
"""In-process: the before/after summary + replacement transcript. Compute host: its result passes
|
|
through (hence open) with ``turn_isolation``; a lock held elsewhere answers ``compressed: false``."""
|
|
|
|
status: str | None = None # compressed | aborted | pending
|
|
removed: int | None = None
|
|
before_messages: int | None = None
|
|
after_messages: int | None = None
|
|
before_tokens: int | None = None
|
|
after_tokens: int | None = None
|
|
summary: CompressionSummary | None = None
|
|
usage: Usage | None = None
|
|
info: SessionLiveInfo | None = None
|
|
messages: list[TranscriptMessage] | None = None
|
|
compressed: bool | None = None
|
|
lock_held: bool | None = None
|
|
message: str | None = None
|
|
turn_isolation: bool | None = None
|
|
host_ack: dict[str, JsonValue] | None = None
|
|
model_config = Result.model_config | {"extra": "allow"}
|
|
|
|
|
|
method("session.compress", params=SessionCompressParams, result=SessionCompressResult,
|
|
doc="Manual /compress of an idle session, optionally focused on a topic.")
|
|
|
|
|
|
# ── interrupt / steer / redirect ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SessionInterruptParams(SessionParams):
|
|
expected_hosted_task_id: str | None = None # only interrupt if this hosted task is the running one
|
|
|
|
|
|
class InterruptStatus(WireEnum):
|
|
interrupted = "interrupted"
|
|
not_interrupted = "not_interrupted"
|
|
|
|
|
|
class SessionInterruptResult(Result):
|
|
status: InterruptStatus
|
|
interrupted: bool | None = None
|
|
turn_isolation: bool | None = None
|
|
|
|
|
|
method("session.interrupt", params=SessionInterruptParams, result=SessionInterruptResult,
|
|
doc="Stop the running turn (and streaming TTS); retires the crash-recovery marker.")
|
|
|
|
|
|
class CorrectionStatus(WireEnum):
|
|
queued = "queued"
|
|
redirected = "redirected"
|
|
rejected = "rejected"
|
|
|
|
|
|
class SessionCorrectionParams(SessionParams):
|
|
text: str
|
|
|
|
|
|
class SessionCorrectionResult(Result):
|
|
status: CorrectionStatus
|
|
text: str
|
|
|
|
|
|
method("session.steer", params=SessionCorrectionParams, result=SessionCorrectionResult,
|
|
doc="Inject text into the next tool result without interrupting the turn.")
|
|
method("session.redirect", params=SessionCorrectionParams, result=SessionCorrectionResult,
|
|
doc="Redirect the active turn (queued for the next turn while the agent is still building).")
|
|
|
|
|
|
# ── spawn trees ───────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class SpawnTreeSaveParams(ProfileParams):
|
|
subagents: list[dict[str, JsonValue]]
|
|
session_id: str | None = None # stored key; "default" when absent
|
|
started_at: float | None = None
|
|
finished_at: float | None = None
|
|
label: str | None = None
|
|
|
|
|
|
class SpawnTreeSaveResult(Result):
|
|
path: str
|
|
session_id: str
|
|
|
|
|
|
method("spawn_tree.save", params=SpawnTreeSaveParams, result=SpawnTreeSaveResult,
|
|
doc="Persist a finished delegation tree snapshot under the session's spawn-trees dir.")
|
|
|
|
|
|
class SpawnTreeListParams(ProfileParams):
|
|
session_id: str | None = None
|
|
cross_session: bool = False
|
|
limit: int | None = None
|
|
|
|
|
|
class SpawnTreeEntry(OpenModel):
|
|
"""Index row (``server._append_spawn_tree_index``) or a legacy file scan."""
|
|
|
|
path: str
|
|
session_id: str | None = None
|
|
started_at: float | None = None
|
|
finished_at: float | None = None
|
|
label: str = ""
|
|
count: int = 0
|
|
|
|
|
|
class SpawnTreeListResult(Result):
|
|
entries: list[SpawnTreeEntry]
|
|
|
|
|
|
method("spawn_tree.list", params=SpawnTreeListParams, result=SpawnTreeListResult,
|
|
doc="Saved spawn-tree snapshots, newest first.")
|
|
|
|
|
|
class SpawnTreeLoadParams(ProfileParams):
|
|
path: str
|
|
|
|
|
|
class SpawnTreeLoadResult(Result):
|
|
"""The snapshot file as written by ``spawn_tree.save`` (open: the file is the contract)."""
|
|
|
|
session_id: str | None = None
|
|
started_at: float | None = None
|
|
finished_at: float | None = None
|
|
label: str | None = None
|
|
subagents: list[dict[str, JsonValue]] = Field(default_factory=list)
|
|
model_config = Result.model_config | {"extra": "allow"}
|
|
|
|
|
|
method("spawn_tree.load", params=SpawnTreeLoadParams, result=SpawnTreeLoadResult,
|
|
doc="Read one saved spawn-tree snapshot (path must be under the spawn-trees root).")
|
|
|
|
|
|
# ── terminal / event replay ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class TerminalResizeParams(SessionParams):
|
|
cols: int | None = None
|
|
|
|
|
|
class TerminalResizeResult(Result):
|
|
cols: int
|
|
|
|
|
|
method("terminal.resize", params=TerminalResizeParams, result=TerminalResizeResult,
|
|
doc="Record the client's column width for server-side rendering.")
|
|
|
|
|
|
class SessionEventsSinceParams(SessionParams):
|
|
last_seen: int | None = None
|
|
|
|
|
|
class SessionEventsSinceResult(Result):
|
|
events: list[dict[str, JsonValue]] # recorded event frames' ``params`` objects
|
|
latest_seq: int
|
|
truncated: bool
|
|
count: int
|
|
epoch: str
|
|
open_requests: list[OpenRequestEntry]
|
|
|
|
|
|
method("session.events.since", params=SessionEventsSinceParams, result=SessionEventsSinceResult,
|
|
doc="Replay events after a seq watermark on WS reconnect; truncated means refetch state.")
|
|
|
|
|
|
class SessionEventsStatsParams(ProfileParams):
|
|
pass
|
|
|
|
|
|
class SessionEventsStatsResult(Result):
|
|
"""``event_replay.replay_stats``."""
|
|
|
|
sessions: int
|
|
events: int
|
|
bytes: int
|
|
max_per_session: int
|
|
max_bytes_per_session: int
|
|
max_bytes_process: int
|
|
|
|
|
|
method("session.events.stats", params=SessionEventsStatsParams, result=SessionEventsStatsResult,
|
|
doc="Replay-buffer occupancy telemetry (ops/debug).")
|
|
|
|
|
|
# ── one-shot LLM ──────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
class LlmOneshotParams(ProfileParams):
|
|
"""Needs a ``template`` or ``instructions`` / ``input``; a live ``session_id`` lends its model."""
|
|
|
|
template: str | None = None
|
|
instructions: str | None = None
|
|
input: str | None = None
|
|
variables: dict[str, JsonValue] | None = None
|
|
task: str | None = None
|
|
temperature: float | None = None
|
|
max_tokens: int | None = None
|
|
session_id: str | None = None
|
|
|
|
|
|
class LlmOneshotResult(Result):
|
|
text: str
|
|
|
|
|
|
method("llm.oneshot", params=LlmOneshotParams, result=LlmOneshotResult,
|
|
doc="Stateless one-shot LLM completion (titles, ideas) on the session's or the task backend.")
|