Documentation
¶
Overview ¶
Assembly is the single composition pipeline for a nexss binary. Every capability on App is a loader: a function that receives the accumulating action set and appends to it. Loaders run in declaration order, which makes override and shadowing rules explicit.
The four rules that make this maintainable:
- Order is deliberate. Prompts and skills load before flows, so a .flow file can reference prompt.summarize by name.
- Last-wins. If two sources produce the same action name, the later source replaces the earlier one. User templates shadow builtins.
- Every With* has an escape hatch. If a loader is not what you want, use WithActions and build the slice yourself.
- Nothing is hidden. Callers see the final action list via App.Actions before Run() starts the transport.
Index ¶
- func ResolveConfigPath(flag, envKey string, defaults ...string) (string, error)
- type App
- func (a *App) Mount(actions ...action.AnyAction) *App
- func (a *App) Run()
- func (a *App) WithActions(fn func(context.Context) ([]action.AnyAction, error)) *App
- func (a *App) WithConsole(opts ...ConsoleOption) *App
- func (a *App) WithFlows(dir string) *App
- func (a *App) WithFlowsFolder(root string) *App
- func (a *App) WithLibraries(libs ...flow.Library) *App
- func (a *App) WithLibrary(lib flow.Library) *App
- func (a *App) WithLoader(l Loader) *App
- type Assembly
- type ConsoleOption
- type ExecutionAuditRecord
- type Loader
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type App ¶
type App struct {
Name string
Version string
Port string
WorkDir string
Actions []action.AnyAction
// contains filtered or unexported fields
}
func (*App) Run ¶
func (a *App) Run()
Run is a thin wrapper. It exists so that the deferred signal-context cleanup inside run() always executes on the normal return path. gocritic exitAfterDefer: os.Exit must not be called from a scope that holds a deferred stop().
func (*App) WithActions ¶
WithActions is the universal escape hatch. Use it for anything that does not have a dedicated With* helper, including domain services you build by hand.
func (*App) WithConsole ¶
func (a *App) WithConsole(opts ...ConsoleOption) *App
func (*App) WithFlows ¶
WithFlows compiles every *.flow file in dir into a named action.
Two passes:
- Read all flow sources and install any :exec= / :remote= / :wasm= capability bindings into the shared registry so their short names resolve when the compiler reads the sources.
- Compile each flow into a named action whose Name is the file stem.
Load WithFlows last so its nodes see every other loader's actions.
func (*App) WithFlowsFolder ¶
WithFlowsFolder scans a directory for .flow files that declare @action and registers each one as a callable action, plus three meta-tools (flow.list, flow.inspect, flow.run).
Registration is deferred to the assembly phase, so the flows see the final action set produced by every other With* call.
func (*App) WithLoader ¶
type Assembly ¶
type Assembly struct {
// Actions in load order. Later entries replace earlier entries with the
// same name via dedupe-by-name during finalize().
Actions []action.AnyAction
// contains filtered or unexported fields
}
Assembly is the running set of actions and shared dependencies built during Run(). Loaders mutate it, but the final slice is frozen once the server starts.
type ConsoleOption ¶
func WithConsoleBasePath ¶
func WithConsoleBasePath(path string) ConsoleOption
func WithConsoleExecute ¶
func WithConsoleExecute() ConsoleOption
func WithConsoleTitle ¶
func WithConsoleTitle(title string) ConsoleOption
type ExecutionAuditRecord ¶
type ExecutionAuditRecord struct {
Timestamp time.Time `json:"timestamp"`
Action string `json:"action"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Payload any `json:"payload"`
Result any `json:"result,omitempty"`
DurationMs int64 `json:"duration_ms"`
Assertions []string `json:"assertions,omitempty"`
}
type Loader ¶
Loader contributes actions to the running assembly. Loaders run in declaration order during Run().
The bootstrap package defines the shape but owns none of the concrete loaders. Ecosystem packages (ai/flow/bootstrap, ai/llm/bootstrap, jumalu/bootstrap) provide their own. This keeps the flow bootstrap free of any direct dependency on ai or jumalu.
A Loader must append to asm.Actions and must not replace the slice:
func MyLoader(...) bootstrap.Loader {
return func(asm *bootstrap.Assembly) error {
asm.Actions = append(asm.Actions, myActions...)
return nil
}
}