@erenari/supercodex 0.2.0
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 +228 -0
- package/dist/backup.d.ts +6 -0
- package/dist/backup.js +37 -0
- package/dist/backup.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +63 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/aliases.d.ts +2 -0
- package/dist/commands/aliases.js +141 -0
- package/dist/commands/aliases.js.map +1 -0
- package/dist/commands/catalog.d.ts +3 -0
- package/dist/commands/catalog.js +103 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/core.d.ts +2 -0
- package/dist/commands/core.js +111 -0
- package/dist/commands/core.js.map +1 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.js +72 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.js +26 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/mcp.d.ts +2 -0
- package/dist/commands/mcp.js +128 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/mode.d.ts +2 -0
- package/dist/commands/mode.js +73 -0
- package/dist/commands/mode.js.map +1 -0
- package/dist/commands/persona.d.ts +2 -0
- package/dist/commands/persona.js +70 -0
- package/dist/commands/persona.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +50 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/utils.d.ts +4 -0
- package/dist/commands/utils.js +28 -0
- package/dist/commands/utils.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.js +56 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +433 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -0
- package/dist/doctor/checks.d.ts +18 -0
- package/dist/doctor/checks.js +100 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/fix.d.ts +6 -0
- package/dist/doctor/fix.js +99 -0
- package/dist/doctor/fix.js.map +1 -0
- package/dist/doctor/index.d.ts +4 -0
- package/dist/doctor/index.js +21 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/report.d.ts +3 -0
- package/dist/doctor/report.js +21 -0
- package/dist/doctor/report.js.map +1 -0
- package/dist/doctor/types.d.ts +16 -0
- package/dist/doctor/types.js +3 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/fs-utils.d.ts +4 -0
- package/dist/fs-utils.js +31 -0
- package/dist/fs-utils.js.map +1 -0
- package/dist/mcp.d.ts +21 -0
- package/dist/mcp.js +222 -0
- package/dist/mcp.js.map +1 -0
- package/dist/operations.d.ts +108 -0
- package/dist/operations.js +388 -0
- package/dist/operations.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +41 -0
- package/dist/paths.js.map +1 -0
- package/dist/project-init.d.ts +8 -0
- package/dist/project-init.js +92 -0
- package/dist/project-init.js.map +1 -0
- package/dist/prompts.d.ts +9 -0
- package/dist/prompts.js +157 -0
- package/dist/prompts.js.map +1 -0
- package/dist/registry/aliases.d.ts +16 -0
- package/dist/registry/aliases.js +347 -0
- package/dist/registry/aliases.js.map +1 -0
- package/dist/registry/builtins.d.ts +8 -0
- package/dist/registry/builtins.js +188 -0
- package/dist/registry/builtins.js.map +1 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.js +21 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/loader.d.ts +16 -0
- package/dist/registry/loader.js +655 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/types.d.ts +79 -0
- package/dist/registry/types.js +3 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/runtime/alias-dispatch.d.ts +10 -0
- package/dist/runtime/alias-dispatch.js +119 -0
- package/dist/runtime/alias-dispatch.js.map +1 -0
- package/dist/runtime/compat.d.ts +6 -0
- package/dist/runtime/compat.js +23 -0
- package/dist/runtime/compat.js.map +1 -0
- package/dist/runtime/context.d.ts +23 -0
- package/dist/runtime/context.js +59 -0
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +21 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/workflow.d.ts +18 -0
- package/dist/runtime/workflow.js +45 -0
- package/dist/runtime/workflow.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadRegistry = loadRegistry;
|
|
7
|
+
exports.validateRegistry = validateRegistry;
|
|
8
|
+
exports.listCatalogEntries = listCatalogEntries;
|
|
9
|
+
exports.searchCatalogEntries = searchCatalogEntries;
|
|
10
|
+
exports.getCatalogEntry = getCatalogEntry;
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const config_1 = require("../config");
|
|
13
|
+
const fs_utils_1 = require("../fs-utils");
|
|
14
|
+
const paths_1 = require("../paths");
|
|
15
|
+
const aliases_1 = require("./aliases");
|
|
16
|
+
const builtins_1 = require("./builtins");
|
|
17
|
+
async function loadRegistry(options = {}) {
|
|
18
|
+
const codexPaths = (0, paths_1.getCodexPaths)(options.codexHome);
|
|
19
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
20
|
+
const userOverlayPath = node_path_1.default.join(codexPaths.home, "supercodex", "registry.toml");
|
|
21
|
+
const projectOverlayPath = node_path_1.default.join(projectRoot, ".codex", "supercodex", "registry.toml");
|
|
22
|
+
const registry = {
|
|
23
|
+
modes: (0, fs_utils_1.deepClone)(builtins_1.BUILTIN_MODES),
|
|
24
|
+
personas: (0, fs_utils_1.deepClone)(builtins_1.BUILTIN_PERSONAS),
|
|
25
|
+
commands: (0, fs_utils_1.deepClone)(builtins_1.BUILTIN_COMMANDS),
|
|
26
|
+
catalog: (0, fs_utils_1.deepClone)(builtins_1.BUILTIN_CATALOG),
|
|
27
|
+
aliases: (0, fs_utils_1.deepClone)(aliases_1.BUILTIN_ALIASES),
|
|
28
|
+
alias_packs: (0, fs_utils_1.deepClone)(aliases_1.BUILTIN_ALIAS_PACKS)
|
|
29
|
+
};
|
|
30
|
+
const issues = [];
|
|
31
|
+
if (await (0, fs_utils_1.pathExists)(userOverlayPath)) {
|
|
32
|
+
const overlay = await readOverlayFile(userOverlayPath, issues);
|
|
33
|
+
if (overlay) {
|
|
34
|
+
applyOverlay(registry, overlay, userOverlayPath, issues);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (await (0, fs_utils_1.pathExists)(projectOverlayPath)) {
|
|
38
|
+
const overlay = await readOverlayFile(projectOverlayPath, issues);
|
|
39
|
+
if (overlay) {
|
|
40
|
+
applyOverlay(registry, overlay, projectOverlayPath, issues);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
registry,
|
|
45
|
+
issues,
|
|
46
|
+
userOverlayPath,
|
|
47
|
+
projectOverlayPath
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function validateRegistry(registry) {
|
|
51
|
+
const issues = [];
|
|
52
|
+
for (const [name, mode] of Object.entries(registry.modes)) {
|
|
53
|
+
if (!mode.description || !mode.description.trim()) {
|
|
54
|
+
issues.push({
|
|
55
|
+
level: "error",
|
|
56
|
+
path: `modes.${name}`,
|
|
57
|
+
message: "Mode description is required."
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const [name, persona] of Object.entries(registry.personas)) {
|
|
62
|
+
if (!persona.description || !persona.description.trim()) {
|
|
63
|
+
issues.push({
|
|
64
|
+
level: "error",
|
|
65
|
+
path: `personas.${name}`,
|
|
66
|
+
message: "Persona description is required."
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const [id, command] of Object.entries(registry.commands)) {
|
|
71
|
+
if (!command.description || !command.description.trim()) {
|
|
72
|
+
issues.push({
|
|
73
|
+
level: "error",
|
|
74
|
+
path: `commands.${id}`,
|
|
75
|
+
message: "Command description is required."
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (const [id, entry] of Object.entries(registry.catalog)) {
|
|
80
|
+
if (entry.transport !== "stdio" && entry.transport !== "http") {
|
|
81
|
+
issues.push({
|
|
82
|
+
level: "error",
|
|
83
|
+
path: `catalog.${id}.transport`,
|
|
84
|
+
message: `Unsupported transport "${String(entry.transport)}".`
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (entry.transport === "stdio" && (!entry.command || !entry.command.trim())) {
|
|
89
|
+
issues.push({
|
|
90
|
+
level: "error",
|
|
91
|
+
path: `catalog.${id}.command`,
|
|
92
|
+
message: "STDIO catalog entry requires command."
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (entry.transport === "http") {
|
|
96
|
+
if (!entry.url || !entry.url.trim()) {
|
|
97
|
+
issues.push({
|
|
98
|
+
level: "error",
|
|
99
|
+
path: `catalog.${id}.url`,
|
|
100
|
+
message: "HTTP catalog entry requires url."
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
try {
|
|
105
|
+
// Validate URL shape
|
|
106
|
+
// eslint-disable-next-line no-new
|
|
107
|
+
new URL(entry.url);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
issues.push({
|
|
111
|
+
level: "error",
|
|
112
|
+
path: `catalog.${id}.url`,
|
|
113
|
+
message: `Invalid URL "${entry.url}".`
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const [aliasName, aliasDefinition] of Object.entries(registry.aliases)) {
|
|
120
|
+
if (!aliasDefinition.description || !aliasDefinition.description.trim()) {
|
|
121
|
+
issues.push({
|
|
122
|
+
level: "error",
|
|
123
|
+
path: `aliases.${aliasName}`,
|
|
124
|
+
message: "Alias description is required."
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (!aliasDefinition.target || !aliasDefinition.target.trim()) {
|
|
128
|
+
issues.push({
|
|
129
|
+
level: "error",
|
|
130
|
+
path: `aliases.${aliasName}.target`,
|
|
131
|
+
message: "Alias target is required."
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
else if (!isValidCommandId(aliasDefinition.target)) {
|
|
135
|
+
issues.push({
|
|
136
|
+
level: "error",
|
|
137
|
+
path: `aliases.${aliasName}.target`,
|
|
138
|
+
message: `Alias target "${aliasDefinition.target}" has invalid format.`
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else if (!Object.hasOwn(registry.commands, aliasDefinition.target)) {
|
|
142
|
+
issues.push({
|
|
143
|
+
level: "warn",
|
|
144
|
+
path: `aliases.${aliasName}.target`,
|
|
145
|
+
message: `Alias target "${aliasDefinition.target}" is not a known command id.`
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const command = registry.commands[aliasDefinition.target];
|
|
150
|
+
if (aliasDefinition.default_mode && !isCompatibleMode(command, aliasDefinition.default_mode)) {
|
|
151
|
+
issues.push({
|
|
152
|
+
level: "warn",
|
|
153
|
+
path: `aliases.${aliasName}.default_mode`,
|
|
154
|
+
message: `Mode "${aliasDefinition.default_mode}" is not compatible with target ` +
|
|
155
|
+
`"${aliasDefinition.target}".`
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (aliasDefinition.default_persona && !isCompatiblePersona(command, aliasDefinition.default_persona)) {
|
|
159
|
+
issues.push({
|
|
160
|
+
level: "warn",
|
|
161
|
+
path: `aliases.${aliasName}.default_persona`,
|
|
162
|
+
message: `Persona "${aliasDefinition.default_persona}" is not compatible with target ` +
|
|
163
|
+
`"${aliasDefinition.target}".`
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (aliasDefinition.default_mode && !Object.hasOwn(registry.modes, aliasDefinition.default_mode)) {
|
|
168
|
+
issues.push({
|
|
169
|
+
level: "warn",
|
|
170
|
+
path: `aliases.${aliasName}.default_mode`,
|
|
171
|
+
message: `Unknown mode "${aliasDefinition.default_mode}" in alias default.`
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (aliasDefinition.default_persona && !Object.hasOwn(registry.personas, aliasDefinition.default_persona)) {
|
|
175
|
+
issues.push({
|
|
176
|
+
level: "warn",
|
|
177
|
+
path: `aliases.${aliasName}.default_persona`,
|
|
178
|
+
message: `Unknown persona "${aliasDefinition.default_persona}" in alias default.`
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
if (aliasDefinition.output &&
|
|
182
|
+
aliasDefinition.output !== "normal" &&
|
|
183
|
+
aliasDefinition.output !== "json") {
|
|
184
|
+
issues.push({
|
|
185
|
+
level: "error",
|
|
186
|
+
path: `aliases.${aliasName}.output`,
|
|
187
|
+
message: `Unsupported alias output mode "${aliasDefinition.output}".`
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
if (aliasDefinition.risk_level &&
|
|
191
|
+
aliasDefinition.risk_level !== "low" &&
|
|
192
|
+
aliasDefinition.risk_level !== "medium" &&
|
|
193
|
+
aliasDefinition.risk_level !== "high") {
|
|
194
|
+
issues.push({
|
|
195
|
+
level: "error",
|
|
196
|
+
path: `aliases.${aliasName}.risk_level`,
|
|
197
|
+
message: `Unsupported alias risk level "${aliasDefinition.risk_level}".`
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (aliasDefinition.stability &&
|
|
201
|
+
aliasDefinition.stability !== "stable" &&
|
|
202
|
+
aliasDefinition.stability !== "experimental") {
|
|
203
|
+
issues.push({
|
|
204
|
+
level: "error",
|
|
205
|
+
path: `aliases.${aliasName}.stability`,
|
|
206
|
+
message: `Unsupported alias stability "${aliasDefinition.stability}".`
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
if (aliasDefinition.pack) {
|
|
210
|
+
const aliasPack = registry.alias_packs[aliasDefinition.pack];
|
|
211
|
+
if (!aliasPack) {
|
|
212
|
+
issues.push({
|
|
213
|
+
level: "warn",
|
|
214
|
+
path: `aliases.${aliasName}.pack`,
|
|
215
|
+
message: `Alias references unknown pack "${aliasDefinition.pack}".`
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else if (!aliasPack.aliases.includes(aliasName)) {
|
|
219
|
+
issues.push({
|
|
220
|
+
level: "warn",
|
|
221
|
+
path: `aliases.${aliasName}.pack`,
|
|
222
|
+
message: `Alias "${aliasName}" is not listed in pack "${aliasDefinition.pack}".`
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if ((0, aliases_1.isReservedTopLevelCommandName)(aliasName)) {
|
|
227
|
+
issues.push({
|
|
228
|
+
level: "warn",
|
|
229
|
+
path: `aliases.${aliasName}`,
|
|
230
|
+
message: `Alias "${aliasName}" collides with a top-level command name. ` +
|
|
231
|
+
`Plain form "supercodex ${aliasName}" will execute the command; use "/sc:${aliasName}" explicitly.`
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (const [packName, packDefinition] of Object.entries(registry.alias_packs)) {
|
|
236
|
+
if (!packDefinition.description || !packDefinition.description.trim()) {
|
|
237
|
+
issues.push({
|
|
238
|
+
level: "error",
|
|
239
|
+
path: `alias_packs.${packName}.description`,
|
|
240
|
+
message: "Alias pack description is required."
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
if (packDefinition.aliases.length === 0) {
|
|
244
|
+
issues.push({
|
|
245
|
+
level: "warn",
|
|
246
|
+
path: `alias_packs.${packName}.aliases`,
|
|
247
|
+
message: "Alias pack does not contain any aliases."
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const seenAliases = new Set();
|
|
251
|
+
for (const aliasName of packDefinition.aliases) {
|
|
252
|
+
if (seenAliases.has(aliasName)) {
|
|
253
|
+
issues.push({
|
|
254
|
+
level: "warn",
|
|
255
|
+
path: `alias_packs.${packName}.aliases`,
|
|
256
|
+
message: `Alias "${aliasName}" is duplicated in pack "${packName}".`
|
|
257
|
+
});
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
seenAliases.add(aliasName);
|
|
261
|
+
if (!Object.hasOwn(registry.aliases, aliasName)) {
|
|
262
|
+
issues.push({
|
|
263
|
+
level: "warn",
|
|
264
|
+
path: `alias_packs.${packName}.aliases`,
|
|
265
|
+
message: `Alias "${aliasName}" in pack "${packName}" is not defined.`
|
|
266
|
+
});
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const alias = registry.aliases[aliasName];
|
|
270
|
+
if (alias.pack && alias.pack !== packName) {
|
|
271
|
+
issues.push({
|
|
272
|
+
level: "warn",
|
|
273
|
+
path: `alias_packs.${packName}.aliases`,
|
|
274
|
+
message: `Alias "${aliasName}" belongs to "${alias.pack}" but is also listed in "${packName}".`
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return issues;
|
|
280
|
+
}
|
|
281
|
+
function listCatalogEntries(registry) {
|
|
282
|
+
return Object.values(registry.catalog).sort((a, b) => a.id.localeCompare(b.id));
|
|
283
|
+
}
|
|
284
|
+
function searchCatalogEntries(registry, query) {
|
|
285
|
+
const normalized = query.trim().toLowerCase();
|
|
286
|
+
if (!normalized) {
|
|
287
|
+
return listCatalogEntries(registry);
|
|
288
|
+
}
|
|
289
|
+
return listCatalogEntries(registry).filter((entry) => {
|
|
290
|
+
const haystack = [
|
|
291
|
+
entry.id,
|
|
292
|
+
entry.name,
|
|
293
|
+
entry.description,
|
|
294
|
+
...(entry.tags ?? []),
|
|
295
|
+
entry.command ?? "",
|
|
296
|
+
entry.url ?? ""
|
|
297
|
+
]
|
|
298
|
+
.join(" ")
|
|
299
|
+
.toLowerCase();
|
|
300
|
+
return haystack.includes(normalized);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function getCatalogEntry(registry, id) {
|
|
304
|
+
return registry.catalog[id] ?? null;
|
|
305
|
+
}
|
|
306
|
+
async function readOverlayFile(overlayPath, issues) {
|
|
307
|
+
try {
|
|
308
|
+
const parsed = await (0, config_1.loadConfig)(overlayPath);
|
|
309
|
+
return (0, fs_utils_1.isPlainObject)(parsed) ? parsed : null;
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
issues.push({
|
|
313
|
+
level: "error",
|
|
314
|
+
path: overlayPath,
|
|
315
|
+
message: `Failed to parse overlay file: ${error instanceof Error ? error.message : String(error)}`
|
|
316
|
+
});
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function applyOverlay(registry, overlay, sourcePath, issues) {
|
|
321
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.modes)) {
|
|
322
|
+
for (const [name, raw] of Object.entries(overlay.modes)) {
|
|
323
|
+
const normalized = normalizeMode(name, raw);
|
|
324
|
+
if (!normalized) {
|
|
325
|
+
issues.push({
|
|
326
|
+
level: "warn",
|
|
327
|
+
path: `${sourcePath}:modes.${name}`,
|
|
328
|
+
message: "Skipped invalid mode entry."
|
|
329
|
+
});
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
registry.modes[name] = normalized;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.personas)) {
|
|
336
|
+
for (const [name, raw] of Object.entries(overlay.personas)) {
|
|
337
|
+
const normalized = normalizePersona(name, raw);
|
|
338
|
+
if (!normalized) {
|
|
339
|
+
issues.push({
|
|
340
|
+
level: "warn",
|
|
341
|
+
path: `${sourcePath}:personas.${name}`,
|
|
342
|
+
message: "Skipped invalid persona entry."
|
|
343
|
+
});
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
registry.personas[name] = normalized;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.commands)) {
|
|
350
|
+
for (const [id, raw] of Object.entries(overlay.commands)) {
|
|
351
|
+
const normalized = normalizeCommand(id, raw);
|
|
352
|
+
if (!normalized) {
|
|
353
|
+
issues.push({
|
|
354
|
+
level: "warn",
|
|
355
|
+
path: `${sourcePath}:commands.${id}`,
|
|
356
|
+
message: "Skipped invalid command entry."
|
|
357
|
+
});
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
registry.commands[id] = normalized;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.catalog)) {
|
|
364
|
+
for (const [id, raw] of Object.entries(overlay.catalog)) {
|
|
365
|
+
const normalized = normalizeCatalogEntry(id, raw);
|
|
366
|
+
if (!normalized) {
|
|
367
|
+
issues.push({
|
|
368
|
+
level: "warn",
|
|
369
|
+
path: `${sourcePath}:catalog.${id}`,
|
|
370
|
+
message: "Skipped invalid catalog entry."
|
|
371
|
+
});
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
registry.catalog[id] = normalized;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.aliases)) {
|
|
378
|
+
for (const [name, raw] of Object.entries(overlay.aliases)) {
|
|
379
|
+
const normalized = normalizeAlias(name, raw);
|
|
380
|
+
if (!normalized) {
|
|
381
|
+
issues.push({
|
|
382
|
+
level: "warn",
|
|
383
|
+
path: `${sourcePath}:aliases.${name}`,
|
|
384
|
+
message: "Skipped invalid alias entry."
|
|
385
|
+
});
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (Object.hasOwn(registry.aliases, normalized.name)) {
|
|
389
|
+
const existing = registry.aliases[normalized.name];
|
|
390
|
+
if (!areAliasesEquivalent(existing, normalized)) {
|
|
391
|
+
issues.push({
|
|
392
|
+
level: "warn",
|
|
393
|
+
path: `${sourcePath}:aliases.${normalized.name}`,
|
|
394
|
+
message: `Alias "${normalized.name}" overrides an existing alias definition.`
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
registry.aliases[normalized.name] = normalized;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if ((0, fs_utils_1.isPlainObject)(overlay.alias_packs)) {
|
|
402
|
+
for (const [name, raw] of Object.entries(overlay.alias_packs)) {
|
|
403
|
+
const normalized = normalizeAliasPack(name, raw);
|
|
404
|
+
if (!normalized) {
|
|
405
|
+
issues.push({
|
|
406
|
+
level: "warn",
|
|
407
|
+
path: `${sourcePath}:alias_packs.${name}`,
|
|
408
|
+
message: "Skipped invalid alias pack entry."
|
|
409
|
+
});
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (Object.hasOwn(registry.alias_packs, name)) {
|
|
413
|
+
const existing = registry.alias_packs[name];
|
|
414
|
+
if (!areAliasPacksEquivalent(existing, normalized)) {
|
|
415
|
+
issues.push({
|
|
416
|
+
level: "warn",
|
|
417
|
+
path: `${sourcePath}:alias_packs.${name}`,
|
|
418
|
+
message: `Alias pack "${name}" overrides an existing pack definition.`
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
registry.alias_packs[name] = normalized;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
function normalizeMode(name, raw) {
|
|
427
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
const description = asString(raw.description);
|
|
431
|
+
if (!description) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
const mode = {
|
|
435
|
+
name,
|
|
436
|
+
description
|
|
437
|
+
};
|
|
438
|
+
const promptOverlay = asString(raw.prompt_overlay);
|
|
439
|
+
if (promptOverlay) {
|
|
440
|
+
mode.prompt_overlay = promptOverlay;
|
|
441
|
+
}
|
|
442
|
+
const temperature = asNumber(raw.temperature);
|
|
443
|
+
if (typeof temperature === "number") {
|
|
444
|
+
mode.temperature = temperature;
|
|
445
|
+
}
|
|
446
|
+
const reasoningBudget = asString(raw.reasoning_budget);
|
|
447
|
+
if (reasoningBudget === "low" || reasoningBudget === "medium" || reasoningBudget === "high") {
|
|
448
|
+
mode.reasoning_budget = reasoningBudget;
|
|
449
|
+
}
|
|
450
|
+
return mode;
|
|
451
|
+
}
|
|
452
|
+
function normalizePersona(name, raw) {
|
|
453
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
const description = asString(raw.description);
|
|
457
|
+
if (!description) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
const persona = {
|
|
461
|
+
name,
|
|
462
|
+
description
|
|
463
|
+
};
|
|
464
|
+
const systemPrompt = asString(raw.system_prompt);
|
|
465
|
+
if (systemPrompt) {
|
|
466
|
+
persona.system_prompt = systemPrompt;
|
|
467
|
+
}
|
|
468
|
+
const tags = asStringArray(raw.policy_tags);
|
|
469
|
+
if (tags.length > 0) {
|
|
470
|
+
persona.policy_tags = tags;
|
|
471
|
+
}
|
|
472
|
+
return persona;
|
|
473
|
+
}
|
|
474
|
+
function normalizeCommand(id, raw) {
|
|
475
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
const description = asString(raw.description);
|
|
479
|
+
if (!description) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
id,
|
|
484
|
+
description,
|
|
485
|
+
enabled: raw.enabled !== false,
|
|
486
|
+
mode_compatible: asStringArray(raw.mode_compatible),
|
|
487
|
+
persona_compatible: asStringArray(raw.persona_compatible)
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
function normalizeCatalogEntry(id, raw) {
|
|
491
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const transport = asString(raw.transport);
|
|
495
|
+
if (transport !== "stdio" && transport !== "http") {
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
const description = asString(raw.description) ?? `Catalog entry ${id}`;
|
|
499
|
+
const name = asString(raw.name) ?? id;
|
|
500
|
+
const entry = {
|
|
501
|
+
id,
|
|
502
|
+
name,
|
|
503
|
+
description,
|
|
504
|
+
transport
|
|
505
|
+
};
|
|
506
|
+
const command = asString(raw.command);
|
|
507
|
+
const args = asStringArray(raw.args);
|
|
508
|
+
const url = asString(raw.url);
|
|
509
|
+
const tags = asStringArray(raw.tags);
|
|
510
|
+
if (transport === "stdio") {
|
|
511
|
+
if (!command) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
entry.command = command;
|
|
515
|
+
if (args.length > 0) {
|
|
516
|
+
entry.args = args;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
if (transport === "http") {
|
|
520
|
+
if (!url) {
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
entry.url = url;
|
|
524
|
+
}
|
|
525
|
+
const env = asStringMap(raw.env);
|
|
526
|
+
if (Object.keys(env).length > 0) {
|
|
527
|
+
entry.env = env;
|
|
528
|
+
}
|
|
529
|
+
if (tags.length > 0) {
|
|
530
|
+
entry.tags = tags;
|
|
531
|
+
}
|
|
532
|
+
return entry;
|
|
533
|
+
}
|
|
534
|
+
function normalizeAlias(name, raw) {
|
|
535
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
const description = asString(raw.description);
|
|
539
|
+
const target = asString(raw.target);
|
|
540
|
+
if (!description || !target) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
const parsedName = (0, aliases_1.normalizeAliasToken)(name);
|
|
544
|
+
const aliasName = (parsedName ? parsedName.name : name).toLowerCase();
|
|
545
|
+
if (!aliasName) {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
const alias = {
|
|
549
|
+
name: aliasName,
|
|
550
|
+
description,
|
|
551
|
+
target
|
|
552
|
+
};
|
|
553
|
+
const pack = asString(raw.pack);
|
|
554
|
+
if (pack) {
|
|
555
|
+
alias.pack = pack;
|
|
556
|
+
}
|
|
557
|
+
const tags = asStringArray(raw.tags);
|
|
558
|
+
if (tags.length > 0) {
|
|
559
|
+
alias.tags = dedupeStrings(tags);
|
|
560
|
+
}
|
|
561
|
+
const riskLevel = asString(raw.risk_level);
|
|
562
|
+
if (riskLevel === "low" || riskLevel === "medium" || riskLevel === "high") {
|
|
563
|
+
alias.risk_level = riskLevel;
|
|
564
|
+
}
|
|
565
|
+
const stability = asString(raw.stability);
|
|
566
|
+
if (stability === "stable" || stability === "experimental") {
|
|
567
|
+
alias.stability = stability;
|
|
568
|
+
}
|
|
569
|
+
const defaultMode = asString(raw.default_mode);
|
|
570
|
+
if (defaultMode) {
|
|
571
|
+
alias.default_mode = defaultMode;
|
|
572
|
+
}
|
|
573
|
+
const defaultPersona = asString(raw.default_persona);
|
|
574
|
+
if (defaultPersona) {
|
|
575
|
+
alias.default_persona = defaultPersona;
|
|
576
|
+
}
|
|
577
|
+
const forwardArgs = asBoolean(raw.forward_args);
|
|
578
|
+
if (typeof forwardArgs === "boolean") {
|
|
579
|
+
alias.forward_args = forwardArgs;
|
|
580
|
+
}
|
|
581
|
+
const output = asString(raw.output);
|
|
582
|
+
if (output === "normal" || output === "json") {
|
|
583
|
+
alias.output = output;
|
|
584
|
+
}
|
|
585
|
+
return alias;
|
|
586
|
+
}
|
|
587
|
+
function normalizeAliasPack(name, raw) {
|
|
588
|
+
if (!(0, fs_utils_1.isPlainObject)(raw)) {
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
const description = asString(raw.description);
|
|
592
|
+
if (!description) {
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
const aliases = dedupeStrings(asStringArray(raw.aliases).map((entry) => entry.toLowerCase()));
|
|
596
|
+
const defaultEnabled = asBoolean(raw.default_enabled);
|
|
597
|
+
return {
|
|
598
|
+
name,
|
|
599
|
+
description,
|
|
600
|
+
default_enabled: defaultEnabled ?? true,
|
|
601
|
+
aliases
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
function asString(value) {
|
|
605
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
606
|
+
}
|
|
607
|
+
function asNumber(value) {
|
|
608
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
609
|
+
}
|
|
610
|
+
function asStringArray(value) {
|
|
611
|
+
if (!Array.isArray(value)) {
|
|
612
|
+
return [];
|
|
613
|
+
}
|
|
614
|
+
return value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
615
|
+
}
|
|
616
|
+
function asStringMap(value) {
|
|
617
|
+
if (!(0, fs_utils_1.isPlainObject)(value)) {
|
|
618
|
+
return {};
|
|
619
|
+
}
|
|
620
|
+
const env = {};
|
|
621
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
622
|
+
if (typeof raw === "string") {
|
|
623
|
+
env[key] = raw;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return env;
|
|
627
|
+
}
|
|
628
|
+
function asBoolean(value) {
|
|
629
|
+
return typeof value === "boolean" ? value : undefined;
|
|
630
|
+
}
|
|
631
|
+
function dedupeStrings(values) {
|
|
632
|
+
return Array.from(new Set(values));
|
|
633
|
+
}
|
|
634
|
+
function isValidCommandId(value) {
|
|
635
|
+
return /^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)*$/.test(value);
|
|
636
|
+
}
|
|
637
|
+
function isCompatibleMode(command, modeName) {
|
|
638
|
+
if (command.mode_compatible.length === 0) {
|
|
639
|
+
return true;
|
|
640
|
+
}
|
|
641
|
+
return command.mode_compatible.includes(modeName);
|
|
642
|
+
}
|
|
643
|
+
function isCompatiblePersona(command, personaName) {
|
|
644
|
+
if (command.persona_compatible.length === 0) {
|
|
645
|
+
return true;
|
|
646
|
+
}
|
|
647
|
+
return command.persona_compatible.includes(personaName);
|
|
648
|
+
}
|
|
649
|
+
function areAliasesEquivalent(a, b) {
|
|
650
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
651
|
+
}
|
|
652
|
+
function areAliasPacksEquivalent(a, b) {
|
|
653
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
654
|
+
}
|
|
655
|
+
//# sourceMappingURL=loader.js.map
|