agentxchain 2.59.0 → 2.60.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 +1 -1
- package/bin/agentxchain.js +1 -1
- package/package.json +1 -1
- package/src/commands/config.js +87 -14
- package/src/commands/init.js +2 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ agentxchain status
|
|
|
74
74
|
agentxchain step --role pm
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
If you skipped `--goal` during scaffold, set
|
|
77
|
+
If you skipped `--goal` during scaffold, run `agentxchain config --set project.goal "Build an API change planner for release teams"` before the first governed turn instead of re-running init in place.
|
|
78
78
|
|
|
79
79
|
The default governed dev runtime is `claude --print --dangerously-skip-permissions` with stdin prompt delivery. The non-interactive governed path needs write access, so do not pretend bare `claude --print` is sufficient for unattended implementation turns. If your local coding agent uses a different launch contract, set it during scaffold creation:
|
|
80
80
|
|
package/bin/agentxchain.js
CHANGED
|
@@ -192,7 +192,7 @@ program
|
|
|
192
192
|
.description('View or edit project configuration')
|
|
193
193
|
.option('--add-agent', 'Add a new agent interactively')
|
|
194
194
|
.option('--remove-agent <id>', 'Remove an agent by ID')
|
|
195
|
-
.option('--set <
|
|
195
|
+
.option('--set <path_and_value...>', 'Set a config value (e.g. --set project.goal "Build a governed CLI")')
|
|
196
196
|
.option('-j, --json', 'Output config as JSON')
|
|
197
197
|
.action(configCommand);
|
|
198
198
|
|
package/package.json
CHANGED
package/src/commands/config.js
CHANGED
|
@@ -2,31 +2,43 @@ import { readFileSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
|
-
import {
|
|
5
|
+
import { loadProjectContext, CONFIG_FILE } from '../lib/config.js';
|
|
6
6
|
import { validateConfigSchema } from '../lib/schema.js';
|
|
7
|
+
import { validateV4Config } from '../lib/normalized-config.js';
|
|
7
8
|
|
|
8
9
|
export async function configCommand(opts) {
|
|
9
|
-
const
|
|
10
|
-
if (!
|
|
10
|
+
const context = loadProjectContext();
|
|
11
|
+
if (!context) {
|
|
11
12
|
console.log(chalk.red(' No agentxchain.json found. Run `agentxchain init` first.'));
|
|
12
13
|
process.exit(1);
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
const { root,
|
|
16
|
+
const { root, rawConfig, version } = context;
|
|
17
|
+
const config = rawConfig;
|
|
16
18
|
const configPath = join(root, CONFIG_FILE);
|
|
17
19
|
|
|
20
|
+
if (version === 4 && opts.addAgent) {
|
|
21
|
+
printLegacyOnlyMutationError('--add-agent');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
if (opts.addAgent) {
|
|
19
26
|
await addAgent(config, configPath);
|
|
20
27
|
return;
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
if (version === 4 && opts.removeAgent) {
|
|
31
|
+
printLegacyOnlyMutationError('--remove-agent');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
if (opts.removeAgent) {
|
|
24
36
|
removeAgent(config, configPath, opts.removeAgent);
|
|
25
37
|
return;
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
if (opts.set) {
|
|
29
|
-
setSetting(config, configPath, opts.set);
|
|
41
|
+
setSetting(config, configPath, opts.set, { version, root });
|
|
30
42
|
return;
|
|
31
43
|
}
|
|
32
44
|
|
|
@@ -35,10 +47,15 @@ export async function configCommand(opts) {
|
|
|
35
47
|
return;
|
|
36
48
|
}
|
|
37
49
|
|
|
38
|
-
|
|
50
|
+
if (version === 4) {
|
|
51
|
+
printGovernedConfig(config);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
printLegacyConfig(config);
|
|
39
56
|
}
|
|
40
57
|
|
|
41
|
-
function
|
|
58
|
+
function printLegacyConfig(config) {
|
|
42
59
|
console.log('');
|
|
43
60
|
console.log(chalk.bold(' AgentXchain Config'));
|
|
44
61
|
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
@@ -69,6 +86,32 @@ function printConfig(config) {
|
|
|
69
86
|
console.log('');
|
|
70
87
|
}
|
|
71
88
|
|
|
89
|
+
function printGovernedConfig(config) {
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(chalk.bold(' AgentXchain Governed Config'));
|
|
92
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log(` ${chalk.dim('Project:')} ${config.project?.name || '(unknown)'}`);
|
|
95
|
+
console.log(` ${chalk.dim('Project ID:')} ${config.project?.id || '(unknown)'}`);
|
|
96
|
+
console.log(` ${chalk.dim('Goal:')} ${config.project?.goal || '(not set)'}`);
|
|
97
|
+
console.log(` ${chalk.dim('Template:')} ${config.template || 'generic'}`);
|
|
98
|
+
console.log(` ${chalk.dim('Roles:')} ${Object.keys(config.roles || {}).length}`);
|
|
99
|
+
console.log(` ${chalk.dim('Runtimes:')} ${Object.keys(config.runtimes || {}).length}`);
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log(chalk.dim(' Commands:'));
|
|
102
|
+
console.log(` ${chalk.bold('agentxchain config --set project.goal "Build a ..."')} Set mission context without hand-editing JSON`);
|
|
103
|
+
console.log(` ${chalk.bold('agentxchain config --set roles.qa.runtime manual-qa')} Switch a governed role runtime`);
|
|
104
|
+
console.log(` ${chalk.bold('agentxchain config --json')} Output raw config`);
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function printLegacyOnlyMutationError(flag) {
|
|
109
|
+
console.log(chalk.red(` ${flag} is legacy-only.`));
|
|
110
|
+
console.log(chalk.dim(' Governed repos use roles and runtimes instead of legacy v3 agents.'));
|
|
111
|
+
console.log(chalk.dim(' Use `agentxchain config --set <path> <value>` for governed config changes.'));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
72
115
|
async function addAgent(config, configPath) {
|
|
73
116
|
const answers = await inquirer.prompt([
|
|
74
117
|
{
|
|
@@ -117,16 +160,15 @@ function removeAgent(config, configPath, id) {
|
|
|
117
160
|
console.log('');
|
|
118
161
|
}
|
|
119
162
|
|
|
120
|
-
function setSetting(config, configPath, keyValPair) {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
163
|
+
function setSetting(config, configPath, keyValPair, context) {
|
|
164
|
+
const parsed = parseSetInput(keyValPair);
|
|
165
|
+
if (!parsed) {
|
|
123
166
|
console.log(chalk.red(' Usage: agentxchain config --set <key> <value>'));
|
|
124
|
-
console.log(chalk.dim(' Example: agentxchain config --set
|
|
167
|
+
console.log(chalk.dim(' Example: agentxchain config --set project.goal "Build a governed CLI"'));
|
|
125
168
|
process.exit(1);
|
|
126
169
|
}
|
|
127
170
|
|
|
128
|
-
const key =
|
|
129
|
-
const rawVal = parts.slice(1).join(' ');
|
|
171
|
+
const { key, rawVal } = parsed;
|
|
130
172
|
const segments = key.split('.');
|
|
131
173
|
const forbiddenKeys = new Set(['__proto__', 'prototype', 'constructor']);
|
|
132
174
|
|
|
@@ -152,7 +194,7 @@ function setSetting(config, configPath, keyValPair) {
|
|
|
152
194
|
else if (!isNaN(rawVal) && rawVal !== '') val = Number(rawVal);
|
|
153
195
|
|
|
154
196
|
target[lastKey] = val;
|
|
155
|
-
const validation =
|
|
197
|
+
const validation = validateEditedConfig(config, context);
|
|
156
198
|
if (!validation.ok) {
|
|
157
199
|
target[lastKey] = oldVal;
|
|
158
200
|
if (oldVal === undefined) {
|
|
@@ -168,3 +210,34 @@ function setSetting(config, configPath, keyValPair) {
|
|
|
168
210
|
if (oldVal !== undefined) console.log(chalk.dim(` (was: ${oldVal})`));
|
|
169
211
|
console.log('');
|
|
170
212
|
}
|
|
213
|
+
|
|
214
|
+
function parseSetInput(input) {
|
|
215
|
+
if (Array.isArray(input)) {
|
|
216
|
+
if (input.length >= 2) {
|
|
217
|
+
return { key: input[0], rawVal: input.slice(1).join(' ') };
|
|
218
|
+
}
|
|
219
|
+
if (input.length === 1 && typeof input[0] === 'string') {
|
|
220
|
+
const parts = input[0].trim().split(/\s+/);
|
|
221
|
+
if (parts.length >= 2) {
|
|
222
|
+
return { key: parts[0], rawVal: parts.slice(1).join(' ') };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (typeof input === 'string') {
|
|
229
|
+
const parts = input.trim().split(/\s+/);
|
|
230
|
+
if (parts.length >= 2) {
|
|
231
|
+
return { key: parts[0], rawVal: parts.slice(1).join(' ') };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function validateEditedConfig(config, context) {
|
|
239
|
+
if (context.version === 4) {
|
|
240
|
+
return validateV4Config(config, context.root);
|
|
241
|
+
}
|
|
242
|
+
return validateConfigSchema(config);
|
|
243
|
+
}
|
package/src/commands/init.js
CHANGED
|
@@ -978,7 +978,8 @@ async function initGoverned(opts) {
|
|
|
978
978
|
console.log('');
|
|
979
979
|
if (!config?.project?.goal) {
|
|
980
980
|
console.log(` ${chalk.dim('Tip:')} Add a project goal to guide agent context:`);
|
|
981
|
-
console.log(` ${chalk.bold('agentxchain init --governed --goal "Build a ..."')} ${chalk.dim('#
|
|
981
|
+
console.log(` ${chalk.bold('agentxchain init --governed --goal "Build a ..."')} ${chalk.dim('# preferred during scaffold')}`);
|
|
982
|
+
console.log(` ${chalk.bold('agentxchain config --set project.goal "Build a ..."')} ${chalk.dim('# add it later without hand-editing JSON')}`);
|
|
982
983
|
console.log('');
|
|
983
984
|
}
|
|
984
985
|
console.log(` ${chalk.dim('Guide:')} https://agentxchain.dev/docs/getting-started`);
|