Documentation
¶
Overview ¶
Package attachadapter bridges a mast serve-daemon session into pkg/attach's Registrant contract, so operator frontends (mast-web) can list, tail, and inject into sessions over the attach protocol.
One Adapter represents one ADK session triple. All adapters in a daemon share the daemon's eventlog handle — attach's broadcaster filters the stream per session. Construction is explicit (attachadapter.New with a Config); the daemon registers the result on an attach.SessionRegistry.
Index ¶
- type Adapter
- func (ad *Adapter) AppName() string
- func (ad *Adapter) AttachCapabilities() attach.CapabilityReport
- func (ad *Adapter) AttachGuardrails() attach.GuardrailInfo
- func (ad *Adapter) AttachInterrupt() bool
- func (ad *Adapter) AttachResetGuardrail(req attach.GuardrailResetRequest) (attach.GuardrailResetResponse, error)
- func (ad *Adapter) AttachStatus() attach.StatusInfo
- func (ad *Adapter) AttachSubagentCatalog() []attach.SubagentCatalogInfo
- func (ad *Adapter) AttachTools() []attach.ToolInfo
- func (ad *Adapter) AttachUsage() attach.UsageInfo
- func (ad *Adapter) AuditsInterrupts()
- func (ad *Adapter) Description() string
- func (ad *Adapter) EventLog() *eventlog.Handle
- func (ad *Adapter) Inject(message string) error
- func (ad *Adapter) InjectAs(message string, caller auth.Caller) error
- func (ad *Adapter) RequestWake()
- func (ad *Adapter) SessionID() string
- func (ad *Adapter) SetOperatorEventEmitter(f func(eventType string, payload any))
- func (ad *Adapter) UserID() string
- type Config
- type TurnResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter implements attach.Registrant plus the optional capability interfaces mast's daemon can honestly serve: StatusProvider, UsageProvider, ToolsProvider, SubagentCatalogProvider, GuardrailProvider, GuardrailResetter, InterruptProvider, DescriptionProvider, and OperatorEventTarget.
It also implements CapabilityReporter, because satisfying an interface is not the same as being wired: the guardrail methods exist on every Adapter and answer with real data only where the daemon set the corresponding Config func. The report is what the capabilities frame advertises.
Not AgentsProvider: /agents lists spawned background instances, and mast has none to list — every dispatch shape resolves its specialists inside the turn. The configured roster goes to SubagentCatalogProvider instead, which is the distinction #134 was filed over.
func (*Adapter) AttachCapabilities ¶ added in v0.4.0
func (ad *Adapter) AttachCapabilities() attach.CapabilityReport
AttachCapabilities implements attach.CapabilityReporter: what this adapter is actually wired for, as opposed to what its method set happens to satisfy. Interrupt is unconditional (the adapter owns the turn's cancel func); the guardrail keys follow the Config funcs.
CostCeiling asks the projection rather than assuming: a daemon serving a bundle with no `budget:` block has the guardrail surface wired and no ceiling to trip, and advertising a spend cap there would have a client render a limit that does not exist.
func (*Adapter) AttachGuardrails ¶ added in v0.4.0
func (ad *Adapter) AttachGuardrails() attach.GuardrailInfo
AttachGuardrails implements attach.GuardrailProvider. Zero state — nothing armed, nothing tripped — when no GuardrailsFn is wired.
func (*Adapter) AttachInterrupt ¶
AttachInterrupt implements attach.InterruptProvider: cancel the in-flight turn's context. Returns false when no turn is running. Queued messages are NOT discarded — the next one still runs, same as core-agent's interrupt (which stops the turn, not the agent).
func (*Adapter) AttachResetGuardrail ¶ added in v0.4.0
func (ad *Adapter) AttachResetGuardrail(req attach.GuardrailResetRequest) (attach.GuardrailResetResponse, error)
AttachResetGuardrail implements attach.GuardrailResetter. Without a ResetGuardrailFn it returns attach.ErrCapabilityNotRegistered, which the handler renders as 501.
func (*Adapter) AttachStatus ¶
func (ad *Adapter) AttachStatus() attach.StatusInfo
AttachStatus implements attach.StatusProvider.
func (*Adapter) AttachSubagentCatalog ¶ added in v0.4.0
func (ad *Adapter) AttachSubagentCatalog() []attach.SubagentCatalogInfo
AttachSubagentCatalog implements attach.SubagentCatalogProvider. Empty when no SubagentsFn is wired.
func (*Adapter) AttachTools ¶
AttachTools implements attach.ToolsProvider. Empty when no ToolsFn is wired.
func (*Adapter) AttachUsage ¶
AttachUsage implements attach.UsageProvider. Zero UsageInfo when no UsageFn is wired.
func (*Adapter) AuditsInterrupts ¶ added in v0.1.2
func (ad *Adapter) AuditsInterrupts()
AuditsInterrupts implements attach.InterruptSelfAuditor (a capability marker, never called for effect): this adapter records the operator-interrupt audit event from its own turn loop, so the protocol layer's fallback append — which would stale the unwinding turn's session handle — is suppressed.
func (*Adapter) Description ¶
Description implements attach.DescriptionProvider.
func (*Adapter) Inject ¶
Inject implements attach.Registrant: queue a message and run it as its own turn once earlier queued messages finish. Unlike core-agent's inbox (whose agent loop drains the whole batch into one turn), mast maps one injected message to one turn — the daemon has no long-lived loop to batch for.
func (*Adapter) InjectAs ¶
InjectAs implements attach.Registrant. The caller rides the turn context (auth.WithCaller) so the eventlog metadata extractor and any caller-aware substrate see who triggered the turn.
func (*Adapter) RequestWake ¶
func (ad *Adapter) RequestWake()
RequestWake implements attach.Registrant. Core-agent's wake signal re-checks an idle agent loop's inbox; mast's daemon runs turns on demand, so wake only kicks the drainer in case a message is queued with no drainer running (a state that shouldn't occur — this is belt-and-braces, not a scheduler).
func (*Adapter) SetOperatorEventEmitter ¶
SetOperatorEventEmitter implements attach.OperatorEventTarget: the broadcaster installs the typed-event callback at first-subscriber time and clears it (f == nil) when the last subscriber disconnects.
type Config ¶
type Config struct {
// AppName / UserID / SessionID form the ADK session key —
// attach uses (AppName, SessionID) for URL lookup and the
// broadcaster uses all three to filter the eventlog stream.
AppName string
UserID string
SessionID string
// EventLog is the daemon-wide eventlog handle. Attach requires
// it for live-tail (the broadcaster pumps from Stream.Watch).
EventLog *eventlog.Handle
// RunTurn executes one turn for this session: append message as
// user content, drive the runner until the turn completes, and
// return what is known about the turn's token usage. The
// adapter guarantees calls are serialized per session. ctx is
// canceled when an operator interrupts the turn (POST
// /interrupt) or the daemon shuts down.
RunTurn func(ctx context.Context, message string) (TurnResult, error)
// BaseContext bounds every turn this adapter runs; defaults to
// context.Background(). Pass the daemon's serve context so
// in-flight turns die with the process's graceful shutdown.
BaseContext context.Context
// ModelName, when set, is reported on status frames.
ModelName string
// Description, when set, feeds the agent card + session list.
Description string
// UsageFn, when set, supplies the GET /sessions/.../usage
// snapshot (typically from the session's budget meter). Nil
// reports zero usage rather than 501 — same behavior as a
// core-agent registrant with an empty tracker.
UsageFn func() attach.UsageInfo
// ToolsFn, when set, supplies GET /sessions/.../tools. Nil reports
// an empty list — which reads to an operator exactly like a daemon
// that holds no tools, so a caller with tools to report should set
// it. The daemon builds it from the MCP toolsets it wired, because
// that is where the per-server attribution the endpoint reports
// still exists (cmd/mast's toolCatalog; #133). Callers that only
// have the workload bundle's declared tool_catalog can project that
// instead, at the cost of reporting what was declared rather than
// what the servers actually serve.
ToolsFn func() []attach.ToolInfo
// SubagentsFn, when set, supplies GET /sessions/.../subagents: the
// specialist roster the daemon loaded, as opposed to the live
// instances /agents reports. Nil reports an empty list. A daemon
// running a workload bundle has a roster and should set it — an
// empty catalog reads as "this daemon has no specialists", which is
// the wrong answer for every bundle mast ships (#134).
SubagentsFn func() []attach.SubagentCatalogInfo
// GuardrailsFn, when set, supplies GET /sessions/.../guardrails:
// which backstops are armed, which have tripped, and the spend
// behind that. Nil reports everything off — the truthful answer
// for a caller with no budget meter, and the wrong one for a
// daemon running a bundle that declares `budget:` (#135).
GuardrailsFn func() attach.GuardrailInfo
// ResetGuardrailFn, when set, services POST
// /sessions/.../guardrails/reset. Nil is a 501 rather than a
// silent no-op: a session wedged past its ceiling stays wedged for
// the daemon's lifetime, so an operator has to learn immediately
// that this daemon can't hand it more runway.
ResetGuardrailFn func(req attach.GuardrailResetRequest) (attach.GuardrailResetResponse, error)
}
Config wires an Adapter to one session's turn machinery. AppName, UserID, SessionID, EventLog, and RunTurn are required.
type TurnResult ¶
TurnResult carries what the daemon's turn runner knows about a finished turn. Zero values are honest "unknown" — the terminal turn-complete event reports them as-is and authoritative cost arrives via the usage snapshot (UsageFn), matching the attach spec's "cost deferred" wire semantics.