clavix 5.1.1 → 5.3.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 +22 -5
- package/dist/cli/commands/diagnose.d.ts +15 -0
- package/dist/cli/commands/diagnose.js +295 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.js +130 -24
- package/dist/cli/commands/update.js +1 -1
- package/dist/constants.d.ts +18 -0
- package/dist/constants.js +24 -0
- package/dist/core/adapter-registry.d.ts +39 -0
- package/dist/core/adapter-registry.js +208 -0
- package/dist/core/adapters/agents-md-generator.d.ts +0 -10
- package/dist/core/adapters/agents-md-generator.js +7 -41
- package/dist/core/adapters/base-adapter.d.ts +1 -0
- package/dist/core/adapters/base-adapter.js +3 -1
- package/dist/core/adapters/copilot-instructions-generator.d.ts +0 -10
- package/dist/core/adapters/copilot-instructions-generator.js +7 -41
- package/dist/core/adapters/gemini-adapter.d.ts +2 -18
- package/dist/core/adapters/gemini-adapter.js +7 -48
- package/dist/core/adapters/llxprt-adapter.d.ts +2 -18
- package/dist/core/adapters/llxprt-adapter.js +7 -48
- package/dist/core/adapters/octo-md-generator.d.ts +0 -10
- package/dist/core/adapters/octo-md-generator.js +7 -41
- package/dist/core/adapters/qwen-adapter.d.ts +2 -18
- package/dist/core/adapters/qwen-adapter.js +7 -46
- package/dist/core/adapters/toml-formatting-adapter.d.ts +50 -0
- package/dist/core/adapters/toml-formatting-adapter.js +74 -0
- package/dist/core/adapters/universal-adapter.d.ts +49 -0
- package/dist/core/adapters/universal-adapter.js +88 -0
- package/dist/core/adapters/warp-md-generator.d.ts +3 -4
- package/dist/core/adapters/warp-md-generator.js +10 -30
- package/dist/core/command-transformer.d.ts +11 -12
- package/dist/core/command-transformer.js +11 -12
- package/dist/core/doc-injector.d.ts +0 -4
- package/dist/core/doc-injector.js +9 -15
- package/dist/core/template-assembler.d.ts +1 -1
- package/dist/core/template-assembler.js +1 -1
- package/dist/templates/agents/agents.md +9 -4
- package/dist/templates/agents/copilot-instructions.md +7 -4
- package/dist/templates/agents/octo.md +7 -3
- package/dist/templates/agents/warp.md +8 -4
- package/dist/templates/instructions/core/file-operations.md +15 -11
- package/dist/templates/slash-commands/_canonical/plan.md +1 -2
- package/dist/templates/slash-commands/_components/MANIFEST.md +81 -0
- package/dist/templates/slash-commands/_components/agent-protocols/AGENT_MANUAL.md +1 -1
- package/dist/templates/slash-commands/_components/agent-protocols/cli-reference.md +15 -17
- package/dist/types/adapter-config.d.ts +73 -0
- package/dist/types/adapter-config.js +24 -0
- package/dist/types/config.d.ts +0 -80
- package/dist/types/config.js +3 -2
- package/dist/utils/error-utils.d.ts +4 -0
- package/dist/utils/error-utils.js +6 -0
- package/dist/utils/file-system.js +7 -12
- package/dist/utils/legacy-command-cleanup.d.ts +14 -0
- package/dist/utils/legacy-command-cleanup.js +14 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.js +56 -0
- package/dist/utils/string-utils.d.ts +10 -0
- package/dist/utils/string-utils.js +12 -0
- package/dist/utils/version.d.ts +20 -0
- package/dist/utils/version.js +43 -0
- package/oclif.manifest.json +130 -0
- package/package.json +2 -2
- package/dist/cli/commands/config.d.ts +0 -30
- package/dist/cli/commands/config.js +0 -456
- package/dist/templates/slash-commands/_components/agent-protocols/decision-rules.md +0 -232
- package/dist/templates/slash-commands/_components/agent-protocols/error-handling.md +0 -177
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry - Config-driven adapter definitions
|
|
3
|
+
*
|
|
4
|
+
* This registry provides configuration for all simple adapters that can
|
|
5
|
+
* be represented as pure configuration without custom logic.
|
|
6
|
+
*
|
|
7
|
+
* For adapters requiring custom behavior (TOML format, doc injection),
|
|
8
|
+
* dedicated adapter classes still exist.
|
|
9
|
+
*
|
|
10
|
+
* @since v5.3.0
|
|
11
|
+
*/
|
|
12
|
+
import { AdapterConfig } from '../types/adapter-config.js';
|
|
13
|
+
/**
|
|
14
|
+
* Registry of all adapter configurations
|
|
15
|
+
*
|
|
16
|
+
* These configurations describe how each adapter behaves:
|
|
17
|
+
* - Where commands are stored
|
|
18
|
+
* - File extension and naming pattern
|
|
19
|
+
* - Feature support (subdirectories, frontmatter, etc.)
|
|
20
|
+
* - Detection method for project environment
|
|
21
|
+
*/
|
|
22
|
+
export declare const ADAPTER_CONFIGS: AdapterConfig[];
|
|
23
|
+
/**
|
|
24
|
+
* Get adapter configuration by name
|
|
25
|
+
*/
|
|
26
|
+
export declare function getAdapterConfig(name: string): AdapterConfig | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Get all adapter configurations
|
|
29
|
+
*/
|
|
30
|
+
export declare function getAllAdapterConfigs(): AdapterConfig[];
|
|
31
|
+
/**
|
|
32
|
+
* Get adapters that require special handling
|
|
33
|
+
*/
|
|
34
|
+
export declare function getSpecialAdapters(): AdapterConfig[];
|
|
35
|
+
/**
|
|
36
|
+
* Get simple adapters (can use UniversalAdapter)
|
|
37
|
+
*/
|
|
38
|
+
export declare function getSimpleAdapters(): AdapterConfig[];
|
|
39
|
+
//# sourceMappingURL=adapter-registry.d.ts.map
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Registry - Config-driven adapter definitions
|
|
3
|
+
*
|
|
4
|
+
* This registry provides configuration for all simple adapters that can
|
|
5
|
+
* be represented as pure configuration without custom logic.
|
|
6
|
+
*
|
|
7
|
+
* For adapters requiring custom behavior (TOML format, doc injection),
|
|
8
|
+
* dedicated adapter classes still exist.
|
|
9
|
+
*
|
|
10
|
+
* @since v5.3.0
|
|
11
|
+
*/
|
|
12
|
+
import { DEFAULT_MD_FEATURES, DEFAULT_TOML_FEATURES, } from '../types/adapter-config.js';
|
|
13
|
+
/**
|
|
14
|
+
* Registry of all adapter configurations
|
|
15
|
+
*
|
|
16
|
+
* These configurations describe how each adapter behaves:
|
|
17
|
+
* - Where commands are stored
|
|
18
|
+
* - File extension and naming pattern
|
|
19
|
+
* - Feature support (subdirectories, frontmatter, etc.)
|
|
20
|
+
* - Detection method for project environment
|
|
21
|
+
*/
|
|
22
|
+
export const ADAPTER_CONFIGS = [
|
|
23
|
+
// IDE Extensions (Markdown-based)
|
|
24
|
+
{
|
|
25
|
+
name: 'cursor',
|
|
26
|
+
displayName: 'Cursor',
|
|
27
|
+
directory: '.cursor/rules',
|
|
28
|
+
fileExtension: '.md',
|
|
29
|
+
filenamePattern: 'clavix-{name}',
|
|
30
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
31
|
+
detection: { type: 'directory', path: '.cursor' },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'windsurf',
|
|
35
|
+
displayName: 'Windsurf',
|
|
36
|
+
directory: '.windsurf/rules',
|
|
37
|
+
fileExtension: '.md',
|
|
38
|
+
filenamePattern: 'clavix-{name}',
|
|
39
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
40
|
+
detection: { type: 'directory', path: '.windsurf' },
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'kilocode',
|
|
44
|
+
displayName: 'Kilocode',
|
|
45
|
+
directory: '.kilocode/rules',
|
|
46
|
+
fileExtension: '.md',
|
|
47
|
+
filenamePattern: 'clavix-{name}',
|
|
48
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
49
|
+
detection: { type: 'directory', path: '.kilocode' },
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'roocode',
|
|
53
|
+
displayName: 'Roo-Code',
|
|
54
|
+
directory: '.roo/rules',
|
|
55
|
+
fileExtension: '.md',
|
|
56
|
+
filenamePattern: 'clavix-{name}',
|
|
57
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
58
|
+
detection: { type: 'directory', path: '.roo' },
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'cline',
|
|
62
|
+
displayName: 'Cline',
|
|
63
|
+
directory: '.cline/rules',
|
|
64
|
+
fileExtension: '.md',
|
|
65
|
+
filenamePattern: 'clavix-{name}',
|
|
66
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
67
|
+
detection: { type: 'directory', path: '.cline' },
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'droid',
|
|
71
|
+
displayName: 'Droid',
|
|
72
|
+
directory: '.droid/rules',
|
|
73
|
+
fileExtension: '.md',
|
|
74
|
+
filenamePattern: 'clavix-{name}',
|
|
75
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
76
|
+
detection: { type: 'directory', path: '.droid' },
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'opencode',
|
|
80
|
+
displayName: 'OpenCode',
|
|
81
|
+
directory: '.opencode/rules',
|
|
82
|
+
fileExtension: '.md',
|
|
83
|
+
filenamePattern: 'clavix-{name}',
|
|
84
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
85
|
+
detection: { type: 'directory', path: '.opencode' },
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'crush',
|
|
89
|
+
displayName: 'Crush',
|
|
90
|
+
directory: '.crush/rules',
|
|
91
|
+
fileExtension: '.md',
|
|
92
|
+
filenamePattern: 'clavix-{name}',
|
|
93
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
94
|
+
detection: { type: 'directory', path: '.crush' },
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'codex',
|
|
98
|
+
displayName: 'Codex CLI',
|
|
99
|
+
directory: '.codex/instructions',
|
|
100
|
+
fileExtension: '.md',
|
|
101
|
+
filenamePattern: 'clavix-{name}',
|
|
102
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
103
|
+
detection: { type: 'directory', path: '.codex' },
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'codebuddy',
|
|
107
|
+
displayName: 'CodeBuddy',
|
|
108
|
+
directory: '.codebuddy/rules',
|
|
109
|
+
fileExtension: '.md',
|
|
110
|
+
filenamePattern: 'clavix-{name}',
|
|
111
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
112
|
+
detection: { type: 'directory', path: '.codebuddy' },
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'amp',
|
|
116
|
+
displayName: 'Amp',
|
|
117
|
+
directory: '.amp/rules',
|
|
118
|
+
fileExtension: '.md',
|
|
119
|
+
filenamePattern: 'clavix-{name}',
|
|
120
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
121
|
+
detection: { type: 'directory', path: '.amp' },
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'augment',
|
|
125
|
+
displayName: 'Augment Code',
|
|
126
|
+
directory: '.augment/rules',
|
|
127
|
+
fileExtension: '.md',
|
|
128
|
+
filenamePattern: 'clavix-{name}',
|
|
129
|
+
features: { ...DEFAULT_MD_FEATURES },
|
|
130
|
+
detection: { type: 'directory', path: '.augment' },
|
|
131
|
+
},
|
|
132
|
+
// Claude Code (requires doc injection - special adapter kept)
|
|
133
|
+
{
|
|
134
|
+
name: 'claude-code',
|
|
135
|
+
displayName: 'Claude Code',
|
|
136
|
+
directory: '.claude/commands/clavix',
|
|
137
|
+
fileExtension: '.md',
|
|
138
|
+
filenamePattern: '{name}',
|
|
139
|
+
features: {
|
|
140
|
+
...DEFAULT_MD_FEATURES,
|
|
141
|
+
supportsSubdirectories: true,
|
|
142
|
+
supportsFrontmatter: true,
|
|
143
|
+
supportsDocInjection: true,
|
|
144
|
+
commandSeparator: ':',
|
|
145
|
+
},
|
|
146
|
+
detection: { type: 'directory', path: '.claude' },
|
|
147
|
+
specialAdapter: 'doc-injection',
|
|
148
|
+
},
|
|
149
|
+
// TOML-based adapters (require special formatting - special adapter kept)
|
|
150
|
+
{
|
|
151
|
+
name: 'gemini',
|
|
152
|
+
displayName: 'Gemini CLI',
|
|
153
|
+
directory: '.gemini/commands/clavix',
|
|
154
|
+
fileExtension: '.toml',
|
|
155
|
+
filenamePattern: '{name}',
|
|
156
|
+
features: { ...DEFAULT_TOML_FEATURES },
|
|
157
|
+
detection: { type: 'directory', path: '.gemini' },
|
|
158
|
+
specialAdapter: 'toml',
|
|
159
|
+
rootDir: '.gemini',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'qwen',
|
|
163
|
+
displayName: 'Qwen CLI',
|
|
164
|
+
directory: '.qwen/commands/clavix',
|
|
165
|
+
fileExtension: '.toml',
|
|
166
|
+
filenamePattern: '{name}',
|
|
167
|
+
features: { ...DEFAULT_TOML_FEATURES },
|
|
168
|
+
detection: { type: 'directory', path: '.qwen' },
|
|
169
|
+
specialAdapter: 'toml',
|
|
170
|
+
rootDir: '.qwen',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'llxprt',
|
|
174
|
+
displayName: 'LLXpert',
|
|
175
|
+
directory: '.llxprt/commands/clavix',
|
|
176
|
+
fileExtension: '.toml',
|
|
177
|
+
filenamePattern: '{name}',
|
|
178
|
+
features: { ...DEFAULT_TOML_FEATURES },
|
|
179
|
+
detection: { type: 'directory', path: '.llxprt' },
|
|
180
|
+
specialAdapter: 'toml',
|
|
181
|
+
rootDir: '.llxprt',
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
/**
|
|
185
|
+
* Get adapter configuration by name
|
|
186
|
+
*/
|
|
187
|
+
export function getAdapterConfig(name) {
|
|
188
|
+
return ADAPTER_CONFIGS.find((config) => config.name === name);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get all adapter configurations
|
|
192
|
+
*/
|
|
193
|
+
export function getAllAdapterConfigs() {
|
|
194
|
+
return [...ADAPTER_CONFIGS];
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get adapters that require special handling
|
|
198
|
+
*/
|
|
199
|
+
export function getSpecialAdapters() {
|
|
200
|
+
return ADAPTER_CONFIGS.filter((config) => config.specialAdapter !== undefined);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get simple adapters (can use UniversalAdapter)
|
|
204
|
+
*/
|
|
205
|
+
export function getSimpleAdapters() {
|
|
206
|
+
return ADAPTER_CONFIGS.filter((config) => config.specialAdapter === undefined);
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=adapter-registry.js.map
|
|
@@ -4,20 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class AgentsMdGenerator {
|
|
6
6
|
static readonly TARGET_FILE = "AGENTS.md";
|
|
7
|
-
static readonly START_MARKER = "<!-- CLAVIX:START -->";
|
|
8
|
-
static readonly END_MARKER = "<!-- CLAVIX:END -->";
|
|
9
7
|
/**
|
|
10
8
|
* Generate or update AGENTS.md with Clavix workflows
|
|
11
9
|
*/
|
|
12
10
|
static generate(): Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
* Inject or update managed block in AGENTS.md
|
|
15
|
-
*/
|
|
16
|
-
private static injectManagedBlock;
|
|
17
|
-
/**
|
|
18
|
-
* Escape special regex characters
|
|
19
|
-
*/
|
|
20
|
-
private static escapeRegex;
|
|
21
11
|
/**
|
|
22
12
|
* Check if AGENTS.md has Clavix block
|
|
23
13
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { FileSystem } from '../../utils/file-system.js';
|
|
2
1
|
import * as path from 'path';
|
|
3
2
|
import { fileURLToPath } from 'url';
|
|
4
3
|
import { dirname } from 'path';
|
|
4
|
+
import { FileSystem } from '../../utils/file-system.js';
|
|
5
|
+
import { DocInjector } from '../doc-injector.js';
|
|
5
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const __dirname = dirname(__filename);
|
|
7
8
|
/**
|
|
@@ -10,60 +11,25 @@ const __dirname = dirname(__filename);
|
|
|
10
11
|
*/
|
|
11
12
|
export class AgentsMdGenerator {
|
|
12
13
|
static TARGET_FILE = 'AGENTS.md';
|
|
13
|
-
static START_MARKER = '<!-- CLAVIX:START -->';
|
|
14
|
-
static END_MARKER = '<!-- CLAVIX:END -->';
|
|
15
14
|
/**
|
|
16
15
|
* Generate or update AGENTS.md with Clavix workflows
|
|
17
16
|
*/
|
|
18
17
|
static async generate() {
|
|
19
18
|
const templatePath = path.join(__dirname, '../../templates/agents/agents.md');
|
|
20
|
-
// Check if template exists
|
|
21
19
|
if (!(await FileSystem.exists(templatePath))) {
|
|
22
20
|
throw new Error(`AGENTS.md template not found at ${templatePath}`);
|
|
23
21
|
}
|
|
24
22
|
const template = await FileSystem.readFile(templatePath);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* Inject or update managed block in AGENTS.md
|
|
30
|
-
*/
|
|
31
|
-
static async injectManagedBlock(filePath, content) {
|
|
32
|
-
let fileContent = '';
|
|
33
|
-
// Read existing file or start with empty content
|
|
34
|
-
if (await FileSystem.exists(filePath)) {
|
|
35
|
-
fileContent = await FileSystem.readFile(filePath);
|
|
36
|
-
}
|
|
37
|
-
const blockRegex = new RegExp(`${this.escapeRegex(this.START_MARKER)}[\\s\\S]*?${this.escapeRegex(this.END_MARKER)}`, 'g');
|
|
38
|
-
const wrappedContent = `${this.START_MARKER}\n${content}\n${this.END_MARKER}`;
|
|
39
|
-
if (blockRegex.test(fileContent)) {
|
|
40
|
-
// Replace existing block
|
|
41
|
-
fileContent = fileContent.replace(blockRegex, wrappedContent);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// Append new block
|
|
45
|
-
if (fileContent && !fileContent.endsWith('\n\n')) {
|
|
46
|
-
fileContent += '\n\n';
|
|
47
|
-
}
|
|
48
|
-
fileContent += wrappedContent + '\n';
|
|
49
|
-
}
|
|
50
|
-
await FileSystem.writeFileAtomic(filePath, fileContent);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Escape special regex characters
|
|
54
|
-
*/
|
|
55
|
-
static escapeRegex(str) {
|
|
56
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
23
|
+
await DocInjector.injectBlock(this.TARGET_FILE, template, {
|
|
24
|
+
createIfMissing: true,
|
|
25
|
+
validateMarkdown: false, // Template is pre-validated
|
|
26
|
+
});
|
|
57
27
|
}
|
|
58
28
|
/**
|
|
59
29
|
* Check if AGENTS.md has Clavix block
|
|
60
30
|
*/
|
|
61
31
|
static async hasClavixBlock() {
|
|
62
|
-
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
const content = await FileSystem.readFile(this.TARGET_FILE);
|
|
66
|
-
return content.includes(this.START_MARKER);
|
|
32
|
+
return DocInjector.hasBlock(this.TARGET_FILE);
|
|
67
33
|
}
|
|
68
34
|
}
|
|
69
35
|
//# sourceMappingURL=agents-md-generator.js.map
|
|
@@ -52,6 +52,7 @@ export declare abstract class BaseAdapter implements AgentAdapter {
|
|
|
52
52
|
injectDocumentation(_blocks: ManagedBlock[]): Promise<void>;
|
|
53
53
|
/**
|
|
54
54
|
* Escape special regex characters
|
|
55
|
+
* @deprecated Use escapeRegex from utils/string-utils.js directly
|
|
55
56
|
*/
|
|
56
57
|
protected escapeRegex(str: string): string;
|
|
57
58
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import { FileSystem } from '../../utils/file-system.js';
|
|
3
3
|
import { IntegrationError } from '../../types/errors.js';
|
|
4
|
+
import { escapeRegex } from '../../utils/string-utils.js';
|
|
4
5
|
/**
|
|
5
6
|
* Base adapter class with shared logic for all integrations
|
|
6
7
|
* Ensures consistency and reduces code duplication
|
|
@@ -135,9 +136,10 @@ export class BaseAdapter {
|
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
138
|
* Escape special regex characters
|
|
139
|
+
* @deprecated Use escapeRegex from utils/string-utils.js directly
|
|
138
140
|
*/
|
|
139
141
|
escapeRegex(str) {
|
|
140
|
-
return str
|
|
142
|
+
return escapeRegex(str);
|
|
141
143
|
}
|
|
142
144
|
}
|
|
143
145
|
//# sourceMappingURL=base-adapter.js.map
|
|
@@ -4,20 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class CopilotInstructionsGenerator {
|
|
6
6
|
static readonly TARGET_FILE = ".github/copilot-instructions.md";
|
|
7
|
-
static readonly START_MARKER = "<!-- CLAVIX:START -->";
|
|
8
|
-
static readonly END_MARKER = "<!-- CLAVIX:END -->";
|
|
9
7
|
/**
|
|
10
8
|
* Generate or update .github/copilot-instructions.md with Clavix workflows
|
|
11
9
|
*/
|
|
12
10
|
static generate(): Promise<void>;
|
|
13
|
-
/**
|
|
14
|
-
* Inject or update managed block in .github/copilot-instructions.md
|
|
15
|
-
*/
|
|
16
|
-
private static injectManagedBlock;
|
|
17
|
-
/**
|
|
18
|
-
* Escape special regex characters
|
|
19
|
-
*/
|
|
20
|
-
private static escapeRegex;
|
|
21
11
|
/**
|
|
22
12
|
* Check if .github/copilot-instructions.md has Clavix block
|
|
23
13
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { FileSystem } from '../../utils/file-system.js';
|
|
2
1
|
import * as path from 'path';
|
|
3
2
|
import { fileURLToPath } from 'url';
|
|
4
3
|
import { dirname } from 'path';
|
|
4
|
+
import { FileSystem } from '../../utils/file-system.js';
|
|
5
|
+
import { DocInjector } from '../doc-injector.js';
|
|
5
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const __dirname = dirname(__filename);
|
|
7
8
|
/**
|
|
@@ -10,62 +11,27 @@ const __dirname = dirname(__filename);
|
|
|
10
11
|
*/
|
|
11
12
|
export class CopilotInstructionsGenerator {
|
|
12
13
|
static TARGET_FILE = '.github/copilot-instructions.md';
|
|
13
|
-
static START_MARKER = '<!-- CLAVIX:START -->';
|
|
14
|
-
static END_MARKER = '<!-- CLAVIX:END -->';
|
|
15
14
|
/**
|
|
16
15
|
* Generate or update .github/copilot-instructions.md with Clavix workflows
|
|
17
16
|
*/
|
|
18
17
|
static async generate() {
|
|
19
18
|
const templatePath = path.join(__dirname, '../../templates/agents/copilot-instructions.md');
|
|
20
|
-
// Check if template exists
|
|
21
19
|
if (!(await FileSystem.exists(templatePath))) {
|
|
22
20
|
throw new Error(`Copilot instructions template not found at ${templatePath}`);
|
|
23
21
|
}
|
|
24
22
|
const template = await FileSystem.readFile(templatePath);
|
|
25
23
|
// Ensure .github directory exists
|
|
26
24
|
await FileSystem.ensureDir('.github');
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* Inject or update managed block in .github/copilot-instructions.md
|
|
32
|
-
*/
|
|
33
|
-
static async injectManagedBlock(filePath, content) {
|
|
34
|
-
let fileContent = '';
|
|
35
|
-
// Read existing file or start with empty content
|
|
36
|
-
if (await FileSystem.exists(filePath)) {
|
|
37
|
-
fileContent = await FileSystem.readFile(filePath);
|
|
38
|
-
}
|
|
39
|
-
const blockRegex = new RegExp(`${this.escapeRegex(this.START_MARKER)}[\\s\\S]*?${this.escapeRegex(this.END_MARKER)}`, 'g');
|
|
40
|
-
const wrappedContent = `${this.START_MARKER}\n${content}\n${this.END_MARKER}`;
|
|
41
|
-
if (blockRegex.test(fileContent)) {
|
|
42
|
-
// Replace existing block
|
|
43
|
-
fileContent = fileContent.replace(blockRegex, wrappedContent);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// Append new block
|
|
47
|
-
if (fileContent && !fileContent.endsWith('\n\n')) {
|
|
48
|
-
fileContent += '\n\n';
|
|
49
|
-
}
|
|
50
|
-
fileContent += wrappedContent + '\n';
|
|
51
|
-
}
|
|
52
|
-
await FileSystem.writeFileAtomic(filePath, fileContent);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Escape special regex characters
|
|
56
|
-
*/
|
|
57
|
-
static escapeRegex(str) {
|
|
58
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
25
|
+
await DocInjector.injectBlock(this.TARGET_FILE, template, {
|
|
26
|
+
createIfMissing: true,
|
|
27
|
+
validateMarkdown: false,
|
|
28
|
+
});
|
|
59
29
|
}
|
|
60
30
|
/**
|
|
61
31
|
* Check if .github/copilot-instructions.md has Clavix block
|
|
62
32
|
*/
|
|
63
33
|
static async hasClavixBlock() {
|
|
64
|
-
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
const content = await FileSystem.readFile(this.TARGET_FILE);
|
|
68
|
-
return content.includes(this.START_MARKER);
|
|
34
|
+
return DocInjector.hasBlock(this.TARGET_FILE);
|
|
69
35
|
}
|
|
70
36
|
}
|
|
71
37
|
//# sourceMappingURL=copilot-instructions-generator.js.map
|
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CommandTemplate } from '../../types/agent.js';
|
|
1
|
+
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
3
2
|
/**
|
|
4
3
|
* Gemini CLI adapter
|
|
5
4
|
* Commands stored as TOML files under .gemini/commands/clavix by default
|
|
6
5
|
*/
|
|
7
|
-
export declare class GeminiAdapter extends
|
|
8
|
-
private readonly options;
|
|
9
|
-
readonly name = "gemini";
|
|
10
|
-
readonly displayName = "Gemini CLI";
|
|
11
|
-
readonly fileExtension = ".toml";
|
|
12
|
-
readonly features: {
|
|
13
|
-
supportsSubdirectories: boolean;
|
|
14
|
-
supportsFrontmatter: boolean;
|
|
15
|
-
argumentPlaceholder: string;
|
|
16
|
-
};
|
|
6
|
+
export declare class GeminiAdapter extends TomlFormattingAdapter {
|
|
17
7
|
constructor(options?: {
|
|
18
8
|
useNamespace?: boolean;
|
|
19
9
|
});
|
|
20
|
-
get directory(): string;
|
|
21
|
-
detectProject(): Promise<boolean>;
|
|
22
|
-
getCommandPath(): string;
|
|
23
|
-
getTargetFilename(name: string): string;
|
|
24
|
-
protected formatCommand(template: CommandTemplate): string;
|
|
25
|
-
private getHomeDir;
|
|
26
10
|
}
|
|
27
11
|
//# sourceMappingURL=gemini-adapter.d.ts.map
|
|
@@ -1,56 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { BaseAdapter } from './base-adapter.js';
|
|
4
|
-
import { FileSystem } from '../../utils/file-system.js';
|
|
1
|
+
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
5
2
|
/**
|
|
6
3
|
* Gemini CLI adapter
|
|
7
4
|
* Commands stored as TOML files under .gemini/commands/clavix by default
|
|
8
5
|
*/
|
|
9
|
-
export class GeminiAdapter extends
|
|
10
|
-
options;
|
|
11
|
-
name = 'gemini';
|
|
12
|
-
displayName = 'Gemini CLI';
|
|
13
|
-
fileExtension = '.toml';
|
|
14
|
-
features = {
|
|
15
|
-
supportsSubdirectories: true,
|
|
16
|
-
supportsFrontmatter: false,
|
|
17
|
-
argumentPlaceholder: '{{args}}',
|
|
18
|
-
};
|
|
6
|
+
export class GeminiAdapter extends TomlFormattingAdapter {
|
|
19
7
|
constructor(options = {}) {
|
|
20
|
-
super(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return useNamespace
|
|
26
|
-
? path.join('.gemini', 'commands', 'clavix')
|
|
27
|
-
: path.join('.gemini', 'commands');
|
|
28
|
-
}
|
|
29
|
-
async detectProject() {
|
|
30
|
-
if (await FileSystem.exists('.gemini')) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
const homePath = path.join(this.getHomeDir(), '.gemini');
|
|
34
|
-
return await FileSystem.exists(homePath);
|
|
35
|
-
}
|
|
36
|
-
getCommandPath() {
|
|
37
|
-
return this.directory;
|
|
38
|
-
}
|
|
39
|
-
getTargetFilename(name) {
|
|
40
|
-
const commandPath = this.getCommandPath();
|
|
41
|
-
const namespaced = commandPath.endsWith(path.join('commands', 'clavix'));
|
|
42
|
-
const baseName = namespaced ? name : `clavix-${name}`;
|
|
43
|
-
return `${baseName}${this.fileExtension}`;
|
|
44
|
-
}
|
|
45
|
-
formatCommand(template) {
|
|
46
|
-
const description = template.description.trim().length > 0
|
|
47
|
-
? `description = ${JSON.stringify(template.description)}\n\n`
|
|
48
|
-
: '';
|
|
49
|
-
const content = template.content.replace(/\{\{ARGS\}\}/g, '{{args}}');
|
|
50
|
-
return `${description}prompt = """\n${content}\n"""\n`;
|
|
51
|
-
}
|
|
52
|
-
getHomeDir() {
|
|
53
|
-
return process.env.CLAVIX_HOME_OVERRIDE || os.homedir();
|
|
8
|
+
super({
|
|
9
|
+
name: 'gemini',
|
|
10
|
+
displayName: 'Gemini CLI',
|
|
11
|
+
rootDir: '.gemini',
|
|
12
|
+
}, options);
|
|
54
13
|
}
|
|
55
14
|
}
|
|
56
15
|
//# sourceMappingURL=gemini-adapter.js.map
|
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CommandTemplate } from '../../types/agent.js';
|
|
1
|
+
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
3
2
|
/**
|
|
4
3
|
* LLXPRT adapter
|
|
5
4
|
* Commands stored as TOML files under .llxprt/commands/clavix by default
|
|
6
5
|
*/
|
|
7
|
-
export declare class LlxprtAdapter extends
|
|
8
|
-
private readonly options;
|
|
9
|
-
readonly name = "llxprt";
|
|
10
|
-
readonly displayName = "LLXPRT";
|
|
11
|
-
readonly fileExtension = ".toml";
|
|
12
|
-
readonly features: {
|
|
13
|
-
supportsSubdirectories: boolean;
|
|
14
|
-
supportsFrontmatter: boolean;
|
|
15
|
-
argumentPlaceholder: string;
|
|
16
|
-
};
|
|
6
|
+
export declare class LlxprtAdapter extends TomlFormattingAdapter {
|
|
17
7
|
constructor(options?: {
|
|
18
8
|
useNamespace?: boolean;
|
|
19
9
|
});
|
|
20
|
-
get directory(): string;
|
|
21
|
-
detectProject(): Promise<boolean>;
|
|
22
|
-
getCommandPath(): string;
|
|
23
|
-
getTargetFilename(name: string): string;
|
|
24
|
-
protected formatCommand(template: CommandTemplate): string;
|
|
25
|
-
private getHomeDir;
|
|
26
10
|
}
|
|
27
11
|
//# sourceMappingURL=llxprt-adapter.d.ts.map
|
|
@@ -1,56 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { BaseAdapter } from './base-adapter.js';
|
|
4
|
-
import { FileSystem } from '../../utils/file-system.js';
|
|
1
|
+
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
5
2
|
/**
|
|
6
3
|
* LLXPRT adapter
|
|
7
4
|
* Commands stored as TOML files under .llxprt/commands/clavix by default
|
|
8
5
|
*/
|
|
9
|
-
export class LlxprtAdapter extends
|
|
10
|
-
options;
|
|
11
|
-
name = 'llxprt';
|
|
12
|
-
displayName = 'LLXPRT';
|
|
13
|
-
fileExtension = '.toml';
|
|
14
|
-
features = {
|
|
15
|
-
supportsSubdirectories: true,
|
|
16
|
-
supportsFrontmatter: false,
|
|
17
|
-
argumentPlaceholder: '{{args}}',
|
|
18
|
-
};
|
|
6
|
+
export class LlxprtAdapter extends TomlFormattingAdapter {
|
|
19
7
|
constructor(options = {}) {
|
|
20
|
-
super(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return useNamespace
|
|
26
|
-
? path.join('.llxprt', 'commands', 'clavix')
|
|
27
|
-
: path.join('.llxprt', 'commands');
|
|
28
|
-
}
|
|
29
|
-
async detectProject() {
|
|
30
|
-
if (await FileSystem.exists('.llxprt')) {
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
const homePath = path.join(this.getHomeDir(), '.llxprt');
|
|
34
|
-
return await FileSystem.exists(homePath);
|
|
35
|
-
}
|
|
36
|
-
getCommandPath() {
|
|
37
|
-
return this.directory;
|
|
38
|
-
}
|
|
39
|
-
getTargetFilename(name) {
|
|
40
|
-
const commandPath = this.getCommandPath();
|
|
41
|
-
const namespaced = commandPath.endsWith(path.join('commands', 'clavix'));
|
|
42
|
-
const baseName = namespaced ? name : `clavix-${name}`;
|
|
43
|
-
return `${baseName}${this.fileExtension}`;
|
|
44
|
-
}
|
|
45
|
-
formatCommand(template) {
|
|
46
|
-
const description = template.description.trim().length > 0
|
|
47
|
-
? `description = ${JSON.stringify(template.description)}\n\n`
|
|
48
|
-
: '';
|
|
49
|
-
const content = template.content.replace(/\{\{ARGS\}\}/g, '{{args}}');
|
|
50
|
-
return `${description}prompt = """\n${content}\n"""\n`;
|
|
51
|
-
}
|
|
52
|
-
getHomeDir() {
|
|
53
|
-
return process.env.CLAVIX_HOME_OVERRIDE || os.homedir();
|
|
8
|
+
super({
|
|
9
|
+
name: 'llxprt',
|
|
10
|
+
displayName: 'LLXPRT',
|
|
11
|
+
rootDir: '.llxprt',
|
|
12
|
+
}, options);
|
|
54
13
|
}
|
|
55
14
|
}
|
|
56
15
|
//# sourceMappingURL=llxprt-adapter.js.map
|