clavix 5.9.0 ā 5.9.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.
- package/dist/cli/commands/init.js +93 -3
- package/dist/cli/commands/update.js +5 -1
- package/dist/cli/helpers/init/config.d.ts +1 -1
- package/dist/cli/helpers/init/config.js +7 -1
- package/dist/config/integrations.json +1 -1
- package/dist/core/adapters/claude-code-adapter.d.ts +3 -0
- package/dist/core/adapters/claude-code-adapter.js +5 -0
- package/dist/core/adapters/gemini-adapter.d.ts +3 -1
- package/dist/core/adapters/gemini-adapter.js +25 -6
- package/dist/core/adapters/llxprt-adapter.d.ts +3 -1
- package/dist/core/adapters/llxprt-adapter.js +25 -6
- package/dist/core/adapters/qwen-adapter.d.ts +3 -1
- package/dist/core/adapters/qwen-adapter.js +25 -6
- package/dist/core/adapters/toml-formatting-adapter.d.ts +3 -0
- package/dist/core/adapters/toml-formatting-adapter.js +2 -0
- package/dist/core/adapters/universal-adapter.d.ts +3 -1
- package/dist/core/adapters/universal-adapter.js +6 -7
- package/dist/core/agent-manager.d.ts +3 -1
- package/dist/core/agent-manager.js +8 -6
- package/dist/templates/slash-commands/_canonical/archive.md +1 -1
- package/dist/templates/slash-commands/_canonical/implement.md +1 -1
- package/dist/templates/slash-commands/_canonical/improve.md +1 -1
- package/dist/templates/slash-commands/_canonical/plan.md +1 -1
- package/dist/templates/slash-commands/_canonical/prd.md +1 -1
- package/dist/templates/slash-commands/_canonical/refine.md +1 -1
- package/dist/templates/slash-commands/_canonical/start.md +1 -1
- package/dist/templates/slash-commands/_canonical/summarize.md +1 -1
- package/dist/templates/slash-commands/_canonical/verify.md +1 -1
- package/dist/types/config.d.ts +10 -1
- package/dist/utils/integration-selector.js +1 -1
- package/dist/utils/path-resolver.d.ts +28 -0
- package/dist/utils/path-resolver.js +57 -0
- package/dist/utils/schemas.d.ts +24 -9
- package/dist/utils/schemas.js +16 -1
- package/package.json +2 -1
|
@@ -25,8 +25,8 @@ export default class Init extends Command {
|
|
|
25
25
|
async run() {
|
|
26
26
|
this.log(chalk.bold.cyan('\nš Clavix Initialization\n'));
|
|
27
27
|
try {
|
|
28
|
-
const agentManager = new AgentManager();
|
|
29
28
|
let existingIntegrations = [];
|
|
29
|
+
let existingConfig;
|
|
30
30
|
// Load existing config if present
|
|
31
31
|
if (await FileSystem.exists('.clavix/config.json')) {
|
|
32
32
|
try {
|
|
@@ -37,6 +37,7 @@ export default class Init extends Command {
|
|
|
37
37
|
if (validationResult.success && validationResult.data) {
|
|
38
38
|
existingIntegrations =
|
|
39
39
|
validationResult.data.integrations || validationResult.data.providers || [];
|
|
40
|
+
existingConfig = validationResult.data;
|
|
40
41
|
// Log warnings (non-blocking)
|
|
41
42
|
if (validationResult.warnings) {
|
|
42
43
|
for (const warning of validationResult.warnings) {
|
|
@@ -60,6 +61,8 @@ export default class Init extends Command {
|
|
|
60
61
|
// Continue with empty array - will prompt for new configuration
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
// Initialize agent manager with existing config (for custom integration paths)
|
|
65
|
+
const agentManager = new AgentManager(existingConfig);
|
|
63
66
|
// Check if already initialized
|
|
64
67
|
if (await FileSystem.exists('.clavix')) {
|
|
65
68
|
// Show current state
|
|
@@ -176,12 +179,93 @@ export default class Init extends Command {
|
|
|
176
179
|
}
|
|
177
180
|
// If 'skip': do nothing
|
|
178
181
|
}
|
|
182
|
+
// Collect custom integration paths (e.g., for Codex with $CODEX_HOME)
|
|
183
|
+
const integrationPaths = {};
|
|
184
|
+
// Prompt about Codex path if Codex is selected
|
|
185
|
+
if (selectedIntegrations.includes('codex')) {
|
|
186
|
+
this.log(chalk.cyan('\nš§ Codex Configuration'));
|
|
187
|
+
const hasEnvVar = process.env.CODEX_HOME;
|
|
188
|
+
const defaultPath = '~/.codex/prompts';
|
|
189
|
+
if (hasEnvVar) {
|
|
190
|
+
// $CODEX_HOME is detected - ask for confirmation
|
|
191
|
+
const { useEnvPath } = await inquirer.prompt([
|
|
192
|
+
{
|
|
193
|
+
type: 'confirm',
|
|
194
|
+
name: 'useEnvPath',
|
|
195
|
+
message: `Detected $CODEX_HOME=${hasEnvVar}. Use this path instead of ${defaultPath}?`,
|
|
196
|
+
default: true,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
if (useEnvPath) {
|
|
200
|
+
integrationPaths.codex = hasEnvVar;
|
|
201
|
+
this.log(chalk.gray(` ā Using $CODEX_HOME: ${hasEnvVar}`));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// Ask if they want to use a custom path
|
|
205
|
+
const { useCustomPath } = await inquirer.prompt([
|
|
206
|
+
{
|
|
207
|
+
type: 'confirm',
|
|
208
|
+
name: 'useCustomPath',
|
|
209
|
+
message: 'Use a custom Codex prompts directory?',
|
|
210
|
+
default: false,
|
|
211
|
+
},
|
|
212
|
+
]);
|
|
213
|
+
if (useCustomPath) {
|
|
214
|
+
const { customPath } = await inquirer.prompt([
|
|
215
|
+
{
|
|
216
|
+
type: 'input',
|
|
217
|
+
name: 'customPath',
|
|
218
|
+
message: 'Enter path to Codex prompts directory:',
|
|
219
|
+
default: defaultPath,
|
|
220
|
+
validate: (input) => {
|
|
221
|
+
if (!input || input.trim().length === 0) {
|
|
222
|
+
return 'Path cannot be empty';
|
|
223
|
+
}
|
|
224
|
+
return true;
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
integrationPaths.codex = customPath;
|
|
229
|
+
this.log(chalk.gray(` ā Using custom path: ${customPath}`));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
// No $CODEX_HOME - ask if they want a custom path
|
|
235
|
+
const { useCustomPath } = await inquirer.prompt([
|
|
236
|
+
{
|
|
237
|
+
type: 'confirm',
|
|
238
|
+
name: 'useCustomPath',
|
|
239
|
+
message: 'Use a custom Codex prompts directory?',
|
|
240
|
+
default: false,
|
|
241
|
+
},
|
|
242
|
+
]);
|
|
243
|
+
if (useCustomPath) {
|
|
244
|
+
const { customPath } = await inquirer.prompt([
|
|
245
|
+
{
|
|
246
|
+
type: 'input',
|
|
247
|
+
name: 'customPath',
|
|
248
|
+
message: 'Enter path to Codex prompts directory:',
|
|
249
|
+
default: defaultPath,
|
|
250
|
+
validate: (input) => {
|
|
251
|
+
if (!input || input.trim().length === 0) {
|
|
252
|
+
return 'Path cannot be empty';
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
]);
|
|
258
|
+
integrationPaths.codex = customPath;
|
|
259
|
+
this.log(chalk.gray(` ā Using custom path: ${customPath}`));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
179
263
|
// Create .clavix directory structure
|
|
180
264
|
this.log(chalk.cyan('\nš Creating directory structure...'));
|
|
181
265
|
await this.createDirectoryStructure();
|
|
182
266
|
// Generate config
|
|
183
267
|
this.log(chalk.cyan('āļø Generating configuration...'));
|
|
184
|
-
await this.generateConfig(selectedIntegrations);
|
|
268
|
+
await this.generateConfig(selectedIntegrations, integrationPaths);
|
|
185
269
|
// Generate INSTRUCTIONS.md and QUICKSTART.md
|
|
186
270
|
await this.generateInstructions();
|
|
187
271
|
await this.generateQuickstart();
|
|
@@ -396,11 +480,17 @@ export default class Init extends Command {
|
|
|
396
480
|
await FileSystem.ensureDir(dir);
|
|
397
481
|
}
|
|
398
482
|
}
|
|
399
|
-
async generateConfig(integrations) {
|
|
483
|
+
async generateConfig(integrations, integrationPaths = {}) {
|
|
400
484
|
const config = {
|
|
401
485
|
...DEFAULT_CONFIG,
|
|
402
486
|
integrations,
|
|
403
487
|
};
|
|
488
|
+
// Add integration paths to experimental if any
|
|
489
|
+
if (Object.keys(integrationPaths).length > 0) {
|
|
490
|
+
config.experimental = {
|
|
491
|
+
integrationPaths,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
404
494
|
const configPath = '.clavix/config.json';
|
|
405
495
|
const configContent = JSON.stringify(config, null, 2);
|
|
406
496
|
await FileSystem.writeFileAtomic(configPath, configContent);
|
|
@@ -72,6 +72,8 @@ export default class Update extends Command {
|
|
|
72
72
|
this.log(chalk.yellow(` ā ${warning}`));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
// Type assertion: validationResult.data is User type which has optional version
|
|
76
|
+
// We know version exists in valid configs, so we can assert
|
|
75
77
|
config = validationResult.data;
|
|
76
78
|
}
|
|
77
79
|
catch (error) {
|
|
@@ -84,8 +86,10 @@ export default class Update extends Command {
|
|
|
84
86
|
chalk.cyan('clavix init') +
|
|
85
87
|
chalk.yellow(' to regenerate.'));
|
|
86
88
|
}
|
|
89
|
+
// Handle legacy 'providers' field for backward compatibility
|
|
87
90
|
const integrations = config.integrations || config.providers || ['claude-code'];
|
|
88
|
-
|
|
91
|
+
// Initialize agent manager with config (for custom integration paths)
|
|
92
|
+
const agentManager = new AgentManager(config);
|
|
89
93
|
const updateDocs = flags['docs-only'] || (!flags['docs-only'] && !flags['commands-only']);
|
|
90
94
|
const updateCommands = flags['commands-only'] || (!flags['docs-only'] && !flags['commands-only']);
|
|
91
95
|
let updatedCount = 0;
|
|
@@ -12,7 +12,7 @@ export declare function loadExistingConfig(): Promise<{
|
|
|
12
12
|
/**
|
|
13
13
|
* Generate and save the Clavix config file
|
|
14
14
|
*/
|
|
15
|
-
export declare function generateConfig(integrations: string[]): Promise<void>;
|
|
15
|
+
export declare function generateConfig(integrations: string[], integrationPaths?: Record<string, string>): Promise<void>;
|
|
16
16
|
/**
|
|
17
17
|
* Check if Clavix is already initialized in the current directory
|
|
18
18
|
*/
|
|
@@ -31,11 +31,17 @@ export async function loadExistingConfig() {
|
|
|
31
31
|
/**
|
|
32
32
|
* Generate and save the Clavix config file
|
|
33
33
|
*/
|
|
34
|
-
export async function generateConfig(integrations) {
|
|
34
|
+
export async function generateConfig(integrations, integrationPaths = {}) {
|
|
35
35
|
const config = {
|
|
36
36
|
...DEFAULT_CONFIG,
|
|
37
37
|
integrations,
|
|
38
38
|
};
|
|
39
|
+
// Add integration paths to experimental if any
|
|
40
|
+
if (Object.keys(integrationPaths).length > 0) {
|
|
41
|
+
config.experimental = {
|
|
42
|
+
integrationPaths,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
39
45
|
const configPath = '.clavix/config.json';
|
|
40
46
|
const configContent = JSON.stringify(config, null, 2);
|
|
41
47
|
await FileSystem.writeFileAtomic(configPath, configContent);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseAdapter } from './base-adapter.js';
|
|
2
2
|
import { ManagedBlock } from '../../types/agent.js';
|
|
3
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
3
4
|
/**
|
|
4
5
|
* Claude Code agent adapter
|
|
5
6
|
*/
|
|
@@ -11,6 +12,8 @@ export declare class ClaudeCodeAdapter extends BaseAdapter {
|
|
|
11
12
|
readonly features: {
|
|
12
13
|
supportsSubdirectories: boolean;
|
|
13
14
|
};
|
|
15
|
+
protected readonly userConfig?: ClavixConfig;
|
|
16
|
+
constructor(userConfig?: ClavixConfig);
|
|
14
17
|
/**
|
|
15
18
|
* Detect if Claude Code is available in the project
|
|
16
19
|
*/
|
|
@@ -14,6 +14,11 @@ export class ClaudeCodeAdapter extends BaseAdapter {
|
|
|
14
14
|
features = {
|
|
15
15
|
supportsSubdirectories: true,
|
|
16
16
|
};
|
|
17
|
+
userConfig;
|
|
18
|
+
constructor(userConfig) {
|
|
19
|
+
super();
|
|
20
|
+
this.userConfig = userConfig;
|
|
21
|
+
}
|
|
17
22
|
/**
|
|
18
23
|
* Detect if Claude Code is available in the project
|
|
19
24
|
*/
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
2
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
2
3
|
/**
|
|
3
4
|
* Gemini CLI adapter
|
|
4
5
|
* Commands stored as TOML files under .gemini/commands/clavix by default
|
|
5
6
|
*/
|
|
6
7
|
export declare class GeminiAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
+
constructor(userConfigOrOptions?: ClavixConfig | {
|
|
8
9
|
useNamespace?: boolean;
|
|
10
|
+
userConfig?: ClavixConfig;
|
|
9
11
|
});
|
|
10
12
|
}
|
|
11
13
|
//# sourceMappingURL=gemini-adapter.d.ts.map
|
|
@@ -4,12 +4,31 @@ import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
|
4
4
|
* Commands stored as TOML files under .gemini/commands/clavix by default
|
|
5
5
|
*/
|
|
6
6
|
export class GeminiAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
constructor(userConfigOrOptions) {
|
|
8
|
+
// Support both old API (options object) and new API (userConfig directly)
|
|
9
|
+
if (!userConfigOrOptions) {
|
|
10
|
+
super({
|
|
11
|
+
name: 'gemini',
|
|
12
|
+
displayName: 'Gemini CLI',
|
|
13
|
+
rootDir: '.gemini',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if ('useNamespace' in userConfigOrOptions) {
|
|
17
|
+
// It's the options object
|
|
18
|
+
super({
|
|
19
|
+
name: 'gemini',
|
|
20
|
+
displayName: 'Gemini CLI',
|
|
21
|
+
rootDir: '.gemini',
|
|
22
|
+
}, userConfigOrOptions);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// It's the userConfig directly - pass as options
|
|
26
|
+
super({
|
|
27
|
+
name: 'gemini',
|
|
28
|
+
displayName: 'Gemini CLI',
|
|
29
|
+
rootDir: '.gemini',
|
|
30
|
+
}, { userConfig: userConfigOrOptions });
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
}
|
|
15
34
|
//# sourceMappingURL=gemini-adapter.js.map
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
2
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
2
3
|
/**
|
|
3
4
|
* LLXPRT adapter
|
|
4
5
|
* Commands stored as TOML files under .llxprt/commands/clavix by default
|
|
5
6
|
*/
|
|
6
7
|
export declare class LlxprtAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
+
constructor(userConfigOrOptions?: ClavixConfig | {
|
|
8
9
|
useNamespace?: boolean;
|
|
10
|
+
userConfig?: ClavixConfig;
|
|
9
11
|
});
|
|
10
12
|
}
|
|
11
13
|
//# sourceMappingURL=llxprt-adapter.d.ts.map
|
|
@@ -4,12 +4,31 @@ import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
|
4
4
|
* Commands stored as TOML files under .llxprt/commands/clavix by default
|
|
5
5
|
*/
|
|
6
6
|
export class LlxprtAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
constructor(userConfigOrOptions) {
|
|
8
|
+
// Support both old API (options object) and new API (userConfig directly)
|
|
9
|
+
if (!userConfigOrOptions) {
|
|
10
|
+
super({
|
|
11
|
+
name: 'llxprt',
|
|
12
|
+
displayName: 'LLXPRT',
|
|
13
|
+
rootDir: '.llxprt',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if ('useNamespace' in userConfigOrOptions) {
|
|
17
|
+
// It's the options object
|
|
18
|
+
super({
|
|
19
|
+
name: 'llxprt',
|
|
20
|
+
displayName: 'LLXPRT',
|
|
21
|
+
rootDir: '.llxprt',
|
|
22
|
+
}, userConfigOrOptions);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// It's the userConfig directly - pass as options
|
|
26
|
+
super({
|
|
27
|
+
name: 'llxprt',
|
|
28
|
+
displayName: 'LLXPRT',
|
|
29
|
+
rootDir: '.llxprt',
|
|
30
|
+
}, { userConfig: userConfigOrOptions });
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
}
|
|
15
34
|
//# sourceMappingURL=llxprt-adapter.js.map
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
2
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
2
3
|
/**
|
|
3
4
|
* Qwen Code CLI adapter
|
|
4
5
|
* Commands stored as TOML files under .qwen/commands/clavix by default
|
|
5
6
|
*/
|
|
6
7
|
export declare class QwenAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
+
constructor(userConfigOrOptions?: ClavixConfig | {
|
|
8
9
|
useNamespace?: boolean;
|
|
10
|
+
userConfig?: ClavixConfig;
|
|
9
11
|
});
|
|
10
12
|
}
|
|
11
13
|
//# sourceMappingURL=qwen-adapter.d.ts.map
|
|
@@ -4,12 +4,31 @@ import { TomlFormattingAdapter } from './toml-formatting-adapter.js';
|
|
|
4
4
|
* Commands stored as TOML files under .qwen/commands/clavix by default
|
|
5
5
|
*/
|
|
6
6
|
export class QwenAdapter extends TomlFormattingAdapter {
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
constructor(userConfigOrOptions) {
|
|
8
|
+
// Support both old API (options object) and new API (userConfig directly)
|
|
9
|
+
if (!userConfigOrOptions) {
|
|
10
|
+
super({
|
|
11
|
+
name: 'qwen',
|
|
12
|
+
displayName: 'Qwen Code',
|
|
13
|
+
rootDir: '.qwen',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if ('useNamespace' in userConfigOrOptions) {
|
|
17
|
+
// It's the options object
|
|
18
|
+
super({
|
|
19
|
+
name: 'qwen',
|
|
20
|
+
displayName: 'Qwen Code',
|
|
21
|
+
rootDir: '.qwen',
|
|
22
|
+
}, userConfigOrOptions);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// It's the userConfig directly - pass as options
|
|
26
|
+
super({
|
|
27
|
+
name: 'qwen',
|
|
28
|
+
displayName: 'Qwen Code',
|
|
29
|
+
rootDir: '.qwen',
|
|
30
|
+
}, { userConfig: userConfigOrOptions });
|
|
31
|
+
}
|
|
13
32
|
}
|
|
14
33
|
}
|
|
15
34
|
//# sourceMappingURL=qwen-adapter.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseAdapter } from './base-adapter.js';
|
|
2
2
|
import { CommandTemplate } from '../../types/agent.js';
|
|
3
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration for TOML-based adapters
|
|
5
6
|
*/
|
|
@@ -30,8 +31,10 @@ export declare abstract class TomlFormattingAdapter extends BaseAdapter {
|
|
|
30
31
|
argumentPlaceholder: string;
|
|
31
32
|
};
|
|
32
33
|
protected readonly config: TomlAdapterConfig;
|
|
34
|
+
protected readonly userConfig?: ClavixConfig;
|
|
33
35
|
constructor(config: TomlAdapterConfig, options?: {
|
|
34
36
|
useNamespace?: boolean;
|
|
37
|
+
userConfig?: ClavixConfig;
|
|
35
38
|
});
|
|
36
39
|
get name(): string;
|
|
37
40
|
get displayName(): string;
|
|
@@ -19,12 +19,14 @@ export class TomlFormattingAdapter extends BaseAdapter {
|
|
|
19
19
|
argumentPlaceholder: '{{args}}',
|
|
20
20
|
};
|
|
21
21
|
config;
|
|
22
|
+
userConfig;
|
|
22
23
|
constructor(config, options = {}) {
|
|
23
24
|
super();
|
|
24
25
|
this.config = {
|
|
25
26
|
...config,
|
|
26
27
|
useNamespace: options.useNamespace ?? config.useNamespace ?? true,
|
|
27
28
|
};
|
|
29
|
+
this.userConfig = options.userConfig;
|
|
28
30
|
}
|
|
29
31
|
get name() {
|
|
30
32
|
return this.config.name;
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
import { BaseAdapter } from './base-adapter.js';
|
|
14
14
|
import { AdapterConfig } from '../../types/adapter-config.js';
|
|
15
15
|
import { IntegrationFeatures } from '../../types/agent.js';
|
|
16
|
+
import { ClavixConfig } from '../../types/config.js';
|
|
16
17
|
export declare class UniversalAdapter extends BaseAdapter {
|
|
17
18
|
private config;
|
|
18
19
|
readonly features: IntegrationFeatures;
|
|
19
|
-
|
|
20
|
+
private userConfig?;
|
|
21
|
+
constructor(config: AdapterConfig, userConfig?: ClavixConfig);
|
|
20
22
|
get name(): string;
|
|
21
23
|
get displayName(): string;
|
|
22
24
|
get directory(): string;
|
|
@@ -11,14 +11,16 @@
|
|
|
11
11
|
* @since v5.3.0
|
|
12
12
|
*/
|
|
13
13
|
import { BaseAdapter } from './base-adapter.js';
|
|
14
|
+
import { resolveIntegrationPath } from '../../utils/path-resolver.js';
|
|
14
15
|
import * as path from 'path';
|
|
15
|
-
import * as os from 'os';
|
|
16
16
|
export class UniversalAdapter extends BaseAdapter {
|
|
17
17
|
config;
|
|
18
18
|
features;
|
|
19
|
-
|
|
19
|
+
userConfig;
|
|
20
|
+
constructor(config, userConfig) {
|
|
20
21
|
super();
|
|
21
22
|
this.config = config;
|
|
23
|
+
this.userConfig = userConfig;
|
|
22
24
|
// Set features from config for interface compatibility
|
|
23
25
|
this.features = {
|
|
24
26
|
supportsSubdirectories: config.features.supportsSubdirectories,
|
|
@@ -34,11 +36,8 @@ export class UniversalAdapter extends BaseAdapter {
|
|
|
34
36
|
return this.config.displayName;
|
|
35
37
|
}
|
|
36
38
|
get directory() {
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
return this.config.directory.replace('~', os.homedir());
|
|
40
|
-
}
|
|
41
|
-
return this.config.directory;
|
|
39
|
+
// Use path resolver for proper environment variable and config override support
|
|
40
|
+
return resolveIntegrationPath(this.config, this.userConfig);
|
|
42
41
|
}
|
|
43
42
|
/**
|
|
44
43
|
* Check if this adapter uses global (home directory) installation
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgentAdapter, ValidationResult } from '../types/agent.js';
|
|
2
|
+
import { ClavixConfig } from '../types/config.js';
|
|
2
3
|
/**
|
|
3
4
|
* Agent Manager - handles agent detection and registration
|
|
4
5
|
*
|
|
@@ -9,7 +10,8 @@ import { AgentAdapter, ValidationResult } from '../types/agent.js';
|
|
|
9
10
|
*/
|
|
10
11
|
export declare class AgentManager {
|
|
11
12
|
private adapters;
|
|
12
|
-
|
|
13
|
+
private userConfig?;
|
|
14
|
+
constructor(userConfig?: ClavixConfig);
|
|
13
15
|
/**
|
|
14
16
|
* Register a new agent adapter
|
|
15
17
|
*/
|
|
@@ -15,18 +15,20 @@ import { IntegrationError } from '../types/errors.js';
|
|
|
15
15
|
*/
|
|
16
16
|
export class AgentManager {
|
|
17
17
|
adapters = new Map();
|
|
18
|
-
|
|
18
|
+
userConfig;
|
|
19
|
+
constructor(userConfig) {
|
|
20
|
+
this.userConfig = userConfig;
|
|
19
21
|
// Register special adapters (require custom logic)
|
|
20
|
-
this.registerAdapter(new ClaudeCodeAdapter()); // Doc injection
|
|
21
|
-
this.registerAdapter(new GeminiAdapter()); // TOML format
|
|
22
|
-
this.registerAdapter(new QwenAdapter()); // TOML format
|
|
23
|
-
this.registerAdapter(new LlxprtAdapter()); // TOML format
|
|
22
|
+
this.registerAdapter(new ClaudeCodeAdapter(userConfig)); // Doc injection
|
|
23
|
+
this.registerAdapter(new GeminiAdapter(userConfig)); // TOML format
|
|
24
|
+
this.registerAdapter(new QwenAdapter(userConfig)); // TOML format
|
|
25
|
+
this.registerAdapter(new LlxprtAdapter(userConfig)); // TOML format
|
|
24
26
|
// Register simple adapters from config (using UniversalAdapter factory)
|
|
25
27
|
for (const config of getSimpleAdapters()) {
|
|
26
28
|
// Skip adapters that have special handlers registered above
|
|
27
29
|
if (this.adapters.has(config.name))
|
|
28
30
|
continue;
|
|
29
|
-
this.registerAdapter(new UniversalAdapter(config));
|
|
31
|
+
this.registerAdapter(new UniversalAdapter(config, userConfig));
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
@@ -354,7 +354,7 @@ The validation ensures generated PRDs are immediately usable for AI consumption
|
|
|
354
354
|
|
|
355
355
|
---
|
|
356
356
|
|
|
357
|
-
## Agent Transparency (v5.9.
|
|
357
|
+
## Agent Transparency (v5.9.2)
|
|
358
358
|
|
|
359
359
|
### Agent Manual (Universal Protocols)
|
|
360
360
|
{{INCLUDE:agent-protocols/AGENT_MANUAL.md}}
|
|
@@ -230,7 +230,7 @@ The goal is natural exploration of requirements, not a rigid questionnaire. Foll
|
|
|
230
230
|
|
|
231
231
|
---
|
|
232
232
|
|
|
233
|
-
## Agent Transparency (v5.9.
|
|
233
|
+
## Agent Transparency (v5.9.2)
|
|
234
234
|
|
|
235
235
|
### Agent Manual (Universal Protocols)
|
|
236
236
|
{{INCLUDE:agent-protocols/AGENT_MANUAL.md}}
|
|
@@ -409,7 +409,7 @@ The `/clavix:summarize` command extracts requirements from exploratory conversat
|
|
|
409
409
|
|
|
410
410
|
---
|
|
411
411
|
|
|
412
|
-
## Agent Transparency (v5.9.
|
|
412
|
+
## Agent Transparency (v5.9.2)
|
|
413
413
|
|
|
414
414
|
### Agent Manual (Universal Protocols)
|
|
415
415
|
{{INCLUDE:agent-protocols/AGENT_MANUAL.md}}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -7,7 +7,9 @@ export interface ClavixConfig {
|
|
|
7
7
|
templates: TemplateConfig;
|
|
8
8
|
outputs: OutputConfig;
|
|
9
9
|
preferences: PreferencesConfig;
|
|
10
|
-
experimental?: Record<string, unknown
|
|
10
|
+
experimental?: Record<string, unknown> & {
|
|
11
|
+
integrationPaths?: IntegrationPathsConfig;
|
|
12
|
+
};
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Legacy config format (pre-v3.5.0)
|
|
@@ -37,6 +39,13 @@ export interface PreferencesConfig {
|
|
|
37
39
|
autoOpenOutputs: boolean;
|
|
38
40
|
verboseLogging: boolean;
|
|
39
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Custom directory paths for integrations
|
|
44
|
+
* Maps integration name (e.g., 'codex') to custom directory path
|
|
45
|
+
*/
|
|
46
|
+
export interface IntegrationPathsConfig {
|
|
47
|
+
[integrationName: string]: string;
|
|
48
|
+
}
|
|
40
49
|
export declare const DEFAULT_CONFIG: ClavixConfig;
|
|
41
50
|
/**
|
|
42
51
|
* Migrate legacy config to current format (v3.5.0+)
|
|
@@ -35,7 +35,7 @@ export async function selectIntegrations(agentManager, preSelected = []) {
|
|
|
35
35
|
{ name: 'Cline (.cline/workflows/)', value: 'cline' },
|
|
36
36
|
{ name: 'Cursor (.cursor/commands/)', value: 'cursor' },
|
|
37
37
|
{ name: 'Kilocode (.kilo/clavix/)', value: 'kilocode' },
|
|
38
|
-
{ name: 'Roocode (.roo/
|
|
38
|
+
{ name: 'Roocode (.roo/commands/)', value: 'roocode' },
|
|
39
39
|
{ name: 'Windsurf (.windsurf/rules/)', value: 'windsurf' },
|
|
40
40
|
new inquirer.Separator(),
|
|
41
41
|
new inquirer.Separator('=== Optional Universal Adapters ==='),
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path resolution utility for integration directories
|
|
3
|
+
*
|
|
4
|
+
* Supports environment variable overrides with proper priority:
|
|
5
|
+
* 1. Environment variable (e.g., $CODEX_HOME)
|
|
6
|
+
* 2. User config override (experimental.integrationPaths)
|
|
7
|
+
* 3. Built-in default from integrations.json
|
|
8
|
+
*/
|
|
9
|
+
import type { ClavixConfig } from '../types/config.js';
|
|
10
|
+
import type { AdapterConfig } from '../types/adapter-config.js';
|
|
11
|
+
/**
|
|
12
|
+
* Mapping of integration names to their environment variable names
|
|
13
|
+
*
|
|
14
|
+
* Future extensibility: Add more integrations here as needed
|
|
15
|
+
*/
|
|
16
|
+
export declare const ENV_VAR_MAP: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the directory path for an integration based on priority:
|
|
19
|
+
* 1. Environment variable (highest priority)
|
|
20
|
+
* 2. User config override
|
|
21
|
+
* 3. Built-in default (fallback)
|
|
22
|
+
*
|
|
23
|
+
* @param config - The adapter configuration from integrations.json
|
|
24
|
+
* @param userConfig - The user's Clavix config (optional)
|
|
25
|
+
* @returns The resolved directory path with tilde expansion
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveIntegrationPath(config: AdapterConfig, userConfig?: ClavixConfig): string;
|
|
28
|
+
//# sourceMappingURL=path-resolver.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path resolution utility for integration directories
|
|
3
|
+
*
|
|
4
|
+
* Supports environment variable overrides with proper priority:
|
|
5
|
+
* 1. Environment variable (e.g., $CODEX_HOME)
|
|
6
|
+
* 2. User config override (experimental.integrationPaths)
|
|
7
|
+
* 3. Built-in default from integrations.json
|
|
8
|
+
*/
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
/**
|
|
11
|
+
* Mapping of integration names to their environment variable names
|
|
12
|
+
*
|
|
13
|
+
* Future extensibility: Add more integrations here as needed
|
|
14
|
+
*/
|
|
15
|
+
export const ENV_VAR_MAP = {
|
|
16
|
+
codex: 'CODEX_HOME',
|
|
17
|
+
// Future: cursor: 'CURSOR_HOME',
|
|
18
|
+
// Future: gemini: 'GEMINI_HOME',
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Resolves the directory path for an integration based on priority:
|
|
22
|
+
* 1. Environment variable (highest priority)
|
|
23
|
+
* 2. User config override
|
|
24
|
+
* 3. Built-in default (fallback)
|
|
25
|
+
*
|
|
26
|
+
* @param config - The adapter configuration from integrations.json
|
|
27
|
+
* @param userConfig - The user's Clavix config (optional)
|
|
28
|
+
* @returns The resolved directory path with tilde expansion
|
|
29
|
+
*/
|
|
30
|
+
export function resolveIntegrationPath(config, userConfig) {
|
|
31
|
+
const integrationName = config.name;
|
|
32
|
+
// Priority 1: Environment variable
|
|
33
|
+
const envVar = ENV_VAR_MAP[integrationName];
|
|
34
|
+
if (envVar && process.env[envVar]) {
|
|
35
|
+
return process.env[envVar];
|
|
36
|
+
}
|
|
37
|
+
// Priority 2: User config override
|
|
38
|
+
const customPath = userConfig?.experimental?.integrationPaths?.[integrationName];
|
|
39
|
+
if (customPath && typeof customPath === 'string') {
|
|
40
|
+
return expandTilde(customPath);
|
|
41
|
+
}
|
|
42
|
+
// Priority 3: Built-in default from config
|
|
43
|
+
return expandTilde(config.directory);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Expands tilde (~) to the user's home directory
|
|
47
|
+
*
|
|
48
|
+
* @param dir - Directory path that may start with ~/
|
|
49
|
+
* @returns Directory path with ~ expanded to home directory
|
|
50
|
+
*/
|
|
51
|
+
function expandTilde(dir) {
|
|
52
|
+
if (dir.startsWith('~/')) {
|
|
53
|
+
return dir.replace('~', os.homedir());
|
|
54
|
+
}
|
|
55
|
+
return dir;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=path-resolver.js.map
|
package/dist/utils/schemas.d.ts
CHANGED
|
@@ -119,7 +119,6 @@ export declare const IntegrationsConfigSchema: z.ZodObject<{
|
|
|
119
119
|
placeholder?: string | undefined;
|
|
120
120
|
}[]>;
|
|
121
121
|
}, "strip", z.ZodTypeAny, {
|
|
122
|
-
version: string;
|
|
123
122
|
integrations: {
|
|
124
123
|
name: string;
|
|
125
124
|
directory: string;
|
|
@@ -134,9 +133,9 @@ export declare const IntegrationsConfigSchema: z.ZodObject<{
|
|
|
134
133
|
global?: boolean | undefined;
|
|
135
134
|
placeholder?: string | undefined;
|
|
136
135
|
}[];
|
|
136
|
+
version: string;
|
|
137
137
|
$schema?: string | undefined;
|
|
138
138
|
}, {
|
|
139
|
-
version: string;
|
|
140
139
|
integrations: {
|
|
141
140
|
name: string;
|
|
142
141
|
directory: string;
|
|
@@ -151,8 +150,14 @@ export declare const IntegrationsConfigSchema: z.ZodObject<{
|
|
|
151
150
|
global?: boolean | undefined;
|
|
152
151
|
placeholder?: string | undefined;
|
|
153
152
|
}[];
|
|
153
|
+
version: string;
|
|
154
154
|
$schema?: string | undefined;
|
|
155
155
|
}>;
|
|
156
|
+
/**
|
|
157
|
+
* Schema for integration paths in experimental config
|
|
158
|
+
* Maps integration name to custom directory path
|
|
159
|
+
*/
|
|
160
|
+
export declare const IntegrationPathsSchema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
156
161
|
/**
|
|
157
162
|
* Schema for user's .clavix/config.json
|
|
158
163
|
* Matches ClavixConfig interface in src/types/config.ts
|
|
@@ -194,11 +199,17 @@ export declare const UserConfigSchema: z.ZodObject<{
|
|
|
194
199
|
autoOpenOutputs: boolean;
|
|
195
200
|
verboseLogging: boolean;
|
|
196
201
|
}>>;
|
|
197
|
-
experimental: z.ZodOptional<z.
|
|
202
|
+
experimental: z.ZodOptional<z.ZodObject<{
|
|
203
|
+
integrationPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
204
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
205
|
+
integrationPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
206
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
207
|
+
integrationPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
208
|
+
}, z.ZodTypeAny, "passthrough">>>;
|
|
198
209
|
}, "strip", z.ZodTypeAny, {
|
|
199
|
-
version?: string | undefined;
|
|
200
|
-
integrations?: string[] | undefined;
|
|
201
210
|
providers?: string[] | undefined;
|
|
211
|
+
integrations?: string[] | undefined;
|
|
212
|
+
version?: string | undefined;
|
|
202
213
|
templates?: {
|
|
203
214
|
prdQuestions: string;
|
|
204
215
|
fullPrd: string;
|
|
@@ -212,11 +223,13 @@ export declare const UserConfigSchema: z.ZodObject<{
|
|
|
212
223
|
autoOpenOutputs: boolean;
|
|
213
224
|
verboseLogging: boolean;
|
|
214
225
|
} | undefined;
|
|
215
|
-
experimental?:
|
|
226
|
+
experimental?: z.objectOutputType<{
|
|
227
|
+
integrationPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
228
|
+
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
216
229
|
}, {
|
|
217
|
-
version?: string | undefined;
|
|
218
|
-
integrations?: string[] | undefined;
|
|
219
230
|
providers?: string[] | undefined;
|
|
231
|
+
integrations?: string[] | undefined;
|
|
232
|
+
version?: string | undefined;
|
|
220
233
|
templates?: {
|
|
221
234
|
prdQuestions: string;
|
|
222
235
|
fullPrd: string;
|
|
@@ -230,7 +243,9 @@ export declare const UserConfigSchema: z.ZodObject<{
|
|
|
230
243
|
autoOpenOutputs: boolean;
|
|
231
244
|
verboseLogging: boolean;
|
|
232
245
|
} | undefined;
|
|
233
|
-
experimental?:
|
|
246
|
+
experimental?: z.objectInputType<{
|
|
247
|
+
integrationPaths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
248
|
+
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
234
249
|
}>;
|
|
235
250
|
/**
|
|
236
251
|
* Inferred TypeScript types from schemas
|
package/dist/utils/schemas.js
CHANGED
|
@@ -63,6 +63,21 @@ const PreferencesConfigSchema = z.object({
|
|
|
63
63
|
autoOpenOutputs: z.boolean(),
|
|
64
64
|
verboseLogging: z.boolean(),
|
|
65
65
|
});
|
|
66
|
+
/**
|
|
67
|
+
* Schema for integration paths in experimental config
|
|
68
|
+
* Maps integration name to custom directory path
|
|
69
|
+
*/
|
|
70
|
+
export const IntegrationPathsSchema = z
|
|
71
|
+
.record(z.string().min(1, 'Integration name is required'), z.string().min(1, 'Path cannot be empty'))
|
|
72
|
+
.optional();
|
|
73
|
+
/**
|
|
74
|
+
* Schema for experimental configuration
|
|
75
|
+
*/
|
|
76
|
+
const ExperimentalConfigSchema = z
|
|
77
|
+
.object({
|
|
78
|
+
integrationPaths: IntegrationPathsSchema,
|
|
79
|
+
})
|
|
80
|
+
.passthrough(); // Allow other experimental fields
|
|
66
81
|
/**
|
|
67
82
|
* Schema for user's .clavix/config.json
|
|
68
83
|
* Matches ClavixConfig interface in src/types/config.ts
|
|
@@ -78,7 +93,7 @@ export const UserConfigSchema = z.object({
|
|
|
78
93
|
templates: TemplateConfigSchema.optional(),
|
|
79
94
|
outputs: OutputConfigSchema.optional(),
|
|
80
95
|
preferences: PreferencesConfigSchema.optional(),
|
|
81
|
-
experimental:
|
|
96
|
+
experimental: ExperimentalConfigSchema.optional(),
|
|
82
97
|
});
|
|
83
98
|
/**
|
|
84
99
|
* Validate integrations.json content (build-time, strict)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clavix",
|
|
3
|
-
"version": "5.9.
|
|
3
|
+
"version": "5.9.2",
|
|
4
4
|
"description": "Agentic-first prompt workflows. Markdown templates that teach AI agents how to optimize prompts, create PRDs, and manage implementation.\n\nSLASH COMMANDS (in your AI assistant):\n /clavix:improve Optimize prompts with auto-depth\n /clavix:prd Generate PRD through questions\n /clavix:plan Create task breakdown from PRD\n /clavix:implement Execute tasks with progress tracking\n /clavix:start Begin conversational session\n /clavix:summarize Extract requirements from conversation\n /clavix:refine Refine existing PRD or prompt\n /clavix:verify Verify implementation against requirements\n /clavix:archive Archive completed projects\n\nWorks with Claude Code, Cursor, Windsurf, and 20 AI coding tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"@oclif/core": "^4.8.0",
|
|
71
71
|
"@oclif/plugin-help": "^6.2.35",
|
|
72
72
|
"chalk": "^5.6.2",
|
|
73
|
+
"clavix": "^5.9.2",
|
|
73
74
|
"fs-extra": "^11.3.2",
|
|
74
75
|
"inquirer": "^12.11.1",
|
|
75
76
|
"zod": "^3.24.4"
|