@aiderdesk/aiderdesk 0.61.0 → 0.61.1

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 (22) hide show
  1. package/out/resources/skills/extension-creator/SKILL.md +320 -0
  2. package/out/resources/skills/extension-creator/assets/templates/Component.jsx.template +76 -0
  3. package/out/resources/skills/extension-creator/assets/templates/ConfigComponent.jsx.template +38 -0
  4. package/out/resources/skills/extension-creator/assets/templates/folder-extension/config.ts.template +29 -0
  5. package/out/resources/skills/extension-creator/assets/templates/folder-extension/index.ts.template +42 -0
  6. package/out/resources/skills/extension-creator/assets/templates/folder-extension/package.json +12 -0
  7. package/out/resources/skills/extension-creator/assets/templates/folder-extension/tsconfig.json +23 -0
  8. package/out/resources/skills/extension-creator/assets/templates/folder-extension-with-config/index.ts.template +80 -0
  9. package/out/resources/skills/extension-creator/assets/templates/single-file.ts.template +30 -0
  10. package/out/resources/skills/extension-creator/assets/templates/ui-component-external.ts.template +91 -0
  11. package/out/resources/skills/extension-creator/assets/templates/ui-component.ts.template +79 -0
  12. package/out/resources/skills/extension-creator/references/command-definition.md +170 -0
  13. package/out/resources/skills/extension-creator/references/config-components.md +427 -0
  14. package/out/resources/skills/extension-creator/references/event-types.md +156 -0
  15. package/out/resources/skills/extension-creator/references/examples-gallery.md +583 -0
  16. package/out/resources/skills/extension-creator/references/extension-interface.md +240 -0
  17. package/out/resources/skills/extension-creator/references/extension-types.md +186 -0
  18. package/out/resources/skills/extension-creator/references/in-repo-flow.md +132 -0
  19. package/out/resources/skills/extension-creator/references/install-targets.md +96 -0
  20. package/out/resources/skills/extension-creator/references/project-global-flow.md +76 -0
  21. package/out/resources/skills/extension-creator/references/ui-components.md +663 -0
  22. package/package.json +1 -1
@@ -0,0 +1,320 @@
1
+ ---
2
+ name: extension-creator
3
+ description: Create AiderDesk extensions by setting up extension files, defining metadata, implementing Extension interface methods, and updating documentation. Use when building a new extension, creating extension commands, tools, or event handlers.
4
+ ---
5
+
6
+ # Extension Creator
7
+
8
+ Create AiderDesk extensions that extend functionality through events, commands, tools, agents, and modes.
9
+
10
+ ## When to Use
11
+
12
+ Use this skill when:
13
+
14
+ - Building a new AiderDesk extension
15
+ - Creating extension commands, tools, or event handlers
16
+ - Implementing the Extension interface
17
+ - Setting up extension metadata and documentation
18
+
19
+ Do not use when:
20
+
21
+ - Simply activating an existing extension
22
+ - Making general code changes unrelated to extensions
23
+ - Running tests or builds
24
+
25
+ ## Rules
26
+
27
+ ### Rule: Choose installation target first
28
+
29
+ **When:** Starting extension creation
30
+
31
+ **Then:** Ask the user where to install the extension
32
+
33
+ **If:** Working inside the AiderDesk project (the current project is the aider-desk repository)
34
+
35
+ **Then:** Offer three options:
36
+ 1. **Current Project** — Install to `.aider-desk/extensions/` in the current project (project-scoped)
37
+ 2. **Global** — Install to `~/.aider-desk/extensions/` (available in all projects)
38
+ 3. **In-Repo** — Create inside `packages/extensions/extensions/` (ships with AiderDesk app)
39
+
40
+ **If:** Working outside the AiderDesk project
41
+
42
+ **Then:** Offer two options:
43
+ 1. **Current Project** — Install to `.aider-desk/extensions/` in the current project (project-scoped)
44
+ 2. **Global** — Install to `~/.aider-desk/extensions/` (available in all projects)
45
+
46
+ **Must:** Wait for user's choice before proceeding. The chosen target determines the entire workflow.
47
+
48
+ **Reference:** [references/install-targets.md](references/install-targets.md) for full details on each target.
49
+
50
+ ### Rule: Follow the correct flow for the chosen target
51
+
52
+ **When:** User has chosen an installation target
53
+
54
+ **If:** Target is **Current Project** or **Global**
55
+
56
+ **Then:** Follow the [Project / Global Flow](references/project-global-flow.md):
57
+ 1. Determine extension type (single-file or folder)
58
+ 2. Create extension file(s) in the target directory (`.aider-desk/extensions/` or `~/.aider-desk/extensions/`)
59
+ 3. Implement Extension interface methods
60
+ 4. Export metadata and default class
61
+ 5. Verify the extension loads (auto-discovered, no registry needed)
62
+
63
+ **If:** Target is **In-Repo**
64
+
65
+ **Then:** Follow the [In-Repo Flow](references/in-repo-flow.md):
66
+ 1. Determine extension type (single-file or folder)
67
+ 2. Create extension file(s) in `packages/extensions/extensions/`
68
+ 3. Implement Extension interface methods
69
+ 4. Export metadata and default class
70
+ 5. **Register in `packages/extensions/extensions.json`**
71
+ 6. **Document in `docs-site/docs/extensions/examples.md`**
72
+ 7. Install npm dependencies if folder extension
73
+ 8. Verify with type checking
74
+
75
+ ### Rule: Determine extension type
76
+
77
+ **When:** Creating extension files (after target is chosen)
78
+
79
+ **Then:** Check if extension needs npm dependencies or multiple files
80
+
81
+ **If:** Extension needs dependencies or multiple files
82
+
83
+ **Then:** Create folder extension
84
+
85
+ **If:** Extension is simple with no dependencies
86
+
87
+ **Then:** Create single-file extension
88
+
89
+ ### Rule: Implement Extension interface
90
+
91
+ **When:** Creating extension file
92
+
93
+ **Then:** Implement required methods from Extension interface
94
+
95
+ **Must:** Define `static metadata` property on the class with name, version, description, author, capabilities
96
+
97
+ **Must:** Export class as `default` (e.g., `export default class MyExtension implements Extension`)
98
+
99
+ **Never:** Use `@/` imports in extension files
100
+
101
+ ### Rule: Add UI components when needed
102
+
103
+ **When:** Extension needs to display UI elements in task page placements
104
+
105
+ **Then:** Implement `getUIComponents()` method
106
+
107
+ **Must:** Return array of UIComponentDefinition objects with id, placement, jsx
108
+
109
+ **Must:** Define components as JSX strings or load from .jsx files
110
+
111
+ **If:** Component needs data, set `loadData: true` and implement `getUIExtensionData()`
112
+
113
+ **If:** Component triggers actions, implement `executeUIExtensionAction()`
114
+
115
+ ### Rule: Add config component for extension settings
116
+
117
+ **When:** Extension needs user-configurable settings (shown in gear icon dialog)
118
+
119
+ **Then:** Implement three methods: `getConfigComponent()`, `getConfigData()`, `saveConfigData()`
120
+
121
+ **Must:** Return JSX string from `getConfigComponent()` — use external .jsx file for components > 20 lines
122
+
123
+ **Must:** Load/merge defaults in `getConfigData()`, persist merged data in `saveConfigData()`
124
+
125
+ **Must:** Store config file in extension directory via `join(__dirname, 'config.json')`
126
+
127
+ **Must:** Use `ui.*` components (`ui.Input`, `ui.Checkbox`, etc.) instead of raw HTML elements
128
+
129
+ **Should:** Avoid inner state (`useState`/`useEffect`) for simple form fields — read directly from `config` prop, call `updateConfig` on change. Only use local state for derived values or transient UI state.
130
+
131
+ **Never:** Use `'extension-settings'` placement — it was removed; use the dedicated config API instead
132
+
133
+ ### Rule: Update registry and docs (In-Repo only)
134
+
135
+ **When:** Target is In-Repo and extension file is created
136
+
137
+ **Then:** Add entry to `packages/extensions/extensions.json`
138
+
139
+ **Must:** Include id, name, description, file or folder path, type, capabilities
140
+
141
+ **Must:** Set `hasDependencies: true` for folder extensions
142
+
143
+ **Then:** Add entry to `docs-site/docs/extensions/examples.md` table
144
+
145
+ **Must:** Include extension name, description, capabilities, and type
146
+
147
+ **When:** Target is Project or Global
148
+
149
+ **Then:** Do NOT modify `extensions.json` or `examples.md` — these are only for built-in extensions
150
+
151
+ ### Rule: Use proper TypeScript config for folders
152
+
153
+ **When:** Creating folder extension
154
+
155
+ **Then:** Include `tsconfig.json` with `module: ES2020+`
156
+
157
+ **Must:** Include `package.json` with name, version, main, dependencies
158
+
159
+ ### Rule: Store config in extension directory
160
+
161
+ **When:** Extension needs persistent config
162
+
163
+ **Then:** Store config files in extension directory
164
+
165
+ **Never:** Store config outside extension directory
166
+
167
+ ## Process Overview
168
+
169
+ ### For Project / Global targets:
170
+
171
+ 1. Ask user: Current Project or Global?
172
+ 2. Determine extension type (single-file or folder)
173
+ 3. Create extension file or directory structure in target dir
174
+ 4. Implement Extension interface methods
175
+ 5. Export metadata and default class
176
+ 6. Verify extension loads (auto-discovered)
177
+
178
+ **Between steps 3 and 5:**
179
+ - If extension needs config storage, create config.ts (or use inline getConfigData/saveConfigData)
180
+ - If extension has a settings UI (config component), create ConfigComponent.jsx and implement the three config methods
181
+ - If extension needs logging, create logger.ts
182
+ - If extension needs constants, create constants.ts
183
+ - If extension has placement-based UI components, create .jsx files for components (recommended for components > 20 lines)
184
+
185
+ ### For In-Repo target:
186
+
187
+ 1. Confirm user wants In-Repo (only available in aider-desk project)
188
+ 2. Determine extension type (single-file or folder)
189
+ 3. Create extension file or directory structure in `packages/extensions/extensions/`
190
+ 4. Implement Extension interface methods
191
+ 5. Export metadata and default class
192
+ 6. **Register in `packages/extensions/extensions.json`**
193
+ 7. **Document in `docs-site/docs/extensions/examples.md`**
194
+ 8. Run `npm install` in `packages/extensions/` (folder extensions)
195
+ 9. Verify with type checking
196
+
197
+ **Between steps 3 and 5:**
198
+ - Same optional files as Project/Global flow above
199
+
200
+ ## Preconditions
201
+
202
+ Before using this skill, verify:
203
+
204
+ - Installation target has been chosen by the user
205
+ - Extension purpose and required capabilities are clear
206
+ - Extension type (single-file or folder) is determined
207
+ - Extension interface and types are understood
208
+
209
+ If any precondition fails:
210
+
211
+ - Review [packages/common/src/extensions.ts](https://raw.githubusercontent.com/hotovo/aider-desk/refs/heads/main/packages/common/src/extensions.ts) for types
212
+ - Check [references/install-targets.md](references/install-targets.md) for target options
213
+ - Check [references/event-types.md](references/event-types.md) for event types
214
+ - Check [references/command-definition.md](references/command-definition.md) for command structure
215
+
216
+ ## Postconditions
217
+
218
+ After completing this skill, verify:
219
+
220
+ - Extension implements Extension interface correctly
221
+ - Static `metadata` property on the class includes all required fields (name, version)
222
+ - Default export is the extension class
223
+ - No `@/` imports used
224
+ - **If In-Repo:** extensions.json updated correctly
225
+ - **If In-Repo:** docs-site/docs/extensions/examples.md updated
226
+ - **If In-Repo:** Type checking passes
227
+ - Extension loads without errors
228
+ - Extension appears in extensions list
229
+ - Extension capabilities work as expected
230
+
231
+ **Success metrics:**
232
+
233
+ - Extension loads without errors
234
+ - Extension appears in extensions list
235
+ - Extension capabilities work as expected
236
+
237
+ ## Common Situations
238
+
239
+ **Situation:** Extension needs to handle events
240
+
241
+ **Pattern:**
242
+ - When: Extension needs to modify agent behavior
243
+ - Then: Implement event handler methods (onAgentStarted, onToolCalled, etc.)
244
+ - Return: Partial event object to modify behavior
245
+
246
+ **Situation:** Extension needs to register commands
247
+
248
+ **Pattern:**
249
+ - When: Extension provides slash commands
250
+ - Then: Implement getCommands() method
251
+ - Return: Array of CommandDefinition objects
252
+
253
+ **Situation:** Extension needs to add UI components
254
+
255
+ **Pattern:**
256
+ - When: Extension needs to display information in UI
257
+ - Then: Implement getUIComponents() method
258
+ - Return: Array of UIComponentDefinition objects
259
+ - Use: JSX strings or external .jsx files
260
+ - Load data: Implement getUIExtensionData() if component needs data
261
+ - Handle actions: Implement executeUIExtensionAction() for user interactions
262
+
263
+ **Situation:** Extension needs to log messages
264
+
265
+ **Pattern:**
266
+ - If: Debug/internal logging (developer diagnostics, not shown to users)
267
+ - Then: Use `context.log(message, type)` — logs to backend console only
268
+ - If: User-visible output (showing results, status, timing info in the chat)
269
+ - Then: Use `context.getTaskContext()?.addLogMessage(level, message)` — displays in task's chat UI
270
+ - When ambiguous: If the user says "log", "show", "display", or "report" something, default to `addLogMessage` (user-visible). Use `context.log` only for internal diagnostics.
271
+ - Note: `context.log` is always available; `getTaskContext()` returns `null` outside a task, so always use optional chaining (`?.`)
272
+
273
+ **Situation:** Extension needs config storage
274
+
275
+ **Pattern:**
276
+ - Check: Extension needs persistent settings
277
+ - If yes: Create config.ts with loadConfig and saveConfig functions
278
+ - Store: Config files in extension directory
279
+
280
+ **Situation:** Extension needs a settings UI (config component)
281
+
282
+ **Pattern:**
283
+ - When: Extension has user-configurable options that should appear in the Settings dialog
284
+ - Then: Implement `getConfigComponent()`, `getConfigData()`, `saveConfigData()` methods
285
+ - JSX: Return a `.jsx` file content via `readFileSync(join(__dirname, './ConfigComponent.jsx'), 'utf-8')`
286
+ - Props: Component receives `{ config, updateConfig, ui, icons, models, providers, ... }`
287
+ - Flow: Dialog opens → loads data via getConfigData → renders JSX with props → user edits → Save calls saveConfigData
288
+ - Reference: [config-components.md](references/config-components.md) for full guide and examples
289
+
290
+ ## References
291
+
292
+ ### Target Selection
293
+
294
+ - [install-targets.md](references/install-targets.md) - All three installation targets, when to use each, key differences
295
+
296
+ ### Flows
297
+
298
+ - [project-global-flow.md](references/project-global-flow.md) - Step-by-step for Project and Global installations
299
+ - [in-repo-flow.md](references/in-repo-flow.md) - Step-by-step for In-Repo (packages/extensions/) installations
300
+
301
+ ### Technical Reference (all targets)
302
+
303
+ - [packages/common/src/extensions.ts](https://raw.githubusercontent.com/hotovo/aider-desk/refs/heads/main/packages/common/src/extensions.ts) - Extension types and interfaces
304
+ - [extension-interface.md](references/extension-interface.md) - Full Extension interface, ExtensionContext, TaskContext, Metadata
305
+ - [extension-types.md](references/extension-types.md) - Single-file vs folder extensions, examples, extensions.json format
306
+ - [event-types.md](references/event-types.md) - All event types and payloads
307
+ - [command-definition.md](references/command-definition.md) - Command structure
308
+ - [ui-components.md](references/ui-components.md) - UI component system, placements, and available components
309
+ - [config-components.md](references/config-components.md) - Config component API (settings UI), methods, JSX format, and patterns
310
+ - [examples-gallery.md](references/examples-gallery.md) - Real extension examples
311
+
312
+ ## Assets
313
+
314
+ - [templates/single-file.ts.template](assets/templates/single-file.ts.template) - Single-file template
315
+ - [templates/folder-extension/](assets/templates/folder-extension/) - Folder template (basic)
316
+ - [templates/folder-extension-with-config/index.ts.template](assets/templates/folder-extension-with-config/index.ts.template) - Folder template with config component API
317
+ - [templates/ui-component.ts.template](assets/templates/ui-component.ts.template) - UI component inline template
318
+ - [templates/ui-component-external.ts.template](assets/templates/ui-component-external.ts.template) - UI component with external JSX
319
+ - [templates/Component.jsx.template](assets/templates/Component.jsx.template) - Placement-based JSX component template
320
+ - [templates/ConfigComponent.jsx.template](assets/templates/ConfigComponent.jsx.template) - Config/settings JSX component template
@@ -0,0 +1,76 @@
1
+ /**
2
+ * UI Component for {{EXTENSION_NAME}}
3
+ *
4
+ * Note: React is globally available (use React.useState, React.useEffect, etc.)
5
+ *
6
+ * Available props (via 'props' or destructured):
7
+ * - data: Data from getUIExtensionData()
8
+ * - task: Current TaskData
9
+ * - projectDir: Project directory path
10
+ * - models: Available models
11
+ * - providers: Available providers
12
+ * - ui: UI components (Button, Checkbox, Input, etc.)
13
+ * - icons: React Icons organized by set (Fi, Hi, Cg, etc.)
14
+ * - executeExtensionAction: Function to call extension actions
15
+ */
16
+
17
+ (props) => {
18
+ const { data, task, ui, icons, executeExtensionAction } = props;
19
+ const { useState, useCallback } = React;
20
+ const { Button } = ui;
21
+ const { FiCheckCircle } = icons.Fi;
22
+
23
+ // Early return if no data
24
+ if (!data) return null;
25
+
26
+ // Local state
27
+ const [isHovered, setIsHovered] = useState(false);
28
+
29
+ // Event handlers
30
+ const handleIncrement = useCallback(async () => {
31
+ const result = await executeExtensionAction('increment');
32
+ console.log('Increment result:', result);
33
+ }, [executeExtensionAction]);
34
+
35
+ const handleSetMessage = useCallback(async () => {
36
+ await executeExtensionAction('set-message', 'New message!');
37
+ }, [executeExtensionAction]);
38
+
39
+ return (
40
+ <div
41
+ className="flex items-center gap-2 p-2 bg-bg-secondary rounded"
42
+ onMouseEnter={() => setIsHovered(true)}
43
+ onMouseLeave={() => setIsHovered(false)}
44
+ >
45
+ <FiCheckCircle className="w-4 h-4 text-success" />
46
+
47
+ <div className="flex-1">
48
+ <div className="text-sm text-text-primary">
49
+ {data.message}
50
+ </div>
51
+ <div className="text-xs text-text-secondary">
52
+ Count: {data.count}
53
+ </div>
54
+ </div>
55
+
56
+ {isHovered && (
57
+ <div className="flex gap-1">
58
+ <Button
59
+ size="xs"
60
+ variant="outline"
61
+ onClick={handleIncrement}
62
+ >
63
+ +1
64
+ </Button>
65
+ <Button
66
+ size="xs"
67
+ variant="outline"
68
+ onClick={handleSetMessage}
69
+ >
70
+ Change
71
+ </Button>
72
+ </div>
73
+ )}
74
+ </div>
75
+ );
76
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Config Component for {{EXTENSION_NAME}}
3
+ *
4
+ * Renders a settings UI in the ExtensionSettingsDialog.
5
+ *
6
+ * Available props:
7
+ * - config: Current config data from getConfigData()
8
+ * - updateConfig: Callback to mutate in-memory config (does NOT persist)
9
+ * - ui: UI components (Button, Checkbox, Input, Select, TextArea, etc.) — prefer these over raw HTML
10
+ * - icons: React Icons organized by set (Fi, Hi, Cg, etc.)
11
+ * - models: Available models
12
+ * - providers: Available providers
13
+ * - projectDir: Project directory path
14
+ * - task: Current TaskData
15
+ * - mode: Current mode string
16
+ * - api: ApplicationAPI reference
17
+ *
18
+ * Note: React is globally available (use React.useState, React.useEffect, etc.)
19
+ * Note: Prefer ui.* components over raw HTML elements for consistent styling
20
+ */
21
+
22
+ ({ config, updateConfig, ui }) => {
23
+ const { Input } = ui;
24
+
25
+ return (
26
+ <div className="flex flex-col gap-4">
27
+ <Input
28
+ label="My Setting Label"
29
+ value={config?.mySetting || ''}
30
+ onChange={(value) => updateConfig({ ...config, mySetting: value })}
31
+ placeholder="Enter a value..."
32
+ />
33
+ <p className="text-xs text-text-secondary -mt-2">
34
+ Description of what this setting controls and how it affects the extension behavior.
35
+ </p>
36
+ </div>
37
+ );
38
+ };
@@ -0,0 +1,29 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ export interface {EXTENSION_NAME}Config {
8
+ // Add config properties
9
+ }
10
+
11
+ const DEFAULT_CONFIG: {EXTENSION_NAME}Config = {
12
+ // Add default values
13
+ };
14
+
15
+ const CONFIG_FILE = path.join(__dirname, 'config.json');
16
+
17
+ export const loadConfig = async (): Promise<{EXTENSION_NAME}Config> => {
18
+ try {
19
+ const data = await fs.readFile(CONFIG_FILE, 'utf-8');
20
+ const config = JSON.parse(data);
21
+ return { ...DEFAULT_CONFIG, ...config };
22
+ } catch {
23
+ return { ...DEFAULT_CONFIG };
24
+ }
25
+ };
26
+
27
+ export const saveConfig = async (config: {EXTENSION_NAME}Config): Promise<void> => {
28
+ await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
29
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * {EXTENSION_NAME} Extension
3
+ *
4
+ * {DESCRIPTION}
5
+ */
6
+
7
+ import type { Extension, ExtensionContext, AgentStartedEvent, CommandDefinition } from '@aiderdesk/extensions';
8
+
9
+ import { loadConfig, saveConfig } from './config';
10
+ import type { {EXTENSION_NAME}Config } from './config';
11
+
12
+ const DEFAULT_CONFIG: {EXTENSION_NAME}Config = {
13
+ // Add default config values
14
+ };
15
+
16
+ export default class {CLASS_NAME} implements Extension {
17
+ static metadata = {
18
+ name: '{EXTENSION_NAME}',
19
+ version: '1.0.0',
20
+ description: '{DESCRIPTION}',
21
+ author: '{AUTHOR}',
22
+ capabilities: ['events', 'commands'],
23
+ };
24
+
25
+ private config: {EXTENSION_NAME}Config = DEFAULT_CONFIG;
26
+
27
+ async onLoad(context: ExtensionContext): Promise<void> {
28
+ context.log('{EXTENSION_NAME} Extension loaded', 'info');
29
+ this.config = await loadConfig();
30
+ }
31
+
32
+ getCommands(_context: ExtensionContext): CommandDefinition[] {
33
+ return [
34
+ // Add commands here
35
+ ];
36
+ }
37
+
38
+ async onAgentStarted(event: AgentStartedEvent, context: ExtensionContext): Promise<void | Partial<AgentStartedEvent>> {
39
+ // Handle event
40
+ return undefined;
41
+ }
42
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "{extension-name}",
3
+ "version": "1.0.0",
4
+ "description": "{DESCRIPTION}",
5
+ "main": "index.ts",
6
+ "keywords": ["aiderdesk", "extension"],
7
+ "author": "{AUTHOR}",
8
+ "license": "MIT",
9
+ "dependencies": {
10
+ // Add npm dependencies here
11
+ }
12
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ES2020",
5
+ "lib": ["ES2020"],
6
+ "moduleResolution": "node",
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "strict": true,
10
+ "resolveJsonModule": true,
11
+ "declaration": true,
12
+ "declarationMap": true,
13
+ "sourceMap": true,
14
+ "outDir": "./dist",
15
+ "rootDir": ".",
16
+ "forceConsistentCasingInFileNames": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true
20
+ },
21
+ "include": ["*.ts"],
22
+ "exclude": ["node_modules", "dist", "__tests__"]
23
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * {EXTENSION_NAME} Extension
3
+ *
4
+ * {DESCRIPTION}
5
+ */
6
+
7
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+
10
+ import type { Extension, ExtensionContext } from '@aiderdesk/extensions';
11
+
12
+ // Load config JSX at module level (read once, reused on every getConfigComponent call)
13
+ const configComponentJsx = readFileSync(join(__dirname, './ConfigComponent.jsx'), 'utf-8');
14
+
15
+ interface {EXTENSION_NAME}Config {
16
+ // Add your config properties here
17
+ mySetting: string;
18
+ enabled: boolean;
19
+ }
20
+
21
+ const DEFAULT_CONFIG: {EXTENSION_NAME}Config = {
22
+ mySetting: '',
23
+ enabled: true,
24
+ };
25
+
26
+ export default class {CLASS_NAME} implements Extension {
27
+ static metadata = {
28
+ name: '{EXTENSION_NAME}',
29
+ version: '1.0.0',
30
+ description: '{DESCRIPTION}',
31
+ author: '{AUTHOR}',
32
+ capabilities: ['context'],
33
+ // iconUrl: 'https://...',
34
+ };
35
+
36
+ private configPath: string;
37
+
38
+ constructor() {
39
+ this.configPath = join(__dirname, 'config.json');
40
+ }
41
+
42
+ async onLoad(context: ExtensionContext): Promise<void> {
43
+ context.log('{EXTENSION_NAME} Extension loaded', 'info');
44
+ }
45
+
46
+ // --- Config Component API ---
47
+
48
+ getConfigComponent(_context: ExtensionContext): string {
49
+ return configComponentJsx;
50
+ }
51
+
52
+ async getConfigData(_context: ExtensionContext): Promise<{EXTENSION_NAME}Config> {
53
+ try {
54
+ if (existsSync(this.configPath)) {
55
+ const data = readFileSync(this.configPath, 'utf-8');
56
+ const parsed = JSON.parse(data);
57
+ return { ...DEFAULT_CONFIG, ...parsed };
58
+ }
59
+ } catch {
60
+ // Ignore errors, fall back to defaults
61
+ }
62
+ return { ...DEFAULT_CONFIG };
63
+ }
64
+
65
+ async saveConfigData(configData: unknown, _context: ExtensionContext): Promise<unknown> {
66
+ const merged: {EXTENSION_NAME}Config = {
67
+ ...DEFAULT_CONFIG,
68
+ ...configData as Partial<{EXTENSION_NAME}Config>,
69
+ };
70
+ writeFileSync(this.configPath, JSON.stringify(merged, null, 2), 'utf-8');
71
+ return merged;
72
+ }
73
+
74
+ // --- Event Handlers / Other Methods ---
75
+
76
+ // async onRuleFilesRetrieved(event: RuleFilesRetrievedEvent, context: ExtensionContext) {
77
+ // const config = await this.getConfigData(context);
78
+ // Use config values in your logic...
79
+ // }
80
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * {EXTENSION_NAME} Extension
3
+ *
4
+ * {DESCRIPTION}
5
+ */
6
+
7
+ import type { Extension, ExtensionContext } from '@aiderdesk/extensions';
8
+
9
+ export default class {CLASS_NAME} implements Extension {
10
+ static metadata = {
11
+ name: '{EXTENSION_NAME}',
12
+ version: '1.0.0',
13
+ description: '{DESCRIPTION}',
14
+ author: '{AUTHOR}',
15
+ capabilities: ['{CAPABILITY}'],
16
+ };
17
+
18
+ async onLoad(context: ExtensionContext): Promise<void> {
19
+ context.log('{EXTENSION_NAME} Extension loaded', 'info');
20
+ }
21
+
22
+ // Add methods as needed:
23
+ // - getCommands()
24
+ // - getTools()
25
+ // - getAgents()
26
+ // - getModes()
27
+ // - onAgentStarted()
28
+ // - onToolCalled()
29
+ // etc.
30
+ }