Documentation
¶
Index ¶
- Constants
- Variables
- func ActionApplicability(action actions.Action, item DecodedActionItem, remotes RemoteGenerator) (ok bool, reason string)
- func RenderClipboardText(action actions.Action, key string, payload []byte, inputs map[string]string, ...) (string, error)
- func RenderRepoTarget(action actions.Action, key string, payload []byte, inputs map[string]string, ...) (string, error)
- func SessionDraftMetadata(draft SessionDraft) map[string]string
- func WithRunLog(ctx context.Context, l *RunLog) context.Context
- type ActionInvocationInput
- type ActionLister
- type ActionRunView
- type ClipboardExecutionOutcome
- type ClipboardExecutor
- type CreateSessionRequest
- type DecodedActionItem
- type Dispatcher
- type ExecEnvironment
- type ExecutionLog
- type ExecutionOutcome
- type ExecutionResult
- type Executor
- type FlowActions
- type FlowLister
- type InboxItemLocator
- type ItemSessionLinker
- type LaunchNodeActionConfig
- type LaunchSessionExecutor
- type LaunchSessionRequest
- type LaunchWorkspaceSessionRequest
- type MessageExecutionOutcome
- type MessageService
- type NotificationGate
- type NotificationPolicy
- type NotifyActionConfig
- type NotifyExecutor
- type OutputCommandStore
- type OutputData
- type PublishMessageExecutor
- type RemoteGenerator
- type RepositoryLauncher
- type RunLog
- type RunLogSink
- type SessionCreateFailure
- type SessionCreator
- type SessionDraft
- type SessionDraftItem
- type SessionExecutionOutcome
- type SessionInvocationInput
- type SessionLaunchOptions
- type SessionLaunchRepository
- type SessionLaunchWorkspace
- type SessionLauncher
- type SessionPromptData
- type SessionTarget
- type ShellExecutor
- type SystemNotification
- type SystemNotifier
- type TerminalTarget
- type WindowTarget
- type Worker
- func (w *Worker) Cancel(commandID int64) bool
- func (w *Worker) Confirm(ctx context.Context, actionID, key string, payload []byte, ...) (ActionRunView, error)
- func (w *Worker) SetJobRecorder(r jobs.Recorder)
- func (w *Worker) SetRecorder(r activity.Recorder)
- func (w *Worker) SetRunLogSink(s RunLogSink)
- func (w *Worker) Start(ctx context.Context)
- func (w *Worker) Stop(ctx context.Context) error
- func (w *Worker) Tick(ctx context.Context)
- func (w *Worker) WaitIdle(ctx context.Context) error
- type WorkspaceSessionLauncher
Constants ¶
const ( DefaultOutputWorkerInterval = 5 * time.Second DefaultOutputWorkerBatch = 50 DefaultManualConcurrency = 4 DefaultAutomaticConcurrency = 4 MaxOutputCommandAttempts = 5 )
const ( RunLogStdout = "stdout" RunLogStderr = "stderr" RunLogSystem = "system" )
const ( RetryMetadataKey = "retry" RetryKindSessionCreate = "session-create" )
Activity-metadata keys for a retryable failed form, the persisted half of the retry. RetryKindSessionCreate marks the bag so the Activity view can offer the button without interpreting the rest of it; nothing outside this file knows these strings.
const ActionTypeLaunchSession = "launch-session"
const ActionTypeNotify = "notify"
ActionTypeNotify is the action type the notify executor is registered under. Unlike "shell" or "publish-message" it is never authored in actions.yml: a notify node carries its config inline, and FlowActions synthesizes the Action the dispatcher needs from the live flow set.
const DefaultItemKind = "Item"
DefaultItemKind is the kind an item carries when its payload declares none. Every item has a kind so every item is automatable: an action with applies_to: [Item] targets exactly the untyped ones, instead of them being reachable only by an action with no applies_to at all. Must stay in sync with the frontend's DEFAULT_ITEM_KIND (lib/itemPresentation.ts), which feeds the actions editor's autocomplete. Matching is case-insensitive, so a hand-written applies_to: [item] works too. See docs/decisions/2026-07-24-canonical-item-contract.md.
const DefaultSessionPromptTemplate = `` /* 178-byte string literal not displayed */
DefaultSessionPromptTemplate renders an inbox item into the starting prompt for a session created from it. Repo is omitted; it prefills the form's own repository field.
const MessageSender = "hive-desktop"
const ( // NotifyMaxAge bounds how stale a queued notification may be when the // worker gets to it. A notification is a live interrupt: one enqueued // while the app was closed, or stranded behind a long backlog, is no // longer worth surfacing by the time it would fire. Past this age the // command completes without delivering — the second line of defense // behind replay's own guarantees (see the package-level note on // NotifyExecutor). NotifyMaxAge = 10 * time.Minute )
Variables ¶
var ErrDispatchBusy = errors.New("action dispatch is busy")
Functions ¶
func ActionApplicability ¶
func ActionApplicability(action actions.Action, item DecodedActionItem, remotes RemoteGenerator) (ok bool, reason string)
ActionApplicability reports whether action can run against item and, when it cannot, a human-readable reason (applies_to mismatch, blank repo render, or the underlying template render error) so the invoke path stays debuggable. The hard-requirement rule derives from actions.Action.HeadlessCapable() — non-blank repo_template ⇒ requires a renderable, non-blank repo target — keeping the knowledge of which action types impose payload requirements next to the type definitions in package actions. All other action types and templates impose no applicability requirement.
func RenderClipboardText ¶
func RenderClipboardText(action actions.Action, key string, payload []byte, inputs map[string]string, remotes RemoteGenerator) (string, error)
RenderClipboardText renders a clipboard action's text_template over the item — the same OutputData context a shell action's command_template renders over, with the shq helper available — and trims it. A blank render is an error, not an empty copy.
It is the single renderer both the detail-pane render-only path (InboxService.RenderClipboardAction) and ClipboardExecutor call, so the text a user copies can never drift from what a durable dispatch would produce.
func RenderRepoTarget ¶
func RenderRepoTarget(action actions.Action, key string, payload []byte, inputs map[string]string, remotes RemoteGenerator) (string, error)
RenderRepoTarget renders a launch-session action's repo_template over the SAME OutputData context the executor renders with (zero CommandID / IsRerun) and trims the result. Extracted from LaunchSessionExecutor — which now calls it — so the applicability probe and the executor can never drift: a template referencing .Raw or .Key probes exactly as it executes. Actions without a repo_template (interactive or workspace launch-session actions, and every other type) render "" with no error; they impose no repository requirement on the payload.
func SessionDraftMetadata ¶
func SessionDraftMetadata(draft SessionDraft) map[string]string
SessionDraftMetadata encodes a failed form onto an activity row. The progress tail is left out: an audit row is not the place for a hook's output, and the ERR line has it.
Types ¶
type ActionInvocationInput ¶
type ActionInvocationInput struct {
Session *SessionInvocationInput `json:"session,omitempty"`
// Inputs are the values collected for the action's declared inputs, keyed
// by input name. They are validated against the catalog's declaration on
// every invocation, so a name the action does not declare is refused.
Inputs map[string]string `json:"inputs,omitempty"`
Rerun bool `json:"rerun,omitempty"`
}
ActionInvocationInput contains only user-supplied action inputs. It never carries executable configuration or message attribution.
type ActionRunView ¶
type ActionRunView struct {
CommandID int64 `json:"commandId"`
Status string `json:"status"`
Result *ExecutionOutcome `json:"result,omitempty"`
Error string `json:"error,omitempty"`
ConfirmationRequired bool `json:"confirmationRequired,omitempty"`
}
type ClipboardExecutionOutcome ¶
type ClipboardExecutionOutcome struct {
Text string `json:"text"`
}
ClipboardExecutionOutcome carries the text a clipboard action rendered. The clipboard write itself is the desktop adapter's: the core produces the text and the frontend copies it (see the detail-pane render path), so this is the executor's whole result.
type ClipboardExecutor ¶
type ClipboardExecutor struct{}
ClipboardExecutor renders a clipboard action's text_template and returns the text as its outcome. A clipboard action is never enqueued as an output_command — both the detail pane and the terminal surfaces render it non-durably, because text is not a side effect worth replaying — so this executor is what the render-only paths dispatch through, and what keeps the dispatch contract complete (every catalog action type has one).
func NewClipboardExecutor ¶
func NewClipboardExecutor() *ClipboardExecutor
func (*ClipboardExecutor) Execute ¶
func (e *ClipboardExecutor) Execute(_ context.Context, action actions.Action, data OutputData, _ ActionInvocationInput) (ExecutionResult, error)
type CreateSessionRequest ¶
type CreateSessionRequest struct {
Repository string `json:"repository,omitempty"`
Workspace string `json:"workspace,omitempty"`
Name string `json:"name"`
Prompt string `json:"prompt"`
Agent string `json:"agent,omitempty"`
ItemIDs []int64 `json:"itemIds,omitempty"`
}
CreateSessionRequest is a user-submitted New Session form. ItemIDs are the inbox items the form was drafted from; the core resolves their identities and never takes item refs from a client.
type DecodedActionItem ¶
DecodedActionItem is the canonical action-item projection of a persisted inbox payload: identity, canonical kind, and the payload bytes handed to the output worker for template rendering. The desktop service deliberately never accepts this shape from a client.
func DecodeActionItem ¶
func DecodeActionItem(payload []byte, externalID string) (DecodedActionItem, error)
DecodeActionItem projects any source's persisted inbox payload into the canonical action item. Object payloads: `id` accepts a string or number; a missing/blank id is filled from the row's external id (re-marshaling only in that case); `kind` is the canonical top-level string, falling back to DefaultItemKind so every item is targetable by applies_to. Non-object payloads (arrays, scalars) pass through untouched — ID comes from externalID, kind is the default, and no id injection is attempted. All other fields pass through untouched (grab bag preserved). The default is applied here, at the one decode boundary, rather than written into stored payloads: no migration, and the raw payload still answers "did the source actually send a kind?".
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
func NewDispatcher ¶
func NewDispatcher(executors map[string]Executor, remotes RemoteGenerator) *Dispatcher
func (*Dispatcher) Execute ¶
func (d *Dispatcher) Execute(ctx context.Context, a actions.Action, data OutputData, input ActionInvocationInput) (result ExecutionResult, err error)
type ExecEnvironment ¶
ExecEnvironment supplies the environment a spawned command runs in. A shell action's command is the user's own, so it needs the PATH their terminal has rather than the one a desktop launch inherits (ADR subprocess-environment).
type ExecutionLog ¶
type ExecutionOutcome ¶
type ExecutionOutcome struct {
Session *SessionExecutionOutcome `json:"session,omitempty"`
Message *MessageExecutionOutcome `json:"message,omitempty"`
Clipboard *ClipboardExecutionOutcome `json:"clipboard,omitempty"`
}
ExecutionOutcome is a tagged-by-presence union. Exactly one branch is set for successful side-effecting executors.
type ExecutionResult ¶
type ExecutionResult struct {
// Attempted is internal execution state, not frontend data. It separates a
// side effect that returned an error after dispatch from validation/config
// failures before dispatch.
Attempted bool `json:"-"`
Outcome *ExecutionOutcome `json:"outcome,omitempty"`
Log ExecutionLog `json:"log"`
}
type Executor ¶
type Executor interface {
Execute(context.Context, actions.Action, OutputData, ActionInvocationInput) (ExecutionResult, error)
}
type FlowActions ¶
type FlowActions struct {
// contains filtered or unexported fields
}
FlowActions resolves notify and launch node ids from the live flows on each lookup, so flow edits apply without a restart, and delegates other ids to the actions.yml catalog.
func NewFlowActions ¶
func NewFlowActions(flows FlowLister, catalog ActionLister) *FlowActions
type FlowLister ¶
FlowLister is the subset of *flow.FlowStore this package needs: the current set of loaded flows. It is declared per consuming package rather than shared, so a package's dependency on the flow store is exactly the method it calls.
type InboxItemLocator ¶
type ItemSessionLinker ¶
type ItemSessionLinker interface {
Link(ctx context.Context, sessionID string, ref models.ItemRef) error
}
ItemSessionLinker persists the association between an inbox item and a session created for it, so the item can find the session again after a restart.
type LaunchNodeActionConfig ¶
type LaunchNodeActionConfig struct {
actions.LaunchSessionConfig
NameTemplate string
}
LaunchNodeActionConfig is a launch node projected onto the launch-session executor. It is rebuilt on every resolution, never persisted.
type LaunchSessionExecutor ¶
type LaunchSessionExecutor struct {
// contains filtered or unexported fields
}
LaunchSessionExecutor renders a launch-session action's templates over the triggering message and routes it to the configured target launcher.
func NewLaunchSessionExecutor ¶
func NewLaunchSessionExecutor(logger zerolog.Logger, launcher SessionLauncher, workspaceLauncher WorkspaceSessionLauncher, env ExecEnvironment) *LaunchSessionExecutor
func (*LaunchSessionExecutor) Execute ¶
func (e *LaunchSessionExecutor) Execute(ctx context.Context, action actions.Action, data OutputData, input ActionInvocationInput) (ExecutionResult, error)
type LaunchSessionRequest ¶
type LaunchSessionRequest struct {
Name string
Prompt string
Agent string
Repo string
CollisionSuffix string
// Origins are the inbox items the session is being created for. An empty
// slice means the session has no inbox item behind it.
Origins []models.ItemRef
}
LaunchSessionRequest is a rendered launch-session action, ready to hand to a SessionLauncher.
type MessageExecutionOutcome ¶
type MessageService ¶
type MessageService interface {
Publish(context.Context, messaging.Message, []string) (messaging.PublishResult, error)
}
MessageService is satisfied by *msgsvc.Service.
type NotificationGate ¶
type NotificationGate interface {
NotificationPolicy() NotificationPolicy
}
NotificationGate resolves the app-level notification policy. It is read live on every delivery (Settings -> Notifications), so a toggle applies to the very next notification: a flow node must never be able to notify past "notifications off".
type NotificationPolicy ¶
type NotificationPolicy struct {
// Allowed is the kill switch. False means no flow may notify, whatever
// its nodes say.
Allowed bool
// Sound is the app-level sound preference. A node can silence itself,
// but it cannot make a notification audible once this is off.
Sound bool
// InApp routes this delivery inside Hive instead of to an OS banner. The
// gate resolves it from the user's delivery preference and, for the
// automatic mode, the window's current focus — so this package needs no
// vocabulary for either.
InApp bool
}
NotificationPolicy is the app-level notification configuration one delivery must respect.
type NotifyActionConfig ¶
type NotifyActionConfig struct {
Title string
Body string
Severity string
Sound bool
// Cooldown is the node's resolved per-item delivery floor:
// flow.NotifyCooldownDefault when the node declares none, 0 when it
// explicitly disabled the cooldown.
Cooldown time.Duration
}
NotifyActionConfig is the executor-facing projection of a notify node's flow.NotifyConfig. It exists because the output worker speaks in actions.Action values (whose Config is an actions.ActionConfig), while the authoritative definition stays the flow node — this type is rebuilt from that node on every resolution, never persisted.
func (*NotifyActionConfig) Validate ¶
func (c *NotifyActionConfig) Validate() error
Validate satisfies actions.ActionConfig. The flow's own validator is authoritative (SaveFlow rejects a notify node without a title before it can ever reach a queue), so this only re-states the one invariant the executor depends on.
type NotifyExecutor ¶
type NotifyExecutor struct {
// contains filtered or unexported fields
}
NotifyExecutor delivers a notify terminal's queued command as a native notification, rendering the node's title/body templates over the triggering item.
It never fires for historical events. Three independent things ensure that: a replay recomputes the graph without committing its outputs (only feed claims reach the backend), a snapshot-tagged message is dropped before it can reach a non-feed terminal, and — for anything that slips past both, such as a command queued before a restart — NotifyMaxAge makes a stale command a no-op rather than an interrupt.
func NewNotifyExecutor ¶
func NewNotifyExecutor(notifier SystemNotifier, gate NotificationGate, items InboxItemLocator, logger zerolog.Logger) *NotifyExecutor
NewNotifyExecutor builds a NotifyExecutor. A nil notifier leaves the executor unavailable rather than acknowledging a notification it never sent; a nil gate means "no app-level kill switch" (tests); a nil locator means a delivered notification carries no item link, so a click only raises the window.
func (*NotifyExecutor) Execute ¶
func (e *NotifyExecutor) Execute(ctx context.Context, action actions.Action, data OutputData, _ ActionInvocationInput) (ExecutionResult, error)
type OutputCommandStore ¶
type OutputCommandStore interface {
ClaimNextAutomatic(context.Context, int64, string) (stores.OutputCommand, bool, error)
Confirm(context.Context, string, string, []byte, models.ItemRef, string) (stores.OutputCommand, bool, error)
Rerun(context.Context, string, string, []byte, models.ItemRef, string) (stores.OutputCommand, error)
Get(context.Context, int64) (stores.OutputCommand, error)
Complete(context.Context, int64, string, string) error
Fail(context.Context, int64, string, string) error
Requeue(context.Context, int64, string, string, time.Duration) error
Cancel(context.Context, int64, string, string) error
}
type OutputData ¶
type OutputData struct {
Key string
Payload map[string]any
Raw json.RawMessage
Inputs map[string]string
Session *SessionTarget
Window *WindowTarget
CreatedAt int64
CommandID int64
IsRerun bool
Origin models.ItemRef
// contains filtered or unexported fields
}
func (OutputData) ItemRemote ¶
func (d OutputData) ItemRemote() string
ItemRemote is the clone URL for the item's repo, as templates see it.
type PublishMessageExecutor ¶
type PublishMessageExecutor struct {
// contains filtered or unexported fields
}
PublishMessageExecutor calls messages once per execution, so a hive config reload (a changed messaging.max_messages) reaches the next publish.
func NewPublishMessageExecutor ¶
func NewPublishMessageExecutor(messages func() MessageService) *PublishMessageExecutor
func (*PublishMessageExecutor) Execute ¶
func (e *PublishMessageExecutor) Execute(ctx context.Context, action actions.Action, data OutputData, _ ActionInvocationInput) (ExecutionResult, error)
type RemoteGenerator ¶ added in v0.66.0
RemoteGenerator turns an item's repo and web URL into the clone URL hive generates (session.Service.GeneratedRemote).
type RepositoryLauncher ¶
type RepositoryLauncher struct {
// contains filtered or unexported fields
}
RepositoryLauncher creates a hive session for a launch request, then links it to the inbox items it came from and records it in the activity log. It calls sessions once per launch, so a hive config reload reaches the next one.
func NewRepositoryLauncher ¶
func NewRepositoryLauncher(sessions func() SessionCreator, links ItemSessionLinker, recorder activity.Recorder, logger zerolog.Logger) *RepositoryLauncher
NewRepositoryLauncher returns a launcher over sessions. links and recorder may be nil: the session is still created, with no link and no activity row.
func (*RepositoryLauncher) LaunchSession ¶
func (l *RepositoryLauncher) LaunchSession(ctx context.Context, req LaunchSessionRequest) (SessionExecutionOutcome, error)
type RunLog ¶ added in v0.62.0
type RunLog struct {
// contains filtered or unexported fields
}
RunLog collects what one attempt of an output command did: the output of any process it ran and the system lines an executor writes to describe steps that have no process, such as creating a session. Lines reach the sink in batches while the attempt runs, so a viewer can follow it live.
A nil *RunLog discards everything, which is what an execution without a durable command (a terminal-target action) gets.
func RunLogFrom ¶ added in v0.62.0
type RunLogSink ¶ added in v0.62.0
type RunLogSink interface {
AppendLog(ctx context.Context, commandID, attempt int64, lines []stores.NewActionRunLogLine) error
}
RunLogSink persists the lines of one attempt of an output command.
type SessionCreateFailure ¶
type SessionCreateFailure struct {
// Reason is the wrapped error, a chain like
// "clone repository: git clone: exec git: exit status 1".
Reason string `json:"reason"`
// Step is the last thing creation reported: "Cloning repository...",
// "Executing rules...".
Step string `json:"step"`
// Output is the tail of the attempt's progress output, hook output included.
Output string `json:"output"`
// CloneStrategy is "full" or "worktree".
CloneStrategy string `json:"cloneStrategy"`
// Destination is the checkout hive resolved for the attempt.
Destination string `json:"destination"`
// LeftoverCheckout reports that Destination survived the failure, which is
// what makes it a directory to go and delete. A refused clone names a
// destination git already removed.
LeftoverCheckout bool `json:"leftoverCheckout"`
At time.Time `json:"at"`
}
SessionCreateFailure is why one session creation attempt failed.
type SessionCreator ¶
type SessionCreator interface {
CreateFromRequest(context.Context, sessionsvc.LaunchRequest) (session.Session, error)
}
SessionCreator is satisfied by *sessionsvc.Service.
type SessionDraft ¶
type SessionDraft struct {
Repository string `json:"repository,omitempty"`
Workspace string `json:"workspace,omitempty"`
Name string `json:"name"`
Prompt string `json:"prompt"`
Agent string `json:"agent,omitempty"`
ItemIDs []int64 `json:"itemIds,omitempty"`
// nil on a draft that is not a retry, which is also what "no attempt is
// waiting" looks like to a caller.
Failure *SessionCreateFailure `json:"failure,omitempty"`
}
SessionDraft is a New Session form the app prefills: from inbox items, or from a creation attempt that failed and is being handed back. Agent and ItemIDs are only meaningful for the second, which has to restore both because the form they came from is gone.
func RenderSessionDraft ¶
func RenderSessionDraft(title, url string, payload []byte, remotes RemoteGenerator) (SessionDraft, error)
RenderSessionDraft projects one persisted inbox item into a New Session draft.
func RenderSessionDraftItems ¶
func RenderSessionDraftItems(items []SessionDraftItem, remotes RemoteGenerator) (SessionDraft, error)
RenderSessionDraftItems projects ordered inbox items into one New Session draft and one prompt. A single item retains the established draft exactly.
func SessionDraftFromMetadata ¶
func SessionDraftFromMetadata(meta map[string]string) (SessionDraft, bool)
SessionDraftFromMetadata decodes what SessionDraftMetadata wrote. It reports false for a bag that is not a session-create retry or does not name exactly one launch target, so a forged or truncated row prefills nothing.
type SessionDraftItem ¶
SessionDraftItem is the persisted inbox data needed to build one context section in a New Session draft.
type SessionExecutionOutcome ¶
type SessionExecutionOutcome struct {
ID string `json:"id"`
Name string `json:"name"`
// Slug names the tmux session; Path is the checkout a post hook runs in.
Slug string `json:"slug,omitempty"`
Path string `json:"path,omitempty"`
// Remote is the session's stored remote; it differs from the request when
// launch resolution kept a checkout's spelling.
Remote string `json:"remote,omitempty"`
}
type SessionInvocationInput ¶
type SessionLaunchOptions ¶
type SessionLaunchOptions struct {
Repositories []SessionLaunchRepository `json:"repositories"`
DefaultRepository string `json:"defaultRepository"`
Workspaces []SessionLaunchWorkspace `json:"workspaces"`
Agents []string `json:"agents"`
DefaultAgent string `json:"defaultAgent"`
PromptFileThresholdBytes int `json:"promptFileThresholdBytes"`
}
SessionLaunchOptions is the narrow DTO used by the session launch dialog.
type SessionLaunchRepository ¶
type SessionLaunchRepository struct {
Name string `json:"name"`
Repository string `json:"repository"`
}
SessionLaunchRepository is the safe presentation of a repository available to an interactive action. Local checkout paths stay backend-only.
type SessionLaunchWorkspace ¶
type SessionLaunchWorkspace struct {
Dir string `json:"dir"`
Name string `json:"name"`
SupportsPrompt bool `json:"supportsPrompt"`
}
SessionLaunchWorkspace identifies a configured workspace by its stable directory name.
type SessionLauncher ¶
type SessionLauncher interface {
LaunchSession(ctx context.Context, req LaunchSessionRequest) (SessionExecutionOutcome, error)
}
SessionLauncher spawns a hive session for a launch-session action.
type SessionPromptData ¶
type SessionPromptData struct {
Title string
Kind string
Repo string
Num int
Author string
Body string
URL string
Labels []string
State string
}
SessionPromptData is the canonical item contract (ADR canonical-item-contract) the session prompt template renders over. Keep in sync with the frontend's canonicalPayload (lib/itemPresentation.ts).
type SessionTarget ¶
type SessionTarget struct {
ID string
Name string
Slug string
Repo string
Path string
Branch string
// WebURL is the repository's web page, resolved through the forge that
// serves the remote. It is empty for a remote with no host.
WebURL string
}
SessionTarget is the session half of a terminal action's template data, reachable from every template as `.Session.<field>`.
type ShellExecutor ¶
type ShellExecutor struct {
// contains filtered or unexported fields
}
ShellExecutor runs a shell action's command_template via `sh -c`. The command is author-trusted config (actions.yml is a local file the desktop user authors themselves, not untrusted input), so no sandboxing beyond cwd/env/timeout is applied — matching the design's "author-trusted, no heavy sandbox" posture for flow function nodes.
func NewShellExecutor ¶
func NewShellExecutor(logger zerolog.Logger, env ExecEnvironment) *ShellExecutor
func (*ShellExecutor) Execute ¶
func (e *ShellExecutor) Execute(ctx context.Context, action actions.Action, data OutputData, _ ActionInvocationInput) (ExecutionResult, error)
type SystemNotification ¶
type SystemNotification struct {
Title string
Body string
Severity string
Sound bool
// InApp asks the delivery adapter to surface this inside Hive rather than
// as an OS banner. Copied from the policy; see NotificationPolicy.InApp.
InApp bool
// Data rides along to the native notification and comes back when the
// user clicks it, which is how a banner knows which item to reveal.
Data map[string]any
}
SystemNotification is a rendered notification, ready for the OS.
type SystemNotifier ¶
type SystemNotifier interface {
Notify(ctx context.Context, n SystemNotification) error
}
SystemNotifier delivers a notification through the operating system.
type TerminalTarget ¶
type TerminalTarget struct {
Slug string `json:"slug"`
// WindowID is set when the invocation came from a window row. It is what
// separates a window invocation from a session one, and it is the tmux
// window id, so it addresses the window across renames.
WindowID string `json:"windowId,omitempty"`
}
TerminalTarget identifies the terminal session — and optionally the window inside it — an action was invoked from. It carries identity only: every value a template can read is resolved from the session record at invocation time, so a client cannot hand an executor a checkout path of its choosing.
type WindowTarget ¶
type WindowTarget struct {
ID string
}
WindowTarget is the window half, reachable as `.Window.<field>`. Only the id is carried: it is what a tmux command addresses a window by, and unlike the name it does not change under the user.
type Worker ¶
type Worker struct {
// contains filtered or unexported fields
}
func NewWorker ¶
func NewWorker(db OutputCommandStore, as ActionLister, d *Dispatcher, interval time.Duration, logger zerolog.Logger) *Worker
func (*Worker) Confirm ¶
func (w *Worker) Confirm(ctx context.Context, actionID, key string, payload []byte, origin models.ItemRef, input ActionInvocationInput) (ActionRunView, error)
func (*Worker) SetJobRecorder ¶
func (*Worker) SetRecorder ¶
func (*Worker) SetRunLogSink ¶ added in v0.62.0
func (w *Worker) SetRunLogSink(s RunLogSink)
type WorkspaceSessionLauncher ¶
type WorkspaceSessionLauncher interface {
LaunchWorkspaceSession(ctx context.Context, req LaunchWorkspaceSessionRequest) (SessionExecutionOutcome, error)
}