@open-agent-toolkit/cli 0.1.45 → 0.1.46
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/agents/oat-reviewer.md +2 -2
- package/assets/docs/cli-utilities/config-and-local-state.md +7 -0
- package/assets/docs/cli-utilities/configuration.md +51 -11
- package/assets/docs/provider-sync/config.md +5 -1
- package/assets/docs/provider-sync/manifest-and-drift.md +6 -1
- package/assets/docs/provider-sync/providers.md +6 -3
- package/assets/docs/provider-sync/scope-and-surface.md +2 -1
- package/assets/docs/reference/oat-directory-structure.md +2 -2
- package/assets/docs/workflows/projects/dispatch-ceiling.md +41 -28
- package/assets/docs/workflows/projects/implementation-execution.md +20 -13
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +114 -59
- package/assets/skills/oat-project-quick-start/SKILL.md +32 -20
- package/dist/commands/config/index.d.ts +2 -2
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +71 -20
- package/dist/commands/doctor/index.d.ts +2 -2
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +83 -27
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +137 -10
- package/dist/commands/providers/codex/index.d.ts +4 -0
- package/dist/commands/providers/codex/index.d.ts.map +1 -0
- package/dist/commands/providers/codex/index.js +7 -0
- package/dist/commands/providers/codex/materialize.d.ts +5 -0
- package/dist/commands/providers/codex/materialize.d.ts.map +1 -0
- package/dist/commands/providers/codex/materialize.js +152 -0
- package/dist/commands/providers/index.d.ts +2 -2
- package/dist/commands/providers/index.d.ts.map +1 -1
- package/dist/commands/providers/index.js +4 -2
- package/dist/commands/providers/providers.types.d.ts +23 -0
- package/dist/commands/providers/providers.types.d.ts.map +1 -1
- package/dist/commands/shared/codex-strays.d.ts.map +1 -1
- package/dist/commands/shared/codex-strays.js +11 -1
- package/dist/commands/status/index.d.ts +4 -1
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +1 -1
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +1 -1
- package/dist/commands/sync/sync.types.d.ts +4 -1
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/config/dispatch-ceiling-preset.d.ts +4 -0
- package/dist/config/dispatch-ceiling-preset.d.ts.map +1 -1
- package/dist/config/dispatch-ceiling-preset.js +3 -0
- package/dist/config/dispatch-policy-options.d.ts +20 -0
- package/dist/config/dispatch-policy-options.d.ts.map +1 -0
- package/dist/config/dispatch-policy-options.js +96 -0
- package/dist/config/oat-config.d.ts +6 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +15 -0
- package/dist/providers/ceiling/registry.d.ts +7 -5
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +16 -5
- package/dist/providers/codex/codec/config-merge.d.ts +6 -0
- package/dist/providers/codex/codec/config-merge.d.ts.map +1 -1
- package/dist/providers/codex/codec/config-merge.js +7 -0
- package/dist/providers/codex/codec/materialize.d.ts +16 -0
- package/dist/providers/codex/codec/materialize.d.ts.map +1 -0
- package/dist/providers/codex/codec/materialize.js +57 -0
- package/dist/providers/codex/codec/shared.d.ts +1 -0
- package/dist/providers/codex/codec/shared.d.ts.map +1 -1
- package/dist/providers/codex/codec/shared.js +9 -1
- package/dist/providers/codex/codec/sync-extension.d.ts +7 -1
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +183 -46
- package/dist/providers/identity/availability.d.ts +24 -1
- package/dist/providers/identity/availability.d.ts.map +1 -1
- package/dist/providers/identity/availability.js +253 -19
- package/package.json +2 -2
|
@@ -5,11 +5,12 @@ import { resolveProjectsRoot } from '../shared/oat-paths.js';
|
|
|
5
5
|
import { confirmAction, } from '../shared/shared.prompts.js';
|
|
6
6
|
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
7
7
|
import { compileDispatchCeilingPreset } from '../../config/dispatch-ceiling-preset.js';
|
|
8
|
-
import {
|
|
8
|
+
import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
|
|
9
|
+
import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, isCodexMaterializedRouteTarget, readOatConfig, readOatLocalConfig, readUserConfig, validateDispatchRouteTarget, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
|
|
9
10
|
import { resolveEffectiveConfig, } from '../../config/resolve.js';
|
|
10
11
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
11
12
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
12
|
-
import { validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
13
|
+
import { normalizeMatrixCellAvailability, validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
13
14
|
import { Command } from 'commander';
|
|
14
15
|
import { createConfigDumpCommand } from './dump.js';
|
|
15
16
|
const DISPATCH_CEILING_PROVIDER_KEY_PREFIX = 'workflow.dispatchCeiling.providers.';
|
|
@@ -478,7 +479,7 @@ const CONFIG_CATALOG = [
|
|
|
478
479
|
defaultValue: 'unset',
|
|
479
480
|
mutability: 'read/write',
|
|
480
481
|
owningCommand: 'oat config set workflow.dispatchPolicy.mode <value>',
|
|
481
|
-
description:
|
|
482
|
+
description: dispatchPolicyModeDescription(),
|
|
482
483
|
},
|
|
483
484
|
{
|
|
484
485
|
key: 'workflow.dispatchPolicy.policy',
|
|
@@ -489,7 +490,7 @@ const CONFIG_CATALOG = [
|
|
|
489
490
|
defaultValue: 'unset',
|
|
490
491
|
mutability: 'read/write',
|
|
491
492
|
owningCommand: 'oat config set workflow.dispatchPolicy.policy <value>',
|
|
492
|
-
description:
|
|
493
|
+
description: dispatchPolicyPolicyDescription(),
|
|
493
494
|
},
|
|
494
495
|
{
|
|
495
496
|
key: 'workflow.dispatchCeiling.providers.codex',
|
|
@@ -614,14 +615,8 @@ const WORKFLOW_ENUM_VALUES = {
|
|
|
614
615
|
'workflow.postImplementSequence': ['wait', 'summary', 'pr', 'docs-pr'],
|
|
615
616
|
'workflow.reviewExecutionModel': ['subagent', 'inline', 'fresh-session'],
|
|
616
617
|
'workflow.designMode': ['collaborative', 'selective', 'draft'],
|
|
617
|
-
'workflow.dispatchPolicy.mode': [
|
|
618
|
-
'workflow.dispatchPolicy.policy': [
|
|
619
|
-
'economy',
|
|
620
|
-
'balanced',
|
|
621
|
-
'high',
|
|
622
|
-
'frontier',
|
|
623
|
-
'uncapped',
|
|
624
|
-
],
|
|
618
|
+
'workflow.dispatchPolicy.mode': [...VALID_DISPATCH_POLICY_MODES],
|
|
619
|
+
'workflow.dispatchPolicy.policy': [...VALID_MANAGED_DISPATCH_POLICIES],
|
|
625
620
|
'workflow.dispatchCeiling.preset': ['balanced', 'maximum', 'cost-conscious'],
|
|
626
621
|
'workflow.dispatchCeiling.providers.codex': [
|
|
627
622
|
'low',
|
|
@@ -747,13 +742,15 @@ function isRecord(value) {
|
|
|
747
742
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
748
743
|
}
|
|
749
744
|
function matrixCellAvailabilityWarning(path, value, availability) {
|
|
750
|
-
|
|
745
|
+
const result = normalizeMatrixCellAvailability(availability);
|
|
746
|
+
if (result.availability === 'valid') {
|
|
751
747
|
return null;
|
|
752
748
|
}
|
|
753
|
-
|
|
754
|
-
|
|
749
|
+
const details = result.message ? ` ${result.message}` : '';
|
|
750
|
+
if (result.availability === 'unknown-value') {
|
|
751
|
+
return `${path} value '${value}' was not recognized by the provider availability oracle; saving anyway.${details}`;
|
|
755
752
|
}
|
|
756
|
-
return `${path} value '${value}' could not be validated because the provider availability oracle is unavailable; saving anyway
|
|
753
|
+
return `${path} value '${value}' could not be validated because the provider availability oracle is unavailable; saving anyway.${details}`;
|
|
757
754
|
}
|
|
758
755
|
function parseDispatchMatrixRecommendation(raw) {
|
|
759
756
|
const parsed = JSON.parse(raw);
|
|
@@ -775,6 +772,9 @@ function parseDispatchMatrixRecommendation(raw) {
|
|
|
775
772
|
function isRouteTarget(entry) {
|
|
776
773
|
return isRecord(entry);
|
|
777
774
|
}
|
|
775
|
+
function formatRouteTargetValue(entry) {
|
|
776
|
+
return [entry.model, entry.effort].filter(Boolean).join('/');
|
|
777
|
+
}
|
|
778
778
|
function addDispatchMatrixCellRefs(refs, provider, path, cell) {
|
|
779
779
|
if (typeof cell === 'string') {
|
|
780
780
|
refs.push({ provider, value: cell, path });
|
|
@@ -789,11 +789,31 @@ function addDispatchMatrixCellRefs(refs, provider, path, cell) {
|
|
|
789
789
|
if (!isRouteTarget(entry)) {
|
|
790
790
|
continue;
|
|
791
791
|
}
|
|
792
|
+
const targetProvider = entry.harness ?? provider;
|
|
793
|
+
if (isCodexMaterializedRouteTarget(provider, entry)) {
|
|
794
|
+
if (entry.model && entry.effort) {
|
|
795
|
+
refs.push({
|
|
796
|
+
provider: targetProvider,
|
|
797
|
+
value: formatRouteTargetValue(entry),
|
|
798
|
+
path: entryPath,
|
|
799
|
+
target: entry,
|
|
800
|
+
});
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
792
804
|
if (entry.model) {
|
|
793
|
-
refs.push({
|
|
805
|
+
refs.push({
|
|
806
|
+
provider: targetProvider,
|
|
807
|
+
value: entry.model,
|
|
808
|
+
path: `${entryPath}.model`,
|
|
809
|
+
});
|
|
794
810
|
}
|
|
795
811
|
if (entry.effort) {
|
|
796
|
-
refs.push({
|
|
812
|
+
refs.push({
|
|
813
|
+
provider: targetProvider,
|
|
814
|
+
value: entry.effort,
|
|
815
|
+
path: `${entryPath}.effort`,
|
|
816
|
+
});
|
|
797
817
|
}
|
|
798
818
|
}
|
|
799
819
|
}
|
|
@@ -814,6 +834,30 @@ function collectDispatchMatrixCellRefs(providers) {
|
|
|
814
834
|
}
|
|
815
835
|
return refs;
|
|
816
836
|
}
|
|
837
|
+
function collectDispatchMatrixTargetValidationErrors(providers) {
|
|
838
|
+
const errors = [];
|
|
839
|
+
for (const [provider, providerValue] of Object.entries(providers)) {
|
|
840
|
+
if (typeof providerValue === 'string') {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
const providerPath = `workflow.dispatchCeiling.providers.${provider}`;
|
|
844
|
+
for (const [tier, cell] of Object.entries(providerValue)) {
|
|
845
|
+
if (!Array.isArray(cell)) {
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
for (const [index, entry] of cell.entries()) {
|
|
849
|
+
if (!isRouteTarget(entry)) {
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
const validation = validateDispatchRouteTarget(provider, entry);
|
|
853
|
+
if (!validation.valid) {
|
|
854
|
+
errors.push(`${providerPath}.${tier}[${index}]: ${validation.reason}`);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return errors;
|
|
860
|
+
}
|
|
817
861
|
function applyWorkflowValue(workflow, key, value) {
|
|
818
862
|
const subKey = key.slice('workflow.'.length);
|
|
819
863
|
if (subKey === 'dispatchPolicy.mode') {
|
|
@@ -826,7 +870,7 @@ function applyWorkflowValue(workflow, key, value) {
|
|
|
826
870
|
}
|
|
827
871
|
const policy = workflow.dispatchPolicy?.policy;
|
|
828
872
|
if (!policy) {
|
|
829
|
-
throw new Error(
|
|
873
|
+
throw new Error(`Cannot set workflow.dispatchPolicy.mode to managed without an existing workflow.dispatchPolicy.policy. Set workflow.dispatchPolicy.policy <${managedDispatchPolicyValueList('|')}> instead.`);
|
|
830
874
|
}
|
|
831
875
|
return {
|
|
832
876
|
...workflow,
|
|
@@ -956,6 +1000,7 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
956
1000
|
const availability = await dependencies.validateMatrixCell(providerNameFromConfigKey(key), parsedValue, {
|
|
957
1001
|
cwd: repoRoot,
|
|
958
1002
|
env: dependencies.processEnv,
|
|
1003
|
+
detailed: true,
|
|
959
1004
|
});
|
|
960
1005
|
const warning = dispatchProviderAvailabilityWarning(key, parsedValue, availability);
|
|
961
1006
|
if (warning) {
|
|
@@ -1149,9 +1194,13 @@ async function loadDispatchMatrixRecommendation(dependencies) {
|
|
|
1149
1194
|
return parseDispatchMatrixRecommendation(await dependencies.readFile(assetPath));
|
|
1150
1195
|
}
|
|
1151
1196
|
async function validateRecommendationCells(repoRoot, recommendation, dependencies, warn) {
|
|
1197
|
+
const targetErrors = collectDispatchMatrixTargetValidationErrors(recommendation.providers);
|
|
1198
|
+
if (targetErrors.length > 0) {
|
|
1199
|
+
throw new Error(targetErrors.join('\n'));
|
|
1200
|
+
}
|
|
1152
1201
|
for (const ref of collectDispatchMatrixCellRefs(recommendation.providers)) {
|
|
1153
1202
|
const closedValues = closedDispatchProviderValues(ref.provider);
|
|
1154
|
-
if (closedValues && !closedValues.includes(ref.value)) {
|
|
1203
|
+
if (!ref.target && closedValues && !closedValues.includes(ref.value)) {
|
|
1155
1204
|
throw new Error(`Invalid value for ${ref.path}: expected one of ${closedValues.join(' | ')}, got '${ref.value}'`);
|
|
1156
1205
|
}
|
|
1157
1206
|
let availability;
|
|
@@ -1159,6 +1208,8 @@ async function validateRecommendationCells(repoRoot, recommendation, dependencie
|
|
|
1159
1208
|
availability = await dependencies.validateMatrixCell(ref.provider, ref.value, {
|
|
1160
1209
|
cwd: repoRoot,
|
|
1161
1210
|
env: dependencies.processEnv,
|
|
1211
|
+
detailed: true,
|
|
1212
|
+
...(ref.target ? { target: ref.target } : {}),
|
|
1162
1213
|
});
|
|
1163
1214
|
}
|
|
1164
1215
|
catch {
|
|
@@ -2,7 +2,7 @@ import { type CommandContext, type GlobalOptions } from '../../app/command-conte
|
|
|
2
2
|
import { type PjmDoctorOptions } from '../pjm/doctor.js';
|
|
3
3
|
import { type OatConfig, type OatLocalConfig, type UserConfig } from '../../config/oat-config.js';
|
|
4
4
|
import { type Manifest } from '../../manifest/index.js';
|
|
5
|
-
import { type
|
|
5
|
+
import { type MatrixCellAvailabilityResponse, type ValidateMatrixCellOptions } from '../../providers/identity/availability.js';
|
|
6
6
|
import type { ConcreteScope } from '../../shared/types.js';
|
|
7
7
|
import { type DoctorCheck } from '../../ui/output.js';
|
|
8
8
|
import { Command } from 'commander';
|
|
@@ -22,7 +22,7 @@ interface DoctorDependencies {
|
|
|
22
22
|
readOatConfig: (repoRoot: string) => Promise<OatConfig>;
|
|
23
23
|
readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
|
|
24
24
|
readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
|
|
25
|
-
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<
|
|
25
|
+
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
|
|
26
26
|
processEnv: NodeJS.ProcessEnv;
|
|
27
27
|
runPjmDoctorChecks: (repoRoot: string, options?: PjmDoctorOptions) => Promise<DoctorCheck[]>;
|
|
28
28
|
checkSkillVersions: (scopeRoot: string, assetsRoot: string, pathExists: (path: string) => Promise<boolean>) => Promise<SkillVersionReport>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,17 +7,18 @@ import { createPjmDisabledCheck, runPjmDoctorChecks, } from '../pjm/doctor.js';
|
|
|
7
7
|
import { getSkillVersion } from '../shared/frontmatter.js';
|
|
8
8
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
9
9
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
10
|
-
import { readOatConfig, readOatLocalConfig, readUserConfig, } from '../../config/oat-config.js';
|
|
10
|
+
import { readOatConfig, readOatLocalConfig, readUserConfig, isCodexMaterializedRouteTarget, } from '../../config/oat-config.js';
|
|
11
11
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
12
12
|
import { resolveProjectRoot, resolveScopeRoot } from '../../fs/paths.js';
|
|
13
13
|
import TOML from '@iarna/toml';
|
|
14
14
|
import { loadManifest } from '../../manifest/index.js';
|
|
15
15
|
import { claudeAdapter } from '../../providers/claude/index.js';
|
|
16
16
|
import { codexAdapter } from '../../providers/codex/index.js';
|
|
17
|
+
import { isOatManagedCodexRoleFile } from '../../providers/codex/codec/shared.js';
|
|
17
18
|
import { copilotAdapter } from '../../providers/copilot/index.js';
|
|
18
19
|
import { cursorAdapter } from '../../providers/cursor/index.js';
|
|
19
20
|
import { geminiAdapter } from '../../providers/gemini/index.js';
|
|
20
|
-
import { validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
21
|
+
import { normalizeMatrixCellAvailability, validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
21
22
|
import { formatDoctorResults } from '../../ui/output.js';
|
|
22
23
|
import { Command } from 'commander';
|
|
23
24
|
async function pathExistsDefault(path) {
|
|
@@ -143,6 +144,9 @@ function createDependencies() {
|
|
|
143
144
|
function isRouteTarget(entry) {
|
|
144
145
|
return typeof entry === 'object' && entry !== null && !Array.isArray(entry);
|
|
145
146
|
}
|
|
147
|
+
function formatRouteTargetValue(entry) {
|
|
148
|
+
return [entry.model, entry.effort].filter(Boolean).join('/');
|
|
149
|
+
}
|
|
146
150
|
function addDispatchMatrixCellRefs(refs, layer, provider, path, cell) {
|
|
147
151
|
if (typeof cell === 'string') {
|
|
148
152
|
refs.push({ layer, provider, value: cell, path });
|
|
@@ -157,10 +161,23 @@ function addDispatchMatrixCellRefs(refs, layer, provider, path, cell) {
|
|
|
157
161
|
if (!isRouteTarget(entry)) {
|
|
158
162
|
continue;
|
|
159
163
|
}
|
|
164
|
+
const targetProvider = entry.harness ?? provider;
|
|
165
|
+
if (isCodexMaterializedRouteTarget(provider, entry)) {
|
|
166
|
+
if (entry.model && entry.effort) {
|
|
167
|
+
refs.push({
|
|
168
|
+
layer,
|
|
169
|
+
provider: targetProvider,
|
|
170
|
+
value: formatRouteTargetValue(entry),
|
|
171
|
+
path: entryPath,
|
|
172
|
+
target: entry,
|
|
173
|
+
});
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
160
177
|
if (entry.model) {
|
|
161
178
|
refs.push({
|
|
162
179
|
layer,
|
|
163
|
-
provider,
|
|
180
|
+
provider: targetProvider,
|
|
164
181
|
value: entry.model,
|
|
165
182
|
path: `${entryPath}.model`,
|
|
166
183
|
});
|
|
@@ -168,7 +185,7 @@ function addDispatchMatrixCellRefs(refs, layer, provider, path, cell) {
|
|
|
168
185
|
if (entry.effort) {
|
|
169
186
|
refs.push({
|
|
170
187
|
layer,
|
|
171
|
-
provider,
|
|
188
|
+
provider: targetProvider,
|
|
172
189
|
value: entry.effort,
|
|
173
190
|
path: `${entryPath}.effort`,
|
|
174
191
|
});
|
|
@@ -203,7 +220,12 @@ function collectDispatchMatrixCellRefs(layers) {
|
|
|
203
220
|
}
|
|
204
221
|
function formatDispatchMatrixIssueList(issues) {
|
|
205
222
|
return issues
|
|
206
|
-
.map((issue) =>
|
|
223
|
+
.map((issue) => {
|
|
224
|
+
const suffix = 'message' in issue && typeof issue.message === 'string'
|
|
225
|
+
? `; ${issue.message}`
|
|
226
|
+
: '';
|
|
227
|
+
return `${issue.path}=${issue.value} (${issue.layer} config)${suffix}`;
|
|
228
|
+
})
|
|
207
229
|
.join(', ');
|
|
208
230
|
}
|
|
209
231
|
async function createDispatchMatrixDoctorCheck(scopeRoot, layers, dependencies) {
|
|
@@ -218,18 +240,24 @@ async function createDispatchMatrixDoctorCheck(scopeRoot, layers, dependencies)
|
|
|
218
240
|
}
|
|
219
241
|
const issues = [];
|
|
220
242
|
for (const ref of refs) {
|
|
221
|
-
let
|
|
243
|
+
let result;
|
|
222
244
|
try {
|
|
223
|
-
|
|
245
|
+
result = normalizeMatrixCellAvailability(await dependencies.validateMatrixCell(ref.provider, ref.value, {
|
|
224
246
|
cwd: scopeRoot,
|
|
225
247
|
env: dependencies.processEnv,
|
|
226
|
-
|
|
248
|
+
detailed: true,
|
|
249
|
+
...(ref.target ? { target: ref.target } : {}),
|
|
250
|
+
}));
|
|
227
251
|
}
|
|
228
252
|
catch {
|
|
229
|
-
|
|
253
|
+
result = { availability: 'unvalidated' };
|
|
230
254
|
}
|
|
231
|
-
if (availability !== 'valid') {
|
|
232
|
-
issues.push({
|
|
255
|
+
if (result.availability !== 'valid') {
|
|
256
|
+
issues.push({
|
|
257
|
+
...ref,
|
|
258
|
+
availability: result.availability,
|
|
259
|
+
...(result.message ? { message: result.message } : {}),
|
|
260
|
+
});
|
|
233
261
|
}
|
|
234
262
|
}
|
|
235
263
|
if (issues.length === 0) {
|
|
@@ -250,16 +278,45 @@ async function createDispatchMatrixDoctorCheck(scopeRoot, layers, dependencies)
|
|
|
250
278
|
messageParts.push(`Unvalidated dispatch matrix cells: ${formatDispatchMatrixIssueList(unvalidated)}`);
|
|
251
279
|
}
|
|
252
280
|
const hasUnknown = unknown.length > 0;
|
|
281
|
+
const hasUnvalidated = unvalidated.length > 0;
|
|
253
282
|
return {
|
|
254
283
|
name: 'project:dispatch_matrix',
|
|
255
284
|
description: 'Dispatch matrix cell availability',
|
|
256
|
-
status: hasUnknown ? 'warn' : 'pass',
|
|
285
|
+
status: hasUnknown || hasUnvalidated ? 'warn' : 'pass',
|
|
257
286
|
message: messageParts.join('. '),
|
|
258
287
|
fix: hasUnknown
|
|
259
288
|
? 'Run `oat config set workflow.dispatchCeiling.providers.<provider> <value>` with an available value, or refresh provider assets with `oat sync --scope project`.'
|
|
260
289
|
: undefined,
|
|
261
290
|
};
|
|
262
291
|
}
|
|
292
|
+
function getCodexAgentConfigFile(config) {
|
|
293
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const configFile = config.config_file;
|
|
297
|
+
return typeof configFile === 'string' && configFile.startsWith('agents/')
|
|
298
|
+
? configFile
|
|
299
|
+
: null;
|
|
300
|
+
}
|
|
301
|
+
function isLikelyOatGeneratedCodexRoleName(roleName) {
|
|
302
|
+
return (roleName === 'oat-phase-implementer' ||
|
|
303
|
+
roleName === 'oat-reviewer' ||
|
|
304
|
+
roleName.startsWith('oat-phase-implementer-') ||
|
|
305
|
+
roleName.startsWith('oat-reviewer-'));
|
|
306
|
+
}
|
|
307
|
+
async function isManagedCodexRoleConfig(scopeRoot, roleName, configFile, dependencies) {
|
|
308
|
+
const absoluteRolePath = join(scopeRoot, '.codex', configFile);
|
|
309
|
+
if (!(await dependencies.pathExists(absoluteRolePath))) {
|
|
310
|
+
return isLikelyOatGeneratedCodexRoleName(roleName);
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
const roleContent = await dependencies.readFile(absoluteRolePath);
|
|
314
|
+
return isOatManagedCodexRoleFile(roleContent, roleName);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
263
320
|
async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies) {
|
|
264
321
|
const checks = [];
|
|
265
322
|
const skillsPath = join(scopeRoot, '.agents', 'skills');
|
|
@@ -419,17 +476,18 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
419
476
|
!Array.isArray(parsedConfig.agents)
|
|
420
477
|
? parsedConfig.agents
|
|
421
478
|
: null;
|
|
422
|
-
const managedRoles =
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
479
|
+
const managedRoles = [];
|
|
480
|
+
const roleConfigFiles = new Map();
|
|
481
|
+
for (const [roleName, roleConfig] of Object.entries(agents ?? {})) {
|
|
482
|
+
const configFile = getCodexAgentConfigFile(roleConfig);
|
|
483
|
+
if (!configFile) {
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
roleConfigFiles.set(roleName, configFile);
|
|
487
|
+
if (await isManagedCodexRoleConfig(scopeRoot, roleName, configFile, dependencies)) {
|
|
488
|
+
managedRoles.push(roleName);
|
|
428
489
|
}
|
|
429
|
-
|
|
430
|
-
return (typeof configFile === 'string' && configFile.startsWith('agents/'));
|
|
431
|
-
})
|
|
432
|
-
.map(([roleName]) => roleName);
|
|
490
|
+
}
|
|
433
491
|
if (managedRoles.length > 0) {
|
|
434
492
|
const multiAgentEnabled = features?.multi_agent === true || features?.multi_agent === 'true';
|
|
435
493
|
checks.push({
|
|
@@ -445,11 +503,9 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
445
503
|
});
|
|
446
504
|
const missingRoleFiles = [];
|
|
447
505
|
for (const roleName of managedRoles) {
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
if (typeof configFile !== 'string') {
|
|
506
|
+
const configFile = roleConfigFiles.get(roleName);
|
|
507
|
+
if (!configFile)
|
|
451
508
|
continue;
|
|
452
|
-
}
|
|
453
509
|
const absoluteRolePath = join(scopeRoot, '.codex', configFile);
|
|
454
510
|
if (!(await dependencies.pathExists(absoluteRolePath))) {
|
|
455
511
|
missingRoleFiles.push(configFile);
|
|
@@ -464,7 +520,7 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
464
520
|
: `Missing codex role files: ${missingRoleFiles.join(', ')}`,
|
|
465
521
|
fix: missingRoleFiles.length === 0
|
|
466
522
|
? undefined
|
|
467
|
-
: 'Regenerate codex roles with `oat sync --scope project
|
|
523
|
+
: 'Regenerate codex roles with `oat sync --scope project`, or materialize a single role with `oat providers codex materialize ...`.',
|
|
468
524
|
});
|
|
469
525
|
}
|
|
470
526
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAY9B,OAAO,EAOL,KAAK,uBAAuB,EAU7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAazB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgCpC,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA4pDD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAwET"}
|