@agent-native/core 0.51.9 → 0.51.11
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/dist/cli/index.js +3 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +47 -11
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/skills.d.ts +25 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +268 -39
- package/dist/cli/skills.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/skills.js
CHANGED
|
@@ -1889,6 +1889,10 @@ A few recap-specific authoring rules the registry table cannot encode:
|
|
|
1889
1889
|
shared optional \`summary\` / \`editable\` envelope; give a block a heading by
|
|
1890
1890
|
placing a \`rich-text\` block with a Markdown \`###\` heading directly above it
|
|
1891
1891
|
(blocks no longer take a \`title\`).
|
|
1892
|
+
- Every capitalized block component must be self-closing (\`<RichText ... />\`) or
|
|
1893
|
+
explicitly closed around children (\`<RichText ...>...</RichText>\`). Never
|
|
1894
|
+
leave a bare opening tag like \`<RichText ...>\` in a paragraph; MDX treats it
|
|
1895
|
+
as unclosed JSX and import fails before the recap can render.
|
|
1892
1896
|
- \`Endpoint\`: prose \`description\` is the MDX **children** (body between the
|
|
1893
1897
|
tags), not an attribute; for a WebSocket upgrade use \`method="GET"\`. Each
|
|
1894
1898
|
request/response \`example\` is a JSON **string** (the renderer parses it into
|
|
@@ -2635,12 +2639,19 @@ function clientPromptOptions() {
|
|
|
2635
2639
|
hint: CLIENT_HINTS[client],
|
|
2636
2640
|
}));
|
|
2637
2641
|
}
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2642
|
+
const DEFAULT_PUBLIC_SKILLS_SOURCE = "BuilderIO/skills";
|
|
2643
|
+
const PUBLIC_SKILL_TARGET_PREFIX = "public-skills:";
|
|
2644
|
+
const BUILT_IN_SKILL_PROMPT_OPTIONS = [
|
|
2645
|
+
{
|
|
2646
|
+
value: "assets",
|
|
2647
|
+
label: "assets",
|
|
2648
|
+
hint: BUILT_IN_APP_SKILLS.assets.manifest.description,
|
|
2649
|
+
},
|
|
2650
|
+
{
|
|
2651
|
+
value: "design-exploration",
|
|
2652
|
+
label: "design-exploration",
|
|
2653
|
+
hint: BUILT_IN_APP_SKILLS.design.manifest.description,
|
|
2654
|
+
},
|
|
2644
2655
|
{
|
|
2645
2656
|
value: "visual-plan",
|
|
2646
2657
|
label: "visual-plan",
|
|
@@ -2651,9 +2662,58 @@ const PLAN_SKILL_PROMPT_OPTIONS = [
|
|
|
2651
2662
|
label: "visual-recap",
|
|
2652
2663
|
hint: "Interactive visual recap that maps PRs/diffs with diagrams, annotated diffs, API/schema summaries, and review notes.",
|
|
2653
2664
|
},
|
|
2665
|
+
{
|
|
2666
|
+
value: "context-xray",
|
|
2667
|
+
label: "context-xray",
|
|
2668
|
+
hint: BUILT_IN_APP_SKILLS["context-xray"].manifest.description,
|
|
2669
|
+
},
|
|
2654
2670
|
];
|
|
2655
|
-
|
|
2656
|
-
|
|
2671
|
+
const DEFAULT_SKILL_PROMPT_TARGETS = ["visual-plan", "visual-recap"];
|
|
2672
|
+
function publicSkillEntries(options) {
|
|
2673
|
+
if (options.catalogMode !== "all")
|
|
2674
|
+
return [];
|
|
2675
|
+
const seen = new Set();
|
|
2676
|
+
return (options.publicSkillEntries ?? [])
|
|
2677
|
+
.map((entry) => ({
|
|
2678
|
+
name: entry.name.trim().toLowerCase(),
|
|
2679
|
+
description: entry.description,
|
|
2680
|
+
}))
|
|
2681
|
+
.filter((entry) => {
|
|
2682
|
+
if (!entry.name || isKnownSkill(entry.name) || seen.has(entry.name)) {
|
|
2683
|
+
return false;
|
|
2684
|
+
}
|
|
2685
|
+
seen.add(entry.name);
|
|
2686
|
+
return true;
|
|
2687
|
+
})
|
|
2688
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
2689
|
+
}
|
|
2690
|
+
function publicSkillNames(options) {
|
|
2691
|
+
return new Set(publicSkillEntries(options).map((entry) => entry.name));
|
|
2692
|
+
}
|
|
2693
|
+
function publicSkillPromptOptions(options) {
|
|
2694
|
+
return publicSkillEntries(options).map((entry) => ({
|
|
2695
|
+
value: entry.name,
|
|
2696
|
+
label: entry.name,
|
|
2697
|
+
hint: entry.description ?? "Public skill from the BuilderIO skills catalog.",
|
|
2698
|
+
}));
|
|
2699
|
+
}
|
|
2700
|
+
function skillPromptOptions(options = {}) {
|
|
2701
|
+
return [
|
|
2702
|
+
...BUILT_IN_SKILL_PROMPT_OPTIONS,
|
|
2703
|
+
...publicSkillPromptOptions(options),
|
|
2704
|
+
];
|
|
2705
|
+
}
|
|
2706
|
+
function publicSkillSelectionTarget(skillNames) {
|
|
2707
|
+
return `${PUBLIC_SKILL_TARGET_PREFIX}${skillNames.join(",")}`;
|
|
2708
|
+
}
|
|
2709
|
+
function publicSkillSelectionNames(target) {
|
|
2710
|
+
if (!target.startsWith(PUBLIC_SKILL_TARGET_PREFIX))
|
|
2711
|
+
return null;
|
|
2712
|
+
return target
|
|
2713
|
+
.slice(PUBLIC_SKILL_TARGET_PREFIX.length)
|
|
2714
|
+
.split(",")
|
|
2715
|
+
.map((name) => name.trim().toLowerCase())
|
|
2716
|
+
.filter(Boolean);
|
|
2657
2717
|
}
|
|
2658
2718
|
function prVisualRecapWorkflowPath(baseDir) {
|
|
2659
2719
|
return path.join(baseDir, ".github", "workflows", "pr-visual-recap.yml");
|
|
@@ -2783,6 +2843,18 @@ async function promptForPlanMcpUrl() {
|
|
|
2783
2843
|
}
|
|
2784
2844
|
return String(result).trim();
|
|
2785
2845
|
}
|
|
2846
|
+
async function promptForUpdateInstructions() {
|
|
2847
|
+
const clack = await import("@clack/prompts");
|
|
2848
|
+
const result = await clack.confirm({
|
|
2849
|
+
message: "Add managed AGENTS.md / CLAUDE.md instructions for always-on skill behavior?",
|
|
2850
|
+
initialValue: true,
|
|
2851
|
+
});
|
|
2852
|
+
if (clack.isCancel(result)) {
|
|
2853
|
+
clack.cancel("Skipped managed instruction updates.");
|
|
2854
|
+
return null;
|
|
2855
|
+
}
|
|
2856
|
+
return Boolean(result);
|
|
2857
|
+
}
|
|
2786
2858
|
async function promptForSkills(context) {
|
|
2787
2859
|
const clack = await import("@clack/prompts");
|
|
2788
2860
|
const result = await clack.multiselect({
|
|
@@ -2844,12 +2916,66 @@ function targetIncludesPlans(target) {
|
|
|
2844
2916
|
function targetsIncludePlans(targets) {
|
|
2845
2917
|
return targets.some(targetIncludesPlans);
|
|
2846
2918
|
}
|
|
2919
|
+
function planSkillNamesSelected(skillNames) {
|
|
2920
|
+
return Boolean(skillNames?.some((name) => normalizeKnownSkillTarget(name) === "visual-plans"));
|
|
2921
|
+
}
|
|
2922
|
+
function recapSkillNamesSelected(skillNames) {
|
|
2923
|
+
return Boolean(skillNames?.some((name) => {
|
|
2924
|
+
const normalized = name.trim().toLowerCase();
|
|
2925
|
+
return (normalized === "visual-recap" ||
|
|
2926
|
+
normalized === "visual-recaps" ||
|
|
2927
|
+
normalizeKnownSkillTarget(normalized) === "visual-plans");
|
|
2928
|
+
}));
|
|
2929
|
+
}
|
|
2930
|
+
function resolveSelectedSkillTargets(selected, options) {
|
|
2931
|
+
const publicNames = publicSkillNames(options);
|
|
2932
|
+
const builtInSelections = [];
|
|
2933
|
+
const publicSelections = [];
|
|
2934
|
+
for (const raw of selected) {
|
|
2935
|
+
const skill = raw.trim().toLowerCase();
|
|
2936
|
+
if (!skill)
|
|
2937
|
+
continue;
|
|
2938
|
+
if (isKnownSkill(skill)) {
|
|
2939
|
+
builtInSelections.push(skill);
|
|
2940
|
+
continue;
|
|
2941
|
+
}
|
|
2942
|
+
if (publicNames.has(skill)) {
|
|
2943
|
+
publicSelections.push(skill);
|
|
2944
|
+
continue;
|
|
2945
|
+
}
|
|
2946
|
+
throw new Error(`Unknown skill: ${raw}. Run "npx @agent-native/core@latest skills list".`);
|
|
2947
|
+
}
|
|
2948
|
+
const out = [];
|
|
2949
|
+
const planSubskills = ["visual-plan", "visual-recap"];
|
|
2950
|
+
const selectedPlanSubskills = planSubskills.filter((skill) => builtInSelections.includes(skill));
|
|
2951
|
+
if (selectedPlanSubskills.length === planSubskills.length) {
|
|
2952
|
+
out.push("visual-plans");
|
|
2953
|
+
}
|
|
2954
|
+
else {
|
|
2955
|
+
out.push(...selectedPlanSubskills);
|
|
2956
|
+
}
|
|
2957
|
+
out.push(...builtInSelections.filter((skill) => !planSubskills.includes(skill) && !out.includes(skill)));
|
|
2958
|
+
if (publicSelections.length > 0) {
|
|
2959
|
+
out.push(publicSkillSelectionTarget([...new Set(publicSelections)]));
|
|
2960
|
+
}
|
|
2961
|
+
return out;
|
|
2962
|
+
}
|
|
2847
2963
|
async function resolveSkillTargets(parsed, options) {
|
|
2964
|
+
if (!parsed.target && parsed.plainSkillNames?.length) {
|
|
2965
|
+
return resolveSelectedSkillTargets(parsed.plainSkillNames, options);
|
|
2966
|
+
}
|
|
2848
2967
|
if (parsed.target || !shouldPrompt(parsed, options)) {
|
|
2849
|
-
|
|
2968
|
+
const target = parsed.target ?? "assets";
|
|
2969
|
+
if (!parsed.target)
|
|
2970
|
+
return [target];
|
|
2971
|
+
const normalizedTarget = target.trim().toLowerCase();
|
|
2972
|
+
if (publicSkillNames(options).has(normalizedTarget)) {
|
|
2973
|
+
return [publicSkillSelectionTarget([normalizedTarget])];
|
|
2974
|
+
}
|
|
2975
|
+
return [target];
|
|
2850
2976
|
}
|
|
2851
2977
|
const prompt = options.promptSkills ?? promptForSkills;
|
|
2852
|
-
const promptOptions = skillPromptOptions();
|
|
2978
|
+
const promptOptions = skillPromptOptions(options);
|
|
2853
2979
|
// The interactive multiselect skill picker is about to be shown (no --skill /
|
|
2854
2980
|
// target passed and we are interactive) — record the funnel "prompted" step.
|
|
2855
2981
|
options.telemetry?.track("skills_cli skills prompted", {
|
|
@@ -2857,22 +2983,12 @@ async function resolveSkillTargets(parsed, options) {
|
|
|
2857
2983
|
available: promptOptions.map((option) => option.value).join(","),
|
|
2858
2984
|
});
|
|
2859
2985
|
const selected = await prompt({
|
|
2860
|
-
initialTargets:
|
|
2986
|
+
initialTargets: DEFAULT_SKILL_PROMPT_TARGETS,
|
|
2861
2987
|
options: promptOptions,
|
|
2862
2988
|
});
|
|
2863
2989
|
if (!selected || selected.length === 0)
|
|
2864
2990
|
return null;
|
|
2865
|
-
|
|
2866
|
-
// them through the bundle target — that registers/authenticates the connector
|
|
2867
|
-
// once instead of twice.
|
|
2868
|
-
const planSubskills = ["visual-plan", "visual-recap"];
|
|
2869
|
-
if (planSubskills.every((skill) => selected.includes(skill))) {
|
|
2870
|
-
return [
|
|
2871
|
-
"visual-plans",
|
|
2872
|
-
...selected.filter((s) => !planSubskills.includes(s)),
|
|
2873
|
-
];
|
|
2874
|
-
}
|
|
2875
|
-
return selected;
|
|
2991
|
+
return resolveSelectedSkillTargets(selected, options);
|
|
2876
2992
|
}
|
|
2877
2993
|
export function parseSkillsArgs(argv) {
|
|
2878
2994
|
const first = argv[0];
|
|
@@ -2928,6 +3044,14 @@ export function parseSkillsArgs(argv) {
|
|
|
2928
3044
|
out.client = value;
|
|
2929
3045
|
out.clientExplicit = true;
|
|
2930
3046
|
}
|
|
3047
|
+
else if ((value = eat("--agent")) !== undefined) {
|
|
3048
|
+
out.client = value;
|
|
3049
|
+
out.clientExplicit = true;
|
|
3050
|
+
}
|
|
3051
|
+
else if ((value = eat("-a")) !== undefined) {
|
|
3052
|
+
out.client = value;
|
|
3053
|
+
out.clientExplicit = true;
|
|
3054
|
+
}
|
|
2931
3055
|
else if ((value = eat("--skill")) !== undefined) {
|
|
2932
3056
|
out.plainSkillNames = [...(out.plainSkillNames ?? []), value];
|
|
2933
3057
|
}
|
|
@@ -2938,6 +3062,8 @@ export function parseSkillsArgs(argv) {
|
|
|
2938
3062
|
out.scope = value;
|
|
2939
3063
|
out.scopeExplicit = true;
|
|
2940
3064
|
}
|
|
3065
|
+
else if ((value = eat("--cwd")) !== undefined)
|
|
3066
|
+
out.baseDir = value;
|
|
2941
3067
|
else if ((value = eat("--mcp-url")) !== undefined)
|
|
2942
3068
|
out.mcpUrl = value;
|
|
2943
3069
|
else if ((value = eat("--mode")) !== undefined)
|
|
@@ -2954,6 +3080,18 @@ export function parseSkillsArgs(argv) {
|
|
|
2954
3080
|
out.dryRun = true;
|
|
2955
3081
|
else if (arg === "--json")
|
|
2956
3082
|
out.printJson = true;
|
|
3083
|
+
else if (arg === "-g" || arg === "--global") {
|
|
3084
|
+
out.scope = "user";
|
|
3085
|
+
out.scopeExplicit = true;
|
|
3086
|
+
}
|
|
3087
|
+
else if (arg === "--project") {
|
|
3088
|
+
out.scope = "project";
|
|
3089
|
+
out.scopeExplicit = true;
|
|
3090
|
+
}
|
|
3091
|
+
else if (arg === "--copy") {
|
|
3092
|
+
// Compatibility with @agent-native/skills. Core always copies skill
|
|
3093
|
+
// instructions instead of linking to the source repo.
|
|
3094
|
+
}
|
|
2957
3095
|
else if (arg === "--mcp-only")
|
|
2958
3096
|
out.instructions = false;
|
|
2959
3097
|
else if (arg === "--instructions-only" || arg === "--no-mcp")
|
|
@@ -3230,6 +3368,12 @@ function agentNativeSkillsInstallArgs(parsed, target, clients) {
|
|
|
3230
3368
|
args.push("--with-github-action");
|
|
3231
3369
|
if (parsed.force)
|
|
3232
3370
|
args.push("--force");
|
|
3371
|
+
if (parsed.planMode)
|
|
3372
|
+
args.push("--mode", parsed.planMode);
|
|
3373
|
+
if (parsed.mcpUrl)
|
|
3374
|
+
args.push("--mcp-url", parsed.mcpUrl);
|
|
3375
|
+
if (!parsed.mcp)
|
|
3376
|
+
args.push("--no-mcp");
|
|
3233
3377
|
if (!parsed.connect)
|
|
3234
3378
|
args.push("--no-connect");
|
|
3235
3379
|
for (const skill of parsed.plainSkillNames ?? []) {
|
|
@@ -3241,6 +3385,8 @@ function agentNativeSkillsInstallArgs(parsed, target, clients) {
|
|
|
3241
3385
|
args.push("--no-update-instructions");
|
|
3242
3386
|
if (parsed.yes)
|
|
3243
3387
|
args.push("--yes");
|
|
3388
|
+
if (parsed.dryRun)
|
|
3389
|
+
args.push("--dry-run");
|
|
3244
3390
|
return args;
|
|
3245
3391
|
}
|
|
3246
3392
|
async function addPlainSkillRepo(parsed, options) {
|
|
@@ -3248,11 +3394,12 @@ async function addPlainSkillRepo(parsed, options) {
|
|
|
3248
3394
|
if (!parsed.instructions && parsed.mcp) {
|
|
3249
3395
|
throw new Error("Plain skill repositories only install skill instructions. Run without --mcp-only.");
|
|
3250
3396
|
}
|
|
3251
|
-
if (parsed.mcpUrl) {
|
|
3397
|
+
if (parsed.mcpUrl && !planSkillNamesSelected(parsed.plainSkillNames)) {
|
|
3252
3398
|
throw new Error("--mcp-url only applies to app-backed Agent Native skills.");
|
|
3253
3399
|
}
|
|
3254
3400
|
const clients = parsed.clients ?? resolveClients(parsed.client);
|
|
3255
3401
|
const skillsAgents = skillsAgentsForClients(clients);
|
|
3402
|
+
const selectedSkillNames = parsed.plainSkillNames ?? [];
|
|
3256
3403
|
if (skillsAgents.length === 0) {
|
|
3257
3404
|
throw new Error("Plain skill repositories can only install instructions for Codex or Claude Code clients.");
|
|
3258
3405
|
}
|
|
@@ -3265,15 +3412,17 @@ async function addPlainSkillRepo(parsed, options) {
|
|
|
3265
3412
|
throw new Error(`npx @agent-native/skills@latest add exited with ${code}.`);
|
|
3266
3413
|
}
|
|
3267
3414
|
options.telemetry?.track("skills_cli install completed", {
|
|
3268
|
-
skills: target,
|
|
3415
|
+
skills: selectedSkillNames.length ? selectedSkillNames.join(",") : target,
|
|
3269
3416
|
clients: clients.join(","),
|
|
3270
3417
|
scope: parsed.scope,
|
|
3271
3418
|
dryRun: Boolean(parsed.dryRun),
|
|
3272
3419
|
});
|
|
3273
3420
|
return {
|
|
3274
3421
|
id: target,
|
|
3275
|
-
displayName:
|
|
3276
|
-
|
|
3422
|
+
displayName: selectedSkillNames.length
|
|
3423
|
+
? selectedSkillNames.join(", ")
|
|
3424
|
+
: target,
|
|
3425
|
+
skillNames: selectedSkillNames,
|
|
3277
3426
|
skillsAgents,
|
|
3278
3427
|
mcpUrl: "",
|
|
3279
3428
|
mcpClients: [],
|
|
@@ -3356,6 +3505,14 @@ async function connectAfterEnsure(installTarget, clients, parsed, options) {
|
|
|
3356
3505
|
}
|
|
3357
3506
|
export async function addAgentNativeSkill(parsed, options = {}) {
|
|
3358
3507
|
const target = parsed.target ?? "assets";
|
|
3508
|
+
const publicSelection = publicSkillSelectionNames(target);
|
|
3509
|
+
if (publicSelection) {
|
|
3510
|
+
return addPlainSkillRepo({
|
|
3511
|
+
...parsed,
|
|
3512
|
+
target: options.publicSkillSource ?? DEFAULT_PUBLIC_SKILLS_SOURCE,
|
|
3513
|
+
plainSkillNames: publicSelection,
|
|
3514
|
+
}, options);
|
|
3515
|
+
}
|
|
3359
3516
|
const knownTarget = normalizeKnownSkillTarget(target);
|
|
3360
3517
|
const planMode = knownTarget === "visual-plans"
|
|
3361
3518
|
? (parsed.planMode ?? (parsed.mcpUrl ? "self-hosted" : "hosted"))
|
|
@@ -3651,15 +3808,29 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3651
3808
|
installTarget.cleanup?.();
|
|
3652
3809
|
}
|
|
3653
3810
|
}
|
|
3654
|
-
function listSkills() {
|
|
3655
|
-
return
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3811
|
+
function listSkills(options = {}) {
|
|
3812
|
+
return [
|
|
3813
|
+
...Object.values(BUILT_IN_APP_SKILLS).map((entry) => ({
|
|
3814
|
+
id: entry.manifest.id,
|
|
3815
|
+
aliases: BUILT_IN_APP_SKILL_DISPLAY_ALIASES[entry.manifest.id] ?? [],
|
|
3816
|
+
name: entry.manifest.displayName,
|
|
3817
|
+
description: entry.manifest.description,
|
|
3818
|
+
mcpUrl: isLocalOnlyBuiltInSkill(entry)
|
|
3819
|
+
? ""
|
|
3820
|
+
: entry.manifest.hosted.mcpUrl,
|
|
3821
|
+
local: isLocalOnlyBuiltInSkill(entry),
|
|
3822
|
+
source: "agent-native",
|
|
3823
|
+
})),
|
|
3824
|
+
...publicSkillEntries(options).map((entry) => ({
|
|
3825
|
+
id: entry.name,
|
|
3826
|
+
aliases: [],
|
|
3827
|
+
name: entry.name,
|
|
3828
|
+
description: entry.description ?? "Public skill from the BuilderIO skills catalog.",
|
|
3829
|
+
mcpUrl: "",
|
|
3830
|
+
local: true,
|
|
3831
|
+
source: options.publicSkillSource ?? DEFAULT_PUBLIC_SKILLS_SOURCE,
|
|
3832
|
+
})),
|
|
3833
|
+
];
|
|
3663
3834
|
}
|
|
3664
3835
|
function skillStateJson(state) {
|
|
3665
3836
|
return {
|
|
@@ -3692,6 +3863,39 @@ function planModeSummary(mode) {
|
|
|
3692
3863
|
return "Self-hosted/custom Plan app";
|
|
3693
3864
|
return "Hosted Plans - shareable links and comments";
|
|
3694
3865
|
}
|
|
3866
|
+
function instructionContentForSkill(skillName) {
|
|
3867
|
+
if (skillName === "quick-recap") {
|
|
3868
|
+
return "When writing final response status indicators, use the /quick-recap skill always.";
|
|
3869
|
+
}
|
|
3870
|
+
if (skillName === "efficient-fable") {
|
|
3871
|
+
return "When operating as Claude Fable, use the /efficient-fable skill always.";
|
|
3872
|
+
}
|
|
3873
|
+
if (skillName === "efficient-frontier") {
|
|
3874
|
+
return "When using a high-cost frontier model for codebase-heavy work, use the /efficient-frontier skill always.";
|
|
3875
|
+
}
|
|
3876
|
+
if (skillName === "stay-within-limits") {
|
|
3877
|
+
return "When long-running or parallel work needs usage-limit checks, use the /stay-within-limits skill always.";
|
|
3878
|
+
}
|
|
3879
|
+
if (skillName === "visual-plan") {
|
|
3880
|
+
return "When work needs an interactive visual plan before implementation, use the /visual-plan skill always.";
|
|
3881
|
+
}
|
|
3882
|
+
if (skillName === "visual-recap") {
|
|
3883
|
+
return "When a PR, branch, commit, or diff needs an interactive visual recap, use the /visual-recap skill always.";
|
|
3884
|
+
}
|
|
3885
|
+
return null;
|
|
3886
|
+
}
|
|
3887
|
+
function selectedPlainSkillNamesForInstructionPrompt(targets, parsed) {
|
|
3888
|
+
const names = new Set(parsed.plainSkillNames ?? []);
|
|
3889
|
+
for (const target of targets) {
|
|
3890
|
+
for (const name of publicSkillSelectionNames(target) ?? []) {
|
|
3891
|
+
names.add(name);
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
return [...names];
|
|
3895
|
+
}
|
|
3896
|
+
function hasManagedInstructionBlock(skillNames) {
|
|
3897
|
+
return skillNames.some((name) => Boolean(instructionContentForSkill(name)));
|
|
3898
|
+
}
|
|
3695
3899
|
function runSkillsStatusOrUpdate(parsed, options, update) {
|
|
3696
3900
|
const before = collectSkillInstallStates(parsed, options);
|
|
3697
3901
|
const changed = update ? updateSkillInstallStates(before, parsed.dryRun) : [];
|
|
@@ -3748,6 +3952,9 @@ function readCliVersion() {
|
|
|
3748
3952
|
}
|
|
3749
3953
|
export async function runSkills(argv, options = {}) {
|
|
3750
3954
|
const parsed = parseSkillsArgs(argv);
|
|
3955
|
+
if (parsed.baseDir) {
|
|
3956
|
+
options = { ...options, baseDir: path.resolve(parsed.baseDir) };
|
|
3957
|
+
}
|
|
3751
3958
|
const log = parsed.printJson
|
|
3752
3959
|
? undefined
|
|
3753
3960
|
: (message) => process.stdout.write(`${message}\n`);
|
|
@@ -3760,6 +3967,7 @@ export async function runSkills(argv, options = {}) {
|
|
|
3760
3967
|
// `npx @agent-native/skills@latest add …`; this env guard tells that child process
|
|
3761
3968
|
// to run its OWN headless installer instead of bouncing back into core,
|
|
3762
3969
|
// which would otherwise be an infinite skills → core → skills loop.
|
|
3970
|
+
const previousDirect = process.env.AGENT_NATIVE_SKILLS_DIRECT;
|
|
3763
3971
|
process.env.AGENT_NATIVE_SKILLS_DIRECT = "1";
|
|
3764
3972
|
// Best-effort install-funnel telemetry. Created once per run and flushed in a
|
|
3765
3973
|
// finally so events send on success, error, and cancellation — the CLI is
|
|
@@ -3776,7 +3984,7 @@ export async function runSkills(argv, options = {}) {
|
|
|
3776
3984
|
try {
|
|
3777
3985
|
telemetry.track("skills_cli started");
|
|
3778
3986
|
if (parsed.command === "list") {
|
|
3779
|
-
const skills = listSkills();
|
|
3987
|
+
const skills = listSkills(optionsWithTelemetry);
|
|
3780
3988
|
telemetry.track("skills_cli skills listed", {
|
|
3781
3989
|
availableCount: skills.length,
|
|
3782
3990
|
available: skills.map((skill) => skill.id).join(","),
|
|
@@ -3811,10 +4019,11 @@ export async function runSkills(argv, options = {}) {
|
|
|
3811
4019
|
// Best-effort "took everything offered" signal: compare against the
|
|
3812
4020
|
// interactive picker's option count (the plan sub-skills collapse into a
|
|
3813
4021
|
// single bundle target, so this is approximate, like the standalone CLI).
|
|
3814
|
-
selectedAll: targets.length === skillPromptOptions().length,
|
|
4022
|
+
selectedAll: targets.length === skillPromptOptions(options).length,
|
|
3815
4023
|
preselected,
|
|
3816
4024
|
});
|
|
3817
|
-
const includesPlans = targetsIncludePlans(targets)
|
|
4025
|
+
const includesPlans = targetsIncludePlans(targets) ||
|
|
4026
|
+
planSkillNamesSelected(parsed.plainSkillNames);
|
|
3818
4027
|
if (parsed.planMode && !includesPlans) {
|
|
3819
4028
|
throw new Error("--mode only applies to visual-plan / visual-recap.");
|
|
3820
4029
|
}
|
|
@@ -3874,6 +4083,20 @@ export async function runSkills(argv, options = {}) {
|
|
|
3874
4083
|
parsed.scope = scope;
|
|
3875
4084
|
}
|
|
3876
4085
|
telemetry.track("skills_cli scope selected", { scope: parsed.scope });
|
|
4086
|
+
const instructionSkillNames = selectedPlainSkillNamesForInstructionPrompt(targets, parsed);
|
|
4087
|
+
if (parsed.updateInstructions === undefined &&
|
|
4088
|
+
hasManagedInstructionBlock(instructionSkillNames) &&
|
|
4089
|
+
shouldPrompt(parsed, options)) {
|
|
4090
|
+
const prompt = options.promptUpdateInstructions ?? promptForUpdateInstructions;
|
|
4091
|
+
const choice = await prompt();
|
|
4092
|
+
if (choice === null) {
|
|
4093
|
+
telemetry.track("skills_cli cancelled", {
|
|
4094
|
+
step: "managed-instructions",
|
|
4095
|
+
});
|
|
4096
|
+
return;
|
|
4097
|
+
}
|
|
4098
|
+
parsed.updateInstructions = choice === true;
|
|
4099
|
+
}
|
|
3877
4100
|
// Decide the optional PR Visual Recap GitHub Action UP FRONT — before any
|
|
3878
4101
|
// install or MCP registration — so every prompt is answered before we touch
|
|
3879
4102
|
// disk. The choice is threaded into each install via `withGithubAction` +
|
|
@@ -3884,7 +4107,7 @@ export async function runSkills(argv, options = {}) {
|
|
|
3884
4107
|
return false;
|
|
3885
4108
|
const only = builtInOnlySkillNames(target);
|
|
3886
4109
|
return !only || only.includes("visual-recap");
|
|
3887
|
-
});
|
|
4110
|
+
}) || recapSkillNamesSelected(parsed.plainSkillNames);
|
|
3888
4111
|
if (anyRecapTarget &&
|
|
3889
4112
|
!parsed.withGithubAction &&
|
|
3890
4113
|
!fs.existsSync(prVisualRecapWorkflowPath(recapBaseDir)) &&
|
|
@@ -4028,6 +4251,12 @@ export async function runSkills(argv, options = {}) {
|
|
|
4028
4251
|
}
|
|
4029
4252
|
finally {
|
|
4030
4253
|
await telemetry.flush();
|
|
4254
|
+
if (previousDirect === undefined) {
|
|
4255
|
+
delete process.env.AGENT_NATIVE_SKILLS_DIRECT;
|
|
4256
|
+
}
|
|
4257
|
+
else {
|
|
4258
|
+
process.env.AGENT_NATIVE_SKILLS_DIRECT = previousDirect;
|
|
4259
|
+
}
|
|
4031
4260
|
}
|
|
4032
4261
|
}
|
|
4033
4262
|
//# sourceMappingURL=skills.js.map
|