Skip to content

Commit e4e1230

Browse files
grokifyclaude
andcommitted
feat(migration): add migration guide and adapter utilities
Add migration package for PlexusOne projects transitioning from bespoke tool layers to omniskill: - docs/migration/README.md: Step-by-step migration guide with before/after code examples - migration/adapter.go: Adapters to wrap legacy Tool and Skill interfaces for gradual migration - migration/check.go: Validation to verify migration completeness Adapters allow legacy tools to work with omniskill registry while native implementations are written. Check() identifies remaining migration work (adapted items, missing descriptions, etc). Refs: RMI-OMNISKILL-018 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 521e105 commit e4e1230

6 files changed

Lines changed: 1256 additions & 0 deletions

File tree

docs/migration/README.md

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
# Migrating to OmniSkill
2+
3+
This guide helps PlexusOne agent projects migrate from bespoke tool layers to the standardized OmniSkill framework.
4+
5+
## Why Migrate?
6+
7+
OmniSkill provides:
8+
9+
- **Unified interfaces**: `skill.Skill` and `skill.Tool` work across all PlexusOne agents
10+
- **Registry and discovery**: Central tool registration with `registry.InMemory`
11+
- **MCP compatibility**: Expose skills as MCP servers with minimal code
12+
- **Pack distribution**: Bundle and share skills via ClawHub or Go modules
13+
- **Role composition**: Build agent personas from reusable skill sets
14+
- **Version management**: Semantic versioning with constraint resolution
15+
16+
## Migration Checklist
17+
18+
### Phase 1: Interface Alignment
19+
20+
- [ ] Identify all custom tool types in your project
21+
- [ ] Map each to `skill.Tool` or `skill.Skill`
22+
- [ ] Replace custom parameter types with `skill.Parameter`
23+
- [ ] Update tool execution to return `(any, error)` tuples
24+
25+
### Phase 2: Registry Migration
26+
27+
- [ ] Replace custom tool registries with `registry.InMemory`
28+
- [ ] Update tool lookup calls to use `registry.Get()` / `registry.GetTool()`
29+
- [ ] Migrate initialization code to `registry.Init(ctx)`
30+
31+
### Phase 3: Skill Organization
32+
33+
- [ ] Group related tools into skills (one skill = one capability domain)
34+
- [ ] Add `Init()` and `Close()` lifecycle methods
35+
- [ ] Implement `Description()` and `Version()` for each skill
36+
37+
### Phase 4: MCP Exposure (Optional)
38+
39+
- [ ] Wrap skills with `mcp/server` for remote access
40+
- [ ] Configure OAuth if authentication is needed
41+
- [ ] Add rate limiting and authorization middleware
42+
43+
### Phase 5: Validation
44+
45+
- [ ] Run `migration.Check()` to verify completeness
46+
- [ ] Test all tools through the registry interface
47+
- [ ] Update integration tests to use omniskill types
48+
49+
## Common Patterns
50+
51+
### Custom Tool → skill.Tool
52+
53+
**Before (bespoke):**
54+
55+
```go
56+
type MyTool struct {
57+
name string
58+
description string
59+
handler func(args map[string]any) (any, error)
60+
}
61+
62+
func (t *MyTool) Execute(args map[string]any) (any, error) {
63+
return t.handler(args)
64+
}
65+
```
66+
67+
**After (omniskill):**
68+
69+
```go
70+
import "github.com/plexusone/omniskill/skill"
71+
72+
type MyTool struct {
73+
skill.BaseTool
74+
}
75+
76+
func NewMyTool() *MyTool {
77+
return &MyTool{
78+
BaseTool: skill.BaseTool{
79+
ToolName: "my-tool",
80+
ToolDescription: "Does something useful",
81+
ToolParameters: []skill.Parameter{
82+
{Name: "input", Type: "string", Required: true},
83+
},
84+
},
85+
}
86+
}
87+
88+
func (t *MyTool) Execute(ctx context.Context, args map[string]any) (any, error) {
89+
input, _ := args["input"].(string)
90+
// ... implementation
91+
return result, nil
92+
}
93+
```
94+
95+
### Custom Registry → registry.InMemory
96+
97+
**Before (bespoke):**
98+
99+
```go
100+
type ToolRegistry struct {
101+
tools map[string]Tool
102+
}
103+
104+
func (r *ToolRegistry) Register(t Tool) {
105+
r.tools[t.Name()] = t
106+
}
107+
108+
func (r *ToolRegistry) Get(name string) Tool {
109+
return r.tools[name]
110+
}
111+
```
112+
113+
**After (omniskill):**
114+
115+
```go
116+
import "github.com/plexusone/omniskill/registry"
117+
118+
reg := registry.New()
119+
reg.Register(mySkill)
120+
121+
// Get a skill
122+
s, err := reg.Get("my-skill")
123+
124+
// Get a specific tool
125+
t, err := reg.GetTool("my-skill.my-tool")
126+
127+
// List all tools across skills
128+
tools := reg.ListTools()
129+
```
130+
131+
### Custom Parameters → skill.Parameter
132+
133+
**Before (bespoke):**
134+
135+
```go
136+
type Param struct {
137+
Name string
138+
Type string
139+
Required bool
140+
Default any
141+
}
142+
```
143+
144+
**After (omniskill):**
145+
146+
```go
147+
import "github.com/plexusone/omniskill/skill"
148+
149+
params := []skill.Parameter{
150+
{
151+
Name: "query",
152+
Type: "string",
153+
Description: "Search query",
154+
Required: true,
155+
},
156+
{
157+
Name: "limit",
158+
Type: "integer",
159+
Description: "Max results",
160+
Default: 10,
161+
Minimum: ptrFloat(1),
162+
Maximum: ptrFloat(100),
163+
},
164+
{
165+
Name: "format",
166+
Type: "string",
167+
Enum: []string{"json", "csv", "text"},
168+
Default: "json",
169+
},
170+
}
171+
```
172+
173+
### Skill Grouping
174+
175+
**Before (flat tools):**
176+
177+
```go
178+
RegisterTool(&SearchTool{})
179+
RegisterTool(&IndexTool{})
180+
RegisterTool(&DeleteTool{})
181+
```
182+
183+
**After (grouped skill):**
184+
185+
```go
186+
import "github.com/plexusone/omniskill/skill"
187+
188+
type SearchSkill struct {
189+
skill.BaseSkill
190+
}
191+
192+
func NewSearchSkill() *SearchSkill {
193+
return &SearchSkill{
194+
BaseSkill: skill.BaseSkill{
195+
SkillName: "search",
196+
SkillDescription: "Full-text search capabilities",
197+
SkillTools: []skill.Tool{
198+
NewSearchTool(),
199+
NewIndexTool(),
200+
NewDeleteTool(),
201+
},
202+
},
203+
}
204+
}
205+
206+
// Register the skill (not individual tools)
207+
reg.Register(NewSearchSkill())
208+
```
209+
210+
## Using Migration Adapters
211+
212+
For gradual migration, use the `migration` package adapters:
213+
214+
```go
215+
import "github.com/plexusone/omniskill/migration"
216+
217+
// Wrap a legacy tool
218+
legacyTool := &MyLegacyTool{}
219+
adapted := migration.AdaptTool(legacyTool)
220+
221+
// Wrap a legacy registry
222+
legacyReg := &MyLegacyRegistry{}
223+
adapted := migration.AdaptRegistry(legacyReg)
224+
225+
// Check migration completeness
226+
issues := migration.Check(reg)
227+
for _, issue := range issues {
228+
fmt.Printf("[%s] %s: %s\n", issue.Severity, issue.Location, issue.Message)
229+
}
230+
```
231+
232+
## Validation
233+
234+
Run the migration checker to verify completeness:
235+
236+
```go
237+
import "github.com/plexusone/omniskill/migration"
238+
239+
issues := migration.Check(myRegistry)
240+
if len(issues) > 0 {
241+
for _, issue := range issues {
242+
log.Printf("%s: %s", issue.Location, issue.Message)
243+
}
244+
}
245+
```
246+
247+
Common issues detected:
248+
249+
- Missing `Description()` implementations
250+
- Tools without parameters defined
251+
- Skills without `Version()` method
252+
- Uninitialized skills in registry
253+
254+
## Testing Migration
255+
256+
```go
257+
func TestMigration(t *testing.T) {
258+
reg := registry.New()
259+
reg.Register(NewMySkill())
260+
261+
issues := migration.Check(reg)
262+
if len(issues) > 0 {
263+
for _, issue := range issues {
264+
t.Errorf("%s: %s", issue.Location, issue.Message)
265+
}
266+
}
267+
}
268+
```
269+
270+
## Getting Help
271+
272+
- Review existing skills in `roles/` for reference implementations
273+
- Check `skill/skill_test.go` for interface examples
274+
- File issues at github.com/plexusone/omniskill/issues

0 commit comments

Comments
 (0)