@open-agent-toolkit/cli 0.1.33 → 0.1.34
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/assets/docs/cli-utilities/config-and-local-state.md +20 -0
- package/assets/docs/cli-utilities/configuration.md +17 -6
- package/assets/docs/cli-utilities/index.md +5 -0
- package/assets/docs/cli-utilities/workflow-gates.md +163 -0
- package/assets/docs/contributing/skills.md +25 -0
- package/assets/docs/reference/cli-reference.md +3 -0
- package/assets/docs/reference/file-locations.md +1 -0
- package/assets/docs/reference/oat-directory-structure.md +3 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +23 -1
- package/assets/skills/oat-project-plan/SKILL.md +23 -1
- package/dist/commands/gate/index.d.ts +35 -0
- package/dist/commands/gate/index.d.ts.map +1 -0
- package/dist/commands/gate/index.js +500 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/internal/validate-oat-skills.d.ts +3 -0
- package/dist/commands/internal/validate-oat-skills.d.ts.map +1 -1
- package/dist/commands/internal/validate-oat-skills.js +44 -2
- package/dist/config/oat-config.d.ts +22 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +136 -0
- package/dist/config/resolve.d.ts +3 -1
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +103 -1
- package/dist/validation/skills.d.ts +2 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +39 -0
- package/package.json +2 -2
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { buildCommandContext, } from '../../app/command-context.js';
|
|
4
|
+
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
5
|
+
import { BUILTIN_EXEC_TARGETS, readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
|
|
6
|
+
import { resolveEffectiveConfig, resolveExecTargets, resolveGate, } from '../../config/resolve.js';
|
|
7
|
+
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
const DEFAULT_DEPENDENCIES = {
|
|
10
|
+
buildCommandContext,
|
|
11
|
+
resolveProjectRoot,
|
|
12
|
+
readOatConfig,
|
|
13
|
+
writeOatConfig,
|
|
14
|
+
readOatLocalConfig,
|
|
15
|
+
writeOatLocalConfig,
|
|
16
|
+
readUserConfig,
|
|
17
|
+
writeUserConfig,
|
|
18
|
+
resolveEffectiveConfig,
|
|
19
|
+
runProcess: runChildProcess,
|
|
20
|
+
processEnv: process.env,
|
|
21
|
+
};
|
|
22
|
+
const VALID_ON_FAILURE = ['block', 'prompt', 'warn'];
|
|
23
|
+
const VALID_WRITE_LAYERS = [
|
|
24
|
+
'shared',
|
|
25
|
+
'local',
|
|
26
|
+
'user',
|
|
27
|
+
];
|
|
28
|
+
const VALID_CROSS_PROVIDER_AVOIDS = [
|
|
29
|
+
'same-runtime',
|
|
30
|
+
'none',
|
|
31
|
+
];
|
|
32
|
+
async function runChildProcess(command, args, options) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const child = spawn(command, args, {
|
|
35
|
+
cwd: options.cwd,
|
|
36
|
+
env: options.env,
|
|
37
|
+
stdio: options.stdio,
|
|
38
|
+
});
|
|
39
|
+
child.on('error', reject);
|
|
40
|
+
child.on('close', (code) => {
|
|
41
|
+
resolve({ exitCode: code ?? 1 });
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function isGateWriteLayer(value) {
|
|
46
|
+
return VALID_WRITE_LAYERS.includes(value);
|
|
47
|
+
}
|
|
48
|
+
function writeError(context, error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
if (context.json) {
|
|
51
|
+
context.logger.json({ status: 'error', message });
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
context.logger.error(message);
|
|
55
|
+
}
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
}
|
|
58
|
+
function writeJsonValue(context, payload) {
|
|
59
|
+
if (context.json) {
|
|
60
|
+
context.logger.json(payload);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
context.logger.info(JSON.stringify(payload, null, 2));
|
|
64
|
+
}
|
|
65
|
+
function writeSuccess(context, payload) {
|
|
66
|
+
if (context.json) {
|
|
67
|
+
context.logger.json({ status: 'ok', ...payload });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
context.logger.info(JSON.stringify({ status: 'ok', ...payload }, null, 2));
|
|
71
|
+
}
|
|
72
|
+
function trimRequired(value, label) {
|
|
73
|
+
const trimmed = value.trim();
|
|
74
|
+
if (!trimmed) {
|
|
75
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
76
|
+
}
|
|
77
|
+
return trimmed;
|
|
78
|
+
}
|
|
79
|
+
function parseLayer(value) {
|
|
80
|
+
const layer = value?.trim() || 'user';
|
|
81
|
+
if (!isGateWriteLayer(layer)) {
|
|
82
|
+
throw new Error('--layer must be one of shared | local | user; auto is not supported for gate writes.');
|
|
83
|
+
}
|
|
84
|
+
return layer;
|
|
85
|
+
}
|
|
86
|
+
function parseCrossProviderAvoid(value) {
|
|
87
|
+
const avoid = value?.trim() || 'same-runtime';
|
|
88
|
+
if (!VALID_CROSS_PROVIDER_AVOIDS.includes(avoid)) {
|
|
89
|
+
throw new Error('--avoid must be one of same-runtime | none.');
|
|
90
|
+
}
|
|
91
|
+
return avoid;
|
|
92
|
+
}
|
|
93
|
+
function parseOnFailure(value) {
|
|
94
|
+
if (!value || !VALID_ON_FAILURE.includes(value)) {
|
|
95
|
+
throw new Error('--on-failure must be one of block | prompt | warn.');
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
function parsePositiveInteger(value, flag, defaultValue) {
|
|
100
|
+
if (value === undefined) {
|
|
101
|
+
return defaultValue;
|
|
102
|
+
}
|
|
103
|
+
const parsed = Number(value);
|
|
104
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
105
|
+
throw new Error(`${flag} must be an integer greater than or equal to 1.`);
|
|
106
|
+
}
|
|
107
|
+
return parsed;
|
|
108
|
+
}
|
|
109
|
+
function parseNumericFlag(value, flag, defaultValue) {
|
|
110
|
+
if (value === undefined) {
|
|
111
|
+
return defaultValue;
|
|
112
|
+
}
|
|
113
|
+
const parsed = Number(value);
|
|
114
|
+
if (!Number.isFinite(parsed)) {
|
|
115
|
+
throw new Error(`${flag} must be a finite number.`);
|
|
116
|
+
}
|
|
117
|
+
return parsed;
|
|
118
|
+
}
|
|
119
|
+
function parseArgvJson(value, flag) {
|
|
120
|
+
let parsed;
|
|
121
|
+
try {
|
|
122
|
+
parsed = JSON.parse(value);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
const detail = error instanceof Error ? `: ${error.message}` : '';
|
|
126
|
+
throw new Error(`${flag} must be valid JSON${detail}`, { cause: error });
|
|
127
|
+
}
|
|
128
|
+
if (!Array.isArray(parsed) ||
|
|
129
|
+
parsed.length === 0 ||
|
|
130
|
+
!parsed.every((item) => typeof item === 'string') ||
|
|
131
|
+
!parsed[0]?.trim()) {
|
|
132
|
+
throw new Error(`${flag} must be a non-empty JSON array of strings whose first item is not empty.`);
|
|
133
|
+
}
|
|
134
|
+
return [...parsed];
|
|
135
|
+
}
|
|
136
|
+
function parseOptionalArgvJson(value, flag) {
|
|
137
|
+
return value === undefined ? undefined : parseArgvJson(value, flag);
|
|
138
|
+
}
|
|
139
|
+
function parseGateConfig(options) {
|
|
140
|
+
if (options.disable) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
command: trimRequired(options.command ?? '', '--command'),
|
|
145
|
+
onFailure: parseOnFailure(options.onFailure),
|
|
146
|
+
maxAttempts: parsePositiveInteger(options.maxAttempts, '--max-attempts', 2),
|
|
147
|
+
...(options.description?.trim()
|
|
148
|
+
? { description: options.description.trim() }
|
|
149
|
+
: {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function parseExecTargetConfig(options) {
|
|
153
|
+
if (options.disable) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const baseCommandJson = options.baseCommandJson;
|
|
157
|
+
if (baseCommandJson === undefined) {
|
|
158
|
+
throw new Error('--base-command-json is required unless --disable is set.');
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
runtime: trimRequired(options.runtime ?? '', '--runtime'),
|
|
162
|
+
baseCommand: parseArgvJson(baseCommandJson, '--base-command-json'),
|
|
163
|
+
priority: parseNumericFlag(options.priority, '--priority', 0),
|
|
164
|
+
...(options.hostDetectionJson !== undefined
|
|
165
|
+
? {
|
|
166
|
+
hostDetectionCommand: parseOptionalArgvJson(options.hostDetectionJson, '--host-detection-json'),
|
|
167
|
+
}
|
|
168
|
+
: {}),
|
|
169
|
+
...(options.availabilityJson !== undefined
|
|
170
|
+
? {
|
|
171
|
+
availabilityCommand: parseOptionalArgvJson(options.availabilityJson, '--availability-json'),
|
|
172
|
+
}
|
|
173
|
+
: {}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function updateWorkflowGates(config, update) {
|
|
177
|
+
return {
|
|
178
|
+
...config,
|
|
179
|
+
workflow: {
|
|
180
|
+
...config.workflow,
|
|
181
|
+
gates: update(config.workflow?.gates ?? {}),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function setSkillGate(config, skillName, gate) {
|
|
186
|
+
return updateWorkflowGates(config, (gates) => ({
|
|
187
|
+
...gates,
|
|
188
|
+
skills: {
|
|
189
|
+
...gates.skills,
|
|
190
|
+
[skillName]: gate,
|
|
191
|
+
},
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
function unsetSkillGate(config, skillName) {
|
|
195
|
+
return updateWorkflowGates(config, (gates) => {
|
|
196
|
+
const skills = { ...gates.skills };
|
|
197
|
+
delete skills[skillName];
|
|
198
|
+
return {
|
|
199
|
+
...gates,
|
|
200
|
+
skills,
|
|
201
|
+
};
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function setExecTarget(config, targetId, target) {
|
|
205
|
+
return updateWorkflowGates(config, (gates) => ({
|
|
206
|
+
...gates,
|
|
207
|
+
execTargets: {
|
|
208
|
+
...gates.execTargets,
|
|
209
|
+
[targetId]: target,
|
|
210
|
+
},
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
function unsetExecTarget(config, targetId) {
|
|
214
|
+
return updateWorkflowGates(config, (gates) => {
|
|
215
|
+
const execTargets = { ...gates.execTargets };
|
|
216
|
+
delete execTargets[targetId];
|
|
217
|
+
return {
|
|
218
|
+
...gates,
|
|
219
|
+
execTargets,
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
async function readEffectiveConfig(context, dependencies) {
|
|
224
|
+
const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
225
|
+
const userConfigDir = join(context.home, '.oat');
|
|
226
|
+
return dependencies.resolveEffectiveConfig(repoRoot, userConfigDir, dependencies.processEnv);
|
|
227
|
+
}
|
|
228
|
+
function sortedExecTargetEntries(registry) {
|
|
229
|
+
return Object.entries(registry)
|
|
230
|
+
.map(([id, target]) => ({ id, target }))
|
|
231
|
+
.sort((left, right) => {
|
|
232
|
+
const priority = right.target.priority - left.target.priority;
|
|
233
|
+
return priority === 0 ? left.id.localeCompare(right.id) : priority;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function cloneExecTarget(target) {
|
|
237
|
+
return {
|
|
238
|
+
runtime: target.runtime,
|
|
239
|
+
baseCommand: [...target.baseCommand],
|
|
240
|
+
priority: target.priority,
|
|
241
|
+
...(target.hostDetectionCommand
|
|
242
|
+
? { hostDetectionCommand: [...target.hostDetectionCommand] }
|
|
243
|
+
: {}),
|
|
244
|
+
...(target.availabilityCommand
|
|
245
|
+
? { availabilityCommand: [...target.availabilityCommand] }
|
|
246
|
+
: {}),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function argvHead(argv) {
|
|
250
|
+
return [argv[0] ?? '', argv.slice(1)];
|
|
251
|
+
}
|
|
252
|
+
function listExecTargetCandidates(registry, currentRuntime, avoid) {
|
|
253
|
+
const shouldAvoidSameRuntime = avoid === 'same-runtime' && currentRuntime !== 'unknown';
|
|
254
|
+
return sortedExecTargetEntries(registry)
|
|
255
|
+
.filter(({ target }) => !shouldAvoidSameRuntime || target.runtime !== currentRuntime)
|
|
256
|
+
.map(({ id, target }) => ({ id, target: cloneExecTarget(target) }));
|
|
257
|
+
}
|
|
258
|
+
export function selectExecTarget(registry, currentRuntime, avoid) {
|
|
259
|
+
return listExecTargetCandidates(registry, currentRuntime, avoid)[0] ?? null;
|
|
260
|
+
}
|
|
261
|
+
async function checkArgv(argv, purpose, context, dependencies) {
|
|
262
|
+
const [command, args] = argvHead(argv);
|
|
263
|
+
if (!command) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
const result = await dependencies.runProcess(command, args, {
|
|
268
|
+
cwd: context.cwd,
|
|
269
|
+
env: dependencies.processEnv,
|
|
270
|
+
purpose,
|
|
271
|
+
stdio: 'ignore',
|
|
272
|
+
});
|
|
273
|
+
return result.exitCode === 0;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function resolveCurrentRuntime(currentRuntime, context, dependencies) {
|
|
280
|
+
const override = currentRuntime?.trim();
|
|
281
|
+
if (override) {
|
|
282
|
+
return override;
|
|
283
|
+
}
|
|
284
|
+
for (const { target } of sortedExecTargetEntries(BUILTIN_EXEC_TARGETS)) {
|
|
285
|
+
if (target.hostDetectionCommand &&
|
|
286
|
+
(await checkArgv(target.hostDetectionCommand, 'host-detection', context, dependencies))) {
|
|
287
|
+
return target.runtime;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return 'unknown';
|
|
291
|
+
}
|
|
292
|
+
async function selectAvailableExecTarget(registry, currentRuntime, avoid, context, dependencies) {
|
|
293
|
+
for (const candidate of listExecTargetCandidates(registry, currentRuntime, avoid)) {
|
|
294
|
+
const availabilityCommand = candidate.target.availabilityCommand;
|
|
295
|
+
if (!availabilityCommand ||
|
|
296
|
+
(await checkArgv(availabilityCommand, 'availability', context, dependencies))) {
|
|
297
|
+
return candidate;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
async function executeTarget(selected, prompt, context, dependencies) {
|
|
303
|
+
const [command, baseArgs] = argvHead(selected.target.baseCommand);
|
|
304
|
+
if (!command) {
|
|
305
|
+
throw new Error(`Exec target "${selected.id}" has an empty base command.`);
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const result = await dependencies.runProcess(command, [...baseArgs, ...prompt], {
|
|
309
|
+
cwd: context.cwd,
|
|
310
|
+
env: dependencies.processEnv,
|
|
311
|
+
purpose: 'execute',
|
|
312
|
+
stdio: 'inherit',
|
|
313
|
+
});
|
|
314
|
+
return result.exitCode;
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
318
|
+
throw new Error(`Failed to launch exec target "${selected.id}" (${command}): ${message}`, { cause: error });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function noEligibleTargetMessage(currentRuntime, avoid) {
|
|
322
|
+
return `No eligible gate exec target found for current runtime "${currentRuntime}" with --avoid ${avoid}. Install or configure an alternate runtime, rerun with --avoid none, or pin a target with --target <id>.`;
|
|
323
|
+
}
|
|
324
|
+
async function updateConfigLayer(context, layer, dependencies, mutate) {
|
|
325
|
+
const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
326
|
+
const userConfigDir = join(context.home, '.oat');
|
|
327
|
+
if (layer === 'shared') {
|
|
328
|
+
const config = await dependencies.readOatConfig(repoRoot);
|
|
329
|
+
await dependencies.writeOatConfig(repoRoot, mutate(config));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (layer === 'local') {
|
|
333
|
+
const config = await dependencies.readOatLocalConfig(repoRoot);
|
|
334
|
+
await dependencies.writeOatLocalConfig(repoRoot, mutate(config));
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const config = await dependencies.readUserConfig(userConfigDir);
|
|
338
|
+
await dependencies.writeUserConfig(userConfigDir, mutate(config));
|
|
339
|
+
}
|
|
340
|
+
async function runResolve(skillName, context, dependencies) {
|
|
341
|
+
try {
|
|
342
|
+
const effective = await readEffectiveConfig(context, dependencies);
|
|
343
|
+
writeJsonValue(context, resolveGate(effective, skillName));
|
|
344
|
+
process.exitCode = 0;
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
writeError(context, error);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async function runGateSet(skillName, options, context, dependencies) {
|
|
351
|
+
try {
|
|
352
|
+
const layer = parseLayer(options.layer);
|
|
353
|
+
const normalizedSkill = trimRequired(skillName, '<skill>');
|
|
354
|
+
const gate = parseGateConfig(options);
|
|
355
|
+
await updateConfigLayer(context, layer, dependencies, (config) => setSkillGate(config, normalizedSkill, gate));
|
|
356
|
+
writeSuccess(context, { layer, skill: normalizedSkill, gate });
|
|
357
|
+
process.exitCode = 0;
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
writeError(context, error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async function runGateUnset(skillName, options, context, dependencies) {
|
|
364
|
+
try {
|
|
365
|
+
const layer = parseLayer(options.layer);
|
|
366
|
+
const normalizedSkill = trimRequired(skillName, '<skill>');
|
|
367
|
+
await updateConfigLayer(context, layer, dependencies, (config) => unsetSkillGate(config, normalizedSkill));
|
|
368
|
+
writeSuccess(context, { layer, skill: normalizedSkill });
|
|
369
|
+
process.exitCode = 0;
|
|
370
|
+
}
|
|
371
|
+
catch (error) {
|
|
372
|
+
writeError(context, error);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async function runTargetSet(targetId, options, context, dependencies) {
|
|
376
|
+
try {
|
|
377
|
+
const layer = parseLayer(options.layer);
|
|
378
|
+
const normalizedTargetId = trimRequired(targetId, '<id>');
|
|
379
|
+
const target = parseExecTargetConfig(options);
|
|
380
|
+
await updateConfigLayer(context, layer, dependencies, (config) => setExecTarget(config, normalizedTargetId, target));
|
|
381
|
+
writeSuccess(context, { layer, target: normalizedTargetId, value: target });
|
|
382
|
+
process.exitCode = 0;
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
writeError(context, error);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
async function runTargetUnset(targetId, options, context, dependencies) {
|
|
389
|
+
try {
|
|
390
|
+
const layer = parseLayer(options.layer);
|
|
391
|
+
const normalizedTargetId = trimRequired(targetId, '<id>');
|
|
392
|
+
await updateConfigLayer(context, layer, dependencies, (config) => unsetExecTarget(config, normalizedTargetId));
|
|
393
|
+
writeSuccess(context, { layer, target: normalizedTargetId });
|
|
394
|
+
process.exitCode = 0;
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
writeError(context, error);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
async function runCrossProviderExec(prompt, options, context, dependencies) {
|
|
401
|
+
try {
|
|
402
|
+
const effective = await readEffectiveConfig(context, dependencies);
|
|
403
|
+
const targets = resolveExecTargets(effective);
|
|
404
|
+
const explicitTarget = options.target?.trim();
|
|
405
|
+
if (explicitTarget) {
|
|
406
|
+
const target = targets[explicitTarget];
|
|
407
|
+
if (!target) {
|
|
408
|
+
throw new Error(`Unknown exec target "${explicitTarget}".`);
|
|
409
|
+
}
|
|
410
|
+
process.exitCode = await executeTarget({ id: explicitTarget, target: cloneExecTarget(target) }, prompt, context, dependencies);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const avoid = parseCrossProviderAvoid(options.avoid);
|
|
414
|
+
const currentRuntime = await resolveCurrentRuntime(options.currentRuntime, context, dependencies);
|
|
415
|
+
const selected = await selectAvailableExecTarget(targets, currentRuntime, avoid, context, dependencies);
|
|
416
|
+
if (!selected) {
|
|
417
|
+
throw new Error(noEligibleTargetMessage(currentRuntime, avoid));
|
|
418
|
+
}
|
|
419
|
+
process.exitCode = await executeTarget(selected, prompt, context, dependencies);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
writeError(context, error);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
export function createGateCommand(overrides = {}) {
|
|
426
|
+
const dependencies = {
|
|
427
|
+
...DEFAULT_DEPENDENCIES,
|
|
428
|
+
...overrides,
|
|
429
|
+
};
|
|
430
|
+
const cmd = new Command('gate').description('Resolve and manage workflow gate configuration');
|
|
431
|
+
cmd
|
|
432
|
+
.command('resolve')
|
|
433
|
+
.description('Print the resolved gate configuration for a skill')
|
|
434
|
+
.argument('<skill>', 'Gate-aware skill name')
|
|
435
|
+
.action(async (skillName, _options, command) => {
|
|
436
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
437
|
+
await runResolve(skillName, context, dependencies);
|
|
438
|
+
});
|
|
439
|
+
cmd
|
|
440
|
+
.command('set')
|
|
441
|
+
.description('Set a skill gate in a concrete config layer')
|
|
442
|
+
.argument('<skill>', 'Gate-aware skill name')
|
|
443
|
+
.option('--command <command>', 'Gate command to run')
|
|
444
|
+
.option('--description <description>', 'Gate purpose and follow-up notes')
|
|
445
|
+
.option('--on-failure <mode>', 'Failure behavior: block, prompt, or warn')
|
|
446
|
+
.option('--max-attempts <count>', 'Maximum block remediation attempts')
|
|
447
|
+
.option('--disable', 'Disable this skill gate in the selected layer')
|
|
448
|
+
.option('--layer <layer>', 'Config layer to write: shared, local, or user')
|
|
449
|
+
.action(async (skillName, options, command) => {
|
|
450
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
451
|
+
await runGateSet(skillName, options, context, dependencies);
|
|
452
|
+
});
|
|
453
|
+
cmd
|
|
454
|
+
.command('unset')
|
|
455
|
+
.description('Remove a skill gate entry from a concrete config layer')
|
|
456
|
+
.argument('<skill>', 'Gate-aware skill name')
|
|
457
|
+
.option('--layer <layer>', 'Config layer to write: shared, local, or user')
|
|
458
|
+
.action(async (skillName, options, command) => {
|
|
459
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
460
|
+
await runGateUnset(skillName, options, context, dependencies);
|
|
461
|
+
});
|
|
462
|
+
cmd
|
|
463
|
+
.command('cross-provider-exec')
|
|
464
|
+
.description('Run a prompt through an alternate configured runtime target')
|
|
465
|
+
.option('--target <id>', 'Run this exact exec target')
|
|
466
|
+
.option('--avoid <mode>', 'Avoidance mode: same-runtime or none')
|
|
467
|
+
.option('--current-runtime <runtime>', 'Override detected runtime for testing or manual routing')
|
|
468
|
+
.argument('<prompt...>', 'Prompt arguments appended to the target command')
|
|
469
|
+
.action(async (prompt, options, command) => {
|
|
470
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
471
|
+
await runCrossProviderExec(prompt, options, context, dependencies);
|
|
472
|
+
});
|
|
473
|
+
const target = new Command('target').description('Manage gate execution targets');
|
|
474
|
+
target
|
|
475
|
+
.command('set')
|
|
476
|
+
.description('Set an exec target in a concrete config layer')
|
|
477
|
+
.argument('<id>', 'Exec target id')
|
|
478
|
+
.option('--runtime <runtime>', 'Logical runtime family')
|
|
479
|
+
.option('--base-command-json <json>', 'JSON argv array for the base command')
|
|
480
|
+
.option('--host-detection-json <json>', 'JSON argv array for host detection')
|
|
481
|
+
.option('--availability-json <json>', 'JSON argv array for availability')
|
|
482
|
+
.option('--priority <number>', 'Target priority, higher wins')
|
|
483
|
+
.option('--disable', 'Disable this exec target in the selected layer')
|
|
484
|
+
.option('--layer <layer>', 'Config layer to write: shared, local, or user')
|
|
485
|
+
.action(async (targetId, options, command) => {
|
|
486
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
487
|
+
await runTargetSet(targetId, options, context, dependencies);
|
|
488
|
+
});
|
|
489
|
+
target
|
|
490
|
+
.command('unset')
|
|
491
|
+
.description('Remove an exec target entry from a concrete config layer')
|
|
492
|
+
.argument('<id>', 'Exec target id')
|
|
493
|
+
.option('--layer <layer>', 'Config layer to write: shared, local, or user')
|
|
494
|
+
.action(async (targetId, options, command) => {
|
|
495
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
496
|
+
await runTargetUnset(targetId, options, context, dependencies);
|
|
497
|
+
});
|
|
498
|
+
cmd.addCommand(target);
|
|
499
|
+
return cmd;
|
|
500
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuBvD"}
|
package/dist/commands/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createConfigCommand } from './config/index.js';
|
|
|
4
4
|
import { createDecisionCommand } from './decision/index.js';
|
|
5
5
|
import { createDocsCommand } from './docs/index.js';
|
|
6
6
|
import { createDoctorCommand } from './doctor/index.js';
|
|
7
|
+
import { createGateCommand } from './gate/index.js';
|
|
7
8
|
import { createIndexCommand } from './index-cmd/index.js';
|
|
8
9
|
import { createInitCommand } from './init/index.js';
|
|
9
10
|
import { createInstructionsCommand } from './instructions/index.js';
|
|
@@ -26,6 +27,7 @@ export function registerCommands(program) {
|
|
|
26
27
|
program.addCommand(createStatusCommand());
|
|
27
28
|
program.addCommand(createSyncCommand());
|
|
28
29
|
program.addCommand(createConfigCommand());
|
|
30
|
+
program.addCommand(createGateCommand());
|
|
29
31
|
program.addCommand(createLocalCommand());
|
|
30
32
|
program.addCommand(createProvidersCommand());
|
|
31
33
|
program.addCommand(createRemoveCommand());
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
|
+
import { type ResolvedConfig } from '../../config/resolve.js';
|
|
2
3
|
import { type ValidateOatSkillsOptions, type ValidateOatSkillsResult } from '../../validation/index.js';
|
|
3
4
|
import { Command } from 'commander';
|
|
4
5
|
interface ValidateOatSkillsDependencies {
|
|
5
6
|
buildCommandContext: (options: GlobalOptions) => CommandContext;
|
|
6
7
|
validateOatSkills: (repoRoot: string, options?: ValidateOatSkillsOptions) => Promise<ValidateOatSkillsResult>;
|
|
8
|
+
resolveEffectiveConfig: (repoRoot: string, userConfigDir: string, env?: NodeJS.ProcessEnv) => Promise<ResolvedConfig>;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
7
10
|
}
|
|
8
11
|
export declare function createValidateOatSkillsCommand(overrides?: Partial<ValidateOatSkillsDependencies>): Command;
|
|
9
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-oat-skills.d.ts","sourceRoot":"","sources":["../../../src/commands/internal/validate-oat-skills.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate-oat-skills.d.ts","sourceRoot":"","sources":["../../../src/commands/internal/validate-oat-skills.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAE7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,UAAU,6BAA6B;IACrC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,iBAAiB,EAAE,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,wBAAwB,KAC/B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACtC,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,KACpB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AA+HD,wBAAgB,8BAA8B,CAC5C,SAAS,GAAE,OAAO,CAAC,6BAA6B,CAAM,GACrD,OAAO,CAkBT"}
|
|
@@ -1,11 +1,30 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
1
2
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
2
3
|
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
4
|
+
import { resolveEffectiveConfig as defaultResolveEffectiveConfig, } from '../../config/resolve.js';
|
|
3
5
|
import { validateOatSkills as defaultValidateOatSkills, } from '../../validation/index.js';
|
|
4
6
|
import { Command } from 'commander';
|
|
5
7
|
const DEFAULT_DEPENDENCIES = {
|
|
6
8
|
buildCommandContext,
|
|
7
9
|
validateOatSkills: defaultValidateOatSkills,
|
|
10
|
+
resolveEffectiveConfig: defaultResolveEffectiveConfig,
|
|
8
11
|
};
|
|
12
|
+
function collectConfiguredGateSkillNames(effective) {
|
|
13
|
+
const names = new Set();
|
|
14
|
+
for (const layer of [effective.shared, effective.local, effective.user]) {
|
|
15
|
+
const skills = layer.workflow?.gates?.skills;
|
|
16
|
+
if (!skills) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
for (const skillName of Object.keys(skills)) {
|
|
20
|
+
names.add(skillName);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [...names].sort();
|
|
24
|
+
}
|
|
25
|
+
function isBlockingFinding(finding) {
|
|
26
|
+
return finding.severity !== 'warning';
|
|
27
|
+
}
|
|
9
28
|
function reportFindings(context, result) {
|
|
10
29
|
if (context.json) {
|
|
11
30
|
context.logger.json({
|
|
@@ -21,14 +40,37 @@ function reportFindings(context, result) {
|
|
|
21
40
|
}
|
|
22
41
|
context.logger.error('\nFix the issues above, then re-run: pnpm oat:validate-skills');
|
|
23
42
|
}
|
|
43
|
+
function reportWarnings(context, result) {
|
|
44
|
+
if (context.json) {
|
|
45
|
+
context.logger.json({
|
|
46
|
+
status: 'ok',
|
|
47
|
+
validatedSkillCount: result.validatedSkillCount,
|
|
48
|
+
findings: result.findings,
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
context.logger.warn('OAT skill validation warnings:\n');
|
|
53
|
+
for (const finding of result.findings) {
|
|
54
|
+
context.logger.warn(`- ${finding.file}: ${finding.message}`);
|
|
55
|
+
}
|
|
56
|
+
context.logger.info(`OK: validated ${result.validatedSkillCount} oat-* skills`);
|
|
57
|
+
}
|
|
24
58
|
async function runValidateOatSkills(context, options, dependencies) {
|
|
25
59
|
try {
|
|
26
|
-
const
|
|
27
|
-
|
|
60
|
+
const effectiveConfig = await dependencies.resolveEffectiveConfig(context.cwd, join(context.home, '.oat'), dependencies.env ?? process.env);
|
|
61
|
+
const gateSkillNames = collectConfiguredGateSkillNames(effectiveConfig);
|
|
62
|
+
const validationOptions = gateSkillNames.length > 0 ? { ...options, gateSkillNames } : options;
|
|
63
|
+
const result = await dependencies.validateOatSkills(context.cwd, validationOptions);
|
|
64
|
+
if (result.findings.some(isBlockingFinding)) {
|
|
28
65
|
reportFindings(context, result);
|
|
29
66
|
process.exitCode = 1;
|
|
30
67
|
return;
|
|
31
68
|
}
|
|
69
|
+
if (result.findings.length > 0) {
|
|
70
|
+
reportWarnings(context, result);
|
|
71
|
+
process.exitCode = 0;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
32
74
|
if (context.json) {
|
|
33
75
|
context.logger.json({
|
|
34
76
|
status: 'ok',
|
|
@@ -23,6 +23,8 @@ export type WorkflowDesignMode = 'collaborative' | 'selective' | 'draft';
|
|
|
23
23
|
export type WorkflowCodexDispatchCeiling = 'low' | 'medium' | 'high' | 'xhigh';
|
|
24
24
|
export type WorkflowClaudeDispatchCeiling = 'haiku' | 'sonnet' | 'opus';
|
|
25
25
|
export type WorkflowDispatchCeilingPreset = 'balanced' | 'maximum' | 'cost-conscious';
|
|
26
|
+
export type GateOnFailure = 'block' | 'prompt' | 'warn';
|
|
27
|
+
export type GateAvoid = 'same-runtime' | 'none';
|
|
26
28
|
export interface WorkflowDispatchCeiling {
|
|
27
29
|
preset?: WorkflowDispatchCeilingPreset;
|
|
28
30
|
providers?: {
|
|
@@ -34,6 +36,24 @@ export interface WorkflowAutoArtifactReview {
|
|
|
34
36
|
plan?: boolean;
|
|
35
37
|
analysis?: boolean;
|
|
36
38
|
}
|
|
39
|
+
export interface GateConfig {
|
|
40
|
+
command: string;
|
|
41
|
+
onFailure: GateOnFailure;
|
|
42
|
+
description?: string;
|
|
43
|
+
maxAttempts?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface ExecTarget {
|
|
46
|
+
runtime: string;
|
|
47
|
+
baseCommand: string[];
|
|
48
|
+
hostDetectionCommand?: string[];
|
|
49
|
+
availabilityCommand?: string[];
|
|
50
|
+
priority: number;
|
|
51
|
+
}
|
|
52
|
+
export type ExecTargetConfig = Partial<ExecTarget>;
|
|
53
|
+
export interface WorkflowGatesConfig {
|
|
54
|
+
execTargets?: Record<string, ExecTargetConfig | null>;
|
|
55
|
+
skills?: Record<string, GateConfig | null>;
|
|
56
|
+
}
|
|
37
57
|
export interface OatWorkflowConfig {
|
|
38
58
|
hillCheckpointDefault?: WorkflowHillCheckpointDefault;
|
|
39
59
|
archiveOnComplete?: boolean;
|
|
@@ -45,10 +65,12 @@ export interface OatWorkflowConfig {
|
|
|
45
65
|
autoArtifactReview?: WorkflowAutoArtifactReview;
|
|
46
66
|
designMode?: WorkflowDesignMode;
|
|
47
67
|
dispatchCeiling?: WorkflowDispatchCeiling;
|
|
68
|
+
gates?: WorkflowGatesConfig;
|
|
48
69
|
}
|
|
49
70
|
export declare const VALID_CODEX_DISPATCH_CEILINGS: readonly WorkflowCodexDispatchCeiling[];
|
|
50
71
|
export declare const VALID_CLAUDE_DISPATCH_CEILINGS: readonly WorkflowClaudeDispatchCeiling[];
|
|
51
72
|
export declare const VALID_DISPATCH_CEILING_PRESETS: readonly WorkflowDispatchCeilingPreset[];
|
|
73
|
+
export declare const BUILTIN_EXEC_TARGETS: Readonly<Record<string, ExecTarget>>;
|
|
52
74
|
export type OatToolsConfig = Partial<Record<'core' | 'ideas' | 'docs' | 'workflows' | 'utility' | 'project-management' | 'research' | 'brainstorm', boolean>>;
|
|
53
75
|
export interface OatConfig {
|
|
54
76
|
version: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,6BAA6B,GACrC,MAAM,GACN,SAAS,GACT,IAAI,GACJ,SAAS,CAAC;AACd,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,QAAQ,GACR,eAAe,CAAC;AACpB,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,WAAW,GAAG,OAAO,CAAC;AACzE,MAAM,MAAM,4BAA4B,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC/E,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,6BAA6B,GACrC,UAAU,GACV,SAAS,GACT,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
|