@the-aico/cli 1.0.1 → 1.0.2
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 +10 -10
- package/dist/index.js +435 -110
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,8 +95,8 @@ function handleError(error, options = {}) {
|
|
|
95
95
|
console.error(kleur.red("\u2716 Validation Error:"));
|
|
96
96
|
console.error("");
|
|
97
97
|
for (const issue of error.issues) {
|
|
98
|
-
const
|
|
99
|
-
console.error(` ${kleur.yellow(
|
|
98
|
+
const path10 = issue.path.length > 0 ? issue.path.join(".") : "value";
|
|
99
|
+
console.error(` ${kleur.yellow(path10)}: ${issue.message}`);
|
|
100
100
|
}
|
|
101
101
|
console.error("");
|
|
102
102
|
console.error(kleur.cyan(" Suggestion:"));
|
|
@@ -238,15 +238,15 @@ var DEFAULT_PLATFORMS = {
|
|
|
238
238
|
skills: ".claude/skills",
|
|
239
239
|
commands: ".claude/commands"
|
|
240
240
|
},
|
|
241
|
-
// Codex
|
|
242
|
-
// - skills:
|
|
243
|
-
// - commands (prompts):
|
|
244
|
-
//
|
|
245
|
-
//
|
|
241
|
+
// Codex platform configuration:
|
|
242
|
+
// - skills: project directory .codex/skills/ (Codex natively supports project-level skills)
|
|
243
|
+
// - commands (prompts): global ~/.codex/prompts/ (install once, available for all projects)
|
|
244
|
+
// Invocation: /prompts:aico.{employee}.{command}
|
|
245
|
+
// Users can override paths in aico.json
|
|
246
246
|
codex: {
|
|
247
247
|
skills: ".codex/skills",
|
|
248
248
|
commands: "~/.codex/prompts"
|
|
249
|
-
// Codex custom prompts (
|
|
249
|
+
// Codex custom prompts (global)
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
252
|
function createDefaultConfig(defaultPlatform = "claude-code") {
|
|
@@ -1224,9 +1224,9 @@ var DependencyResolver = class {
|
|
|
1224
1224
|
/**
|
|
1225
1225
|
* Recursively fetch a skill and all its dependencies
|
|
1226
1226
|
*/
|
|
1227
|
-
async fetchWithDependencies(skillName, visited = /* @__PURE__ */ new Set(),
|
|
1228
|
-
if (
|
|
1229
|
-
const cycle = [...
|
|
1227
|
+
async fetchWithDependencies(skillName, visited = /* @__PURE__ */ new Set(), path10 = []) {
|
|
1228
|
+
if (path10.includes(skillName)) {
|
|
1229
|
+
const cycle = [...path10, skillName].join(" \u2192 ");
|
|
1230
1230
|
throw new AicoError(
|
|
1231
1231
|
`Circular dependency detected: ${cycle}`,
|
|
1232
1232
|
"CIRCULAR_DEPENDENCY",
|
|
@@ -1247,7 +1247,7 @@ var DependencyResolver = class {
|
|
|
1247
1247
|
const depSkills = await this.fetchWithDependencies(
|
|
1248
1248
|
dep,
|
|
1249
1249
|
visited,
|
|
1250
|
-
[...
|
|
1250
|
+
[...path10, skillName]
|
|
1251
1251
|
);
|
|
1252
1252
|
allSkills.push(...depSkills);
|
|
1253
1253
|
}
|
|
@@ -2129,14 +2129,370 @@ var list = new Command4().name("list").description("List available or installed
|
|
|
2129
2129
|
|
|
2130
2130
|
// src/commands/build.ts
|
|
2131
2131
|
import { Command as Command5 } from "commander";
|
|
2132
|
-
import
|
|
2133
|
-
import
|
|
2132
|
+
import fs7 from "fs-extra";
|
|
2133
|
+
import path8 from "path";
|
|
2134
2134
|
import glob from "fast-glob";
|
|
2135
2135
|
import { z as z9 } from "zod";
|
|
2136
|
+
|
|
2137
|
+
// src/commands/build-schema.ts
|
|
2138
|
+
import fs6 from "fs-extra";
|
|
2139
|
+
import path7 from "path";
|
|
2140
|
+
var CONFIG_SCHEMA = {
|
|
2141
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2142
|
+
$id: "https://the-aico.com/schema/config.json",
|
|
2143
|
+
title: "aico Configuration",
|
|
2144
|
+
description: "Configuration file schema for aico.json",
|
|
2145
|
+
type: "object",
|
|
2146
|
+
required: ["defaultPlatform", "platforms"],
|
|
2147
|
+
properties: {
|
|
2148
|
+
$schema: {
|
|
2149
|
+
type: "string",
|
|
2150
|
+
description: "JSON Schema reference"
|
|
2151
|
+
},
|
|
2152
|
+
language: {
|
|
2153
|
+
type: "string",
|
|
2154
|
+
description: "Default language for documentation",
|
|
2155
|
+
default: "en"
|
|
2156
|
+
},
|
|
2157
|
+
defaultPlatform: {
|
|
2158
|
+
type: "string",
|
|
2159
|
+
enum: ["claude-code", "codex"],
|
|
2160
|
+
description: "Default platform for installation"
|
|
2161
|
+
},
|
|
2162
|
+
platforms: {
|
|
2163
|
+
type: "object",
|
|
2164
|
+
description: "Platform-specific path configurations",
|
|
2165
|
+
additionalProperties: {
|
|
2166
|
+
type: "object",
|
|
2167
|
+
required: ["skills", "commands"],
|
|
2168
|
+
properties: {
|
|
2169
|
+
skills: {
|
|
2170
|
+
type: "string",
|
|
2171
|
+
description: "Path to skills directory"
|
|
2172
|
+
},
|
|
2173
|
+
commands: {
|
|
2174
|
+
type: "string",
|
|
2175
|
+
description: "Path to commands directory"
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
},
|
|
2180
|
+
employees: {
|
|
2181
|
+
type: "object",
|
|
2182
|
+
description: "Installed employees state",
|
|
2183
|
+
additionalProperties: {
|
|
2184
|
+
type: "object",
|
|
2185
|
+
required: ["platforms", "installedAt"],
|
|
2186
|
+
properties: {
|
|
2187
|
+
platforms: {
|
|
2188
|
+
type: "array",
|
|
2189
|
+
items: {
|
|
2190
|
+
type: "string",
|
|
2191
|
+
enum: ["claude-code", "codex"]
|
|
2192
|
+
},
|
|
2193
|
+
description: "Platforms this employee is installed on"
|
|
2194
|
+
},
|
|
2195
|
+
installedAt: {
|
|
2196
|
+
type: "string",
|
|
2197
|
+
format: "date-time",
|
|
2198
|
+
description: "Installation timestamp"
|
|
2199
|
+
},
|
|
2200
|
+
version: {
|
|
2201
|
+
type: "string",
|
|
2202
|
+
description: "Installed version"
|
|
2203
|
+
},
|
|
2204
|
+
skills: {
|
|
2205
|
+
type: "array",
|
|
2206
|
+
items: { type: "string" },
|
|
2207
|
+
description: "Installed skill names"
|
|
2208
|
+
},
|
|
2209
|
+
commands: {
|
|
2210
|
+
type: "array",
|
|
2211
|
+
items: { type: "string" },
|
|
2212
|
+
description: "Installed command names"
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
},
|
|
2217
|
+
skills: {
|
|
2218
|
+
type: "object",
|
|
2219
|
+
description: "Standalone installed skills",
|
|
2220
|
+
additionalProperties: {
|
|
2221
|
+
type: "object",
|
|
2222
|
+
required: ["version", "installedAt", "source", "platforms"],
|
|
2223
|
+
properties: {
|
|
2224
|
+
version: {
|
|
2225
|
+
type: "string",
|
|
2226
|
+
description: "Skill version"
|
|
2227
|
+
},
|
|
2228
|
+
installedAt: {
|
|
2229
|
+
type: "string",
|
|
2230
|
+
format: "date-time",
|
|
2231
|
+
description: "Installation timestamp"
|
|
2232
|
+
},
|
|
2233
|
+
source: {
|
|
2234
|
+
type: "string",
|
|
2235
|
+
enum: ["standalone", "employee"],
|
|
2236
|
+
description: "Installation source"
|
|
2237
|
+
},
|
|
2238
|
+
platforms: {
|
|
2239
|
+
type: "array",
|
|
2240
|
+
items: {
|
|
2241
|
+
type: "string",
|
|
2242
|
+
enum: ["claude-code", "codex"]
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
},
|
|
2248
|
+
sharedSkills: {
|
|
2249
|
+
type: "object",
|
|
2250
|
+
description: "Shared skills with reference tracking",
|
|
2251
|
+
additionalProperties: {
|
|
2252
|
+
type: "object",
|
|
2253
|
+
required: ["version", "installedAt", "platforms", "usedBy"],
|
|
2254
|
+
properties: {
|
|
2255
|
+
version: {
|
|
2256
|
+
type: "string",
|
|
2257
|
+
description: "Skill version"
|
|
2258
|
+
},
|
|
2259
|
+
installedAt: {
|
|
2260
|
+
type: "string",
|
|
2261
|
+
format: "date-time",
|
|
2262
|
+
description: "Installation timestamp"
|
|
2263
|
+
},
|
|
2264
|
+
platforms: {
|
|
2265
|
+
type: "array",
|
|
2266
|
+
items: {
|
|
2267
|
+
type: "string",
|
|
2268
|
+
enum: ["claude-code", "codex"]
|
|
2269
|
+
}
|
|
2270
|
+
},
|
|
2271
|
+
usedBy: {
|
|
2272
|
+
type: "array",
|
|
2273
|
+
items: { type: "string" },
|
|
2274
|
+
description: "Employees that depend on this shared skill"
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
},
|
|
2279
|
+
registries: {
|
|
2280
|
+
type: "object",
|
|
2281
|
+
description: "Custom registry configurations",
|
|
2282
|
+
propertyNames: {
|
|
2283
|
+
pattern: "^@"
|
|
2284
|
+
},
|
|
2285
|
+
additionalProperties: {
|
|
2286
|
+
oneOf: [
|
|
2287
|
+
{
|
|
2288
|
+
type: "string",
|
|
2289
|
+
description: "Registry URL with {name} placeholder"
|
|
2290
|
+
},
|
|
2291
|
+
{
|
|
2292
|
+
type: "object",
|
|
2293
|
+
required: ["url"],
|
|
2294
|
+
properties: {
|
|
2295
|
+
url: {
|
|
2296
|
+
type: "string",
|
|
2297
|
+
description: "Registry URL with {name} placeholder"
|
|
2298
|
+
},
|
|
2299
|
+
headers: {
|
|
2300
|
+
type: "object",
|
|
2301
|
+
additionalProperties: { type: "string" },
|
|
2302
|
+
description: "Custom HTTP headers"
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
]
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
};
|
|
2311
|
+
var EMPLOYEE_SCHEMA = {
|
|
2312
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2313
|
+
$id: "https://the-aico.com/schema/employee.json",
|
|
2314
|
+
title: "aico Employee",
|
|
2315
|
+
description: "Employee definition schema for employee.json",
|
|
2316
|
+
type: "object",
|
|
2317
|
+
required: ["name", "role"],
|
|
2318
|
+
properties: {
|
|
2319
|
+
$schema: {
|
|
2320
|
+
type: "string",
|
|
2321
|
+
description: "JSON Schema reference"
|
|
2322
|
+
},
|
|
2323
|
+
name: {
|
|
2324
|
+
type: "string",
|
|
2325
|
+
pattern: "^[a-z0-9-]+$",
|
|
2326
|
+
description: "Employee name (hyphen-case)"
|
|
2327
|
+
},
|
|
2328
|
+
namespace: {
|
|
2329
|
+
type: "string",
|
|
2330
|
+
pattern: "^@[a-z0-9-]+$",
|
|
2331
|
+
description: "Registry namespace (@registry format)"
|
|
2332
|
+
},
|
|
2333
|
+
fullName: {
|
|
2334
|
+
type: "string",
|
|
2335
|
+
pattern: "^@[a-z0-9-]+/[a-z0-9-]+$",
|
|
2336
|
+
description: "Full name (@registry/employee format)"
|
|
2337
|
+
},
|
|
2338
|
+
role: {
|
|
2339
|
+
type: "string",
|
|
2340
|
+
minLength: 1,
|
|
2341
|
+
description: "Employee role title"
|
|
2342
|
+
},
|
|
2343
|
+
description: {
|
|
2344
|
+
type: "string",
|
|
2345
|
+
description: "Employee description"
|
|
2346
|
+
},
|
|
2347
|
+
version: {
|
|
2348
|
+
type: "string",
|
|
2349
|
+
pattern: "^\\d+\\.\\d+\\.\\d+$",
|
|
2350
|
+
description: "Semantic version"
|
|
2351
|
+
},
|
|
2352
|
+
category: {
|
|
2353
|
+
type: "string",
|
|
2354
|
+
enum: ["pm", "frontend", "backend", "devops", "general"],
|
|
2355
|
+
description: "Employee category"
|
|
2356
|
+
},
|
|
2357
|
+
skills: {
|
|
2358
|
+
type: "array",
|
|
2359
|
+
description: "Employee skills",
|
|
2360
|
+
items: {
|
|
2361
|
+
oneOf: [
|
|
2362
|
+
{
|
|
2363
|
+
type: "string",
|
|
2364
|
+
description: "Skill fullName reference"
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
type: "object",
|
|
2368
|
+
required: ["name", "files"],
|
|
2369
|
+
properties: {
|
|
2370
|
+
name: {
|
|
2371
|
+
type: "string",
|
|
2372
|
+
pattern: "^[a-z0-9-]+$",
|
|
2373
|
+
description: "Skill name (hyphen-case)"
|
|
2374
|
+
},
|
|
2375
|
+
files: {
|
|
2376
|
+
type: "array",
|
|
2377
|
+
minItems: 1,
|
|
2378
|
+
items: {
|
|
2379
|
+
$ref: "#/definitions/fileSource"
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
]
|
|
2385
|
+
}
|
|
2386
|
+
},
|
|
2387
|
+
commands: {
|
|
2388
|
+
type: "array",
|
|
2389
|
+
description: "Employee commands",
|
|
2390
|
+
items: {
|
|
2391
|
+
type: "object",
|
|
2392
|
+
required: ["name", "files"],
|
|
2393
|
+
properties: {
|
|
2394
|
+
name: {
|
|
2395
|
+
type: "string",
|
|
2396
|
+
pattern: "^[a-z0-9-]+$",
|
|
2397
|
+
description: "Command name (hyphen-case)"
|
|
2398
|
+
},
|
|
2399
|
+
files: {
|
|
2400
|
+
type: "array",
|
|
2401
|
+
minItems: 1,
|
|
2402
|
+
items: {
|
|
2403
|
+
$ref: "#/definitions/file"
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
},
|
|
2409
|
+
docs: {
|
|
2410
|
+
type: "array",
|
|
2411
|
+
description: "Employee documentation",
|
|
2412
|
+
items: {
|
|
2413
|
+
type: "object",
|
|
2414
|
+
required: ["name", "files"],
|
|
2415
|
+
properties: {
|
|
2416
|
+
name: {
|
|
2417
|
+
type: "string",
|
|
2418
|
+
description: "Document name"
|
|
2419
|
+
},
|
|
2420
|
+
files: {
|
|
2421
|
+
type: "array",
|
|
2422
|
+
minItems: 1,
|
|
2423
|
+
items: {
|
|
2424
|
+
$ref: "#/definitions/file"
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
},
|
|
2430
|
+
dependencies: {
|
|
2431
|
+
type: "array",
|
|
2432
|
+
description: "Shared skill dependencies",
|
|
2433
|
+
items: {
|
|
2434
|
+
type: "string",
|
|
2435
|
+
description: "Dependency reference (@registry/_shared/skill)"
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
},
|
|
2439
|
+
definitions: {
|
|
2440
|
+
fileSource: {
|
|
2441
|
+
type: "object",
|
|
2442
|
+
required: ["path", "type"],
|
|
2443
|
+
properties: {
|
|
2444
|
+
path: {
|
|
2445
|
+
type: "string",
|
|
2446
|
+
minLength: 1,
|
|
2447
|
+
description: "Relative file path"
|
|
2448
|
+
},
|
|
2449
|
+
type: {
|
|
2450
|
+
type: "string",
|
|
2451
|
+
enum: ["skill", "command", "doc"],
|
|
2452
|
+
description: "File type"
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
},
|
|
2456
|
+
file: {
|
|
2457
|
+
type: "object",
|
|
2458
|
+
required: ["path", "type"],
|
|
2459
|
+
properties: {
|
|
2460
|
+
path: {
|
|
2461
|
+
type: "string",
|
|
2462
|
+
minLength: 1,
|
|
2463
|
+
description: "Relative file path"
|
|
2464
|
+
},
|
|
2465
|
+
type: {
|
|
2466
|
+
type: "string",
|
|
2467
|
+
enum: ["skill", "command", "doc"],
|
|
2468
|
+
description: "File type"
|
|
2469
|
+
},
|
|
2470
|
+
content: {
|
|
2471
|
+
type: "string",
|
|
2472
|
+
description: "File content (populated at build time)"
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
};
|
|
2478
|
+
async function buildSchemas(outputDir) {
|
|
2479
|
+
const schemaDir = path7.join(outputDir, "schema");
|
|
2480
|
+
await fs6.ensureDir(schemaDir);
|
|
2481
|
+
await fs6.writeJson(path7.join(schemaDir, "config.json"), CONFIG_SCHEMA, {
|
|
2482
|
+
spaces: 2
|
|
2483
|
+
});
|
|
2484
|
+
await fs6.writeJson(path7.join(schemaDir, "employee.json"), EMPLOYEE_SCHEMA, {
|
|
2485
|
+
spaces: 2
|
|
2486
|
+
});
|
|
2487
|
+
logger.success("Built JSON schemas to schema/");
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
// src/commands/build.ts
|
|
2136
2491
|
var buildOptionsSchema = z9.object({
|
|
2137
2492
|
cwd: z9.string(),
|
|
2138
2493
|
employeesDir: z9.string(),
|
|
2139
2494
|
outputDir: z9.string(),
|
|
2495
|
+
schemaDir: z9.string().optional(),
|
|
2140
2496
|
registry: z9.string(),
|
|
2141
2497
|
version: z9.string()
|
|
2142
2498
|
});
|
|
@@ -2151,8 +2507,8 @@ function inferCategory(employeeName) {
|
|
|
2151
2507
|
return categoryMap[employeeName] ?? "general";
|
|
2152
2508
|
}
|
|
2153
2509
|
async function buildSharedSkills(employeesPath, outputPath, registry, version, skillsIndex) {
|
|
2154
|
-
const sharedDir =
|
|
2155
|
-
if (!await
|
|
2510
|
+
const sharedDir = path8.join(employeesPath, "_shared", "skills");
|
|
2511
|
+
if (!await fs7.pathExists(sharedDir)) {
|
|
2156
2512
|
return 0;
|
|
2157
2513
|
}
|
|
2158
2514
|
const skillDirs = await glob("*/SKILL.md", {
|
|
@@ -2163,10 +2519,10 @@ async function buildSharedSkills(employeesPath, outputPath, registry, version, s
|
|
|
2163
2519
|
}
|
|
2164
2520
|
const namespace = `${registry}/_shared`;
|
|
2165
2521
|
for (const skillPath of skillDirs) {
|
|
2166
|
-
const skillName =
|
|
2522
|
+
const skillName = path8.dirname(skillPath);
|
|
2167
2523
|
const skillFullName = `${namespace}/${skillName}`;
|
|
2168
|
-
const skillFilePath =
|
|
2169
|
-
const content = await
|
|
2524
|
+
const skillFilePath = path8.join(sharedDir, skillPath);
|
|
2525
|
+
const content = await fs7.readFile(skillFilePath, "utf-8");
|
|
2170
2526
|
const frontmatter = parseSkillFrontmatter(content);
|
|
2171
2527
|
if (!frontmatter) {
|
|
2172
2528
|
logger.warn(`Shared skill ${skillName} missing frontmatter, skipping`);
|
|
@@ -2189,15 +2545,15 @@ async function buildSharedSkills(employeesPath, outputPath, registry, version, s
|
|
|
2189
2545
|
}
|
|
2190
2546
|
]
|
|
2191
2547
|
};
|
|
2192
|
-
const skillOutputDir =
|
|
2548
|
+
const skillOutputDir = path8.join(
|
|
2193
2549
|
outputPath,
|
|
2194
2550
|
"skills",
|
|
2195
2551
|
registry.replace("@", ""),
|
|
2196
2552
|
"_shared"
|
|
2197
2553
|
);
|
|
2198
|
-
await
|
|
2199
|
-
await
|
|
2200
|
-
|
|
2554
|
+
await fs7.ensureDir(skillOutputDir);
|
|
2555
|
+
await fs7.writeJson(
|
|
2556
|
+
path8.join(skillOutputDir, `${skillName}.json`),
|
|
2201
2557
|
fullSkill,
|
|
2202
2558
|
{ spaces: 2 }
|
|
2203
2559
|
);
|
|
@@ -2214,11 +2570,12 @@ async function buildSharedSkills(employeesPath, outputPath, registry, version, s
|
|
|
2214
2570
|
return skillDirs.length;
|
|
2215
2571
|
}
|
|
2216
2572
|
async function runBuild(options) {
|
|
2217
|
-
const { cwd, employeesDir, outputDir, registry, version } = options;
|
|
2218
|
-
const employeesPath =
|
|
2219
|
-
const outputPath =
|
|
2220
|
-
|
|
2221
|
-
|
|
2573
|
+
const { cwd, employeesDir, outputDir, schemaDir, registry, version } = options;
|
|
2574
|
+
const employeesPath = path8.resolve(cwd, employeesDir);
|
|
2575
|
+
const outputPath = path8.resolve(cwd, outputDir);
|
|
2576
|
+
const schemaPath = schemaDir ? path8.resolve(cwd, schemaDir) : outputPath;
|
|
2577
|
+
if (await fs7.pathExists(outputPath)) {
|
|
2578
|
+
await fs7.emptyDir(outputPath);
|
|
2222
2579
|
}
|
|
2223
2580
|
const employeeFiles = await glob("*/employee.json", {
|
|
2224
2581
|
cwd: employeesPath,
|
|
@@ -2230,19 +2587,17 @@ async function runBuild(options) {
|
|
|
2230
2587
|
}
|
|
2231
2588
|
const s = spinner(`Building ${employeeFiles.length} employee(s)...`).start();
|
|
2232
2589
|
const skillsIndex = [];
|
|
2233
|
-
const employeesIndex = [];
|
|
2234
2590
|
const legacyIndex = [];
|
|
2235
2591
|
for (const employeeFile of employeeFiles) {
|
|
2236
|
-
const employeeName =
|
|
2237
|
-
const employeeDir =
|
|
2592
|
+
const employeeName = path8.dirname(employeeFile);
|
|
2593
|
+
const employeeDir = path8.join(employeesPath, employeeName);
|
|
2238
2594
|
try {
|
|
2239
|
-
const employeeJson = await
|
|
2240
|
-
|
|
2595
|
+
const employeeJson = await fs7.readJson(
|
|
2596
|
+
path8.join(employeeDir, "employee.json")
|
|
2241
2597
|
);
|
|
2242
2598
|
const employeeSource = employeeSourceSchema.parse(employeeJson);
|
|
2243
2599
|
const category = inferCategory(employeeName);
|
|
2244
2600
|
const namespace = `${registry}/${employeeName}`;
|
|
2245
|
-
const employeeFullName = `${registry}/${employeeName}`;
|
|
2246
2601
|
const employee = {
|
|
2247
2602
|
...employeeSource,
|
|
2248
2603
|
skills: employeeSource.skills.map((sk) => ({
|
|
@@ -2258,16 +2613,14 @@ async function runBuild(options) {
|
|
|
2258
2613
|
files: d.files.map((f) => ({ ...f, content: "" }))
|
|
2259
2614
|
}))
|
|
2260
2615
|
};
|
|
2261
|
-
const skillFullNames = [];
|
|
2262
2616
|
for (const skill of employee.skills) {
|
|
2263
2617
|
const skillFullName = `${namespace}/${skill.name}`;
|
|
2264
|
-
skillFullNames.push(skillFullName);
|
|
2265
2618
|
const skillFiles = [];
|
|
2266
2619
|
let skillDescription = "";
|
|
2267
2620
|
for (const file of skill.files) {
|
|
2268
|
-
const filePath =
|
|
2269
|
-
if (await
|
|
2270
|
-
const content = await
|
|
2621
|
+
const filePath = path8.join(employeeDir, file.path);
|
|
2622
|
+
if (await fs7.pathExists(filePath)) {
|
|
2623
|
+
const content = await fs7.readFile(filePath, "utf-8");
|
|
2271
2624
|
file.content = content;
|
|
2272
2625
|
if (file.path.endsWith("SKILL.md")) {
|
|
2273
2626
|
const frontmatter = parseSkillFrontmatter(content);
|
|
@@ -2276,7 +2629,7 @@ async function runBuild(options) {
|
|
|
2276
2629
|
}
|
|
2277
2630
|
}
|
|
2278
2631
|
skillFiles.push({
|
|
2279
|
-
path:
|
|
2632
|
+
path: path8.basename(file.path),
|
|
2280
2633
|
type: file.type === "skill" ? "skill" : "reference",
|
|
2281
2634
|
content
|
|
2282
2635
|
});
|
|
@@ -2295,15 +2648,15 @@ async function runBuild(options) {
|
|
|
2295
2648
|
dependencies: [],
|
|
2296
2649
|
files: skillFiles
|
|
2297
2650
|
};
|
|
2298
|
-
const skillOutputDir =
|
|
2651
|
+
const skillOutputDir = path8.join(
|
|
2299
2652
|
outputPath,
|
|
2300
2653
|
"skills",
|
|
2301
2654
|
registry.replace("@", ""),
|
|
2302
2655
|
employeeName
|
|
2303
2656
|
);
|
|
2304
|
-
await
|
|
2305
|
-
await
|
|
2306
|
-
|
|
2657
|
+
await fs7.ensureDir(skillOutputDir);
|
|
2658
|
+
await fs7.writeJson(
|
|
2659
|
+
path8.join(skillOutputDir, `${skill.name}.json`),
|
|
2307
2660
|
fullSkill,
|
|
2308
2661
|
{ spaces: 2 }
|
|
2309
2662
|
);
|
|
@@ -2319,9 +2672,9 @@ async function runBuild(options) {
|
|
|
2319
2672
|
}
|
|
2320
2673
|
for (const command of employee.commands) {
|
|
2321
2674
|
for (const file of command.files) {
|
|
2322
|
-
const filePath =
|
|
2323
|
-
if (await
|
|
2324
|
-
file.content = await
|
|
2675
|
+
const filePath = path8.join(employeeDir, file.path);
|
|
2676
|
+
if (await fs7.pathExists(filePath)) {
|
|
2677
|
+
file.content = await fs7.readFile(filePath, "utf-8");
|
|
2325
2678
|
} else {
|
|
2326
2679
|
throw new Error(`Command file not found: ${file.path}`);
|
|
2327
2680
|
}
|
|
@@ -2329,48 +2682,17 @@ async function runBuild(options) {
|
|
|
2329
2682
|
}
|
|
2330
2683
|
for (const doc of employee.docs) {
|
|
2331
2684
|
for (const file of doc.files) {
|
|
2332
|
-
const filePath =
|
|
2333
|
-
if (await
|
|
2334
|
-
file.content = await
|
|
2685
|
+
const filePath = path8.join(employeeDir, file.path);
|
|
2686
|
+
if (await fs7.pathExists(filePath)) {
|
|
2687
|
+
file.content = await fs7.readFile(filePath, "utf-8");
|
|
2335
2688
|
} else {
|
|
2336
2689
|
throw new Error(`Doc file not found: ${file.path}`);
|
|
2337
2690
|
}
|
|
2338
2691
|
}
|
|
2339
2692
|
}
|
|
2340
|
-
const legacyOutputPath =
|
|
2341
|
-
await
|
|
2342
|
-
await
|
|
2343
|
-
const employeeExtended = {
|
|
2344
|
-
$schema: "https://the-aico.com/schema/employee.json",
|
|
2345
|
-
name: employee.name,
|
|
2346
|
-
namespace: registry,
|
|
2347
|
-
fullName: employeeFullName,
|
|
2348
|
-
role: employee.role,
|
|
2349
|
-
description: employee.description,
|
|
2350
|
-
version,
|
|
2351
|
-
category,
|
|
2352
|
-
skills: skillFullNames,
|
|
2353
|
-
commands: employee.commands,
|
|
2354
|
-
docs: employee.docs
|
|
2355
|
-
};
|
|
2356
|
-
const employeesOutputDir = path7.join(outputPath, "employees");
|
|
2357
|
-
await fs6.ensureDir(employeesOutputDir);
|
|
2358
|
-
await fs6.writeJson(
|
|
2359
|
-
path7.join(employeesOutputDir, `${employee.name}.json`),
|
|
2360
|
-
employeeExtended,
|
|
2361
|
-
{ spaces: 2 }
|
|
2362
|
-
);
|
|
2363
|
-
employeesIndex.push({
|
|
2364
|
-
name: employee.name,
|
|
2365
|
-
namespace: registry,
|
|
2366
|
-
fullName: employeeFullName,
|
|
2367
|
-
role: employee.role,
|
|
2368
|
-
description: employee.description,
|
|
2369
|
-
version,
|
|
2370
|
-
skillCount: employee.skills.length,
|
|
2371
|
-
commandCount: employee.commands.length,
|
|
2372
|
-
category
|
|
2373
|
-
});
|
|
2693
|
+
const legacyOutputPath = path8.join(outputPath, `${employee.name}.json`);
|
|
2694
|
+
await fs7.ensureDir(outputPath);
|
|
2695
|
+
await fs7.writeJson(legacyOutputPath, employee, { spaces: 2 });
|
|
2374
2696
|
legacyIndex.push({
|
|
2375
2697
|
name: employee.name,
|
|
2376
2698
|
role: employee.role,
|
|
@@ -2393,38 +2715,41 @@ async function runBuild(options) {
|
|
|
2393
2715
|
if (sharedSkillCount > 0) {
|
|
2394
2716
|
s.text = `Built ${sharedSkillCount} shared skill(s)`;
|
|
2395
2717
|
}
|
|
2396
|
-
const skillsIndexPath =
|
|
2397
|
-
await
|
|
2398
|
-
await
|
|
2399
|
-
const
|
|
2400
|
-
await
|
|
2401
|
-
await fs6.writeJson(employeesIndexPath, employeesIndex, { spaces: 2 });
|
|
2402
|
-
const legacyIndexPath = path7.join(outputPath, "index.json");
|
|
2403
|
-
await fs6.writeJson(
|
|
2718
|
+
const skillsIndexPath = path8.join(outputPath, "skills", "index.json");
|
|
2719
|
+
await fs7.ensureDir(path8.dirname(skillsIndexPath));
|
|
2720
|
+
await fs7.writeJson(skillsIndexPath, skillsIndex, { spaces: 2 });
|
|
2721
|
+
const legacyIndexPath = path8.join(outputPath, "index.json");
|
|
2722
|
+
await fs7.writeJson(
|
|
2404
2723
|
legacyIndexPath,
|
|
2405
2724
|
{ employees: legacyIndex },
|
|
2406
2725
|
{ spaces: 2 }
|
|
2407
2726
|
);
|
|
2727
|
+
s.text = "Building JSON schemas...";
|
|
2728
|
+
await buildSchemas(schemaPath);
|
|
2408
2729
|
s.succeed(`Built ${employeeFiles.length} employee(s) to ${outputDir}/`);
|
|
2409
2730
|
logger.break();
|
|
2410
2731
|
logger.success("Registry build complete!");
|
|
2411
2732
|
logger.dim(` Skills: ${skillsIndex.length} (${sharedSkillCount} shared)`);
|
|
2412
|
-
logger.dim(` Employees: ${
|
|
2733
|
+
logger.dim(` Employees: ${legacyIndex.length}`);
|
|
2413
2734
|
logger.break();
|
|
2414
|
-
for (const emp of
|
|
2415
|
-
logger.dim(` - ${emp.name}: ${emp.role}
|
|
2735
|
+
for (const emp of legacyIndex) {
|
|
2736
|
+
logger.dim(` - ${emp.name}: ${emp.role}`);
|
|
2416
2737
|
}
|
|
2417
2738
|
}
|
|
2418
2739
|
var build = new Command5().name("build").description("Build registry from employees directory").option(
|
|
2419
2740
|
"-e, --employees-dir <dir>",
|
|
2420
2741
|
"Employees source directory",
|
|
2421
2742
|
"employees"
|
|
2422
|
-
).option("-o, --output-dir <dir>", "Output directory", "registry").option(
|
|
2743
|
+
).option("-o, --output-dir <dir>", "Output directory", "registry").option(
|
|
2744
|
+
"-s, --schema-dir <dir>",
|
|
2745
|
+
"Schema output directory (defaults to output-dir)"
|
|
2746
|
+
).option("-r, --registry <name>", "Registry namespace", "@the-aico").option("-v, --version <version>", "Version number", "1.0.0").option("-c, --cwd <cwd>", "Working directory", process.cwd()).action(async (opts) => {
|
|
2423
2747
|
try {
|
|
2424
2748
|
const options = buildOptionsSchema.parse({
|
|
2425
2749
|
cwd: opts.cwd,
|
|
2426
2750
|
employeesDir: opts.employeesDir,
|
|
2427
2751
|
outputDir: opts.outputDir,
|
|
2752
|
+
schemaDir: opts.schemaDir,
|
|
2428
2753
|
registry: opts.registry,
|
|
2429
2754
|
version: opts.version
|
|
2430
2755
|
});
|
|
@@ -2435,8 +2760,8 @@ var build = new Command5().name("build").description("Build registry from employ
|
|
|
2435
2760
|
});
|
|
2436
2761
|
|
|
2437
2762
|
// src/commands/diff.ts
|
|
2438
|
-
import
|
|
2439
|
-
import
|
|
2763
|
+
import fs8 from "fs-extra";
|
|
2764
|
+
import path9 from "path";
|
|
2440
2765
|
import { Command as Command6 } from "commander";
|
|
2441
2766
|
import { diffLines } from "diff";
|
|
2442
2767
|
import { z as z10 } from "zod";
|
|
@@ -2449,10 +2774,10 @@ var diffOptionsSchema = z10.object({
|
|
|
2449
2774
|
cwd: z10.string()
|
|
2450
2775
|
});
|
|
2451
2776
|
async function compareFile(localPath, registryContent) {
|
|
2452
|
-
if (!await
|
|
2777
|
+
if (!await fs8.pathExists(localPath)) {
|
|
2453
2778
|
return null;
|
|
2454
2779
|
}
|
|
2455
|
-
const localContent = await
|
|
2780
|
+
const localContent = await fs8.readFile(localPath, "utf-8");
|
|
2456
2781
|
const patch = diffLines(localContent, registryContent);
|
|
2457
2782
|
const hasChanges = patch.some((part) => part.added || part.removed);
|
|
2458
2783
|
return hasChanges ? patch : null;
|
|
@@ -2496,10 +2821,10 @@ async function diffEmployee(employeeName, cwd, config) {
|
|
|
2496
2821
|
for (const skill of registryEmployee.skills) {
|
|
2497
2822
|
const skillDirName = adapter.getSkillDirName(employeeName, skill.name);
|
|
2498
2823
|
for (const file of skill.files) {
|
|
2499
|
-
const localPath =
|
|
2824
|
+
const localPath = path9.join(
|
|
2500
2825
|
skillsDir,
|
|
2501
2826
|
skillDirName,
|
|
2502
|
-
|
|
2827
|
+
path9.basename(file.path)
|
|
2503
2828
|
);
|
|
2504
2829
|
let registryContent = file.content;
|
|
2505
2830
|
if (file.path.endsWith("SKILL.md")) {
|
|
@@ -2508,7 +2833,7 @@ async function diffEmployee(employeeName, cwd, config) {
|
|
|
2508
2833
|
`$1${skillDirName}`
|
|
2509
2834
|
);
|
|
2510
2835
|
}
|
|
2511
|
-
if (!await
|
|
2836
|
+
if (!await fs8.pathExists(localPath)) {
|
|
2512
2837
|
if (!skillsAdded.includes(skill.name)) {
|
|
2513
2838
|
fileChanges.push({
|
|
2514
2839
|
filePath: localPath,
|
|
@@ -2533,8 +2858,8 @@ async function diffEmployee(employeeName, cwd, config) {
|
|
|
2533
2858
|
command.name
|
|
2534
2859
|
);
|
|
2535
2860
|
for (const file of command.files) {
|
|
2536
|
-
const localPath =
|
|
2537
|
-
if (!await
|
|
2861
|
+
const localPath = path9.join(commandsDir, commandFileName);
|
|
2862
|
+
if (!await fs8.pathExists(localPath)) {
|
|
2538
2863
|
if (!commandsAdded.includes(command.name)) {
|
|
2539
2864
|
fileChanges.push({
|
|
2540
2865
|
filePath: localPath,
|
|
@@ -2555,8 +2880,8 @@ async function diffEmployee(employeeName, cwd, config) {
|
|
|
2555
2880
|
}
|
|
2556
2881
|
for (const skillName of skillsRemoved) {
|
|
2557
2882
|
const skillDirName = adapter.getSkillDirName(employeeName, skillName);
|
|
2558
|
-
const skillPath =
|
|
2559
|
-
if (await
|
|
2883
|
+
const skillPath = path9.join(skillsDir, skillDirName);
|
|
2884
|
+
if (await fs8.pathExists(skillPath)) {
|
|
2560
2885
|
fileChanges.push({
|
|
2561
2886
|
filePath: skillPath,
|
|
2562
2887
|
type: "removed"
|
|
@@ -2568,8 +2893,8 @@ async function diffEmployee(employeeName, cwd, config) {
|
|
|
2568
2893
|
employeeName,
|
|
2569
2894
|
commandName
|
|
2570
2895
|
);
|
|
2571
|
-
const commandPath =
|
|
2572
|
-
if (await
|
|
2896
|
+
const commandPath = path9.join(commandsDir, commandFileName);
|
|
2897
|
+
if (await fs8.pathExists(commandPath)) {
|
|
2573
2898
|
fileChanges.push({
|
|
2574
2899
|
filePath: commandPath,
|
|
2575
2900
|
type: "removed"
|
|
@@ -2641,7 +2966,7 @@ async function runDiff(options) {
|
|
|
2641
2966
|
logger.warn(` Removed commands: ${diff2.commandsRemoved.join(", ")}`);
|
|
2642
2967
|
}
|
|
2643
2968
|
for (const change of diff2.fileChanges) {
|
|
2644
|
-
const relativePath =
|
|
2969
|
+
const relativePath = path9.relative(cwd, change.filePath);
|
|
2645
2970
|
if (change.type === "modified") {
|
|
2646
2971
|
logger.info(` Modified: ${relativePath}`);
|
|
2647
2972
|
if (change.patch) {
|