@sveltejs/opencode 0.1.4 → 0.1.6

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 CHANGED
@@ -36,39 +36,76 @@ The plugin injects instructions that teach the agent how to effectively use the
36
36
 
37
37
  ## Configuration
38
38
 
39
- The default configuration:
39
+ Create `svelte.json` to customize how the plugin configures MCP, the Svelte subagent, instructions, and skills.
40
40
 
41
41
  ```json
42
42
  {
43
- "$schema": "https://raw.githubusercontent.com/sveltejs/ai-tools/refs/heads/main/packages/opencode/schema.json",
43
+ "$schema": "https://svelte.dev/opencode/schema.json",
44
44
  "mcp": {
45
45
  "type": "remote",
46
46
  "enabled": true
47
47
  },
48
48
  "subagent": {
49
- "enabled": true
49
+ "enabled": true,
50
+ "agents": {
51
+ "svelte-file-editor": {
52
+ "model": "anthropic/claude-sonnet-4-20250514",
53
+ "temperature": 0.7,
54
+ "top_p": 0.9,
55
+ "maxSteps": 20
56
+ }
57
+ }
50
58
  },
51
59
  "instructions": {
52
60
  "enabled": true
61
+ },
62
+ "skills": {
63
+ "enabled": ["svelte-code-writer", "svelte-core-bestpractices"]
53
64
  }
54
65
  }
55
66
  ```
56
67
 
68
+ ### Defaults
69
+
70
+ If omitted, the plugin uses these defaults:
71
+
72
+ - `mcp.type`: `"remote"`
73
+ - `mcp.enabled`: `true`
74
+ - `subagent.enabled`: `true`
75
+ - `subagent.agents`: `{}`
76
+ - `instructions.enabled`: `true`
77
+ - `skills.enabled`: `true`
78
+
57
79
  ### Configuration Options
58
80
 
59
- | Option | Type | Default | Description |
60
- | ---------------------- | ----------------------- | ---------- | -------------------------------------------------------------------------------- |
61
- | `mcp.type` | `"remote"` \| `"local"` | `"remote"` | Use the remote server at `mcp.svelte.dev` or run locally via `npx @sveltejs/mcp` |
62
- | `mcp.enabled` | `boolean` | `true` | Enable/disable the MCP server |
63
- | `subagent.enabled` | `boolean` | `true` | Enable/disable the Svelte file editor subagent |
64
- | `instructions.enabled` | `boolean` | `true` | Enable/disable agent instructions injection |
81
+ | Option | Type | Default | Description |
82
+ | ------------------------------------------------ | --------------------- | ---------- | ---------------------------------------------------------------------------------------------- |
83
+ | `mcp.type` | `"remote" \| "local"` | `"remote"` | Use `https://mcp.svelte.dev/mcp` (`remote`) or run `@sveltejs/mcp` via `npx` (`local`). |
84
+ | `mcp.enabled` | `boolean` | `true` | Enable or disable the Svelte MCP server entry. |
85
+ | `subagent.enabled` | `boolean` | `true` | Enable or disable registration of the `svelte-file-editor` subagent. |
86
+ | `subagent.agents.svelte-file-editor.model` | `string` | main agent | Override the model used by the Svelte file editor subagent. |
87
+ | `subagent.agents.svelte-file-editor.temperature` | `number` | unset | Set temperature for the subagent. |
88
+ | `subagent.agents.svelte-file-editor.top_p` | `number` | unset | Set top-p sampling for the subagent. |
89
+ | `subagent.agents.svelte-file-editor.maxSteps` | `number` | unlimited | Limit the number of steps the subagent can execute. |
90
+ | `instructions.enabled` | `boolean` | `true` | Enable or disable automatic instruction-file injection. |
91
+ | `skills.enabled` | `boolean \| string[]` | `true` | Enable all skills (`true`), disable all skills (`false`), or enable only specific skill names. |
92
+
93
+ ### Supported Skill Names
94
+
95
+ When using `skills.enabled` as an array, these built-in names are currently available:
96
+
97
+ - `svelte-code-writer`
98
+ - `svelte-core-bestpractices`
99
+
100
+ ### Config File Locations and Precedence
65
101
 
66
- ### Config File Location
102
+ The plugin reads from these files (lowest priority first, highest priority last):
67
103
 
68
- Place your configuration at one of these locations:
104
+ - `~/.config/opencode/svelte.json`
105
+ - `$OPENCODE_CONFIG_DIR/svelte.json` (when `OPENCODE_CONFIG_DIR` is set)
106
+ - `.opencode/svelte.json` in the current project
69
107
 
70
- - `~/.config/opencode/svelte.json` (global)
71
- - `$OPENCODE_CONFIG_DIR/svelte.json` (if `OPENCODE_CONFIG_DIR` is set, takes priority)
108
+ If the same key is defined in multiple files, the later location overrides earlier ones.
72
109
 
73
110
  ## License
74
111
 
package/config.ts CHANGED
@@ -4,6 +4,28 @@ import { homedir } from 'os';
4
4
  import { join } from 'path';
5
5
  import * as v from 'valibot';
6
6
 
7
+ // Schema for individual agent configuration
8
+ const agent_config_schema = v.object({
9
+ model: v.pipe(
10
+ v.optional(v.string()),
11
+ v.description('Model identifier for the agent (e.g., "anthropic/claude-sonnet-4-20250514")'),
12
+ ),
13
+ temperature: v.pipe(
14
+ v.optional(v.number()),
15
+ v.description('Temperature setting for the agent (e.g., 0.7)'),
16
+ ),
17
+ top_p: v.pipe(
18
+ v.optional(v.number()),
19
+ v.description(
20
+ 'Control response diversity with the top_p option. Alternative to temperature for controlling randomness.',
21
+ ),
22
+ ),
23
+ maxSteps: v.pipe(
24
+ v.optional(v.number()),
25
+ v.description('Maximum number of steps the agent can take (e.g., 10)'),
26
+ ),
27
+ });
28
+
7
29
  const default_config = {
8
30
  mcp: {
9
31
  type: 'remote' as 'remote' | 'local',
@@ -11,36 +33,61 @@ const default_config = {
11
33
  },
12
34
  subagent: {
13
35
  enabled: true,
36
+ agents: {} as Record<string, v.InferInput<typeof agent_config_schema>>,
14
37
  },
15
38
  instructions: {
16
39
  enabled: true,
17
40
  },
18
41
  skills: {
19
- enabled: true,
42
+ enabled: true as boolean | string[],
20
43
  },
21
44
  };
22
45
 
23
46
  export const config_schema = v.object({
24
- mcp: v.optional(
25
- v.object({
26
- type: v.optional(v.picklist(['remote', 'local'])),
27
- enabled: v.optional(v.boolean()),
28
- }),
47
+ mcp: v.pipe(
48
+ v.optional(
49
+ v.object({
50
+ type: v.optional(v.picklist(['remote', 'local'])),
51
+ enabled: v.optional(v.boolean()),
52
+ }),
53
+ ),
54
+ v.description(
55
+ "Configuration for the MCP. You can chose if it should be enabled or not and the transport to use 'remote' (default) and 'local'.",
56
+ ),
29
57
  ),
30
- subagent: v.optional(
31
- v.object({
32
- enabled: v.optional(v.boolean()),
33
- }),
58
+ subagent: v.pipe(
59
+ v.optional(
60
+ v.object({
61
+ enabled: v.optional(v.boolean()),
62
+ agents: v.optional(v.record(v.string(), agent_config_schema)),
63
+ }),
64
+ ),
65
+ v.description('Configuration for the subagent. You can choose if it should be enabled or not.'),
34
66
  ),
35
- instructions: v.optional(
36
- v.object({
37
- enabled: v.optional(v.boolean()),
38
- }),
67
+ instructions: v.pipe(
68
+ v.optional(
69
+ v.object({
70
+ enabled: v.optional(v.boolean()),
71
+ }),
72
+ ),
73
+ v.description(
74
+ 'Configuration for the automatic AGENTS.md injection. You can choose if it should be enabled or not.',
75
+ ),
39
76
  ),
40
- skills: v.optional(
41
- v.object({
42
- enabled: v.optional(v.boolean()),
43
- }),
77
+ skills: v.pipe(
78
+ v.optional(
79
+ v.object({
80
+ enabled: v.pipe(
81
+ v.optional(v.union([v.boolean(), v.array(v.string())])),
82
+ v.description(
83
+ 'It can be either a boolean or an array containing the skills that you want to enable',
84
+ ),
85
+ ),
86
+ }),
87
+ ),
88
+ v.description(
89
+ 'Configuration for the skills. You can choose if it they should be enabled or not, or specify an array of skill names to enable only specific skills.',
90
+ ),
44
91
  ),
45
92
  });
46
93
 
@@ -112,8 +159,12 @@ function merge_with_defaults(user_config: Partial<McpConfig>): McpConfig {
112
159
  ...user_config.mcp,
113
160
  },
114
161
  subagent: {
115
- ...default_config.subagent,
162
+ enabled: default_config.subagent.enabled,
116
163
  ...user_config.subagent,
164
+ agents: {
165
+ ...default_config.subagent.agents,
166
+ ...user_config.subagent?.agents,
167
+ },
117
168
  },
118
169
  instructions: {
119
170
  ...default_config.instructions,
@@ -151,7 +202,11 @@ export function get_mcp_config(ctx: PluginInput) {
151
202
  if (parsed.success) {
152
203
  merged = {
153
204
  mcp: { ...merged.mcp, ...parsed.output.mcp },
154
- subagent: { ...merged.subagent, ...parsed.output.subagent },
205
+ subagent: {
206
+ ...merged.subagent,
207
+ ...parsed.output.subagent,
208
+ agents: { ...merged.subagent?.agents, ...parsed.output.subagent?.agents },
209
+ },
155
210
  instructions: { ...merged.instructions, ...parsed.output.instructions },
156
211
  skills: { ...merged.skills, ...parsed.output.skills },
157
212
  };
package/index.ts CHANGED
@@ -39,34 +39,46 @@ export const svelte_plugin: Plugin = async (ctx) => {
39
39
  input.instructions.push(...instructions_paths.map((file) => join(instructions_dir, file)));
40
40
  }
41
41
 
42
- if (mcp_config.skills?.enabled !== false) {
42
+ const skills_enabled = mcp_config.skills?.enabled;
43
+ if (skills_enabled !== false) {
43
44
  const skills_dir = join(current_dir, 'skills');
44
- // @ts-expect-error -- skills is a new opencode feature
45
- input.skills.paths.push(skills_dir);
45
+ if (Array.isArray(skills_enabled)) {
46
+ // only add specific skill directories by name
47
+ for (const skill_name of skills_enabled) {
48
+ const skill_path = join(skills_dir, skill_name);
49
+ // @ts-expect-error -- skills is a new opencode feature
50
+ input.skills.paths.push(skill_path);
51
+ }
52
+ } else {
53
+ // @ts-expect-error -- skills is a new opencode feature
54
+ input.skills.paths.push(skills_dir);
55
+ }
46
56
  }
47
57
 
48
58
  // if the user doesn't have the MCP server already we add one based on config
49
- if (!input.mcp[svelte_mcp_name] && mcp_config.mcp?.enabled !== false) {
59
+ if (!input.mcp[svelte_mcp_name]) {
50
60
  if (mcp_config.mcp?.type === 'remote') {
51
61
  input.mcp[svelte_mcp_name] = {
52
62
  type: 'remote',
53
63
  url: 'https://mcp.svelte.dev/mcp',
64
+ enabled: mcp_config.mcp?.enabled ?? true,
54
65
  };
55
66
  } else {
56
67
  input.mcp[svelte_mcp_name] = {
57
68
  type: 'local',
58
69
  command: ['npx', '-y', '@sveltejs/mcp'],
70
+ enabled: mcp_config.mcp?.enabled ?? true,
59
71
  };
60
72
  }
61
73
  }
62
74
  if (mcp_config.subagent?.enabled !== false) {
63
75
  // we add the editor subagent that will be used when editing Svelte files to prevent wasting context on the main agent
64
- input.agent['svelte-file-editor'] = {
76
+ const default_config: (typeof input.agent)[string] = {
65
77
  color: '#ff3e00',
66
78
  mode: 'subagent',
67
79
  prompt: `You are a Svelte 5 expert responsible for writing, editing, and validating Svelte components and modules. You have access to the Svelte MCP server which provides documentation and code analysis tools. Always use the tools from the svelte MCP server to fetch documentation with \`get_documentation\` and validating the code with \`svelte_autofixer\`. If the autofixer returns any issue or suggestions try to solve them.
68
80
 
69
- If the MCP tools are not available you can use the \`svelte-code-editor\` skill to learn how to use the \`@sveltejs/mcp\` cli to access the same tools.
81
+ If the MCP tools are not available you can use the \`svelte-code-writer\` skill to learn how to use the \`@sveltejs/mcp\` cli to access the same tools.
70
82
 
71
83
  If the skill is not available you can run \`npx @sveltejs/mcp@latest -y --help\` to learn how to use it.
72
84
 
@@ -138,6 +150,27 @@ After completing your work, provide:
138
150
  [`${svelte_mcp_name}_*`]: true,
139
151
  },
140
152
  };
153
+
154
+ // Get per-agent config from svelte.json (if any)
155
+ const svelte_file_editor_config = mcp_config.subagent?.agents?.['svelte-file-editor'];
156
+
157
+ // Configure agent from svelte.json only
158
+ // Priority: svelte.json agent config > defaults
159
+ input.agent['svelte-file-editor'] = {
160
+ ...default_config,
161
+ ...(svelte_file_editor_config?.model !== undefined && {
162
+ model: svelte_file_editor_config.model,
163
+ }),
164
+ ...(svelte_file_editor_config?.temperature !== undefined && {
165
+ temperature: svelte_file_editor_config.temperature,
166
+ }),
167
+ ...(svelte_file_editor_config?.maxSteps !== undefined && {
168
+ maxSteps: svelte_file_editor_config.maxSteps,
169
+ }),
170
+ ...(svelte_file_editor_config?.top_p !== undefined && {
171
+ top_p: svelte_file_editor_config.top_p,
172
+ }),
173
+ };
141
174
  }
142
175
  },
143
176
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/opencode",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/sveltejs/ai-tools#readme",
@@ -134,7 +134,7 @@ The CSS in a component's `<style>` is scoped to that component. If a parent comp
134
134
  </style>
135
135
  ```
136
136
 
137
- If this impossible (for example, the child component comes from a library) you can use `:global` to override styles:
137
+ If this is impossible (for example, the child component comes from a library) you can use `:global` to override styles:
138
138
 
139
139
  ```svelte
140
140
  <div>