agent-skills-standard 2.4.8 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +233 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Sync 242 AI coding standards to any project in one command.** Works with Cursor, Claude Code, GitHub Copilot, Gemini, Windsurf, Trae, Kiro, and Roo.
|
|
7
7
|
|
|
8
|
-
**Current release:** `v2.
|
|
8
|
+
**Current release:** `v2.5.1` — automated SkillSpector security scanning, pull request evaluation gates, and verified release tags.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
npx agent-skills-standard@latest init # detect your stack
|
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ let child_process = require("child_process");
|
|
|
43
43
|
let fs = require("fs");
|
|
44
44
|
var package_default = {
|
|
45
45
|
name: "agent-skills-standard",
|
|
46
|
-
version: "2.
|
|
46
|
+
version: "2.5.1",
|
|
47
47
|
description: "A CLI to manage and sync AI agent skills standard for Cursor, Claude, Copilot, Windsurf, and more.",
|
|
48
48
|
main: "dist/index.js",
|
|
49
49
|
bin: {
|
|
@@ -83,7 +83,7 @@ var package_default = {
|
|
|
83
83
|
"dotenv": "^17.2.3",
|
|
84
84
|
"fs-extra": "^11.2.0",
|
|
85
85
|
"inquirer": "^8.2.5",
|
|
86
|
-
"js-yaml": "^4.
|
|
86
|
+
"js-yaml": "^4.2.0",
|
|
87
87
|
"picocolors": "^1.0.0",
|
|
88
88
|
"zod": "^3.22.4"
|
|
89
89
|
},
|
|
@@ -342,6 +342,7 @@ var Framework = /* @__PURE__ */ function(Framework) {
|
|
|
342
342
|
Framework["Android"] = "android";
|
|
343
343
|
Framework["iOS"] = "ios";
|
|
344
344
|
Framework["Laravel"] = "laravel";
|
|
345
|
+
Framework["Python"] = "python";
|
|
345
346
|
return Framework;
|
|
346
347
|
}({});
|
|
347
348
|
//#endregion
|
|
@@ -672,7 +673,8 @@ var BACKEND_FRAMEWORKS = [
|
|
|
672
673
|
Framework.NestJS,
|
|
673
674
|
Framework.Golang,
|
|
674
675
|
Framework.SpringBoot,
|
|
675
|
-
Framework.Laravel
|
|
676
|
+
Framework.Laravel,
|
|
677
|
+
Framework.Python
|
|
676
678
|
];
|
|
677
679
|
var FRONTEND_FRAMEWORKS = [
|
|
678
680
|
Framework.React,
|
|
@@ -1007,6 +1009,20 @@ var getFrameworkDefinition = (id) => {
|
|
|
1007
1009
|
javascript: ["resources/js", "vite.config.js"]
|
|
1008
1010
|
}
|
|
1009
1011
|
};
|
|
1012
|
+
case Framework.Python: return {
|
|
1013
|
+
id,
|
|
1014
|
+
name: "Python",
|
|
1015
|
+
languages: ["python"],
|
|
1016
|
+
detectionFiles: [
|
|
1017
|
+
"pyproject.toml",
|
|
1018
|
+
"requirements.txt",
|
|
1019
|
+
"setup.py",
|
|
1020
|
+
"setup.cfg",
|
|
1021
|
+
"Pipfile",
|
|
1022
|
+
"poetry.lock",
|
|
1023
|
+
"uv.lock"
|
|
1024
|
+
]
|
|
1025
|
+
};
|
|
1010
1026
|
}
|
|
1011
1027
|
};
|
|
1012
1028
|
var SUPPORTED_AGENTS = Object.values(Agent).map(getAgentDefinition);
|
|
@@ -1042,11 +1058,181 @@ var SkillConfigSchema = zod.z.object({
|
|
|
1042
1058
|
mcp: McpConfigSchema.optional()
|
|
1043
1059
|
});
|
|
1044
1060
|
var DEFAULT_SDLC_SUPPORT_CATEGORIES = ["quality-engineering"];
|
|
1061
|
+
var PRIMARY_CONFIG_FILE = ".skillsrc";
|
|
1062
|
+
var LEGACY_YAML_CONFIG_FILE = ".skillsrc.yaml";
|
|
1045
1063
|
/**
|
|
1046
1064
|
* Service for managing the `.skillsrc` configuration file.
|
|
1047
1065
|
* Handles loading, saving, and initial construction of the configuration based on project metadata.
|
|
1048
1066
|
*/
|
|
1049
1067
|
var ConfigService = class {
|
|
1068
|
+
getPrimaryConfigPath(cwd) {
|
|
1069
|
+
return path.default.join(cwd, PRIMARY_CONFIG_FILE);
|
|
1070
|
+
}
|
|
1071
|
+
getLegacyYamlConfigPath(cwd) {
|
|
1072
|
+
return path.default.join(cwd, LEGACY_YAML_CONFIG_FILE);
|
|
1073
|
+
}
|
|
1074
|
+
async resolveConfigPath(cwd) {
|
|
1075
|
+
const primaryPath = this.getPrimaryConfigPath(cwd);
|
|
1076
|
+
if (await fs_extra.default.pathExists(primaryPath)) return primaryPath;
|
|
1077
|
+
const legacyYamlPath = this.getLegacyYamlConfigPath(cwd);
|
|
1078
|
+
if (await fs_extra.default.pathExists(legacyYamlPath)) return legacyYamlPath;
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
dumpConfig(config) {
|
|
1082
|
+
return js_yaml.default.dump(config, {
|
|
1083
|
+
noRefs: true,
|
|
1084
|
+
lineWidth: -1
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
isRecord(value) {
|
|
1088
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1089
|
+
}
|
|
1090
|
+
stripAngleBrackets(value) {
|
|
1091
|
+
const trimmed = value.trim();
|
|
1092
|
+
if (trimmed.startsWith("<") && trimmed.endsWith(">")) return trimmed.slice(1, -1).trim();
|
|
1093
|
+
return trimmed;
|
|
1094
|
+
}
|
|
1095
|
+
parseLegacyList(value) {
|
|
1096
|
+
const trimmed = value.trim();
|
|
1097
|
+
if (!trimmed || trimmed === "[]") return [];
|
|
1098
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) return trimmed.slice(1, -1).split(",").map((item) => item.trim()).filter(Boolean);
|
|
1099
|
+
if (trimmed.startsWith("- ")) return trimmed.replace(/^-\s+/, "").split(/\s+-\s+/).map((item) => item.trim()).filter(Boolean);
|
|
1100
|
+
return trimmed.split(",").map((item) => item.trim()).filter(Boolean);
|
|
1101
|
+
}
|
|
1102
|
+
parseLegacyBoolean(value) {
|
|
1103
|
+
const normalized = value.trim().toLowerCase();
|
|
1104
|
+
if (normalized === "true") return true;
|
|
1105
|
+
if (normalized === "false") return false;
|
|
1106
|
+
}
|
|
1107
|
+
migrateLegacyTextConfig(content) {
|
|
1108
|
+
const lines = content.split(/\r?\n/);
|
|
1109
|
+
const registryLine = lines.find((line) => line.trim().startsWith("registry:"));
|
|
1110
|
+
const agentsIndex = lines.findIndex((line) => line.trim() === "agents:");
|
|
1111
|
+
const skillsIndex = lines.findIndex((line) => line.trim() === "skills:");
|
|
1112
|
+
if (!registryLine || agentsIndex === -1 || skillsIndex === -1) return null;
|
|
1113
|
+
const registryMatch = registryLine.match(/^\s*registry:\s*(.+)$/);
|
|
1114
|
+
if (!registryMatch) return null;
|
|
1115
|
+
const config = {
|
|
1116
|
+
registry: this.stripAngleBrackets(registryMatch[1]),
|
|
1117
|
+
agents: [],
|
|
1118
|
+
skills: {}
|
|
1119
|
+
};
|
|
1120
|
+
const agents = [];
|
|
1121
|
+
for (let index = agentsIndex + 1; index < skillsIndex; index += 1) {
|
|
1122
|
+
const match = lines[index].match(/^\s*-\s+(.+)$/);
|
|
1123
|
+
if (!match) continue;
|
|
1124
|
+
agents.push(match[1].trim());
|
|
1125
|
+
}
|
|
1126
|
+
config.agents = agents;
|
|
1127
|
+
const sectionNames = new Set([
|
|
1128
|
+
"custom_overrides",
|
|
1129
|
+
"workflows",
|
|
1130
|
+
"mcp"
|
|
1131
|
+
]);
|
|
1132
|
+
let currentCategory = null;
|
|
1133
|
+
for (let index = skillsIndex + 1; index < lines.length; index += 1) {
|
|
1134
|
+
const trimmed = lines[index].trim();
|
|
1135
|
+
if (!trimmed) continue;
|
|
1136
|
+
if (trimmed === "workflows:" || trimmed === "mcp:" || trimmed.startsWith("custom_overrides:")) break;
|
|
1137
|
+
const categoryMatch = trimmed.match(/^([A-Za-z0-9-]+):$/);
|
|
1138
|
+
if (categoryMatch && !sectionNames.has(categoryMatch[1])) {
|
|
1139
|
+
currentCategory = categoryMatch[1];
|
|
1140
|
+
config.skills[currentCategory] = {};
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
if (!currentCategory) continue;
|
|
1144
|
+
const refMatch = trimmed.match(/^ref:\s*(.+)$/);
|
|
1145
|
+
if (refMatch) {
|
|
1146
|
+
config.skills[currentCategory].ref = refMatch[1].trim();
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
const excludeMatch = trimmed.match(/^exclude:\s*(.+)$/);
|
|
1150
|
+
if (excludeMatch) {
|
|
1151
|
+
config.skills[currentCategory].exclude = this.parseLegacyList(excludeMatch[1]);
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
const includeMatch = trimmed.match(/^include:\s*(.+)$/);
|
|
1155
|
+
if (includeMatch) config.skills[currentCategory].include = this.parseLegacyList(includeMatch[1]);
|
|
1156
|
+
}
|
|
1157
|
+
const overridesLine = lines.find((line) => line.trim().startsWith("custom_overrides:"));
|
|
1158
|
+
if (overridesLine) {
|
|
1159
|
+
const match = overridesLine.match(/^\s*custom_overrides:\s*(.*)$/);
|
|
1160
|
+
config.custom_overrides = this.parseLegacyList(match?.[1] ?? "");
|
|
1161
|
+
}
|
|
1162
|
+
const workflowsIndex = lines.findIndex((line) => line.trim() === "workflows:");
|
|
1163
|
+
if (workflowsIndex !== -1) {
|
|
1164
|
+
const workflows = [];
|
|
1165
|
+
for (let index = workflowsIndex + 1; index < lines.length; index += 1) {
|
|
1166
|
+
const trimmed = lines[index].trim();
|
|
1167
|
+
if (!trimmed) continue;
|
|
1168
|
+
if (trimmed === "mcp:") break;
|
|
1169
|
+
const match = trimmed.match(/^-\s+(.+)$/);
|
|
1170
|
+
if (match) workflows.push(match[1].trim());
|
|
1171
|
+
}
|
|
1172
|
+
config.workflows = workflows;
|
|
1173
|
+
}
|
|
1174
|
+
const mcpIndex = lines.findIndex((line) => line.trim() === "mcp:");
|
|
1175
|
+
if (mcpIndex !== -1) {
|
|
1176
|
+
const mcp = {};
|
|
1177
|
+
for (let index = mcpIndex + 1; index < lines.length; index += 1) {
|
|
1178
|
+
const trimmed = lines[index].trim();
|
|
1179
|
+
if (!trimmed) continue;
|
|
1180
|
+
const match = trimmed.match(/^([A-Za-z0-9_]+):\s*(.+)$/);
|
|
1181
|
+
if (!match) continue;
|
|
1182
|
+
const [, key, rawValue] = match;
|
|
1183
|
+
if (key === "enabled" || key === "prompted" || key === "snippets") mcp[key] = this.parseLegacyBoolean(rawValue);
|
|
1184
|
+
else mcp[key] = rawValue.trim();
|
|
1185
|
+
}
|
|
1186
|
+
config.mcp = mcp;
|
|
1187
|
+
}
|
|
1188
|
+
return config;
|
|
1189
|
+
}
|
|
1190
|
+
normalizeRawConfig(rawConfig) {
|
|
1191
|
+
if (!this.isRecord(rawConfig)) return {
|
|
1192
|
+
config: {},
|
|
1193
|
+
migrated: false
|
|
1194
|
+
};
|
|
1195
|
+
const normalized = { ...rawConfig };
|
|
1196
|
+
let migrated = false;
|
|
1197
|
+
if (typeof normalized.registry === "string") {
|
|
1198
|
+
const strippedRegistry = this.stripAngleBrackets(normalized.registry);
|
|
1199
|
+
if (strippedRegistry !== normalized.registry) {
|
|
1200
|
+
normalized.registry = strippedRegistry;
|
|
1201
|
+
migrated = true;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
if (Array.isArray(normalized.agents)) normalized.agents = normalized.agents.map((agent) => {
|
|
1205
|
+
if (typeof agent === "string" && agent.toLowerCase() === "openai") {
|
|
1206
|
+
migrated = true;
|
|
1207
|
+
return Agent.Codex;
|
|
1208
|
+
}
|
|
1209
|
+
return agent;
|
|
1210
|
+
});
|
|
1211
|
+
if (this.isRecord(normalized.skills)) {
|
|
1212
|
+
const normalizedSkills = {};
|
|
1213
|
+
for (const [category, value] of Object.entries(normalized.skills)) {
|
|
1214
|
+
if (!this.isRecord(value)) {
|
|
1215
|
+
normalizedSkills[category] = {};
|
|
1216
|
+
migrated = true;
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1219
|
+
const entry = {};
|
|
1220
|
+
if (typeof value.ref === "string") entry.ref = value.ref;
|
|
1221
|
+
if (Array.isArray(value.include)) entry.include = value.include.filter((item) => typeof item === "string");
|
|
1222
|
+
if (Array.isArray(value.exclude)) entry.exclude = value.exclude.filter((item) => typeof item === "string");
|
|
1223
|
+
else if (typeof value.exclude === "string") {
|
|
1224
|
+
entry.exclude = this.parseLegacyList(value.exclude);
|
|
1225
|
+
migrated = true;
|
|
1226
|
+
}
|
|
1227
|
+
normalizedSkills[category] = entry;
|
|
1228
|
+
}
|
|
1229
|
+
normalized.skills = normalizedSkills;
|
|
1230
|
+
}
|
|
1231
|
+
return {
|
|
1232
|
+
config: normalized,
|
|
1233
|
+
migrated
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1050
1236
|
getCategoryRef(category, metadata) {
|
|
1051
1237
|
const categoryMetadata = metadata.categories?.[category];
|
|
1052
1238
|
if (!categoryMetadata?.version) return "main";
|
|
@@ -1059,27 +1245,26 @@ var ConfigService = class {
|
|
|
1059
1245
|
* @throws Error if the configuration format is invalid
|
|
1060
1246
|
*/
|
|
1061
1247
|
async loadConfig(cwd = process.cwd()) {
|
|
1062
|
-
const configPath =
|
|
1063
|
-
if (!
|
|
1248
|
+
const configPath = await this.resolveConfigPath(cwd);
|
|
1249
|
+
if (!configPath) return null;
|
|
1250
|
+
const primaryConfigPath = this.getPrimaryConfigPath(cwd);
|
|
1251
|
+
const shouldRenameLegacyYamlFile = configPath !== primaryConfigPath;
|
|
1064
1252
|
try {
|
|
1065
1253
|
const content = await fs_extra.default.readFile(configPath, "utf8");
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
return agent;
|
|
1075
|
-
});
|
|
1076
|
-
if (needsMigration) {
|
|
1077
|
-
rawConfig.agents = updatedAgents;
|
|
1078
|
-
await fs_extra.default.outputFile(configPath, js_yaml.default.dump(rawConfig));
|
|
1079
|
-
}
|
|
1254
|
+
let rawConfig;
|
|
1255
|
+
let migratedFromText = false;
|
|
1256
|
+
try {
|
|
1257
|
+
rawConfig = js_yaml.default.load(content);
|
|
1258
|
+
} catch (parseError) {
|
|
1259
|
+
rawConfig = this.migrateLegacyTextConfig(content);
|
|
1260
|
+
migratedFromText = rawConfig !== null;
|
|
1261
|
+
if (!migratedFromText) throw parseError;
|
|
1080
1262
|
}
|
|
1081
|
-
const
|
|
1263
|
+
const { config: normalizedConfig, migrated } = this.normalizeRawConfig(rawConfig);
|
|
1264
|
+
const parsed = SkillConfigSchema.safeParse(normalizedConfig);
|
|
1082
1265
|
if (!parsed.success) throw new Error(`Invalid .skillsrc format: ${parsed.error.message}`);
|
|
1266
|
+
if (migratedFromText || migrated || shouldRenameLegacyYamlFile) await fs_extra.default.outputFile(primaryConfigPath, this.dumpConfig(parsed.data));
|
|
1267
|
+
if (shouldRenameLegacyYamlFile) await fs_extra.default.remove(configPath);
|
|
1083
1268
|
return parsed.data;
|
|
1084
1269
|
} catch (error) {
|
|
1085
1270
|
throw new Error(`Failed to load config: ${error}`);
|
|
@@ -1091,8 +1276,10 @@ var ConfigService = class {
|
|
|
1091
1276
|
* @param cwd Current working directory
|
|
1092
1277
|
*/
|
|
1093
1278
|
async saveConfig(config, cwd = process.cwd()) {
|
|
1094
|
-
const
|
|
1095
|
-
|
|
1279
|
+
const primaryConfigPath = this.getPrimaryConfigPath(cwd);
|
|
1280
|
+
const legacyYamlPath = this.getLegacyYamlConfigPath(cwd);
|
|
1281
|
+
await fs_extra.default.outputFile(primaryConfigPath, this.dumpConfig(config));
|
|
1282
|
+
if (legacyYamlPath !== primaryConfigPath && await fs_extra.default.pathExists(legacyYamlPath)) await fs_extra.default.remove(legacyYamlPath);
|
|
1096
1283
|
}
|
|
1097
1284
|
/**
|
|
1098
1285
|
* Constructs an initial configuration object based on project analysis.
|
|
@@ -1289,7 +1476,9 @@ process.stdin.on('end', () => {
|
|
|
1289
1476
|
'[SKILL TRIGGER] Editing: ' + fileName + '\\n' +
|
|
1290
1477
|
'-> Call load_skills_for_files(files=[ "' + filePath + '" ]) on the ' +
|
|
1291
1478
|
'agent-skills-standard MCP. It returns applicable SKILL.md rules, ' +
|
|
1292
|
-
'or nothing if no skills match this file type
|
|
1479
|
+
'or nothing if no skills match this file type.\\n' +
|
|
1480
|
+
'-> If this work spans a whole framework or migration, also call ' +
|
|
1481
|
+
'get_category_guide(category="...") for the framework-level map.'
|
|
1293
1482
|
);
|
|
1294
1483
|
process.exit(0);
|
|
1295
1484
|
} catch {
|
|
@@ -4188,25 +4377,35 @@ var MarkdownUtils = class {
|
|
|
4188
4377
|
* @param rootDir Project root directory
|
|
4189
4378
|
* @param targets Array of target file names
|
|
4190
4379
|
* @param indexContent The markdown content to inject
|
|
4380
|
+
* @returns Array of target files that were successfully updated/created
|
|
4191
4381
|
*/
|
|
4192
4382
|
static async injectIndex(rootDir, targets, indexContent) {
|
|
4383
|
+
const updated = [];
|
|
4193
4384
|
for (const target of targets) {
|
|
4194
4385
|
const targetPath = path.default.join(rootDir, target);
|
|
4195
4386
|
let content = "";
|
|
4387
|
+
const markerStart = "<!-- SKILLS_INDEX_START -->";
|
|
4388
|
+
const markerEnd = "<!-- SKILLS_INDEX_END -->";
|
|
4196
4389
|
if (await fs_extra.default.pathExists(targetPath)) {
|
|
4197
4390
|
content = await fs_extra.default.readFile(targetPath, "utf8");
|
|
4198
|
-
const markerStart = "<!-- SKILLS_INDEX_START -->";
|
|
4199
|
-
const markerEnd = "<!-- SKILLS_INDEX_END -->";
|
|
4200
4391
|
const startIndex = content.indexOf(markerStart);
|
|
4201
4392
|
const endIndex = content.indexOf(markerEnd);
|
|
4202
4393
|
if (startIndex !== -1 && endIndex !== -1 && startIndex < endIndex) content = `${content.substring(0, startIndex + 27)}\n${indexContent}\n${content.substring(endIndex)}`;
|
|
4203
|
-
else
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4394
|
+
else continue;
|
|
4395
|
+
} else content = [
|
|
4396
|
+
"# Project Context for AI Agents",
|
|
4397
|
+
"",
|
|
4398
|
+
"This file provides context and instructions for AI agents working in this repository.",
|
|
4399
|
+
"",
|
|
4400
|
+
markerStart,
|
|
4401
|
+
indexContent,
|
|
4402
|
+
markerEnd,
|
|
4403
|
+
""
|
|
4404
|
+
].join("\n");
|
|
4208
4405
|
await fs_extra.default.outputFile(targetPath, content);
|
|
4406
|
+
updated.push(target);
|
|
4209
4407
|
}
|
|
4408
|
+
return updated;
|
|
4210
4409
|
}
|
|
4211
4410
|
};
|
|
4212
4411
|
//#endregion
|
|
@@ -4302,13 +4501,11 @@ var SyncService = class {
|
|
|
4302
4501
|
if (Object.keys(categoryIndices).length > 0) console.log(picocolors.default.green(` ✅ Generated _INDEX.md for ${Object.keys(categoryIndices).length} categories.`));
|
|
4303
4502
|
const mcpEnabled = config.mcp?.enabled === true;
|
|
4304
4503
|
const routerIndex = await generator.assembleRouterIndex(baseDir, allowedCategories, mcpEnabled);
|
|
4305
|
-
await MarkdownUtils.injectIndex(process.cwd(), ["AGENTS.md"], routerIndex);
|
|
4306
|
-
console.log(picocolors.default.
|
|
4504
|
+
if ((await MarkdownUtils.injectIndex(process.cwd(), ["AGENTS.md"], routerIndex)).length > 0) console.log(picocolors.default.green(" ✅ AGENTS.md router index updated."));
|
|
4505
|
+
else console.log(picocolors.default.yellow(" ⚠️ Skipped AGENTS.md update: index markers <!-- SKILLS_INDEX_START --> … <!-- SKILLS_INDEX_END --> are missing or out of order. Opt-in by adding these markers to your file."));
|
|
4307
4506
|
const serverDir = path.default.join(process.cwd(), "server");
|
|
4308
|
-
if (await fs_extra.default.pathExists(serverDir))
|
|
4309
|
-
|
|
4310
|
-
console.log(picocolors.default.green(" ✅ server/AGENTS.md router index updated."));
|
|
4311
|
-
}
|
|
4507
|
+
if (await fs_extra.default.pathExists(serverDir)) if ((await MarkdownUtils.injectIndex(serverDir, ["AGENTS.md"], routerIndex)).length > 0) console.log(picocolors.default.green(" ✅ server/AGENTS.md router index updated."));
|
|
4508
|
+
else console.log(picocolors.default.yellow(" ⚠️ Skipped server/AGENTS.md update: index markers <!-- SKILLS_INDEX_START --> … <!-- SKILLS_INDEX_END --> are missing or out of order in server/AGENTS.md. Opt-in via markers."));
|
|
4312
4509
|
await new AgentBridgeService().bridge(process.cwd(), agents);
|
|
4313
4510
|
} catch (error) {
|
|
4314
4511
|
console.log(picocolors.default.yellow(` ⚠️ Failed to update index: ${error}`));
|