Skip to content

A shell is named, not implied by the connection - #188

Merged
vitramir merged 2 commits into
mainfrom
persistent-sandbox-shells
Aug 11, 2026
Merged

A shell is named, not implied by the connection#188
vitramir merged 2 commits into
mainfrom
persistent-sandbox-shells

Conversation

@vitramir

@vitramir vitramir commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Adds the interface for persistent sandbox shells.

Design and rationale: changes/2026-08-11-persistent-sandbox-shells.md in agynio/architecture.

Terminal sessions

SESSION_KIND_SHELL_ATTACH, with two parameters:

Field
shell_id Required for this kind. Opaque, client-generated, ^[A-Za-z0-9_-]{1,64}$
shell_cwd Optional. Absolute. Applied when the shell is created

Added on IssueTicketRequest and CreateTerminalSessionRequest.

Sandbox layouts

GetSandboxLayout / SetSandboxLayout on AgentsService and AgentsGateway, plus internal SetSandboxLayoutDirectories.

SandboxLayout is a versioned document holding an ordered SandboxTab list. identity_id is resolved from authenticated context on the external methods and is not a request field.

Compatibility

Additive. buf lint, buf build and buf breaking against main are clean.

Downstream

terminal-proxy and agents generate from buf.build/agynio/api with .gen/ gitignored. Their CI stays red until this merges and the module is published.

Adds SESSION_KIND_SHELL_ATTACH with the two parameters that distinguish it --
shell_id naming the shell and shell_cwd applied only when one has to be created --
and the layout methods that hold what a client reopens to.

SHELL_ATTACH is a separate kind rather than a flag on SHELL so the command stays a
function of the kind and its parameters, and a client cannot get one behavior while
the ticket describes the other. SHELL keeps its meaning and its command.

SandboxLayout is a versioned document rather than a row per tab. Reordering,
closing and opening are one write, and the fields this is expected to grow --
split geometry, sizes, focus -- arrive without a method each. The version is what
makes two devices safe: the loser refetches rather than silently overwriting.

Identity is never a request field on the external methods. It comes from
authenticated context, so there is no call that reads or writes another person's
tabs.

SetSandboxLayoutDirectories is internal and version-free. The orchestrator is its
sole writer, touching one field immediately before a stop, and failing on a
concurrent reorder would lose the snapshot for no benefit.

Additive throughout; buf breaking is clean against main.
@vitramir
vitramir requested a review from a team as a code owner August 11, 2026 19:53
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow buf-pr / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedAug 11, 2026, 8:00 PM

The proto comments explained service behavior -- attach-or-create semantics,
why a document carries a version, which component is the sole writer of a
field, what a client should do on conflict. None of that is the interface's to
say, and stating it here duplicates it into a place that cannot be kept
correct.

What remains is the wire contract: what a field is, whether it is required,
its pattern, and what an absent value means. The reasoning lives in the change
doc in agynio/architecture.
@vitramir
vitramir merged commit 6bb3a84 into main Aug 11, 2026
1 check 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