Files
openworker/coworker/sessions.py
T
Devika Verma f08a3c425b compaction: engine hook, failure policy, persistence (OPE-27 2/4)
Minimal engine footprint: a checkpoint at each iteration top (between tool
turns and before a new turn), the usage signal captured per round-trip
(context_tokens; chars/4 estimate when never reported), and
_outbound_messages consulting the boundary. The summarizer runs off-loop
through the normal provider router, so the Settings model pin is just an
id.

Failure policy per spec: retry once in both modes; attended sessions get
the Retry / Trim-oldest-10% prompt (via the ask_user plumbing, gated by an
is_attended callback the WS surface wires); unattended runs auto-trim and
continue — never parked on internal bookkeeping. Raw context-overflow 400s
from the main model route into the same policy, progress-guarded so a
still-overflowing model terminates in the error path.

CompactionState persists on the session record (new sqlite column, same
defensive parse as grants), so reloads keep the compacted view. A
persisted compacted notice + a new COMPACTED event mark the spot for
the GUI divider (rendered in commit 3).
2026-07-29 16:13:14 +05:30

40 lines
1.7 KiB
Python

"""Session record — the metadata + messages for one conversation.
Storage lives in `coworker.conversations.ConversationStore`: a SQLite index keyed by
project, with each conversation's messages in an append-only `.jsonl` file.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Optional
@dataclass
class SessionRecord:
session_id: str
workspace: str
model: str
mode: str
messages: list[dict[str, Any]] = field(default_factory=list)
title: Optional[str] = None
agent: str = "code"
message_count: int = 0
updated_at: Optional[str] = None
# Folders added to the session beyond its primary scratch dir, each {path, writable, label}.
# The primary scratch is re-provisioned at engine build, so only these extras are persisted.
extra_roots: list[dict[str, Any]] = field(default_factory=list)
# "Always allow" approvals granted in this session ({tools: [...], commands: [...]}) —
# session-scoped by design, but the session outlives the process, so they must too
# (owner-hit 2026-07-22: grants forgotten on every restart).
grants: dict[str, Any] = field(default_factory=dict)
pinned: bool = False
archived: bool = False
# Where the session came from, when not user-started (§31): machine key + display label
# (e.g. origin="slack", origin_label="#general · T0ABCD"). Set once at spawn.
origin: Optional[str] = None
origin_label: Optional[str] = None
# Auto-compaction state (OPE-27): CompactionState.as_dict(), {} when never compacted.
# Persisted so a reloaded session keeps its compacted outbound view.
compaction: dict[str, Any] = field(default_factory=dict)