-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin.go
More file actions
151 lines (139 loc) · 5.35 KB
/
plugin.go
File metadata and controls
151 lines (139 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Package ai provides a plugin that registers AI pipeline step types
// (ai_complete, ai_classify, ai_extract), the dynamic.component module type,
// and the sub_workflow step.
package ai
import (
"github.com/GoCodeAlone/modular"
aiPkg "github.com/GoCodeAlone/workflow/ai"
"github.com/GoCodeAlone/workflow/capability"
"github.com/GoCodeAlone/workflow/config"
"github.com/GoCodeAlone/workflow/dynamic"
"github.com/GoCodeAlone/workflow/module"
pluginPkg "github.com/GoCodeAlone/workflow/plugin"
)
// Plugin registers AI step factories, dynamic.component module factory,
// and the sub_workflow step factory.
type Plugin struct {
pluginPkg.BaseEnginePlugin
aiRegistry *aiPkg.AIModelRegistry
dynamicRegistry *dynamic.ComponentRegistry
dynamicLoader *dynamic.Loader
workflowRegistry *pluginPkg.PluginWorkflowRegistry
}
// New creates a new AI plugin. Pass nil for any optional registries;
// the plugin will create defaults where needed.
func New() *Plugin {
return &Plugin{
BaseEnginePlugin: pluginPkg.BaseEnginePlugin{
BaseNativePlugin: pluginPkg.BaseNativePlugin{
PluginName: "ai",
PluginVersion: "1.0.0",
PluginDescription: "AI pipeline steps (complete, classify, extract), dynamic components, and sub-workflow orchestration",
},
Manifest: pluginPkg.PluginManifest{
Name: "ai",
Version: "1.0.0",
Author: "GoCodeAlone",
Description: "AI pipeline steps (complete, classify, extract), dynamic components, and sub-workflow orchestration",
Tier: pluginPkg.TierCore,
ModuleTypes: []string{"dynamic.component"},
StepTypes: []string{"step.ai_complete", "step.ai_classify", "step.ai_extract", "step.sub_workflow"},
Capabilities: []pluginPkg.CapabilityDecl{
{Name: "ai-completion", Role: "provider", Priority: 50},
{Name: "ai-classification", Role: "provider", Priority: 50},
{Name: "ai-extraction", Role: "provider", Priority: 50},
},
},
},
aiRegistry: aiPkg.NewAIModelRegistry(),
workflowRegistry: pluginPkg.NewPluginWorkflowRegistry(),
}
}
// Capabilities returns the capability contracts defined by this plugin.
func (p *Plugin) Capabilities() []capability.Contract {
return []capability.Contract{
{Name: "ai-completion", Description: "AI text completion capabilities"},
{Name: "ai-classification", Description: "AI text classification capabilities"},
{Name: "ai-extraction", Description: "AI data extraction capabilities"},
}
}
// SetAIRegistry sets a custom AI model registry (for sharing with other services).
func (p *Plugin) SetAIRegistry(reg *aiPkg.AIModelRegistry) {
p.aiRegistry = reg
}
// SetDynamicRegistry sets the dynamic component registry for dynamic.component modules.
func (p *Plugin) SetDynamicRegistry(reg *dynamic.ComponentRegistry) {
p.dynamicRegistry = reg
}
// SetDynamicLoader sets the dynamic loader for loading components from source files.
func (p *Plugin) SetDynamicLoader(loader *dynamic.Loader) {
p.dynamicLoader = loader
}
// SetWorkflowRegistry sets the plugin workflow registry for sub_workflow steps.
func (p *Plugin) SetWorkflowRegistry(reg *pluginPkg.PluginWorkflowRegistry) {
p.workflowRegistry = reg
}
// ModuleFactories returns module factories for the dynamic.component type.
func (p *Plugin) ModuleFactories() map[string]pluginPkg.ModuleFactory {
return map[string]pluginPkg.ModuleFactory{
"dynamic.component": func(name string, cfg map[string]any) modular.Module {
if p.dynamicRegistry == nil {
return nil
}
componentID := name
if id, ok := cfg["componentId"].(string); ok && id != "" {
componentID = id
}
// Load from source if loader is available
if p.dynamicLoader != nil {
if sourcePath, ok := cfg["source"].(string); ok && sourcePath != "" {
sourcePath = config.ResolvePathInConfig(cfg, sourcePath)
_, _ = p.dynamicLoader.LoadFromFile(componentID, sourcePath)
}
}
comp, ok := p.dynamicRegistry.Get(componentID)
if !ok {
return nil
}
adapter := dynamic.NewModuleAdapter(comp)
providesList := []string{name}
if provides, ok := cfg["provides"].([]any); ok {
for _, pv := range provides {
if s, ok := pv.(string); ok {
providesList = append(providesList, s)
}
}
}
adapter.SetProvides(providesList)
if requires, ok := cfg["requires"].([]any); ok {
svcs := make([]string, 0, len(requires))
for _, r := range requires {
if s, ok := r.(string); ok {
svcs = append(svcs, s)
}
}
adapter.SetRequires(svcs)
}
return adapter
},
}
}
// StepFactories returns step factories for AI steps and sub_workflow.
func (p *Plugin) StepFactories() map[string]pluginPkg.StepFactory {
return map[string]pluginPkg.StepFactory{
"step.ai_complete": wrapStepFactory(module.NewAICompleteStepFactory(p.aiRegistry)),
"step.ai_classify": wrapStepFactory(module.NewAIClassifyStepFactory(p.aiRegistry)),
"step.ai_extract": wrapStepFactory(module.NewAIExtractStepFactory(p.aiRegistry)),
"step.sub_workflow": wrapStepFactory(module.NewSubWorkflowStepFactory(
p.workflowRegistry,
func(pipelineName string, _ *config.WorkflowConfig, _ modular.Application) (*module.Pipeline, error) {
return &module.Pipeline{Name: pipelineName}, nil
},
)),
}
}
func wrapStepFactory(f module.StepFactory) pluginPkg.StepFactory {
return func(name string, cfg map[string]any, app modular.Application) (any, error) {
return f(name, cfg, app)
}
}