opencode-lazy-loader 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +81 -3
  2. package/dist/__tests__/normalize-command.test.d.ts +2 -0
  3. package/dist/__tests__/normalize-command.test.d.ts.map +1 -0
  4. package/dist/__tests__/normalize-command.test.js +187 -0
  5. package/dist/__tests__/normalize-command.test.js.map +1 -0
  6. package/dist/index.d.ts +7 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +63 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/skill-loader.d.ts +27 -0
  11. package/dist/skill-loader.d.ts.map +1 -0
  12. package/dist/skill-loader.js +197 -0
  13. package/dist/skill-loader.js.map +1 -0
  14. package/dist/skill-mcp-manager.d.ts +26 -0
  15. package/dist/skill-mcp-manager.d.ts.map +1 -0
  16. package/dist/skill-mcp-manager.js +279 -0
  17. package/dist/skill-mcp-manager.js.map +1 -0
  18. package/dist/tools/skill-mcp.d.ts +13 -0
  19. package/dist/tools/skill-mcp.d.ts.map +1 -0
  20. package/dist/tools/skill-mcp.js +162 -0
  21. package/dist/tools/skill-mcp.js.map +1 -0
  22. package/dist/tools/skill.d.ts +13 -0
  23. package/dist/tools/skill.d.ts.map +1 -0
  24. package/dist/tools/skill.js +160 -0
  25. package/dist/tools/skill.js.map +1 -0
  26. package/dist/types.d.ts +88 -0
  27. package/dist/types.d.ts.map +1 -0
  28. package/dist/types.js +2 -0
  29. package/dist/types.js.map +1 -0
  30. package/dist/utils/env-vars.d.ts +18 -0
  31. package/dist/utils/env-vars.d.ts.map +1 -0
  32. package/dist/utils/env-vars.js +100 -0
  33. package/dist/utils/env-vars.js.map +1 -0
  34. package/dist/utils/frontmatter.d.ts +10 -0
  35. package/dist/utils/frontmatter.d.ts.map +1 -0
  36. package/dist/utils/frontmatter.js +44 -0
  37. package/dist/utils/frontmatter.js.map +1 -0
  38. package/package.json +18 -5
package/README.md CHANGED
@@ -48,6 +48,22 @@ Or install it locally:
48
48
  }
49
49
  ```
50
50
 
51
+ ## Quick Start
52
+
53
+ This repo includes a working example skill. After installing the plugin, try:
54
+
55
+ ```
56
+ skill(name="playwright-example")
57
+ ```
58
+
59
+ Then use the embedded MCP:
60
+
61
+ ```
62
+ skill_mcp(mcp_name="playwright", tool_name="browser_navigate", arguments='{"url": "https://example.com"}')
63
+ ```
64
+
65
+ See [`.opencode/skill/playwright-example/SKILL.md`](.opencode/skill/playwright-example/SKILL.md) for the full example.
66
+
51
67
  ## Usage
52
68
 
53
69
  ### 1. Create a Skill with Embedded MCP
@@ -127,15 +143,77 @@ Invokes an operation on a skill-embedded MCP server.
127
143
 
128
144
  ## Configuration Format
129
145
 
130
- The MCP configuration supports the standard format:
146
+ The MCP configuration supports multiple formats for compatibility with both OpenCode and oh-my-opencode:
131
147
 
132
148
  ```typescript
133
149
  interface McpServerConfig {
134
- command: string | string[]; // Command to execute (array recommended for args)
135
- environment?: Record<string, string> // Environment variables
150
+ // Command formats (both supported):
151
+ command: string | string[] // Array: ["npx", "-y", "@some/mcp"] or String: "npx"
152
+ args?: string[] // Used with string command: ["-y", "@some/mcp"]
153
+
154
+ // Environment variable formats (both supported):
155
+ env?: Record<string, string> | string[] // Object: { "KEY": "val" } or Array: ["KEY=val"]
156
+ }
157
+ ```
158
+
159
+ ### Examples
160
+
161
+ **Object format for env (recommended):**
162
+ ```json
163
+ {
164
+ "my-server": {
165
+ "command": "npx",
166
+ "args": ["-y", "@some/mcp-server"],
167
+ "env": {
168
+ "API_KEY": "${MY_API_KEY}",
169
+ "DEBUG": "true"
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ **Array format for env (OpenCode style):**
176
+ ```json
177
+ {
178
+ "my-server": {
179
+ "command": ["npx", "-y", "@some/mcp-server"],
180
+ "env": ["API_KEY=${MY_API_KEY}", "DEBUG=true"]
181
+ }
136
182
  }
137
183
  ```
138
184
 
185
+ ## Example Skill
186
+
187
+ Here's a complete example of a skill with an embedded MCP server (from [`.opencode/skill/playwright-example/SKILL.md`](.opencode/skill/playwright-example/SKILL.md)):
188
+
189
+ ```markdown
190
+ ---
191
+ name: playwright-example
192
+ description: Browser automation skill for web testing, scraping, and interaction. Use for end-to-end testing, screenshots, and browser automation tasks.
193
+ argument-hint: describe what you want to do (e.g., "take a screenshot of homepage", "test login flow", "fill out a form")
194
+ mcp:
195
+ playwright:
196
+ command: ["npx", "-y", "@playwright/mcp@latest"]
197
+ ---
198
+
199
+ # Playwright Browser Automation
200
+
201
+ This skill provides browser automation capabilities via the Playwright MCP server.
202
+
203
+ ## Available Operations
204
+
205
+ - **Navigation**: Navigate to URLs, go back/forward, reload pages
206
+ - **Screenshots**: Capture full page or element screenshots
207
+ - **Interactions**: Click, type, select, hover, and other user interactions
208
+ - **Forms**: Fill out forms, submit data, handle file uploads
209
+
210
+ ## Example Tasks
211
+
212
+ - "Navigate to the login page and take a screenshot"
213
+ - "Fill out the registration form with test data"
214
+ - "Extract all product names from the catalog page"
215
+ ```
216
+
139
217
  ## License
140
218
 
141
219
  MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=normalize-command.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-command.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/normalize-command.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,187 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { normalizeCommand, normalizeEnv } from '../utils/env-vars.js';
3
+ describe('normalizeCommand', () => {
4
+ describe('OpenCode format (command as array)', () => {
5
+ it('parses command array with executable and args', () => {
6
+ const config = {
7
+ command: ['npx', '-y', '@playwright/mcp@latest']
8
+ };
9
+ const result = normalizeCommand(config);
10
+ expect(result.command).toBe('npx');
11
+ expect(result.args).toEqual(['-y', '@playwright/mcp@latest']);
12
+ });
13
+ it('handles command array with only executable', () => {
14
+ const config = {
15
+ command: ['node']
16
+ };
17
+ const result = normalizeCommand(config);
18
+ expect(result.command).toBe('node');
19
+ expect(result.args).toEqual([]);
20
+ });
21
+ it('converts non-string array elements to strings', () => {
22
+ const config = {
23
+ command: ['node', '--port', 3000]
24
+ };
25
+ const result = normalizeCommand(config);
26
+ expect(result.command).toBe('node');
27
+ expect(result.args).toEqual(['--port', '3000']);
28
+ });
29
+ });
30
+ describe('oh-my-opencode format (command string + args array)', () => {
31
+ it('parses command string with args array', () => {
32
+ const config = {
33
+ command: 'npx',
34
+ args: ['-y', '@anthropic-ai/mcp-playwright']
35
+ };
36
+ const result = normalizeCommand(config);
37
+ expect(result.command).toBe('npx');
38
+ expect(result.args).toEqual(['-y', '@anthropic-ai/mcp-playwright']);
39
+ });
40
+ it('handles command string without args', () => {
41
+ const config = {
42
+ command: 'node'
43
+ };
44
+ const result = normalizeCommand(config);
45
+ expect(result.command).toBe('node');
46
+ expect(result.args).toEqual([]);
47
+ });
48
+ it('handles command string with empty args array', () => {
49
+ const config = {
50
+ command: 'python',
51
+ args: []
52
+ };
53
+ const result = normalizeCommand(config);
54
+ expect(result.command).toBe('python');
55
+ expect(result.args).toEqual([]);
56
+ });
57
+ it('converts non-string args to strings', () => {
58
+ const config = {
59
+ command: 'node',
60
+ args: ['--port', 8080]
61
+ };
62
+ const result = normalizeCommand(config);
63
+ expect(result.command).toBe('node');
64
+ expect(result.args).toEqual(['--port', '8080']);
65
+ });
66
+ });
67
+ describe('edge cases', () => {
68
+ it('throws error when command is undefined', () => {
69
+ const config = {};
70
+ expect(() => normalizeCommand(config)).toThrow('Invalid MCP command configuration: command must be a string or array');
71
+ });
72
+ it('throws error when command is empty array', () => {
73
+ const config = {
74
+ command: []
75
+ };
76
+ expect(() => normalizeCommand(config)).toThrow('Invalid MCP command configuration: command array must not be empty');
77
+ });
78
+ it('ignores args field when command is array (OpenCode format takes precedence)', () => {
79
+ const config = {
80
+ command: ['npx', '-y', '@some/package'],
81
+ args: ['should', 'be', 'ignored']
82
+ };
83
+ const result = normalizeCommand(config);
84
+ expect(result.command).toBe('npx');
85
+ expect(result.args).toEqual(['-y', '@some/package']);
86
+ });
87
+ });
88
+ });
89
+ describe('normalizeEnv', () => {
90
+ describe('object format (oh-my-opencode style)', () => {
91
+ it('passes through object format unchanged', () => {
92
+ const config = {
93
+ command: 'node',
94
+ env: { API_KEY: 'secret', DEBUG: 'true' }
95
+ };
96
+ const result = normalizeEnv(config);
97
+ expect(result.env).toEqual({ API_KEY: 'secret', DEBUG: 'true' });
98
+ });
99
+ it('handles empty object', () => {
100
+ const config = {
101
+ command: 'node',
102
+ env: {}
103
+ };
104
+ const result = normalizeEnv(config);
105
+ expect(result.env).toEqual({});
106
+ });
107
+ });
108
+ describe('array format (OpenCode style)', () => {
109
+ it('converts array of KEY=value strings to object', () => {
110
+ const config = {
111
+ command: 'node',
112
+ env: ['API_KEY=secret', 'DEBUG=true']
113
+ };
114
+ const result = normalizeEnv(config);
115
+ expect(result.env).toEqual({ API_KEY: 'secret', DEBUG: 'true' });
116
+ });
117
+ it('handles values containing equals sign', () => {
118
+ const config = {
119
+ command: 'node',
120
+ env: ['CONNECTION_STRING=host=localhost;port=5432']
121
+ };
122
+ const result = normalizeEnv(config);
123
+ expect(result.env).toEqual({ CONNECTION_STRING: 'host=localhost;port=5432' });
124
+ });
125
+ it('handles empty array', () => {
126
+ const config = {
127
+ command: 'node',
128
+ env: []
129
+ };
130
+ const result = normalizeEnv(config);
131
+ expect(result.env).toEqual({});
132
+ });
133
+ it('skips malformed entries without equals sign', () => {
134
+ const config = {
135
+ command: 'node',
136
+ env: ['VALID=value', 'INVALID_NO_EQUALS', 'ALSO_VALID=123']
137
+ };
138
+ const result = normalizeEnv(config);
139
+ expect(result.env).toEqual({ VALID: 'value', ALSO_VALID: '123' });
140
+ });
141
+ it('skips entries with empty key (equals at start)', () => {
142
+ const config = {
143
+ command: 'node',
144
+ env: ['=value_with_empty_key', 'VALID=value']
145
+ };
146
+ const result = normalizeEnv(config);
147
+ expect(result.env).toEqual({ VALID: 'value' });
148
+ });
149
+ it('handles empty value after equals sign', () => {
150
+ const config = {
151
+ command: 'node',
152
+ env: ['EMPTY_VALUE=']
153
+ };
154
+ const result = normalizeEnv(config);
155
+ expect(result.env).toEqual({ EMPTY_VALUE: '' });
156
+ });
157
+ });
158
+ describe('edge cases', () => {
159
+ it('returns empty object when env is undefined', () => {
160
+ const config = {
161
+ command: 'node'
162
+ };
163
+ const result = normalizeEnv(config);
164
+ expect(result.env).toEqual({});
165
+ });
166
+ });
167
+ describe('backward compatibility', () => {
168
+ it('supports deprecated environment field', () => {
169
+ const config = {
170
+ command: 'node',
171
+ environment: { LEGACY_KEY: 'legacy_value' }
172
+ };
173
+ const result = normalizeEnv(config);
174
+ expect(result.env).toEqual({ LEGACY_KEY: 'legacy_value' });
175
+ });
176
+ it('prefers env over deprecated environment when both present', () => {
177
+ const config = {
178
+ command: 'node',
179
+ env: { NEW_KEY: 'new_value' },
180
+ environment: { OLD_KEY: 'old_value' }
181
+ };
182
+ const result = normalizeEnv(config);
183
+ expect(result.env).toEqual({ NEW_KEY: 'new_value' });
184
+ });
185
+ });
186
+ });
187
+ //# sourceMappingURL=normalize-command.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-command.test.js","sourceRoot":"","sources":["../../src/__tests__/normalize-command.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Plugin } from '@opencode-ai/plugin';
2
+ export declare const OpenCodeEmbeddedSkillMcp: Plugin;
3
+ export default OpenCodeEmbeddedSkillMcp;
4
+ export type { LoadedSkill, McpServerConfig, SkillScope } from './types.js';
5
+ export { discoverSkills } from './skill-loader.js';
6
+ export { createSkillMcpManager } from './skill-mcp-manager.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAejD,eAAO,MAAM,wBAAwB,EAAE,MAkDtC,CAAA;AAGD,eAAe,wBAAwB,CAAA;AAGvC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ import { createSkillMcpManager } from './skill-mcp-manager.js';
2
+ import { discoverSkills } from './skill-loader.js';
3
+ import { createSkillTool } from './tools/skill.js';
4
+ import { createSkillMcpTool } from './tools/skill-mcp.js';
5
+ function hasOhMyOpencode(plugins) {
6
+ return plugins.some(p => p === 'oh-my-opencode' ||
7
+ p === '@code-yeongyu/oh-my-opencode' ||
8
+ p.endsWith('/oh-my-opencode'));
9
+ }
10
+ export const OpenCodeEmbeddedSkillMcp = async ({ client }) => {
11
+ if (process.env.OPENCODE_LAZY_LOADER_FORCE !== '1') {
12
+ try {
13
+ const { data: config } = await client.config.get();
14
+ if (config?.plugin && hasOhMyOpencode(config.plugin)) {
15
+ console.log('[opencode-lazy-loader] oh-my-opencode detected in config, auto-disabling to avoid conflicts');
16
+ return {};
17
+ }
18
+ }
19
+ catch {
20
+ }
21
+ }
22
+ const manager = createSkillMcpManager();
23
+ let loadedSkills = [];
24
+ let currentSessionID = null;
25
+ // Discover skills on initialization
26
+ try {
27
+ loadedSkills = await discoverSkills();
28
+ }
29
+ catch {
30
+ loadedSkills = [];
31
+ }
32
+ return {
33
+ // Handle session lifecycle events
34
+ event: async ({ event }) => {
35
+ if (event.type === 'session.created') {
36
+ currentSessionID = event.properties.info.id;
37
+ }
38
+ if (event.type === 'session.deleted' && currentSessionID) {
39
+ // Cleanup MCP connections for the deleted session
40
+ await manager.disconnectSession(currentSessionID);
41
+ currentSessionID = null;
42
+ }
43
+ },
44
+ // Register tools
45
+ tool: {
46
+ skill: createSkillTool({
47
+ skills: loadedSkills,
48
+ mcpManager: manager,
49
+ getSessionID: () => currentSessionID || 'unknown'
50
+ }),
51
+ skill_mcp: createSkillMcpTool({
52
+ manager,
53
+ getLoadedSkills: () => loadedSkills,
54
+ getSessionID: () => currentSessionID || 'unknown'
55
+ })
56
+ }
57
+ };
58
+ };
59
+ // Default export for plugin loading
60
+ export default OpenCodeEmbeddedSkillMcp;
61
+ export { discoverSkills } from './skill-loader.js';
62
+ export { createSkillMcpManager } from './skill-mcp-manager.js';
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAGzD,SAAS,eAAe,CAAC,OAAiB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CACtB,CAAC,KAAK,gBAAgB;QACtB,CAAC,KAAK,8BAA8B;QACpC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAC9B,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAW,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IACnE,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,GAAG,EAAE,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA;YAClD,IAAI,MAAM,EAAE,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrD,OAAO,CAAC,GAAG,CAAC,6FAA6F,CAAC,CAAA;gBAC1G,OAAO,EAAE,CAAA;YACX,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;QACT,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAA;IACvC,IAAI,YAAY,GAAkB,EAAE,CAAA;IACpC,IAAI,gBAAgB,GAAkB,IAAI,CAAA;IAE1C,oCAAoC;IACpC,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,cAAc,EAAE,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,OAAO;QACL,kCAAkC;QAClC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACrC,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;YAC7C,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,gBAAgB,EAAE,CAAC;gBACzD,kDAAkD;gBAClD,MAAM,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAA;gBACjD,gBAAgB,GAAG,IAAI,CAAA;YACzB,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,IAAI,EAAE;YACJ,KAAK,EAAE,eAAe,CAAC;gBACrB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,OAAO;gBACnB,YAAY,EAAE,GAAG,EAAE,CAAC,gBAAgB,IAAI,SAAS;aAClD,CAAC;YACF,SAAS,EAAE,kBAAkB,CAAC;gBAC5B,OAAO;gBACP,eAAe,EAAE,GAAG,EAAE,CAAC,YAAY;gBACnC,YAAY,EAAE,GAAG,EAAE,CAAC,gBAAgB,IAAI,SAAS;aAClD,CAAC;SACH;KACF,CAAA;AACH,CAAC,CAAA;AAED,oCAAoC;AACpC,eAAe,wBAAwB,CAAA;AAIvC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { LoadedSkill, McpServerConfig, SkillScope } from './types.js';
2
+ /**
3
+ * Load MCP config from mcp.json file in skill directory
4
+ */
5
+ export declare function loadMcpJsonFromDir(skillDir: string): Promise<Record<string, McpServerConfig> | undefined>;
6
+ /**
7
+ * Load a skill from a markdown file path
8
+ */
9
+ export declare function loadSkillFromPath(skillPath: string, resolvedPath: string, defaultName: string, scope: SkillScope): Promise<LoadedSkill | null>;
10
+ /**
11
+ * Load all skills from a directory
12
+ */
13
+ export declare function loadSkillsFromDir(skillsDir: string, scope: SkillScope): Promise<LoadedSkill[]>;
14
+ /**
15
+ * Discover skills from opencode global directory (~/.config/opencode/skill/)
16
+ */
17
+ export declare function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]>;
18
+ /**
19
+ * Discover skills from opencode project directory (.opencode/skill/)
20
+ */
21
+ export declare function discoverOpencodeProjectSkills(): Promise<LoadedSkill[]>;
22
+ /**
23
+ * Discover all skills from both opencode locations
24
+ * Priority: project > global
25
+ */
26
+ export declare function discoverSkills(): Promise<LoadedSkill[]>;
27
+ //# sourceMappingURL=skill-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAe,MAAM,YAAY,CAAA;AAsBvF;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,CAAC,CA+BtD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAsD7B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyDxB;AAED;;GAEG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAG3E;AAED;;GAEG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAG5E;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAoB7D"}
@@ -0,0 +1,197 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, basename } from 'path';
3
+ import { homedir } from 'os';
4
+ import { parseFrontmatter, parseSkillMcpConfigFromFrontmatter } from './utils/frontmatter.js';
5
+ /**
6
+ * Check if a file is a markdown file
7
+ */
8
+ function isMarkdownFile(entry) {
9
+ return entry.name.endsWith('.md');
10
+ }
11
+ /**
12
+ * Resolve symlink to its target path
13
+ */
14
+ async function resolveSymlinkAsync(entryPath) {
15
+ try {
16
+ const realPath = await fs.realpath(entryPath);
17
+ return realPath;
18
+ }
19
+ catch {
20
+ return entryPath;
21
+ }
22
+ }
23
+ /**
24
+ * Load MCP config from mcp.json file in skill directory
25
+ */
26
+ export async function loadMcpJsonFromDir(skillDir) {
27
+ const mcpJsonPath = join(skillDir, 'mcp.json');
28
+ try {
29
+ const content = await fs.readFile(mcpJsonPath, 'utf-8');
30
+ const parsed = JSON.parse(content);
31
+ // Support { mcpServers: { ... } } format
32
+ if (parsed && typeof parsed === 'object' && 'mcpServers' in parsed && parsed.mcpServers) {
33
+ return parsed.mcpServers;
34
+ }
35
+ // Support { mcp: { ... } } format (OpenCode config style)
36
+ if (parsed && typeof parsed === 'object' && 'mcp' in parsed && parsed.mcp) {
37
+ return parsed.mcp;
38
+ }
39
+ // Support direct { serverName: { command: ... } } format
40
+ if (parsed && typeof parsed === 'object' && !('mcpServers' in parsed) && !('mcp' in parsed)) {
41
+ const hasCommandField = Object.values(parsed).some((v) => v && typeof v === 'object' && 'command' in v);
42
+ if (hasCommandField) {
43
+ return parsed;
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ return undefined;
51
+ }
52
+ /**
53
+ * Load a skill from a markdown file path
54
+ */
55
+ export async function loadSkillFromPath(skillPath, resolvedPath, defaultName, scope) {
56
+ try {
57
+ const content = await fs.readFile(skillPath, 'utf-8');
58
+ const { data } = parseFrontmatter(content);
59
+ // Load MCP config from frontmatter or mcp.json
60
+ const frontmatterMcp = parseSkillMcpConfigFromFrontmatter(content);
61
+ const mcpJsonMcp = await loadMcpJsonFromDir(resolvedPath);
62
+ const mcpConfig = mcpJsonMcp || frontmatterMcp; // mcp.json takes priority
63
+ const skillName = data.name || defaultName;
64
+ const originalDescription = data.description || '';
65
+ const formattedDescription = `(${scope} - Skill) ${originalDescription}`;
66
+ // Create lazy content loader
67
+ const lazyContent = {
68
+ loaded: false,
69
+ content: undefined,
70
+ load: async () => {
71
+ if (!lazyContent.loaded) {
72
+ const fileContent = await fs.readFile(skillPath, 'utf-8');
73
+ const { body } = parseFrontmatter(fileContent);
74
+ lazyContent.content = `<skill-instruction>
75
+ Base directory for this skill: ${resolvedPath}/
76
+ File references (@path) in this skill are relative to this directory.
77
+
78
+ ${body.trim()}
79
+ </skill-instruction>
80
+
81
+ <user-request>
82
+ $ARGUMENTS
83
+ </user-request>`;
84
+ lazyContent.loaded = true;
85
+ }
86
+ return lazyContent.content;
87
+ }
88
+ };
89
+ return {
90
+ name: skillName,
91
+ path: skillPath,
92
+ resolvedPath,
93
+ definition: {
94
+ name: skillName,
95
+ description: formattedDescription,
96
+ template: ''
97
+ },
98
+ scope,
99
+ mcpConfig,
100
+ lazyContent
101
+ };
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ }
107
+ /**
108
+ * Load all skills from a directory
109
+ */
110
+ export async function loadSkillsFromDir(skillsDir, scope) {
111
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true }).catch(() => []);
112
+ const skills = [];
113
+ for (const entry of entries) {
114
+ // Skip hidden files
115
+ if (entry.name.startsWith('.')) {
116
+ continue;
117
+ }
118
+ const entryPath = join(skillsDir, entry.name);
119
+ // Handle directories (skill folders)
120
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
121
+ const resolvedPath = await resolveSymlinkAsync(entryPath);
122
+ const dirName = entry.name;
123
+ // Try SKILL.md first
124
+ const skillMdPath = join(resolvedPath, 'SKILL.md');
125
+ try {
126
+ await fs.access(skillMdPath);
127
+ const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
128
+ if (skill) {
129
+ skills.push(skill);
130
+ }
131
+ continue;
132
+ }
133
+ catch {
134
+ // SKILL.md not found, try {dirname}.md
135
+ }
136
+ // Try {dirname}.md
137
+ const namedSkillMdPath = join(resolvedPath, `${dirName}.md`);
138
+ try {
139
+ await fs.access(namedSkillMdPath);
140
+ const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
141
+ if (skill) {
142
+ skills.push(skill);
143
+ }
144
+ continue;
145
+ }
146
+ catch {
147
+ // Named skill file not found
148
+ }
149
+ continue;
150
+ }
151
+ // Handle standalone markdown files
152
+ if (isMarkdownFile(entry)) {
153
+ const skillName = basename(entry.name, '.md');
154
+ const skill = await loadSkillFromPath(entryPath, skillsDir, skillName, scope);
155
+ if (skill) {
156
+ skills.push(skill);
157
+ }
158
+ }
159
+ }
160
+ return skills;
161
+ }
162
+ /**
163
+ * Discover skills from opencode global directory (~/.config/opencode/skill/)
164
+ */
165
+ export async function discoverOpencodeGlobalSkills() {
166
+ const opencodeSkillsDir = join(homedir(), '.config', 'opencode', 'skill');
167
+ return loadSkillsFromDir(opencodeSkillsDir, 'opencode');
168
+ }
169
+ /**
170
+ * Discover skills from opencode project directory (.opencode/skill/)
171
+ */
172
+ export async function discoverOpencodeProjectSkills() {
173
+ const opencodeProjectDir = join(process.cwd(), '.opencode', 'skill');
174
+ return loadSkillsFromDir(opencodeProjectDir, 'opencode-project');
175
+ }
176
+ /**
177
+ * Discover all skills from both opencode locations
178
+ * Priority: project > global
179
+ */
180
+ export async function discoverSkills() {
181
+ const [projectSkills, globalSkills] = await Promise.all([
182
+ discoverOpencodeProjectSkills(),
183
+ discoverOpencodeGlobalSkills()
184
+ ]);
185
+ // Project skills take priority - dedupe by name
186
+ const skillMap = new Map();
187
+ // Add global skills first
188
+ for (const skill of globalSkills) {
189
+ skillMap.set(skill.name, skill);
190
+ }
191
+ // Project skills override global
192
+ for (const skill of projectSkills) {
193
+ skillMap.set(skill.name, skill);
194
+ }
195
+ return Array.from(skillMap.values());
196
+ }
197
+ //# sourceMappingURL=skill-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import type { McpClientInfo, McpContext, McpServerConfig } from './types.js';
3
+ export interface SkillMcpManager {
4
+ getOrCreateClient(info: McpClientInfo, config: McpServerConfig): Promise<Client>;
5
+ disconnectSession(sessionID: string): Promise<void>;
6
+ disconnectAll(): Promise<void>;
7
+ listTools(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
8
+ listResources(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
9
+ listPrompts(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
10
+ callTool(info: McpClientInfo, context: McpContext, name: string, args: Record<string, unknown>): Promise<unknown>;
11
+ readResource(info: McpClientInfo, context: McpContext, uri: string): Promise<unknown>;
12
+ getPrompt(info: McpClientInfo, context: McpContext, name: string, args: Record<string, string>): Promise<unknown>;
13
+ getConnectedServers(): string[];
14
+ isConnected(info: McpClientInfo): boolean;
15
+ }
16
+ /**
17
+ * Create a SkillMcpManager instance
18
+ *
19
+ * Features:
20
+ * - Connection pooling keyed by session/skill/server
21
+ * - Lazy connection creation
22
+ * - Idle cleanup after 5 minutes
23
+ * - Session/process cleanup
24
+ */
25
+ export declare function createSkillMcpManager(): SkillMcpManager;
26
+ //# sourceMappingURL=skill-mcp-manager.d.ts.map