extensionrun

package
v1.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrExecutionCancelled = errors.New("extension execution was cancelled")

ErrExecutionCancelled marks a run that ended in a terminal CANCELLED status.

For sql-push that is precisely what a rejected confirmation step produces, so it is returned ALONGSIDE a populated *RunResult: a caller that rejected on purpose needs the plan it rejected. Returning an error as well means every existing caller — none of which reject anything — keeps failing exactly as it did before.

Functions

func EffectiveEntityType added in v1.3.2

func EffectiveEntityType(declared extensiongen.EntityType, fieldIdentifier string) extensiongen.EntityType

EffectiveEntityType supplies the entity type for uuid fields whose extension version was registered without one. The sql-*-local extensions declare local_agent and local_agent_connection as bare uuid fields, so on their own they would prompt for a hand-typed UUID instead of offering the agents this machine can actually reach. Those field identifiers are already a contract across the CLI and the web UI, so keying off them is safe.

TODO: remove once those extension versions declare entity types LOCAL_AGENT / LOCAL_AGENT_CONNECTION themselves.

func UUIDFieldEntityType added in v1.3.2

func UUIDFieldEntityType(field *extensiongen.ExtensionInputField) extensiongen.EntityType

UUIDFieldEntityType reads the entity type declared on a uuid field. The sql-*-local extensions omit type_config entirely, so a missing one is normal rather than a reason to skip resolving options — see EffectiveEntityType.

Types

type ConfigFieldSchema added in v1.0.0

type ConfigFieldSchema struct {
	Identifier  string         `json:"identifier"`
	DisplayName string         `json:"display_name,omitempty"`
	Description string         `json:"description,omitempty"`
	Type        string         `json:"type"` // string|integer|float|boolean|uuid|enum|date|datetime
	Required    bool           `json:"required"`
	Multiple    bool           `json:"multiple,omitempty"` // true for arrays / multi-select enums
	Options     []ConfigOption `json:"options,omitempty"`  // allowed values for uuid/enum fields
}

ConfigFieldSchema describes a single configuration field. Arrays and multi-select enums are represented as the element `type` plus `multiple:true` rather than a distinct "array" type, so callers handle them uniformly.

type ConfigOption added in v1.0.0

type ConfigOption struct {
	Value string `json:"value"`
	Label string `json:"label,omitempty"`
}

ConfigOption is one allowed value for a uuid or enum field. `value` is what the caller must place in the config; `label` is a human-friendly name for it.

type ConfigResolver added in v1.3.2

type ConfigResolver struct {
	// contains filtered or unexported fields
}

ConfigResolver resolves and caches the concrete option lists (entities, connections, object stores, local agents) for a project version, so uuid/enum fields can be described and validated without re-fetching per field. It is shared by `describe` (to list options), the non-interactive config apply (to validate membership) and the interactive prompts (to offer choices).

func (*ConfigResolver) OptionsForEntityType added in v1.3.2

func (r *ConfigResolver) OptionsForEntityType(declared extensiongen.EntityType, fieldIdentifier string, agentUUID string) ([]ConfigOption, error)

OptionsForEntityType returns the allowed uuid options for a given uuid entity type. A nil error with an empty slice means "no options available" (the interactive flow falls back to a free-text prompt in that case, and validation accepts any string).

agentUUID scopes LOCAL_AGENT_CONNECTION options to a single agent; passing "" lists the connections of every online agent, which is what `describe` and non-interactive validation want.

type ConfigSchema added in v1.0.0

type ConfigSchema struct {
	Extension      SchemaExtension        `json:"extension"`
	Project        SchemaRef              `json:"project"`
	ProjectVersion SchemaRef              `json:"project_version"`
	Fields         []ConfigFieldSchema    `json:"fields"`
	LastUsedConfig map[string]interface{} `json:"last_used_config,omitempty"`
}

ConfigSchema fully describes what an extension needs in order to run against a specific project version: the list of configuration fields, their types, and — crucially — the concrete set of allowed values for uuid/enum fields, so a caller never has to guess an entity/connection/store UUID.

type ConfigValidationError added in v1.0.0

type ConfigValidationError struct {
	Fields []FieldError `json:"errors"`
}

ConfigValidationError aggregates all per-field problems found while building a config non-interactively, so an agent gets every issue in one shot rather than one-at-a-time.

func (*ConfigValidationError) Error added in v1.0.0

func (e *ConfigValidationError) Error() string

type DisplayBlock added in v1.4.5

type DisplayBlock struct {
	Identifier  string `json:"identifier"`
	Title       string `json:"title,omitempty"`
	Description string `json:"description,omitempty"`
	ContentType string `json:"content_type,omitempty"`
	Content     string `json:"content"`
}

DisplayBlock is a block from a terminal response — how sql-gen returns rendered SQL, and how a future dry-run mode would return a migration without ever raising a confirmation step.

type FieldError added in v1.0.0

type FieldError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

FieldError describes why a single config field failed validation. It is part of the stable JSON error contract emitted in --json mode.

type Implementation

type Implementation struct {
	// contains filtered or unexported fields
}

func New

func New(params Params) (*Implementation, error)

func (*Implementation) BuildConfigFromJSON added in v1.0.0

func (i *Implementation) BuildConfigFromJSON(
	project *nemgen.Project,
	projectVersionUUID string,
	configEntity *extensiongen.ExtensionConfigurationEntity,
	provided map[string]interface{},
	lastConfig map[string]interface{},
) (map[string]interface{}, error)

BuildConfigFromJSON produces the final config value map for a non-interactive run. `provided` (parsed from --config JSON) is merged over `lastConfig`, then every field is coerced and validated against the schema. On any problem it returns a *ConfigValidationError listing all offending fields.

func (*Implementation) CheckExtensionExecutionLimit added in v0.0.52

func (i *Implementation) CheckExtensionExecutionLimit(projectUUID string, extensionUUID string) (*gen.CheckExtensionExecutionLimitResponse, error)

func (*Implementation) DescribeConfig added in v1.0.0

func (i *Implementation) DescribeConfig(
	project *nemgen.Project,
	projectVersion *nemgen.ProjectVersion,
	extension *nemgen.Extension,
	extensionVersion *nemgen.ExtensionVersion,
	configEntity *extensiongen.ExtensionConfigurationEntity,
	lastConfig map[string]interface{},
) (*ConfigSchema, error)

DescribeConfig produces the full, machine-readable configuration schema for an extension against a specific project version.

func (*Implementation) FindExtensionByIdentifier added in v1.1.0

func (i *Implementation) FindExtensionByIdentifier(identifier string) (*nemgen.Extension, error)

FindExtensionByIdentifier finds any published extension by identifier, regardless of type (generator, sql-push, etc.). Used by run-extension when an explicit --extension identifier is supplied so non-generator extensions are runnable too.

func (*Implementation) GetConfigEntity

func (i *Implementation) GetConfigEntity(extensionVersion *nemgen.ExtensionVersion) (*extensiongen.ExtensionConfigurationEntity, error)

func (*Implementation) GetLastUsedConfigs added in v1.3.2

func (i *Implementation) GetLastUsedConfigs(projectVersionUUID string) (map[string]LastUsedEntry, error)

GetLastUsedConfigs returns the saved config per extension identifier for a project version, including each entry's lastUsed timestamp.

func (*Implementation) GetLatestExtensionVersion

func (i *Implementation) GetLatestExtensionVersion(extensionUUID string) (*nemgen.ExtensionVersion, error)

func (*Implementation) GetOnlineLocalAgents added in v1.3.2

func (i *Implementation) GetOnlineLocalAgents() ([]*nemgen.LocalAgent, error)

GetOnlineLocalAgents returns the agents paired to this account that are currently online, each carrying its published connections.

Offline agents are excluded: an extension run through an offline agent can only fail, so offering one would just produce a failed round-trip.

Only the caller's own agents are listed. The web app also offers agents a teammate shared with the project's team, which needs the ListTeamAgentConnections RPC — that one isn't in protodeps/gen yet, so adding shared agents here means regenerating the protos first (protodeps/gen.sh).

func (*Implementation) GetStandaloneEntities

func (i *Implementation) GetStandaloneEntities(projectVersionUUID string) ([]*nemgen.Entity, error)

GetStandaloneEntities returns all standalone entities from a project version.

func (*Implementation) GetTeamConnections

func (i *Implementation) GetTeamConnections(projectTeamUUID string) ([]*nemgen.Connection, error)

GetTeamConnections returns all connections for the team that owns the given project.

func (*Implementation) GetTeamObjectStores

func (i *Implementation) GetTeamObjectStores(projectTeamUUID string) ([]*nemgen.ObjectStore, error)

GetTeamObjectStores returns all object stores for the team that owns the given project.

func (*Implementation) GetUserRoleForProject

func (i *Implementation) GetUserRoleForProject(projectUUID string) (nemgen.UserProjectRole, error)

func (*Implementation) ListGeneratorExtensions

func (i *Implementation) ListGeneratorExtensions() ([]*nemgen.Extension, error)

func (*Implementation) ListProjectVersions

func (i *Implementation) ListProjectVersions(projectUUID string) ([]*nemgen.ProjectVersion, error)

func (*Implementation) ListRunnableExtensions added in v1.3.2

func (i *Implementation) ListRunnableExtensions(pairFronts []string) ([]*nemgen.Extension, error)

ListRunnableExtensions returns the extensions offered in the interactive picker: every published generator, plus the named pair fronts (importers and synchronizers like sql-push, which are otherwise not generators and so would never show up). The agent-side member of a pair is deliberately absent — it is reached by picking its front and answering the connection-mode question.

func (*Implementation) ListUserProjects

func (i *Implementation) ListUserProjects() ([]*nemgen.Project, error)

func (*Implementation) NewConfigResolver added in v1.3.2

func (i *Implementation) NewConfigResolver(project *nemgen.Project, projectVersionUUID string) *ConfigResolver

func (*Implementation) Run

func (i *Implementation) Run(params RunParams) (*RunResult, error)

func (*Implementation) SaveLastUsedConfigEntry added in v1.3.2

func (i *Implementation) SaveLastUsedConfigEntry(projectVersionUUID, extensionIdentifier string, configValues map[string]interface{}) error

SaveLastUsedConfigEntry persists configValues for a single extension identifier, leaving every sibling entry and every other top-level key untouched.

func (*Implementation) ValidateJWTAuthRequirements added in v1.3.3

func (i *Implementation) ValidateJWTAuthRequirements(projectVersionUUID string, configValues map[string]interface{}) (*ConfigValidationError, []string, error)

ValidateJWTAuthRequirements checks the project schema against what the generated JWT server needs, before generation runs. Without it the run "succeeds" and produces a workspace that only fails later at go build, or on deploy, remotely, during the docker build.

It returns a *ConfigValidationError on the "auth" field when generation would break, plus any non-blocking warnings. Both are nil/empty when auth is not set to jwt.

type LastUsedEntry added in v1.3.2

type LastUsedEntry struct {
	ConfigValues map[string]interface{}
	// LastUsed is the zero time when absent or unparsable, which sorts oldest.
	LastUsed time.Time
}

LastUsedEntry is one extension's saved config plus when it was last run.

type Params

type Params struct {
	Auth *auth.AuthClientImplementation
}

type RunParams

type RunParams struct {
	Extension          *nemgen.Extension
	ExtensionVersion   *nemgen.ExtensionVersion
	ProjectUUID        string
	ProjectVersionUUID string
	ConfigValues       map[string]interface{}
	OutputPath         string
	// AutoConfirmSteps auto-approves CONFIRMATION steps (e.g. the SQL-diff
	// review in sql-push) so step-based extensions can run non-interactively.
	// Without it, a confirmation step is an error on the non-interactive path.
	AutoConfirmSteps bool
	// OnConfirmationStep decides each CONFIRMATION step, seeing its payload first.
	// When nil the run falls back to AutoConfirmSteps — confirm everything, or
	// refuse to proceed — which is what `run-extension --confirm-steps` relies on,
	// so leaving this unset preserves the pre-existing behavior exactly.
	OnConfirmationStep StepDecider
}

type RunResult added in v1.0.0

type RunResult struct {
	Status        string   `json:"status"` // "succeeded" | "cancelled"
	ExecutionUUID string   `json:"execution_uuid,omitempty"`
	OutputPath    string   `json:"output_path"`
	FilesWritten  []string `json:"files_written"`
	FilesRemoved  []string `json:"files_removed"`
	// StatusMessage is the extension's terminal message. It used to be discarded,
	// which is why sql-push's "No changes to apply" — the single most useful thing
	// it says — had never reached a user.
	StatusMessage string `json:"status_message,omitempty"`
	// Steps records every confirmation step and how it was answered, so a step's
	// payload outlives the poll loop.
	Steps []StepOutcome `json:"steps,omitempty"`
	// DisplayBlocks are the terminal response's blocks (e.g. sql-gen's rendered
	// SQL), previously discarded along with everything else non-file.
	DisplayBlocks []DisplayBlock `json:"display_blocks,omitempty"`
}

RunResult is the structured outcome of an extension run, suitable for machine-readable (--json) output consumed by agents / MCP tooling.

func (*RunResult) DisplayBlock added in v1.4.5

func (r *RunResult) DisplayBlock(identifier string) *DisplayBlock

DisplayBlock returns the terminal block with the given identifier, or nil.

func (*RunResult) SQLPreview added in v1.4.5

func (r *RunResult) SQLPreview() string

SQLPreview returns the SQL this run was shown, or "".

It prefers a terminal display block over a step's so callers do not care which channel the SQL arrived on. That indifference is deliberate: today sql-push can only surface a migration by raising a confirmation step, but if it ever gains a real dry-run mode it will return the same SQL as a terminal block, and this is the only line that would need to know.

type SchemaExtension added in v1.0.0

type SchemaExtension struct {
	Identifier  string `json:"identifier"`
	DisplayName string `json:"display_name,omitempty"`
	Version     string `json:"version,omitempty"`
	VersionUUID string `json:"version_uuid,omitempty"`
}

SchemaExtension identifies the resolved extension + version the schema is for.

type SchemaRef added in v1.0.0

type SchemaRef struct {
	Uuid       string `json:"uuid"`
	Identifier string `json:"identifier,omitempty"`
}

SchemaRef is a uuid + human identifier pair for a project or project version.

type StepDecider added in v1.4.5

type StepDecider func(StepPrompt) (StepDecision, error)

StepDecider answers every CONFIRMATION step of a run.

Returning an error aborts the run WITHOUT answering the step, which leaves the execution blocked server-side — the same thing the pre-existing non-interactive path did, and the reason that behavior is expressible here at all.

type StepDecision added in v1.4.5

type StepDecision struct {
	Confirm bool
	Reason  string
}

StepDecision is a caller's answer to a StepPrompt. Reason is carried into the RunResult so the caller can explain a rejection in its own words rather than leaving the CLI to guess at one.

type StepOutcome added in v1.4.5

type StepOutcome struct {
	Prompt    StepPrompt `json:"prompt"`
	Confirmed bool       `json:"confirmed"`
	Reason    string     `json:"reason,omitempty"`
}

StepOutcome records a step and how it was answered, so the payload survives the run instead of being consumed by the poll loop.

type StepPrompt added in v1.4.5

type StepPrompt struct {
	StepIdentifier string `json:"step_identifier"`
	// BlockIdentifier names the display block, e.g. "sql-diff".
	BlockIdentifier string `json:"block_identifier,omitempty"`
	Title           string `json:"title,omitempty"`
	Description     string `json:"description,omitempty"`
	// ContentType is the block's content type as a name: "sql", "json", "text"…
	ContentType string `json:"content_type,omitempty"`
	Content     string `json:"content,omitempty"`
}

StepPrompt is a CONFIRMATION step flattened into the shape a caller needs in order to decide on it. For sql-push, Content is the exact apply SQL that will be sent to the database if the step is confirmed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL