// Public, typed contract of the contexts plugin. Contexts are a
// higher-level grouping layer over sessions, used for organizing
// work (project-level boundaries, filter scopes, focus frames).
// Other plugins that depend on `bmux_contexts_plugin_api` import
// these interfaces rather than the contexts plugin implementation.
//
// Three interfaces:
// - `contexts-state` — read-only queries about contexts.
// - `contexts-commands` — mutating operations on contexts.
// - `contexts-events` — lifecycle event stream.
plugin bmux.contexts version 1;
capability CONTEXTS_READ = bmux.contexts.read;
capability CONTEXTS_WRITE = bmux.contexts.write;
@capability(CONTEXTS_READ)
interface contexts-state {
// Snapshot of a single context's public state.
record context-summary {
id: uuid,
name: string?,
attributes: map<string, string>,
}
// Selector identifying a context. Exactly one of `id` or `name`
// should be populated; `id` wins when both are set.
record context-selector {
id: uuid?,
name: string?,
}
// Errors a context query can produce.
variant context-query-error {
not-found,
invalid-selector { reason: string },
}
query list-contexts() -> list<context-summary>;
query get-context(selector: context-selector) -> result<context-summary, context-query-error>;
query current-context() -> context-summary?;
}
@capability(CONTEXTS_WRITE)
interface contexts-commands {
// Errors a `create-context` command can produce.
//
// Names are display hints, not identity: context creation does
// not reject duplicate names. Identity is the UUID assigned at
// creation. A caller may deliberately create two contexts named
// "tab-2" and bmux will honor that.
variant create-context-error {
invalid-name { reason: string },
failed { reason: string },
}
// Errors a `select-context` command can produce.
variant select-context-error {
not-found,
denied { reason: string },
}
// Errors a `close-context` command can produce.
variant close-context-error {
not-found,
denied { reason: string },
failed { reason: string },
}
// Errors a `rename-context` command can produce.
variant rename-context-error {
not-found,
invalid-name { reason: string },
denied { reason: string },
failed { reason: string },
}
// Acknowledgement returned by mutating context commands. `id`
// carries the target context id after the operation (the newly
// created one for `create-context`, or the resolved selector for
// `select-context` / `close-context`).
//
// `session-id` carries the session bound to the context after
// the operation, when knowable. `create-context` always sets it
// (context creation allocates a session atomically).
// `select-context` / `close-context` may set it when the
// selector resolves to a session-bound context; otherwise
// `None`.
record context-ack {
id: uuid,
session-id: uuid?,
}
command create-context(name: string?, attributes: map<string, string>)
-> result<context-ack, create-context-error>;
command select-context(selector: contexts-state.context-selector)
-> result<context-ack, select-context-error>;
command close-context(selector: contexts-state.context-selector, force: bool)
-> result<context-ack, close-context-error>;
command rename-context(selector: contexts-state.context-selector, name: string)
-> result<context-ack, rename-context-error>;
}
interface contexts-events {
// A single event describing a context lifecycle change.
variant context-event {
// A new context was created.
created { context-id: uuid, name: string? },
// A context was closed / removed.
closed { context-id: uuid },
// A context was selected (became current for a client).
selected { context-id: uuid },
// A context's display name changed.
renamed { context-id: uuid, name: string },
// The active context for a session changed. Emitted whenever
// a client's "current context" for a given session flips
// (create, select, or close that promotes a sibling). Carries
// the initiating client id so attach runtimes can distinguish
// "my own action" from "another client's action" and apply
// multi-client follow policy.
session-active-context-changed {
session-id: uuid,
context-id: uuid,
initiator-client-id: uuid?,
},
}
events context-event;
}