first commit
This commit is contained in:
129
go-api/internal/runtime/executor.go
Normal file
129
go-api/internal/runtime/executor.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/krow/krow-backend/go-api/internal/authctx"
|
||||
"github.com/krow/krow-backend/go-api/internal/repo"
|
||||
)
|
||||
|
||||
// AgentExecutor is the boundary interface for executing an authored agent.
|
||||
type AgentExecutor interface {
|
||||
ExecuteAgent(ctx context.Context, agent *Agent, input ExecutionInput) (*ExecutionResult, error)
|
||||
}
|
||||
|
||||
// SkillExecutor is the boundary interface for executing an authored skill.
|
||||
type SkillExecutor interface {
|
||||
ExecuteSkill(ctx context.Context, skill *Skill, input ExecutionInput) (*ExecutionResult, error)
|
||||
}
|
||||
|
||||
// UnavailableExecutor is the Phase 4F default stub executor that explicitly refuses execution
|
||||
// until real AI / Owliver / LangGraph executors are installed in Phase 5.
|
||||
type UnavailableExecutor struct{}
|
||||
|
||||
// ExecuteAgent implements AgentExecutor by returning ErrExecutorUnavailable.
|
||||
func (u *UnavailableExecutor) ExecuteAgent(_ context.Context, agent *Agent, _ ExecutionInput) (*ExecutionResult, error) {
|
||||
skillIDs := make([]string, len(agent.ResolvedSkills))
|
||||
for i, s := range agent.ResolvedSkills {
|
||||
skillIDs[i] = s.ID
|
||||
}
|
||||
|
||||
return &ExecutionResult{
|
||||
Success: false,
|
||||
AgentID: agent.ID,
|
||||
AgentVersion: agent.Version,
|
||||
ResolvedSkills: skillIDs,
|
||||
Error: ErrExecutorUnavailable,
|
||||
}, ErrExecutorUnavailable
|
||||
}
|
||||
|
||||
// ExecuteSkill implements SkillExecutor by returning ErrExecutorUnavailable.
|
||||
func (u *UnavailableExecutor) ExecuteSkill(_ context.Context, skill *Skill, _ ExecutionInput) (*ExecutionResult, error) {
|
||||
return &ExecutionResult{
|
||||
Success: false,
|
||||
Error: ErrExecutorUnavailable,
|
||||
}, ErrExecutorUnavailable
|
||||
}
|
||||
|
||||
// Engine coordinates runtime loading, eligibility checks, dependency resolution and execution.
|
||||
type Engine struct {
|
||||
Loader *Loader
|
||||
AgentExec AgentExecutor
|
||||
SkillExec SkillExecutor
|
||||
}
|
||||
|
||||
// Option configures the runtime engine.
|
||||
type Option func(*Engine)
|
||||
|
||||
// WithAgentExecutor overrides the agent executor implementation.
|
||||
func WithAgentExecutor(exec AgentExecutor) Option {
|
||||
return func(e *Engine) {
|
||||
if exec != nil {
|
||||
e.AgentExec = exec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithSkillExecutor overrides the skill executor implementation.
|
||||
func WithSkillExecutor(exec SkillExecutor) Option {
|
||||
return func(e *Engine) {
|
||||
if exec != nil {
|
||||
e.SkillExec = exec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewEngine builds a runtime engine over a database querier.
|
||||
func NewEngine(db repo.Querier, opts ...Option) *Engine {
|
||||
e := &Engine{
|
||||
Loader: NewLoader(db),
|
||||
AgentExec: &UnavailableExecutor{},
|
||||
SkillExec: &UnavailableExecutor{},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(e)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// RunAgent loads an executable agent with dependencies and dispatches to the executor boundary.
|
||||
func (e *Engine) RunAgent(ctx context.Context, ident authctx.Identity, idOrDefID string, input ExecutionInput) (*ExecutionResult, error) {
|
||||
agent, err := e.Loader.LoadExecutableAgent(ctx, ident, idOrDefID)
|
||||
if err != nil {
|
||||
return &ExecutionResult{
|
||||
Success: false,
|
||||
Error: err,
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := e.AgentExec.ExecuteAgent(ctx, agent, input)
|
||||
if res == nil {
|
||||
res = &ExecutionResult{
|
||||
Success: err == nil,
|
||||
AgentID: agent.ID,
|
||||
AgentVersion: agent.Version,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
// RunSkill loads an executable skill and dispatches to the executor boundary.
|
||||
func (e *Engine) RunSkill(ctx context.Context, ident authctx.Identity, idOrDefID string, input ExecutionInput) (*ExecutionResult, error) {
|
||||
skill, err := e.Loader.LoadExecutableSkill(ctx, ident, idOrDefID)
|
||||
if err != nil {
|
||||
return &ExecutionResult{
|
||||
Success: false,
|
||||
Error: err,
|
||||
}, err
|
||||
}
|
||||
|
||||
res, err := e.SkillExec.ExecuteSkill(ctx, skill, input)
|
||||
if res == nil {
|
||||
res = &ExecutionResult{
|
||||
Success: err == nil,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
Reference in New Issue
Block a user