clavix 5.2.1 → 5.3.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.
- package/README.md +3 -4
- package/dist/cli/commands/diagnose.js +1 -1
- 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/base-adapter.d.ts +1 -0
- package/dist/core/adapters/base-adapter.js +14 -1
- package/dist/core/adapters/universal-adapter.d.ts +49 -0
- package/dist/core/adapters/universal-adapter.js +88 -0
- 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 +5 -10
- package/dist/core/template-assembler.d.ts +1 -1
- package/dist/core/template-assembler.js +1 -1
- package/dist/templates/agents/agents.md +1 -2
- package/dist/templates/agents/copilot-instructions.md +1 -2
- package/dist/templates/agents/octo.md +1 -1
- package/dist/templates/agents/warp.md +2 -2
- 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.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 +1 -1
- package/dist/cli/commands/config.d.ts +0 -28
- package/dist/cli/commands/config.js +0 -447
- 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
|
@@ -1,447 +0,0 @@
|
|
|
1
|
-
import { Command, Args } from '@oclif/core';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import inquirer from 'inquirer';
|
|
6
|
-
import { AgentManager } from '../../core/agent-manager.js';
|
|
7
|
-
import { DEFAULT_CONFIG, isLegacyConfig, migrateConfig } from '../../types/config.js';
|
|
8
|
-
import { loadCommandTemplates } from '../../utils/template-loader.js';
|
|
9
|
-
export default class Config extends Command {
|
|
10
|
-
static description = 'Manage Clavix configuration';
|
|
11
|
-
static examples = [
|
|
12
|
-
'<%= config.bin %> <%= command.id %>',
|
|
13
|
-
'<%= config.bin %> <%= command.id %> get integrations',
|
|
14
|
-
'<%= config.bin %> <%= command.id %> set preferences.verboseLogging true',
|
|
15
|
-
];
|
|
16
|
-
static args = {
|
|
17
|
-
action: Args.string({
|
|
18
|
-
description: 'Action to perform (get, set, edit, reset)',
|
|
19
|
-
options: ['get', 'set', 'edit', 'reset'],
|
|
20
|
-
required: false,
|
|
21
|
-
}),
|
|
22
|
-
key: Args.string({
|
|
23
|
-
description: 'Configuration key',
|
|
24
|
-
required: false,
|
|
25
|
-
}),
|
|
26
|
-
value: Args.string({
|
|
27
|
-
description: 'Configuration value (for set action)',
|
|
28
|
-
required: false,
|
|
29
|
-
}),
|
|
30
|
-
};
|
|
31
|
-
static flags = {};
|
|
32
|
-
async run() {
|
|
33
|
-
const { args } = await this.parse(Config);
|
|
34
|
-
const clavixDir = path.join(process.cwd(), '.clavix');
|
|
35
|
-
const configPath = path.join(clavixDir, 'config.json');
|
|
36
|
-
if (!fs.existsSync(clavixDir) || !fs.existsSync(configPath)) {
|
|
37
|
-
this.error(chalk.red('No .clavix directory found.') +
|
|
38
|
-
'\n' +
|
|
39
|
-
chalk.yellow('Run ') +
|
|
40
|
-
chalk.cyan('clavix init') +
|
|
41
|
-
chalk.yellow(' to initialize Clavix in this project.'));
|
|
42
|
-
}
|
|
43
|
-
// If no action specified, show interactive menu
|
|
44
|
-
if (!args.action) {
|
|
45
|
-
await this.showInteractiveMenu(configPath);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
switch (args.action) {
|
|
49
|
-
case 'get':
|
|
50
|
-
await this.getConfig(configPath, args.key);
|
|
51
|
-
break;
|
|
52
|
-
case 'set':
|
|
53
|
-
await this.setConfig(configPath, args.key, args.value);
|
|
54
|
-
break;
|
|
55
|
-
case 'edit':
|
|
56
|
-
await this.editConfig(configPath);
|
|
57
|
-
break;
|
|
58
|
-
case 'reset':
|
|
59
|
-
await this.resetConfig(configPath);
|
|
60
|
-
break;
|
|
61
|
-
default:
|
|
62
|
-
this.error(chalk.red(`Unknown action: ${args.action}`));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async showInteractiveMenu(configPath) {
|
|
66
|
-
let continueMenu = true;
|
|
67
|
-
while (continueMenu) {
|
|
68
|
-
const config = this.loadConfig(configPath);
|
|
69
|
-
this.log(chalk.bold.cyan('\n⚙️ Clavix Configuration\n'));
|
|
70
|
-
this.displayConfig(config);
|
|
71
|
-
const { action } = await inquirer.prompt([
|
|
72
|
-
{
|
|
73
|
-
type: 'list',
|
|
74
|
-
name: 'action',
|
|
75
|
-
message: 'What would you like to do?',
|
|
76
|
-
choices: [
|
|
77
|
-
{ name: 'View current configuration', value: 'view' },
|
|
78
|
-
{ name: 'Manage integrations (add/remove)', value: 'integrations' },
|
|
79
|
-
{ name: 'Edit preferences', value: 'edit-preferences' },
|
|
80
|
-
{ name: 'Reset to defaults', value: 'reset' },
|
|
81
|
-
{ name: 'Exit', value: 'exit' },
|
|
82
|
-
],
|
|
83
|
-
},
|
|
84
|
-
]);
|
|
85
|
-
switch (action) {
|
|
86
|
-
case 'view':
|
|
87
|
-
// Already displayed above
|
|
88
|
-
break;
|
|
89
|
-
case 'integrations':
|
|
90
|
-
await this.manageIntegrations(config, configPath);
|
|
91
|
-
break;
|
|
92
|
-
case 'edit-preferences':
|
|
93
|
-
await this.editPreferences(configPath, config);
|
|
94
|
-
break;
|
|
95
|
-
case 'reset':
|
|
96
|
-
await this.resetConfig(configPath);
|
|
97
|
-
break;
|
|
98
|
-
case 'exit':
|
|
99
|
-
continueMenu = false;
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
async manageIntegrations(config, configPath) {
|
|
105
|
-
const agentManager = new AgentManager();
|
|
106
|
-
while (true) {
|
|
107
|
-
// Show current integrations
|
|
108
|
-
this.log(chalk.cyan('\n📦 Current Integrations:'));
|
|
109
|
-
if (config.integrations.length === 0) {
|
|
110
|
-
this.log(chalk.gray(' (none configured)'));
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
for (const integrationName of config.integrations) {
|
|
114
|
-
const adapter = agentManager.getAdapter(integrationName);
|
|
115
|
-
const displayName = adapter?.displayName || integrationName;
|
|
116
|
-
this.log(chalk.gray(` • ${displayName}`));
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// Submenu
|
|
120
|
-
const { action } = await inquirer.prompt([
|
|
121
|
-
{
|
|
122
|
-
type: 'list',
|
|
123
|
-
name: 'action',
|
|
124
|
-
message: 'What would you like to do?',
|
|
125
|
-
choices: [
|
|
126
|
-
{ name: 'Add integration', value: 'add' },
|
|
127
|
-
{ name: 'Remove integration', value: 'remove' },
|
|
128
|
-
{ name: 'Replace all integrations', value: 'replace' },
|
|
129
|
-
{ name: 'Back to main menu', value: 'back' },
|
|
130
|
-
],
|
|
131
|
-
},
|
|
132
|
-
]);
|
|
133
|
-
if (action === 'back')
|
|
134
|
-
break;
|
|
135
|
-
switch (action) {
|
|
136
|
-
case 'add':
|
|
137
|
-
await this.addIntegrations(config, configPath);
|
|
138
|
-
break;
|
|
139
|
-
case 'remove':
|
|
140
|
-
await this.removeIntegrations(config, configPath);
|
|
141
|
-
break;
|
|
142
|
-
case 'replace':
|
|
143
|
-
await this.replaceIntegrations(config, configPath);
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
// Reload config after modifications
|
|
147
|
-
config = this.loadConfig(configPath);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
async addIntegrations(config, configPath) {
|
|
151
|
-
const agentManager = new AgentManager();
|
|
152
|
-
const allIntegrations = agentManager.getAdapters();
|
|
153
|
-
// Show only non-selected providers
|
|
154
|
-
const availableToAdd = allIntegrations.filter((a) => !config.integrations.includes(a.name));
|
|
155
|
-
if (availableToAdd.length === 0) {
|
|
156
|
-
this.log(chalk.yellow('\n✓ All integrations already added!'));
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
// Multi-select checkbox
|
|
160
|
-
const { newIntegrations } = await inquirer.prompt([
|
|
161
|
-
{
|
|
162
|
-
type: 'checkbox',
|
|
163
|
-
name: 'newIntegrations',
|
|
164
|
-
message: 'Select providers to add:',
|
|
165
|
-
choices: availableToAdd.map((adapter) => ({
|
|
166
|
-
name: `${adapter.displayName} (${adapter.directory})`,
|
|
167
|
-
value: adapter.name,
|
|
168
|
-
})),
|
|
169
|
-
},
|
|
170
|
-
]);
|
|
171
|
-
if (newIntegrations.length === 0) {
|
|
172
|
-
this.log(chalk.gray('No integrations selected'));
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
// Add to config
|
|
176
|
-
config.integrations.push(...newIntegrations);
|
|
177
|
-
this.saveConfig(configPath, config);
|
|
178
|
-
this.log(chalk.gray('\n🔧 Generating commands for new integrations...'));
|
|
179
|
-
// Generate commands for new integrations
|
|
180
|
-
for (const integrationName of newIntegrations) {
|
|
181
|
-
const adapter = agentManager.getAdapter(integrationName);
|
|
182
|
-
if (!adapter)
|
|
183
|
-
continue;
|
|
184
|
-
const templates = await loadCommandTemplates(adapter);
|
|
185
|
-
await adapter.generateCommands(templates);
|
|
186
|
-
this.log(chalk.green(` ✓ Generated ${templates.length} command(s) for ${adapter.displayName}`));
|
|
187
|
-
}
|
|
188
|
-
this.log(chalk.green('\n✅ Integrations added successfully!'));
|
|
189
|
-
}
|
|
190
|
-
async removeIntegrations(config, configPath) {
|
|
191
|
-
if (config.integrations.length === 0) {
|
|
192
|
-
this.log(chalk.yellow('\n⚠ No integrations configured!'));
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
const agentManager = new AgentManager();
|
|
196
|
-
// Multi-select from current integrations
|
|
197
|
-
const { integrationsToRemove } = await inquirer.prompt([
|
|
198
|
-
{
|
|
199
|
-
type: 'checkbox',
|
|
200
|
-
name: 'integrationsToRemove',
|
|
201
|
-
message: 'Select providers to remove:',
|
|
202
|
-
choices: config.integrations.map((name) => {
|
|
203
|
-
const adapter = agentManager.getAdapter(name);
|
|
204
|
-
return {
|
|
205
|
-
name: `${adapter?.displayName || name} (${adapter?.directory || 'unknown'})`,
|
|
206
|
-
value: name,
|
|
207
|
-
};
|
|
208
|
-
}),
|
|
209
|
-
validate: (answer) => {
|
|
210
|
-
if (answer.length === config.integrations.length) {
|
|
211
|
-
return 'You must keep at least one integration. Use "Reset to defaults" to reconfigure completely.';
|
|
212
|
-
}
|
|
213
|
-
return true;
|
|
214
|
-
},
|
|
215
|
-
},
|
|
216
|
-
]);
|
|
217
|
-
if (integrationsToRemove.length === 0) {
|
|
218
|
-
this.log(chalk.gray('No integrations selected'));
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
// Confirm cleanup
|
|
222
|
-
const { cleanup } = await inquirer.prompt([
|
|
223
|
-
{
|
|
224
|
-
type: 'confirm',
|
|
225
|
-
name: 'cleanup',
|
|
226
|
-
message: 'Remove command files for these integrations?',
|
|
227
|
-
default: true,
|
|
228
|
-
},
|
|
229
|
-
]);
|
|
230
|
-
// Remove from config
|
|
231
|
-
config.integrations = config.integrations.filter((p) => !integrationsToRemove.includes(p));
|
|
232
|
-
this.saveConfig(configPath, config);
|
|
233
|
-
// Clean up command files
|
|
234
|
-
if (cleanup) {
|
|
235
|
-
this.log(chalk.gray('\n🗑️ Cleaning up command files...'));
|
|
236
|
-
for (const integrationName of integrationsToRemove) {
|
|
237
|
-
const adapter = agentManager.getAdapter(integrationName);
|
|
238
|
-
if (adapter) {
|
|
239
|
-
const removed = await adapter.removeAllCommands();
|
|
240
|
-
this.log(chalk.gray(` ✓ Removed ${removed} command(s) from ${adapter.displayName}`));
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
this.log(chalk.green('\n✅ Integrations removed successfully!'));
|
|
245
|
-
}
|
|
246
|
-
async replaceIntegrations(config, configPath) {
|
|
247
|
-
const agentManager = new AgentManager();
|
|
248
|
-
// Use shared provider selector
|
|
249
|
-
const { selectIntegrations } = await import('../../utils/integration-selector.js');
|
|
250
|
-
const newIntegrations = await selectIntegrations(agentManager, config.integrations);
|
|
251
|
-
if (newIntegrations.length === 0) {
|
|
252
|
-
this.log(chalk.gray('No integrations selected'));
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
// Find deselected integrations
|
|
256
|
-
const deselected = config.integrations.filter((p) => !newIntegrations.includes(p));
|
|
257
|
-
// Handle cleanup if providers were deselected
|
|
258
|
-
if (deselected.length > 0) {
|
|
259
|
-
this.log(chalk.yellow('\n⚠ Previously configured but not selected:'));
|
|
260
|
-
for (const integrationName of deselected) {
|
|
261
|
-
const adapter = agentManager.getAdapter(integrationName);
|
|
262
|
-
const displayName = adapter?.displayName || integrationName;
|
|
263
|
-
const directory = adapter?.directory || 'unknown';
|
|
264
|
-
this.log(chalk.gray(` • ${displayName} (${directory})`));
|
|
265
|
-
}
|
|
266
|
-
const { cleanupAction } = await inquirer.prompt([
|
|
267
|
-
{
|
|
268
|
-
type: 'list',
|
|
269
|
-
name: 'cleanupAction',
|
|
270
|
-
message: 'What would you like to do with these integrations?',
|
|
271
|
-
choices: [
|
|
272
|
-
{ name: 'Clean up (remove all command files)', value: 'cleanup' },
|
|
273
|
-
{ name: 'Skip (leave as-is)', value: 'skip' },
|
|
274
|
-
],
|
|
275
|
-
},
|
|
276
|
-
]);
|
|
277
|
-
if (cleanupAction === 'cleanup') {
|
|
278
|
-
this.log(chalk.gray('\n🗑️ Cleaning up deselected integrations...'));
|
|
279
|
-
for (const integrationName of deselected) {
|
|
280
|
-
const adapter = agentManager.getAdapter(integrationName);
|
|
281
|
-
if (adapter) {
|
|
282
|
-
const removed = await adapter.removeAllCommands();
|
|
283
|
-
this.log(chalk.gray(` ✓ Removed ${removed} command(s) from ${adapter.displayName}`));
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
// Update config
|
|
289
|
-
config.integrations = newIntegrations;
|
|
290
|
-
this.saveConfig(configPath, config);
|
|
291
|
-
// Prompt to run update
|
|
292
|
-
const { runUpdate } = await inquirer.prompt([
|
|
293
|
-
{
|
|
294
|
-
type: 'confirm',
|
|
295
|
-
name: 'runUpdate',
|
|
296
|
-
message: 'Run update to regenerate all commands?',
|
|
297
|
-
default: true,
|
|
298
|
-
},
|
|
299
|
-
]);
|
|
300
|
-
if (runUpdate) {
|
|
301
|
-
this.log(chalk.gray('\n🔧 Regenerating commands for all integrations...\n'));
|
|
302
|
-
const Update = (await import('./update.js')).default;
|
|
303
|
-
await Update.run([]);
|
|
304
|
-
}
|
|
305
|
-
this.log(chalk.green('\n✅ Integrations replaced successfully!'));
|
|
306
|
-
}
|
|
307
|
-
async getConfig(configPath, key) {
|
|
308
|
-
const config = this.loadConfig(configPath);
|
|
309
|
-
if (!key) {
|
|
310
|
-
this.log(chalk.bold.cyan('⚙️ Current Configuration\n'));
|
|
311
|
-
this.displayConfig(config);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
const value = this.getNestedValue(config, key);
|
|
315
|
-
if (value === undefined) {
|
|
316
|
-
this.error(chalk.red(`Configuration key "${key}" not found`));
|
|
317
|
-
}
|
|
318
|
-
this.log(chalk.cyan(key) + chalk.gray(': ') + JSON.stringify(value, null, 2));
|
|
319
|
-
}
|
|
320
|
-
async setConfig(configPath, key, value) {
|
|
321
|
-
if (!key || value === undefined) {
|
|
322
|
-
this.error('Usage: clavix config set <key> <value>');
|
|
323
|
-
}
|
|
324
|
-
const config = this.loadConfig(configPath);
|
|
325
|
-
// Parse value as JSON if possible
|
|
326
|
-
let parsedValue;
|
|
327
|
-
try {
|
|
328
|
-
parsedValue = JSON.parse(value);
|
|
329
|
-
}
|
|
330
|
-
catch {
|
|
331
|
-
parsedValue = value;
|
|
332
|
-
}
|
|
333
|
-
this.setNestedValue(config, key, parsedValue);
|
|
334
|
-
this.saveConfig(configPath, config);
|
|
335
|
-
this.log(chalk.green(`✅ Set ${chalk.cyan(key)} to ${JSON.stringify(parsedValue)}`));
|
|
336
|
-
}
|
|
337
|
-
async editConfig(configPath) {
|
|
338
|
-
const config = this.loadConfig(configPath);
|
|
339
|
-
await this.editPreferences(configPath, config);
|
|
340
|
-
}
|
|
341
|
-
async resetConfig(configPath) {
|
|
342
|
-
const { confirm } = await inquirer.prompt([
|
|
343
|
-
{
|
|
344
|
-
type: 'confirm',
|
|
345
|
-
name: 'confirm',
|
|
346
|
-
message: 'Are you sure you want to reset configuration to defaults?',
|
|
347
|
-
default: false,
|
|
348
|
-
},
|
|
349
|
-
]);
|
|
350
|
-
if (!confirm) {
|
|
351
|
-
this.log(chalk.gray('Cancelled'));
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
const config = this.loadConfig(configPath);
|
|
355
|
-
const defaultConfig = {
|
|
356
|
-
...DEFAULT_CONFIG,
|
|
357
|
-
providers: config.integrations, // Keep existing integrations
|
|
358
|
-
};
|
|
359
|
-
this.saveConfig(configPath, defaultConfig);
|
|
360
|
-
this.log(chalk.green('✅ Configuration reset to defaults (integrations preserved)'));
|
|
361
|
-
}
|
|
362
|
-
async editPreferences(configPath, config) {
|
|
363
|
-
const preferences = config.preferences || DEFAULT_CONFIG.preferences;
|
|
364
|
-
const answers = await inquirer.prompt([
|
|
365
|
-
{
|
|
366
|
-
type: 'confirm',
|
|
367
|
-
name: 'autoOpenOutputs',
|
|
368
|
-
message: 'Auto-open generated outputs?',
|
|
369
|
-
default: preferences.autoOpenOutputs,
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
type: 'confirm',
|
|
373
|
-
name: 'verboseLogging',
|
|
374
|
-
message: 'Enable verbose logging?',
|
|
375
|
-
default: preferences.verboseLogging,
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
type: 'confirm',
|
|
379
|
-
name: 'preserveSessions',
|
|
380
|
-
message: 'Preserve completed sessions?',
|
|
381
|
-
default: preferences.preserveSessions,
|
|
382
|
-
},
|
|
383
|
-
]);
|
|
384
|
-
config.preferences = answers;
|
|
385
|
-
this.saveConfig(configPath, config);
|
|
386
|
-
this.log(chalk.green('\n✅ Preferences updated'));
|
|
387
|
-
}
|
|
388
|
-
loadConfig(configPath) {
|
|
389
|
-
try {
|
|
390
|
-
const rawConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
391
|
-
// Check if legacy config and migrate
|
|
392
|
-
if (isLegacyConfig(rawConfig)) {
|
|
393
|
-
this.warn(chalk.yellow('Detected legacy config format. Migrating to new format...'));
|
|
394
|
-
const migratedConfig = migrateConfig(rawConfig);
|
|
395
|
-
this.saveConfig(configPath, migratedConfig);
|
|
396
|
-
return migratedConfig;
|
|
397
|
-
}
|
|
398
|
-
return rawConfig;
|
|
399
|
-
}
|
|
400
|
-
catch (error) {
|
|
401
|
-
this.error(chalk.red(`Failed to load configuration: ${error.message}`));
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
saveConfig(configPath, config) {
|
|
405
|
-
try {
|
|
406
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
407
|
-
}
|
|
408
|
-
catch (error) {
|
|
409
|
-
this.error(chalk.red(`Failed to save configuration: ${error.message}`));
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
displayConfig(config) {
|
|
413
|
-
this.log(` ${chalk.gray('Version:')} ${config.version}`);
|
|
414
|
-
this.log(` ${chalk.gray('Integrations:')} ${config.integrations.map((p) => chalk.cyan(p)).join(', ') || chalk.gray('(none)')}`);
|
|
415
|
-
if (config.preferences) {
|
|
416
|
-
this.log(`\n ${chalk.bold('Preferences:')}`);
|
|
417
|
-
this.log(` ${chalk.gray('Auto-open outputs:')} ${config.preferences.autoOpenOutputs ? chalk.green('yes') : chalk.gray('no')}`);
|
|
418
|
-
this.log(` ${chalk.gray('Verbose logging:')} ${config.preferences.verboseLogging ? chalk.green('yes') : chalk.gray('no')}`);
|
|
419
|
-
this.log(` ${chalk.gray('Preserve sessions:')} ${config.preferences.preserveSessions ? chalk.green('yes') : chalk.gray('no')}`);
|
|
420
|
-
}
|
|
421
|
-
if (config.outputs) {
|
|
422
|
-
this.log(`\n ${chalk.bold('Outputs:')}`);
|
|
423
|
-
this.log(` ${chalk.gray('Path:')} ${config.outputs.path}`);
|
|
424
|
-
this.log(` ${chalk.gray('Format:')} ${config.outputs.format}`);
|
|
425
|
-
}
|
|
426
|
-
this.log('');
|
|
427
|
-
}
|
|
428
|
-
getNestedValue(obj, path) {
|
|
429
|
-
return path.split('.').reduce((current, key) => {
|
|
430
|
-
if (current && typeof current === 'object' && key in current) {
|
|
431
|
-
return current[key];
|
|
432
|
-
}
|
|
433
|
-
return undefined;
|
|
434
|
-
}, obj);
|
|
435
|
-
}
|
|
436
|
-
setNestedValue(obj, path, value) {
|
|
437
|
-
const keys = path.split('.');
|
|
438
|
-
const lastKey = keys.pop();
|
|
439
|
-
const target = keys.reduce((current, key) => {
|
|
440
|
-
if (!current[key])
|
|
441
|
-
current[key] = {};
|
|
442
|
-
return current[key];
|
|
443
|
-
}, obj);
|
|
444
|
-
target[lastKey] = value;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
//# sourceMappingURL=config.js.map
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
## Agent Decision Rules
|
|
2
|
-
|
|
3
|
-
These rules define deterministic agent behavior. Follow exactly - no interpretation needed.
|
|
4
|
-
|
|
5
|
-
### Rule 1: Quality-Based Mode Decision
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
IF quality < 60%:
|
|
9
|
-
IF (completeness < 50%) OR (clarity < 50%) OR (actionability < 50%):
|
|
10
|
-
→ ACTION: Strongly recommend comprehensive depth
|
|
11
|
-
→ SAY: "Quality is [X]%. Comprehensive depth strongly recommended for: [low dimensions]"
|
|
12
|
-
ELSE:
|
|
13
|
-
→ ACTION: Suggest comprehensive depth
|
|
14
|
-
→ SAY: "Quality is [X]%. Consider comprehensive depth for better results."
|
|
15
|
-
|
|
16
|
-
IF quality >= 60% AND quality < 80%:
|
|
17
|
-
→ ACTION: Proceed with optimization
|
|
18
|
-
→ SHOW: Improvement suggestions
|
|
19
|
-
|
|
20
|
-
IF quality >= 80%:
|
|
21
|
-
→ ACTION: Prompt is ready
|
|
22
|
-
→ SAY: "Prompt quality is good ([X]%). Ready to execute."
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Rule 2: Intent Confidence Decision
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
IF confidence >= 85%:
|
|
29
|
-
→ ACTION: Proceed with detected intent
|
|
30
|
-
→ NO secondary intent shown
|
|
31
|
-
|
|
32
|
-
IF confidence 70-84%:
|
|
33
|
-
→ ACTION: Proceed, note secondary if >25%
|
|
34
|
-
→ SHOW: "Primary: [intent] ([X]%). Also detected: [secondary] ([Y]%)"
|
|
35
|
-
|
|
36
|
-
IF confidence 50-69%:
|
|
37
|
-
→ ACTION: Ask user to confirm
|
|
38
|
-
→ ASK: "Detected [intent] with [X]% confidence. Is this correct?"
|
|
39
|
-
|
|
40
|
-
IF confidence < 50%:
|
|
41
|
-
→ ACTION: Cannot proceed autonomously
|
|
42
|
-
→ ASK: "I'm unclear on intent. Is this: [option A] | [option B] | [option C]?"
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Rule 3: Escalation Decision
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
IF escalation_score >= 75:
|
|
49
|
-
→ ACTION: Strongly recommend comprehensive depth
|
|
50
|
-
→ SHOW: Top 3 contributing factors
|
|
51
|
-
|
|
52
|
-
IF escalation_score 60-74:
|
|
53
|
-
→ ACTION: Recommend comprehensive depth
|
|
54
|
-
→ SHOW: Primary contributing factor
|
|
55
|
-
|
|
56
|
-
IF escalation_score 45-59:
|
|
57
|
-
→ ACTION: Suggest comprehensive depth as option
|
|
58
|
-
→ SAY: "Comprehensive depth available for more thorough analysis"
|
|
59
|
-
|
|
60
|
-
IF escalation_score < 45:
|
|
61
|
-
→ ACTION: Standard depth sufficient
|
|
62
|
-
→ NO escalation mention
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Rule 4: Task Completion (Implementation Mode)
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
AFTER implementing task:
|
|
69
|
-
→ EDIT tasks.md: Change - [ ] to - [x] for completed task
|
|
70
|
-
→ Use Edit tool to update the checkbox
|
|
71
|
-
|
|
72
|
-
IF edit succeeds:
|
|
73
|
-
→ SHOW: Next task automatically
|
|
74
|
-
→ CONTINUE with next task
|
|
75
|
-
|
|
76
|
-
IF edit fails:
|
|
77
|
-
→ SHOW error to user
|
|
78
|
-
→ ASK: "Task completion failed: [error]. How to proceed?"
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Rule 5: Workflow State Check
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
BEFORE starting /clavix:implement:
|
|
85
|
-
→ CHECK: .clavix-implement-config.json exists?
|
|
86
|
-
|
|
87
|
-
IF exists AND stats.remaining > 0:
|
|
88
|
-
→ SAY: "Resuming implementation. Progress: [X]/[Y] tasks."
|
|
89
|
-
→ CONTINUE from currentTask
|
|
90
|
-
|
|
91
|
-
IF exists AND stats.remaining == 0:
|
|
92
|
-
→ SAY: "All tasks complete. Consider /clavix:archive"
|
|
93
|
-
|
|
94
|
-
IF not exists:
|
|
95
|
-
→ CREATE config file and start implementation
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Rule 6: File Operations
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
BEFORE writing files:
|
|
102
|
-
→ CHECK: Target directory exists
|
|
103
|
-
→ IF not exists: Create directory first
|
|
104
|
-
|
|
105
|
-
AFTER writing files:
|
|
106
|
-
→ VERIFY: File was created successfully
|
|
107
|
-
→ IF failed: Report error, suggest manual action
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Rule 7: Pattern Application Decision
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
WHEN applying patterns:
|
|
114
|
-
→ ALWAYS show which patterns were applied
|
|
115
|
-
→ LIST each pattern with its effect
|
|
116
|
-
|
|
117
|
-
IF pattern not applicable to intent:
|
|
118
|
-
→ SKIP silently (no output)
|
|
119
|
-
|
|
120
|
-
IF pattern applicable but skipped:
|
|
121
|
-
→ EXPLAIN: "Skipped [pattern] because [reason]"
|
|
122
|
-
|
|
123
|
-
COMPREHENSIVE DEPTH ONLY:
|
|
124
|
-
→ MUST include alternatives (2-3)
|
|
125
|
-
→ MUST include validation checklist
|
|
126
|
-
→ MUST include edge cases
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Rule 8: Mode Transition Decision
|
|
130
|
-
|
|
131
|
-
```
|
|
132
|
-
IF user requests standard depth but quality < 50%:
|
|
133
|
-
→ ACTION: Warn and suggest comprehensive
|
|
134
|
-
→ SAY: "Quality is [X]%. Standard depth may be insufficient."
|
|
135
|
-
→ ALLOW: User can override and proceed
|
|
136
|
-
|
|
137
|
-
IF user requests comprehensive depth but prompt is simple (quality > 85%):
|
|
138
|
-
→ ACTION: Note efficiency
|
|
139
|
-
→ SAY: "Prompt is already high quality. Standard depth would suffice."
|
|
140
|
-
→ CONTINUE: With comprehensive analysis anyway
|
|
141
|
-
|
|
142
|
-
IF strategic keywords detected (3+ architecture/security/scalability):
|
|
143
|
-
→ ACTION: Suggest PRD mode
|
|
144
|
-
→ SAY: "Detected strategic scope. Consider /clavix:prd for comprehensive planning."
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Rule 9: Output Validation Decision
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
BEFORE presenting optimized prompt:
|
|
151
|
-
→ VERIFY: All 6 quality dimensions scored
|
|
152
|
-
→ VERIFY: Intent detected with confidence shown
|
|
153
|
-
→ VERIFY: Patterns applied are listed
|
|
154
|
-
|
|
155
|
-
IF any verification fails:
|
|
156
|
-
→ HALT: Do not present incomplete output
|
|
157
|
-
→ ACTION: Complete missing analysis first
|
|
158
|
-
|
|
159
|
-
AFTER optimization complete:
|
|
160
|
-
→ MUST save prompt to .clavix/outputs/prompts/
|
|
161
|
-
→ SHOW: "✓ Prompt saved: [filename]"
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Rule 10: Error Recovery Decision
|
|
165
|
-
|
|
166
|
-
```
|
|
167
|
-
IF pattern application fails:
|
|
168
|
-
→ LOG: Which pattern failed
|
|
169
|
-
→ CONTINUE: With remaining patterns
|
|
170
|
-
→ REPORT: "Pattern [X] skipped due to error"
|
|
171
|
-
|
|
172
|
-
IF file write fails:
|
|
173
|
-
→ RETRY: Once with alternative path
|
|
174
|
-
→ IF still fails: Report error with manual steps
|
|
175
|
-
|
|
176
|
-
IF CLI command fails:
|
|
177
|
-
→ SHOW: Command output and error
|
|
178
|
-
→ SUGGEST: Alternative action
|
|
179
|
-
→ NEVER: Silently ignore failures
|
|
180
|
-
|
|
181
|
-
IF user prompt is empty/invalid:
|
|
182
|
-
→ ASK: For valid input
|
|
183
|
-
→ NEVER: Proceed with assumption
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Rule 11: Execution Verification (v4.6)
|
|
187
|
-
|
|
188
|
-
```
|
|
189
|
-
BEFORE completing response:
|
|
190
|
-
→ INCLUDE verification block at end
|
|
191
|
-
→ VERIFY all checkpoints met for current mode
|
|
192
|
-
|
|
193
|
-
IF any checkpoint failed:
|
|
194
|
-
→ REPORT which checkpoint failed
|
|
195
|
-
→ EXPLAIN why it failed
|
|
196
|
-
→ SUGGEST recovery action
|
|
197
|
-
|
|
198
|
-
IF all checkpoints passed:
|
|
199
|
-
→ SHOW verification block with all items checked
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
**Verification Block Template:**
|
|
203
|
-
```
|
|
204
|
-
## Clavix Execution Verification
|
|
205
|
-
- [x] Intent detected: {type} ({confidence}%)
|
|
206
|
-
- [x] Quality assessed: {overall}%
|
|
207
|
-
- [x] {N} patterns applied
|
|
208
|
-
- [x] Prompt saved: {filename}
|
|
209
|
-
- [x] Mode: {fast|deep|prd|plan}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
### Rule Summary Table
|
|
215
|
-
|
|
216
|
-
| Condition | Action | User Communication |
|
|
217
|
-
|-----------|--------|-------------------|
|
|
218
|
-
| quality < 60% + critical dim < 50% | Recommend deep | "[X]%. Deep mode recommended" |
|
|
219
|
-
| quality 60-79% | Proceed | Show improvements |
|
|
220
|
-
| quality >= 80% | Ready | "[X]%. Ready to execute" |
|
|
221
|
-
| confidence >= 85% | Proceed | Primary intent only |
|
|
222
|
-
| confidence 70-84% | Proceed | Show secondary if >25% |
|
|
223
|
-
| confidence 50-69% | Confirm | Ask user to verify |
|
|
224
|
-
| confidence < 50% | Cannot proceed | Ask for clarification |
|
|
225
|
-
| escalation >= 75 | Strong recommend | Show top 3 factors |
|
|
226
|
-
| escalation 45-74 | Suggest | Show primary factor |
|
|
227
|
-
| escalation < 45 | No action | Silent |
|
|
228
|
-
| fast requested + quality < 50% | Warn | "Quality low, consider deep" |
|
|
229
|
-
| 3+ strategic keywords | Suggest PRD | "Strategic scope detected" |
|
|
230
|
-
| pattern fails | Skip + report | "Pattern [X] skipped" |
|
|
231
|
-
| file write fails | Retry then report | "Error: [details]" |
|
|
232
|
-
| response complete | Include verification | Show checkpoint status |
|