@open-agent-toolkit/cli 0.2.63 → 0.2.64
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/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/tool-packs.md +83 -0
- package/assets/docs/contributing/skills.md +42 -7
- package/assets/docs/provider-sync/manifest-and-drift.md +105 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/SKILL.md +9 -7
- package/assets/skills/create-agnostic-skill/references/skill-template.md +9 -7
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -0
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -0
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -0
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -0
- package/assets/skills/oat-project-pr-final/SKILL.md +281 -6
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -0
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -0
- package/dist/agents/canonical/resolve.d.ts.map +1 -1
- package/dist/agents/canonical/resolve.js +25 -4
- package/dist/commands/doctor/index.d.ts +7 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +10 -2
- package/dist/commands/init/tools/index.d.ts.map +1 -1
- package/dist/commands/init/tools/index.js +68 -36
- package/dist/commands/shared/frontmatter.d.ts +51 -0
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +118 -6
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +5 -3
- package/dist/commands/sync/index.d.ts +14 -0
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +21 -0
- package/dist/commands/tools/info/index.d.ts.map +1 -1
- package/dist/commands/tools/info/index.js +14 -1
- package/dist/commands/tools/info/info-tool.d.ts +12 -0
- package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
- package/dist/commands/tools/info/info-tool.js +54 -6
- package/dist/commands/tools/info/skill-views.d.ts +86 -0
- package/dist/commands/tools/info/skill-views.d.ts.map +1 -0
- package/dist/commands/tools/info/skill-views.js +383 -0
- package/dist/commands/tools/install/index.d.ts.map +1 -1
- package/dist/commands/tools/install/index.js +3 -25
- package/dist/commands/tools/list/list-tools.d.ts +2 -0
- package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
- package/dist/commands/tools/list/list-tools.js +23 -4
- package/dist/commands/tools/remove/index.d.ts.map +1 -1
- package/dist/commands/tools/remove/index.js +35 -42
- package/dist/commands/tools/remove/remove-tools.d.ts +3 -2
- package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
- package/dist/commands/tools/remove/remove-tools.js +14 -4
- package/dist/commands/tools/shared/auto-sync.d.ts +12 -1
- package/dist/commands/tools/shared/auto-sync.d.ts.map +1 -1
- package/dist/commands/tools/shared/auto-sync.js +20 -4
- package/dist/commands/tools/shared/format-pack-inventory.d.ts +12 -1
- package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -1
- package/dist/commands/tools/shared/format-pack-inventory.js +48 -6
- package/dist/commands/tools/shared/in-process-sync.d.ts +11 -0
- package/dist/commands/tools/shared/in-process-sync.d.ts.map +1 -0
- package/dist/commands/tools/shared/in-process-sync.js +79 -0
- package/dist/commands/tools/shared/pack-evidence.d.ts +78 -2
- package/dist/commands/tools/shared/pack-evidence.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-evidence.js +96 -2
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts +11 -0
- package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-lifecycle-outcome.js +24 -3
- package/dist/commands/tools/shared/pack-provider-evidence.d.ts +73 -0
- package/dist/commands/tools/shared/pack-provider-evidence.d.ts.map +1 -0
- package/dist/commands/tools/shared/pack-provider-evidence.js +161 -0
- package/dist/commands/tools/shared/provider-context.d.ts +88 -0
- package/dist/commands/tools/shared/provider-context.d.ts.map +1 -0
- package/dist/commands/tools/shared/provider-context.js +77 -0
- package/dist/commands/tools/shared/provider-reachability.d.ts +93 -0
- package/dist/commands/tools/shared/provider-reachability.d.ts.map +1 -0
- package/dist/commands/tools/shared/provider-reachability.js +358 -0
- package/dist/commands/tools/shared/sync-evidence.d.ts +57 -0
- package/dist/commands/tools/shared/sync-evidence.d.ts.map +1 -0
- package/dist/commands/tools/shared/sync-evidence.js +147 -0
- package/dist/commands/tools/update/index.d.ts +0 -4
- package/dist/commands/tools/update/index.d.ts.map +1 -1
- package/dist/commands/tools/update/index.js +22 -40
- package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
- package/dist/commands/tools/update/update-tools.js +23 -8
- package/dist/config/json.d.ts +36 -0
- package/dist/config/json.d.ts.map +1 -1
- package/dist/config/json.js +135 -3
- package/dist/drift/index.d.ts +2 -0
- package/dist/drift/index.d.ts.map +1 -1
- package/dist/drift/index.js +1 -0
- package/dist/drift/skill-view-diagnostic.d.ts +197 -0
- package/dist/drift/skill-view-diagnostic.d.ts.map +1 -0
- package/dist/drift/skill-view-diagnostic.js +343 -0
- package/dist/validation/skills.d.ts +1 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +181 -19
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { execFile as execFileCallback } from 'node:child_process';
|
|
|
2
2
|
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
|
-
import { getFrontmatterBlock } from '../commands/shared/frontmatter.js';
|
|
5
|
+
import { getFrontmatterBlock, parseSkillFrontmatter, resolveSkillVersion, } from '../commands/shared/frontmatter.js';
|
|
6
6
|
const execFileAsync = promisify(execFileCallback);
|
|
7
7
|
async function isDirectory(path) {
|
|
8
8
|
try {
|
|
@@ -459,6 +459,66 @@ function hasTrueFrontmatterValue(frontmatter, key) {
|
|
|
459
459
|
return (frontmatterHasKey(frontmatter, key) &&
|
|
460
460
|
getFrontmatterScalar(frontmatter, key) === 'true');
|
|
461
461
|
}
|
|
462
|
+
function unreadableFrontmatterFinding(file) {
|
|
463
|
+
return {
|
|
464
|
+
file,
|
|
465
|
+
code: 'skill-frontmatter-unreadable',
|
|
466
|
+
severity: 'error',
|
|
467
|
+
message: 'Frontmatter must be a valid YAML mapping with unique keys (version could not be read)',
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function pushUniqueFinding(findings, finding) {
|
|
471
|
+
const duplicate = findings.some((existing) => existing.file === finding.file &&
|
|
472
|
+
existing.code === finding.code &&
|
|
473
|
+
existing.message === finding.message);
|
|
474
|
+
if (!duplicate) {
|
|
475
|
+
findings.push(finding);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* A `version` key is present but carries no usable value (empty, or a
|
|
480
|
+
* non-string scalar such as `1.10`, which YAML reads as the number 1.1).
|
|
481
|
+
*
|
|
482
|
+
* This is reported rather than skipped: the value the author wrote is a
|
|
483
|
+
* version OAT cannot read, and letting it resolve to nothing would silently
|
|
484
|
+
* disable both the semver check and bump enforcement for that skill.
|
|
485
|
+
*/
|
|
486
|
+
function unusableVersionFinding(file) {
|
|
487
|
+
return {
|
|
488
|
+
file,
|
|
489
|
+
code: 'skill-version-unusable',
|
|
490
|
+
severity: 'error',
|
|
491
|
+
message: 'Frontmatter declares a version that cannot be read; use a quoted semver string (unquoted, version: 1.10 is the number 1.1)',
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function uncomparableBaseFinding(file, baseRef, reason) {
|
|
495
|
+
return {
|
|
496
|
+
file,
|
|
497
|
+
code: reason === 'unreadable'
|
|
498
|
+
? 'skill-frontmatter-unreadable'
|
|
499
|
+
: 'skill-version-unusable',
|
|
500
|
+
severity: 'error',
|
|
501
|
+
message: reason === 'unreadable'
|
|
502
|
+
? `Changed canonical skill cannot be version-checked against ${baseRef}: the base frontmatter is not a valid YAML mapping with unique keys`
|
|
503
|
+
: `Changed canonical skill cannot be version-checked against ${baseRef}: the base frontmatter declares a version that cannot be read`,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function uncomparableBaseConflictFinding(file, baseRef, conflict) {
|
|
507
|
+
return {
|
|
508
|
+
file,
|
|
509
|
+
code: 'skill-version-conflict',
|
|
510
|
+
severity: 'error',
|
|
511
|
+
message: `Changed canonical skill cannot be version-checked against ${baseRef}: the base frontmatter metadata.version (${conflict.metadata}) and top-level version (${conflict.topLevel}) differ`,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
function versionConflictFinding(file, conflict) {
|
|
515
|
+
return {
|
|
516
|
+
file,
|
|
517
|
+
code: 'skill-version-conflict',
|
|
518
|
+
severity: 'error',
|
|
519
|
+
message: `Frontmatter metadata.version (${conflict.metadata}) and top-level version (${conflict.topLevel}) differ; a conflicting skill has no resolvable version`,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
462
522
|
function isValidSemver(value) {
|
|
463
523
|
return /^\d+\.\d+\.\d+$/.test(value);
|
|
464
524
|
}
|
|
@@ -597,14 +657,52 @@ async function collectChangedSkillVersionBumpFindings(repoRoot, baseRef, changed
|
|
|
597
657
|
if (baseContent === null || baseContent === currentContent) {
|
|
598
658
|
continue;
|
|
599
659
|
}
|
|
600
|
-
const
|
|
601
|
-
const
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
660
|
+
const currentBlock = getFrontmatterBlock(currentContent);
|
|
661
|
+
const parsedCurrent = currentBlock === null ? null : parseSkillFrontmatter(currentBlock);
|
|
662
|
+
const baseBlock = getFrontmatterBlock(baseContent);
|
|
663
|
+
const parsedBase = baseBlock === null ? null : parseSkillFrontmatter(baseBlock);
|
|
664
|
+
// Frontmatter that carries no readable version must never fall through to
|
|
665
|
+
// the `continue` below: a value the resolver cannot read would otherwise
|
|
666
|
+
// disable bump enforcement for that skill entirely. Both sides are
|
|
667
|
+
// guarded, because either one being uncomparable defeats the comparison.
|
|
668
|
+
// `validateOatSkills` runs the structural version-source pass before this
|
|
669
|
+
// collector, so the same file can already carry the current-side finding.
|
|
670
|
+
if (parsedCurrent?.malformed) {
|
|
671
|
+
pushUniqueFinding(findings, unreadableFrontmatterFinding(skillPath));
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
if (parsedCurrent?.unusableVersionDeclaration) {
|
|
675
|
+
pushUniqueFinding(findings, unusableVersionFinding(skillPath));
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
if (parsedBase?.malformed) {
|
|
679
|
+
findings.push(uncomparableBaseFinding(skillPath, baseRef, 'unreadable'));
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
if (parsedBase?.unusableVersionDeclaration) {
|
|
683
|
+
findings.push(uncomparableBaseFinding(skillPath, baseRef, 'unusable'));
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
const resolvedCurrent = parsedCurrent === null ? null : resolveSkillVersion(parsedCurrent);
|
|
687
|
+
const resolvedBase = parsedBase === null ? null : resolveSkillVersion(parsedBase);
|
|
688
|
+
// A conflicting skill has no resolvable version, so it cannot be bump
|
|
689
|
+
// checked. This is the only version-source finding the bump validator
|
|
690
|
+
// emits: `validate-skill-version-bumps.ts` fails the gate on any finding
|
|
691
|
+
// regardless of severity, so the top-level alias deprecation warning stays
|
|
692
|
+
// in structural validation and never reaches this result.
|
|
693
|
+
if (resolvedCurrent?.conflict) {
|
|
694
|
+
findings.push(versionConflictFinding(skillPath, resolvedCurrent.conflict));
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
// A conflicting base has no single version to compare against either:
|
|
698
|
+
// silently taking its metadata side would accept a downgrade relative to
|
|
699
|
+
// the top-level version the base also declares.
|
|
700
|
+
if (resolvedBase?.conflict) {
|
|
701
|
+
findings.push(uncomparableBaseConflictFinding(skillPath, baseRef, resolvedBase.conflict));
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const currentVersion = resolvedCurrent?.version ?? null;
|
|
705
|
+
const baseVersion = resolvedBase?.version ?? null;
|
|
608
706
|
if (!currentVersion || !baseVersion) {
|
|
609
707
|
continue;
|
|
610
708
|
}
|
|
@@ -634,6 +732,67 @@ export async function validateChangedSkillVersionBumps(repoRoot, options, depend
|
|
|
634
732
|
findings,
|
|
635
733
|
};
|
|
636
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Report where each bundled skill keeps its version.
|
|
737
|
+
*
|
|
738
|
+
* This pass deliberately iterates every skill directory, not just `oat-*`:
|
|
739
|
+
* the top-level `version` alias is deprecated across the whole bundle, so a
|
|
740
|
+
* pass that inherited the `oat-*` filter used by the other structural checks
|
|
741
|
+
* could never fire for the 18 non-`oat-*` skills. `skill-version-alias` is a
|
|
742
|
+
* warning (`validate-oat-skills.ts` treats warnings as non-blocking) and
|
|
743
|
+
* `skill-version-conflict` is an error. Neither finding is produced by the
|
|
744
|
+
* bump validator, whose wrapper fails on any finding at all.
|
|
745
|
+
*/
|
|
746
|
+
async function collectSkillVersionSourceFindings(skillsRoot, skillDirs, findings) {
|
|
747
|
+
for (const dir of skillDirs) {
|
|
748
|
+
const skillPath = join(skillsRoot, dir, 'SKILL.md');
|
|
749
|
+
let content;
|
|
750
|
+
try {
|
|
751
|
+
content = await readFile(skillPath, 'utf8');
|
|
752
|
+
}
|
|
753
|
+
catch {
|
|
754
|
+
// A missing SKILL.md is reported by the structural pass for oat-*
|
|
755
|
+
// skills and is not this pass's concern.
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
const block = getFrontmatterBlock(content);
|
|
759
|
+
if (block === null) {
|
|
760
|
+
continue;
|
|
761
|
+
}
|
|
762
|
+
const parsed = parseSkillFrontmatter(block);
|
|
763
|
+
if (parsed.malformed) {
|
|
764
|
+
// Reported for every skill, not just `oat-*` ones: unreadable
|
|
765
|
+
// frontmatter is exactly the state that would otherwise make a version
|
|
766
|
+
// silently unreadable everywhere.
|
|
767
|
+
findings.push(unreadableFrontmatterFinding(skillPath));
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
// Declaration usability is checked here, before the unresolved bail, so it
|
|
771
|
+
// covers every bundled skill. Inside the `oat-*` loop it could never fire
|
|
772
|
+
// for the 18 skills that are not named `oat-*`, which is how an unusable
|
|
773
|
+
// declaration became invisible to validation.
|
|
774
|
+
if (parsed.unusableVersionDeclaration) {
|
|
775
|
+
findings.push(unusableVersionFinding(skillPath));
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
const resolved = resolveSkillVersion(parsed);
|
|
779
|
+
if (!resolved) {
|
|
780
|
+
continue;
|
|
781
|
+
}
|
|
782
|
+
if (resolved.conflict) {
|
|
783
|
+
findings.push(versionConflictFinding(skillPath, resolved.conflict));
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
if (resolved.source === 'top-level') {
|
|
787
|
+
findings.push({
|
|
788
|
+
file: skillPath,
|
|
789
|
+
code: 'skill-version-alias',
|
|
790
|
+
severity: 'warning',
|
|
791
|
+
message: `Frontmatter version ${resolved.version} uses the deprecated top-level alias; move it to metadata.version (metadata.version wins when both are present)`,
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
637
796
|
export async function validateOatSkills(repoRoot, options = {}, dependencies = {}) {
|
|
638
797
|
const skillsRoot = join(repoRoot, '.agents', 'skills');
|
|
639
798
|
const findings = [];
|
|
@@ -641,10 +800,11 @@ export async function validateOatSkills(repoRoot, options = {}, dependencies = {
|
|
|
641
800
|
throw new Error(`skills directory not found: ${skillsRoot}`);
|
|
642
801
|
}
|
|
643
802
|
const entries = await readdir(skillsRoot, { withFileTypes: true });
|
|
644
|
-
const
|
|
645
|
-
.filter((entry) => entry.isDirectory()
|
|
803
|
+
const allSkillDirs = entries
|
|
804
|
+
.filter((entry) => entry.isDirectory())
|
|
646
805
|
.map((entry) => entry.name)
|
|
647
806
|
.sort();
|
|
807
|
+
const oatSkillDirs = allSkillDirs.filter((name) => name.startsWith('oat-'));
|
|
648
808
|
for (const dir of oatSkillDirs) {
|
|
649
809
|
const skillPath = join(skillsRoot, dir, 'SKILL.md');
|
|
650
810
|
let content;
|
|
@@ -707,14 +867,15 @@ export async function validateOatSkills(repoRoot, options = {}, dependencies = {
|
|
|
707
867
|
}
|
|
708
868
|
}
|
|
709
869
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
870
|
+
// Malformed frontmatter and unusable version declarations are reported
|
|
871
|
+
// once, for every skill, by collectSkillVersionSourceFindings; this is the
|
|
872
|
+
// `oat-*` structural rule for a version that does resolve.
|
|
873
|
+
const resolvedVersion = resolveSkillVersion(parseSkillFrontmatter(fm));
|
|
874
|
+
if (resolvedVersion !== null && !isValidSemver(resolvedVersion.version)) {
|
|
875
|
+
findings.push({
|
|
876
|
+
file: skillPath,
|
|
877
|
+
message: 'Frontmatter version must be valid semver (e.g., 1.0.0)',
|
|
878
|
+
});
|
|
718
879
|
}
|
|
719
880
|
if (!hasProgressIndicatorsSection(content)) {
|
|
720
881
|
findings.push({
|
|
@@ -732,6 +893,7 @@ export async function validateOatSkills(repoRoot, options = {}, dependencies = {
|
|
|
732
893
|
validateQuickStartSemantics(skillPath, content, findings);
|
|
733
894
|
}
|
|
734
895
|
}
|
|
896
|
+
await collectSkillVersionSourceFindings(skillsRoot, allSkillDirs, findings);
|
|
735
897
|
await collectSyncedSafetyFindings(repoRoot, oatSkillDirs, findings);
|
|
736
898
|
await collectGateabilityFindings(skillsRoot, options.gateSkillNames, findings);
|
|
737
899
|
if (options.baseRef) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.64",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open Agent Toolkit CLI",
|
|
6
6
|
"homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"ora": "^9.0.0",
|
|
35
35
|
"yaml": "2.8.2",
|
|
36
36
|
"zod": "^3.25.76",
|
|
37
|
-
"@open-agent-toolkit/control-plane": "0.2.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.2.64"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|