|
1 | 1 | import { existsSync } from 'node:fs'; |
2 | 2 | import { join } from 'node:path'; |
3 | 3 | import { homedir } from 'node:os'; |
4 | | -import type { AgentAdapter } from './base.js'; |
5 | | -import { createSkillXml } from './base.js'; |
6 | | -import type { Skill, AgentType } from '@skillkit/core'; |
| 4 | +import { ClawdbotAdapter } from './clawdbot.js'; |
| 5 | +import type { AgentType } from '@skillkit/core'; |
7 | 6 | import { AGENT_CONFIG } from '@skillkit/core'; |
8 | 7 |
|
9 | 8 | const config = AGENT_CONFIG.openclaw; |
10 | 9 |
|
11 | | -/** |
12 | | - * OpenClaw Agent Adapter |
13 | | - * |
14 | | - * OpenClaw (formerly Clawdbot) is a local-first AI agent framework with a |
15 | | - * persistent gateway daemon. Skills use an extended YAML frontmatter schema |
16 | | - * with `permissions`, `triggers`, and `metadata.openclaw.requires` fields. |
17 | | - * |
18 | | - * Key differences from Claude Code: |
19 | | - * - Skills dir: `skills/` (not `.claude/skills/`) |
20 | | - * - Global skills: `~/.openclaw/skills/` |
21 | | - * - Config: `~/.openclaw/openclaw.json` |
22 | | - * - SKILL.md frontmatter includes: permissions, triggers, metadata.openclaw |
23 | | - * - Gateway loads skills contextually per-agent at runtime |
24 | | - * - Skills are organized by department: skills/<dept>/<name>/SKILL.md |
25 | | - */ |
26 | | -export class OpenClawAdapter implements AgentAdapter { |
27 | | - readonly type: AgentType = 'openclaw'; |
28 | | - readonly name = 'OpenClaw'; |
29 | | - readonly skillsDir = config.skillsDir; |
30 | | - readonly configFile = config.configFile; |
| 10 | +export class OpenClawAdapter extends ClawdbotAdapter { |
| 11 | + override readonly type: AgentType = 'openclaw'; |
| 12 | + override readonly name = 'OpenClaw'; |
| 13 | + override readonly skillsDir = config.skillsDir; |
| 14 | + override readonly configFile = config.configFile; |
31 | 15 |
|
32 | | - generateConfig(skills: Skill[]): string { |
33 | | - const enabledSkills = skills.filter(s => s.enabled); |
34 | | - |
35 | | - if (enabledSkills.length === 0) { |
36 | | - return ''; |
37 | | - } |
38 | | - |
39 | | - const skillsXml = enabledSkills.map(createSkillXml).join('\n\n'); |
40 | | - |
41 | | - return `<skills_system priority="1"> |
42 | | -
|
43 | | -## Available Skills |
44 | | -
|
45 | | -<!-- SKILLS_TABLE_START --> |
46 | | -<usage> |
47 | | -When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge. |
48 | | -
|
49 | | -How to use skills: |
50 | | -- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\` |
51 | | -- The skill content will load with detailed instructions on how to complete the task |
52 | | -- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/) |
53 | | -
|
54 | | -Usage notes: |
55 | | -- Only use skills listed in <available_skills> below |
56 | | -- Do not invoke a skill that is already loaded in your context |
57 | | -- Each skill invocation is stateless |
58 | | -</usage> |
59 | | -
|
60 | | -<available_skills> |
61 | | -
|
62 | | -${skillsXml} |
63 | | -
|
64 | | -</available_skills> |
65 | | -<!-- SKILLS_TABLE_END --> |
66 | | -
|
67 | | -</skills_system>`; |
68 | | - } |
69 | | - |
70 | | - parseConfig(content: string): string[] { |
71 | | - const skillNames: string[] = []; |
72 | | - const skillRegex = /<name>([^<]+)<\/name>/g; |
73 | | - let match; |
74 | | - |
75 | | - while ((match = skillRegex.exec(content)) !== null) { |
76 | | - skillNames.push(match[1].trim()); |
77 | | - } |
78 | | - |
79 | | - return skillNames; |
80 | | - } |
81 | | - |
82 | | - getInvokeCommand(skillName: string): string { |
83 | | - return `skillkit read ${skillName}`; |
84 | | - } |
85 | | - |
86 | | - async isDetected(): Promise<boolean> { |
87 | | - // OpenClaw workspace: skills/ dir at project root |
88 | | - const projectSkills = join(process.cwd(), 'skills'); |
89 | | - // OpenClaw global config |
| 16 | + override async isDetected(): Promise<boolean> { |
90 | 17 | const globalOpenClaw = join(homedir(), '.openclaw'); |
91 | | - // OpenClaw config file |
92 | 18 | const openclawConfig = join(process.cwd(), 'openclaw.json'); |
93 | 19 |
|
94 | | - return ( |
95 | | - (existsSync(projectSkills) && existsSync(globalOpenClaw)) || |
96 | | - existsSync(openclawConfig) |
97 | | - ); |
| 20 | + return existsSync(globalOpenClaw) || existsSync(openclawConfig); |
98 | 21 | } |
99 | 22 | } |
0 commit comments