Documentation
¶
Overview ¶
Package command implements the relay's chat-command surface: it brokers interactive OAuth login (bridging Poe turns into fir's _meta.auth.interactive two-call protocol) and the session-control commands (!status, !models, !model, !new, !help).
Each Poe conversation can have at most one in-flight login. The first login command (e.g. "!login anthropic") calls fir's authenticate to produce a URL; the next user turn from the same conversation submits the pasted redirect URL. The broker holds no goroutines — the actual blocking on the user input happens inside fir, parked across turns. The relay only remembers which conversation has a pending login for which method.
Commands accept the sigils "/", "!", and "." but user-facing prose suggests "!" (DisplaySigil): Poe's chat client intercepts "/"-prefixed messages as native slash commands and rejects unknown ones before they reach the bot, so "/login" is unreliable; "!"/"." pass straight through.
Index ¶
Constants ¶
const DisplaySigil = "!"
DisplaySigil is the command prefix shown in user-facing messages. It is deliberately not "/" so the suggested commands survive Poe's client-side slash-command interceptor.
Variables ¶
This section is empty.
Functions ¶
func IsCommand ¶
IsCommand reports whether text is any relay command the broker handles (the login family, "help", or a session command), under any accepted sigil. The HTTP handler uses this to decide whether to route a turn to the broker instead of forwarding it to the agent.
func IsLoginCommand ¶
IsLoginCommand reports whether text is a login/logins/cancel-login command under any accepted sigil (/, !, .). Trims leading whitespace so users can paste the command after a thought.
Types ¶
type Authenticator ¶
type Authenticator interface {
AuthMethods() []client.AuthMethod
Authenticate(ctx context.Context, methodID, id, redirect string, cancel bool) (client.AuthResult, error)
}
Authenticator is the agent-side surface the broker depends on. The full *client.AgentProc satisfies it.
type Broker ¶
type Broker struct {
// contains filtered or unexported fields
}
Broker tracks per-conversation pending logins.
func (*Broker) Handle ¶
Handle dispatches one user turn. Behaviour:
- If the conversation has a pending login, treat any non-command text as the pasted redirect URL.
- Otherwise interpret /login [provider], /logins, /cancel-login.
Returns (nil, nil) if the turn is not auth-related and should be forwarded to the normal prompt path.
func (*Broker) HasPending ¶
HasPending reports whether the conversation is waiting for a pasted redirect URL.
func (*Broker) OfferLogin ¶
OfferLogin renders the onboarding message shown when the agent reports that no usable provider is connected (an "Authentication required" prompt error). It lists the loginable providers using the Poe-safe DisplaySigil. Safe for concurrent use. Returned text is empty-safe: it always yields actionable guidance, even with no OAuth methods.
func (*Broker) Passthrough ¶
Passthrough decides whether text is an allowlisted agent command and, if so, returns the prompt text to forward to the agent (e.g. "!reload" → "/reload"). ok=false means the turn is not a passthrough command and should be handled normally. The command must be both allowlisted and actually advertised by the agent. Requires a wired Controller.
func (*Broker) SetController ¶
func (b *Broker) SetController(c Controller)
SetController wires the session-control surface (the router) used by !status/!models/!model/!new. Call once at startup, after construction, to break the broker↔router construction cycle. Safe before any turns.
type Controller ¶
type Controller interface {
AvailableModels() (models []client.ModelInfo, currentID string)
SetModelOverride(convID, modelID string) error
ResetSession(convID string) error
StatusFor(convID string) router.SessionStatus
AgentCommands() []client.CommandInfo
RelayInfo(convID string) router.RelayInfo
}
Controller is the per-conversation session-control surface used by the non-auth commands (!status, !models, !model, !new). *router.Router satisfies it. Optional: if nil, those commands report unavailable. (router never imports command — the dependency edge is one-way: command → router.)
type Outcome ¶
type Outcome struct {
// Text is a plain message to stream as a Poe `text` event.
Text string
// URL, if non-empty, is the auth URL to surface to the user. Text
// may also be set with prose preceding/following the URL.
URL string
// Instructions accompany URL.
Instructions string
}
Outcome is what the HTTP handler should render to the user. Exactly one of Text / URL / Error is set; Done is always implied (the auth turn never streams further chunks).