opencode-dynamic-skills 1.0.2 → 1.2.0
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.
- package/README.md +58 -19
- package/README.zh-CN.md +53 -19
- package/dist/api.d.ts +21 -61
- package/dist/commands/SlashCommand.d.ts +1 -2
- package/dist/config.d.ts +21 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +840 -598
- package/dist/lib/SkillFs.d.ts +1 -0
- package/dist/lib/formatLoadedSkill.d.ts +6 -0
- package/dist/services/Notifier.d.ts +13 -0
- package/dist/services/Notifier.test.d.ts +1 -0
- package/dist/tools/Skill.d.ts +3 -0
- package/dist/tools/Skill.test.d.ts +1 -0
- package/dist/tools/SkillRecommender.d.ts +25 -8
- package/dist/types.d.ts +17 -19
- package/package.json +1 -1
- package/dist/lib/createPromptRenderer.d.ts +0 -52
- package/dist/lib/createPromptRenderer.test.d.ts +0 -9
- package/dist/lib/getModelFormat.d.ts +0 -35
- package/dist/lib/renderers/JsonPromptRenderer.d.ts +0 -8
- package/dist/lib/renderers/JsonPromptRenderer.test.d.ts +0 -10
- package/dist/lib/renderers/MdPromptRenderer.d.ts +0 -18
- package/dist/lib/renderers/MdPromptRenderer.test.d.ts +0 -11
- package/dist/services/MessageModelIdAccountant.d.ts +0 -22
package/dist/lib/SkillFs.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare const readSkillFile: (path: string) => Promise<string>;
|
|
|
18
18
|
* @returns Array of absolute file paths
|
|
19
19
|
*/
|
|
20
20
|
export declare const listSkillFiles: (skillPath: string, subdirectory: string) => string[];
|
|
21
|
+
export declare const listAllSkillFiles: (skillPath: string) => string[];
|
|
21
22
|
export declare const findSkillPaths: (basePath: string) => Promise<string[]>;
|
|
22
23
|
export declare const doesPathExist: (path: string) => boolean;
|
|
23
24
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NotificationConfig, PluginLogger } from '../types';
|
|
2
|
+
type NotificationRunner = (command: string, args: string[]) => Promise<unknown>;
|
|
3
|
+
export declare function createNotifier(args: {
|
|
4
|
+
config: NotificationConfig;
|
|
5
|
+
logger: PluginLogger;
|
|
6
|
+
shell?: NotificationRunner;
|
|
7
|
+
platform?: NodeJS.Platform;
|
|
8
|
+
}): {
|
|
9
|
+
skillLoaded(skillNames: string[]): Promise<void>;
|
|
10
|
+
resourceLoaded(skillName: string, relativePath: string): Promise<void>;
|
|
11
|
+
error(title: string, message: string): Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,26 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
2
|
+
import type { SkillRecommendConfig, SkillRegistry } from '../types';
|
|
3
|
+
type RecommendationResult = {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
score: number;
|
|
7
|
+
reason: string;
|
|
8
|
+
};
|
|
9
|
+
type RecommenderOptions = {
|
|
10
|
+
client?: PluginInput['client'];
|
|
11
|
+
config: SkillRecommendConfig;
|
|
12
|
+
};
|
|
13
|
+
type ModelRecommendation = {
|
|
14
|
+
name: string;
|
|
15
|
+
reason?: string;
|
|
16
|
+
};
|
|
17
|
+
type ParsedModelSelection = {
|
|
18
|
+
providerID: string;
|
|
19
|
+
modelID: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function parseModelRecommendations(text: string): ModelRecommendation[];
|
|
22
|
+
export declare function parseConfiguredModel(model: string): ParsedModelSelection;
|
|
23
|
+
export declare function createSkillRecommender(provider: SkillRegistry, options: RecommenderOptions): (args: {
|
|
3
24
|
task: string;
|
|
4
25
|
limit?: number;
|
|
5
26
|
}) => Promise<{
|
|
@@ -9,12 +30,7 @@ export declare function createSkillRecommender(provider: SkillRegistry): (args:
|
|
|
9
30
|
name: string;
|
|
10
31
|
description: string;
|
|
11
32
|
}[];
|
|
12
|
-
recommendations:
|
|
13
|
-
name: string;
|
|
14
|
-
description: string;
|
|
15
|
-
score: number;
|
|
16
|
-
reason: string;
|
|
17
|
-
}[];
|
|
33
|
+
recommendations: RecommendationResult[];
|
|
18
34
|
guidance: string;
|
|
19
35
|
summary: {
|
|
20
36
|
total: number;
|
|
@@ -23,3 +39,4 @@ export declare function createSkillRecommender(provider: SkillRegistry): (args:
|
|
|
23
39
|
};
|
|
24
40
|
debug: import("../types").SkillRegistryDebugInfo | undefined;
|
|
25
41
|
}>;
|
|
42
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -3,20 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { ReadyStateMachine } from './lib/ReadyStateMachine';
|
|
5
5
|
/**
|
|
6
|
-
* PromptRenderer Interface
|
|
7
|
-
*
|
|
8
|
-
* WHY: Different LLM models have different strengths and preferences for structured data:
|
|
9
|
-
* - Claude models: trained extensively on XML, prefer structured XML injection
|
|
10
|
-
* - GPT models: strong JSON parsing, prefer JSON-formatted data
|
|
11
|
-
* - Other models: may benefit from markdown readability for better context
|
|
12
|
-
*
|
|
13
|
-
* The provider pattern allows selecting the appropriate renderer at runtime based on:
|
|
14
|
-
* - Model preference (configured in modelRenderers)
|
|
15
|
-
* - Global default (promptRenderer)
|
|
16
|
-
* - Model detection via client.session.message()
|
|
17
|
-
*
|
|
18
|
-
* This abstraction decouples rendering format from tool execution logic,
|
|
19
|
-
* enabling easy format additions without changing plugin code.
|
|
6
|
+
* PromptRenderer Interface for injected XML skill content.
|
|
20
7
|
*/
|
|
21
8
|
type SkillInjectionResult = {
|
|
22
9
|
skill_name: string;
|
|
@@ -65,10 +52,9 @@ export interface PromptRenderer {
|
|
|
65
52
|
*/
|
|
66
53
|
render(args: Args): string;
|
|
67
54
|
/**
|
|
68
|
-
* The format identifier for this renderer
|
|
69
|
-
* Used for logging, debugging, and format selection
|
|
55
|
+
* The format identifier for this renderer.
|
|
70
56
|
*/
|
|
71
|
-
readonly format: '
|
|
57
|
+
readonly format: 'xml';
|
|
72
58
|
}
|
|
73
59
|
/**
|
|
74
60
|
* Skill resource map type for indexing skill resources
|
|
@@ -121,6 +107,7 @@ export type Skill = {
|
|
|
121
107
|
license?: string;
|
|
122
108
|
content: string;
|
|
123
109
|
path: string;
|
|
110
|
+
files: SkillResourceMap;
|
|
124
111
|
scripts: SkillResourceMap;
|
|
125
112
|
references: SkillResourceMap;
|
|
126
113
|
assets: SkillResourceMap;
|
|
@@ -167,10 +154,21 @@ export type SkillRank = {
|
|
|
167
154
|
export type PluginConfig = {
|
|
168
155
|
debug: boolean;
|
|
169
156
|
basePaths: string[];
|
|
170
|
-
promptRenderer: 'json' | 'xml' | 'md';
|
|
171
|
-
modelRenderers?: Record<string, 'json' | 'xml' | 'md'>;
|
|
172
157
|
slashCommandName: string;
|
|
173
158
|
enableSkillAliases: boolean;
|
|
159
|
+
reservedSlashCommands: string[];
|
|
160
|
+
notifications: NotificationConfig;
|
|
161
|
+
skillRecommend: SkillRecommendConfig;
|
|
162
|
+
};
|
|
163
|
+
export type NotificationConfig = {
|
|
164
|
+
enabled: boolean;
|
|
165
|
+
success: boolean;
|
|
166
|
+
errors: boolean;
|
|
167
|
+
};
|
|
168
|
+
export type SkillRecommendConfig = {
|
|
169
|
+
strategy: 'heuristic' | 'model';
|
|
170
|
+
model: string;
|
|
171
|
+
systemPrompt: string;
|
|
174
172
|
};
|
|
175
173
|
export type LogType = 'log' | 'debug' | 'error' | 'warn';
|
|
176
174
|
export type PluginLogger = Record<LogType, (...message: unknown[]) => void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-dynamic-skills",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "OpenCode plugin for dynamic skill loading, slash skill commands, and skill-root-relative resources",
|
|
5
5
|
"homepage": "https://github.com/Wu-H-Y/opencode-dynamic-skills#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prompt Renderer Factory
|
|
3
|
-
*
|
|
4
|
-
* WHY: Factory pattern centralizes renderer instantiation and makes it easy to:
|
|
5
|
-
* - Add new renderer types in the future
|
|
6
|
-
* - Test with different renderers
|
|
7
|
-
* - Handle invalid formats gracefully
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Create a prompt renderer for the specified format
|
|
11
|
-
*
|
|
12
|
-
* @param format The desired format: 'json' | 'xml' | 'md'
|
|
13
|
-
* @returns A PromptRenderer instance for the specified format
|
|
14
|
-
* @throws Error if format is not recognized
|
|
15
|
-
*/
|
|
16
|
-
export declare function createPromptRenderer(): {
|
|
17
|
-
getFormatter: (format: "json" | "xml" | "md") => (args: {
|
|
18
|
-
data: import("../types").Skill;
|
|
19
|
-
type: "Skill";
|
|
20
|
-
} | {
|
|
21
|
-
data: {
|
|
22
|
-
skill_name: string;
|
|
23
|
-
resource_path: string;
|
|
24
|
-
resource_mimetype: string;
|
|
25
|
-
content: string;
|
|
26
|
-
};
|
|
27
|
-
type: "SkillResource";
|
|
28
|
-
} | {
|
|
29
|
-
data: {
|
|
30
|
-
mode?: "search" | "recommend";
|
|
31
|
-
query: string | string[];
|
|
32
|
-
skills: Array<{
|
|
33
|
-
name: string;
|
|
34
|
-
description: string;
|
|
35
|
-
}>;
|
|
36
|
-
summary: {
|
|
37
|
-
total: number;
|
|
38
|
-
matches: number;
|
|
39
|
-
feedback: string;
|
|
40
|
-
};
|
|
41
|
-
recommendations?: Array<{
|
|
42
|
-
name: string;
|
|
43
|
-
description: string;
|
|
44
|
-
score: number;
|
|
45
|
-
reason: string;
|
|
46
|
-
}>;
|
|
47
|
-
guidance?: string;
|
|
48
|
-
debug?: import("../types").SkillRegistryDebugInfo;
|
|
49
|
-
};
|
|
50
|
-
type: "SkillSearchResults";
|
|
51
|
-
}) => string;
|
|
52
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model Format Resolver - Select renderer based on active LLM model
|
|
3
|
-
*
|
|
4
|
-
* WHY: Different LLM models have different preferences and strengths:
|
|
5
|
-
* - Claude models: optimized for XML, prefer structured XML injection
|
|
6
|
-
* - GPT models: strong JSON parsing, prefer JSON-formatted data
|
|
7
|
-
* - Other models: may benefit from markdown readability
|
|
8
|
-
*
|
|
9
|
-
* This function detects the active model and selects the configured
|
|
10
|
-
* format preference for that model, falling back to progressively more
|
|
11
|
-
* generic model patterns.
|
|
12
|
-
*
|
|
13
|
-
* HOW IT WORKS:
|
|
14
|
-
* 1. Query the current session via client.session.message()
|
|
15
|
-
* 2. Extract the modelID from the response (e.g., "anthropic-claude-3-5-sonnet")
|
|
16
|
-
* 3. Try matching in order:
|
|
17
|
-
* - Full model ID (e.g., "anthropic-claude-3-5-sonnet")
|
|
18
|
-
* - Generic model pattern (e.g., "claude-3-5-sonnet")
|
|
19
|
-
* 4. If no match, fall back to promptRenderer default
|
|
20
|
-
*/
|
|
21
|
-
import type { PluginConfig } from '../types';
|
|
22
|
-
/**
|
|
23
|
-
* Resolve the appropriate prompt format for the current model
|
|
24
|
-
*
|
|
25
|
-
* @param args An object containing:
|
|
26
|
-
* - modelId?: The identifier of the active model (e.g., "claude-3-5-sonnet")
|
|
27
|
-
* - providerId?: The identifier of the model provider (e.g., "anthropic")
|
|
28
|
-
* - config: The plugin configuration (has promptRenderer and modelRenderers)
|
|
29
|
-
* @returns The format to use: 'json' | 'xml' | 'md'
|
|
30
|
-
*/
|
|
31
|
-
export declare function getModelFormat(args: {
|
|
32
|
-
modelId?: string;
|
|
33
|
-
providerId?: string;
|
|
34
|
-
config: PluginConfig;
|
|
35
|
-
}): 'json' | 'xml' | 'md';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JsonPromptRenderer - Format objects as JSON
|
|
3
|
-
*
|
|
4
|
-
* WHY: Some LLM models (especially GPT family) have strong JSON parsing
|
|
5
|
-
* and prefer structured JSON data over XML for reliability and clarity.
|
|
6
|
-
*/
|
|
7
|
-
import type { PromptRenderer } from '../../types';
|
|
8
|
-
export declare const createJsonPromptRenderer: () => PromptRenderer;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JsonPromptRenderer Tests
|
|
3
|
-
*
|
|
4
|
-
* Test coverage for real use cases:
|
|
5
|
-
* - Rendering Skill objects for prompt injection
|
|
6
|
-
* - Rendering SkillResource objects (file content)
|
|
7
|
-
* - Rendering SkillSearchResults objects (search results)
|
|
8
|
-
* - Proper JSON formatting with indentation
|
|
9
|
-
*/
|
|
10
|
-
export {};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MdPromptRenderer - Format objects as human-readable Markdown
|
|
3
|
-
*
|
|
4
|
-
* WHY: Markdown provides human-readable formatting that works well for:
|
|
5
|
-
* - Models that benefit from visual structure and readability
|
|
6
|
-
* - Debugging and development (easier to read in logs)
|
|
7
|
-
* - Accessibility and presentation
|
|
8
|
-
*
|
|
9
|
-
* STRUCTURE:
|
|
10
|
-
* - Top-level keys → H3 headings (### key)
|
|
11
|
-
* - Nested objects → H4 headings (#### key) with increased indentation
|
|
12
|
-
* - Leaf nodes → nested bullet list items with emphasis: - **key**: *value*
|
|
13
|
-
* - Arrays → nested bullets under parent key
|
|
14
|
-
* - Special characters → HTML-escaped (<, >, &)
|
|
15
|
-
* - Skill content → appended after --- separator with ### Content heading
|
|
16
|
-
*/
|
|
17
|
-
import type { PromptRenderer } from '../../types';
|
|
18
|
-
export declare const createMdPromptRenderer: () => PromptRenderer;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MdPromptRenderer Tests
|
|
3
|
-
*
|
|
4
|
-
* Test coverage for real use cases:
|
|
5
|
-
* - Rendering Skill objects with metadata, references, scripts, assets
|
|
6
|
-
* - Rendering SkillResource objects (file content)
|
|
7
|
-
* - Rendering SkillSearchResults objects
|
|
8
|
-
* - HTML character escaping for security
|
|
9
|
-
* - Special values handling (null, undefined)
|
|
10
|
-
*/
|
|
11
|
-
export {};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
declare function createMessageModelIdAccountant(): {
|
|
2
|
-
reset: () => void;
|
|
3
|
-
track: (info: {
|
|
4
|
-
sessionID: string;
|
|
5
|
-
messageID: string;
|
|
6
|
-
modelID: string;
|
|
7
|
-
providerID: string;
|
|
8
|
-
}) => void;
|
|
9
|
-
untrackMessage: (args: {
|
|
10
|
-
messageID: string;
|
|
11
|
-
sessionID: string;
|
|
12
|
-
}) => void;
|
|
13
|
-
untrackSession: (sessionID: string) => void;
|
|
14
|
-
getModelInfo: (args: {
|
|
15
|
-
messageID: string;
|
|
16
|
-
sessionID: string;
|
|
17
|
-
}) => {
|
|
18
|
-
modelID: string;
|
|
19
|
-
providerID: string;
|
|
20
|
-
} | undefined;
|
|
21
|
-
};
|
|
22
|
-
export { createMessageModelIdAccountant };
|