@agentyx/core 0.2.0 → 0.3.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/dist/index.d.mts +151 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +404 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/skills/api-documentation/SKILL.md +34 -0
- package/skills/aria-patterns/SKILL.md +36 -0
- package/skills/auth-patterns/SKILL.md +35 -0
- package/skills/branching-strategy/SKILL.md +34 -0
- package/skills/ci-pipelines/SKILL.md +34 -0
- package/skills/commit-hygiene/SKILL.md +34 -0
- package/skills/containerization/SKILL.md +38 -0
- package/skills/data-modeling/SKILL.md +34 -0
- package/skills/decision-records/SKILL.md +34 -0
- package/skills/dependency-hygiene/SKILL.md +34 -0
- package/skills/dependency-security/SKILL.md +35 -0
- package/skills/deployment-safety/SKILL.md +33 -0
- package/skills/e2e-testing/SKILL.md +34 -0
- package/skills/flaky-tests/SKILL.md +29 -0
- package/skills/incident-response/SKILL.md +34 -0
- package/skills/infrastructure-as-code/SKILL.md +34 -0
- package/skills/keyboard-navigation/SKILL.md +34 -0
- package/skills/legacy-code/SKILL.md +34 -0
- package/skills/metrics-and-tracing/SKILL.md +33 -0
- package/skills/performance-profiling/SKILL.md +34 -0
- package/skills/pull-requests/SKILL.md +34 -0
- package/skills/query-performance/SKILL.md +34 -0
- package/skills/refactoring-safely/SKILL.md +34 -0
- package/skills/schema-migrations/SKILL.md +34 -0
- package/skills/secrets-handling/SKILL.md +34 -0
- package/skills/secure-coding/SKILL.md +33 -0
- package/skills/semantic-html/SKILL.md +34 -0
- package/skills/structured-logging/SKILL.md +34 -0
- package/skills/technical-writing/SKILL.md +34 -0
- package/skills/test-doubles/SKILL.md +30 -0
- package/skills/test-strategy/SKILL.md +35 -0
- package/skills/transactions-and-consistency/SKILL.md +34 -0
- package/skills/web-vitals/SKILL.md +34 -0
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { access, readFile } from "node:fs/promises";
|
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
6
7
|
//#region src/errors.ts
|
|
7
8
|
/**
|
|
8
9
|
* Base class for every failure Agentyx raises deliberately.
|
|
@@ -20,6 +21,27 @@ var AgentyxError = class extends Error {
|
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
//#endregion
|
|
24
|
+
//#region src/issues.ts
|
|
25
|
+
/**
|
|
26
|
+
* Turns a Zod failure into locations a reader can find in the file.
|
|
27
|
+
*
|
|
28
|
+
* Shared by every document Agentyx validates, so a problem in `.agentyx.json`
|
|
29
|
+
* and a problem in `.agentyx.lock.json` are reported the same way.
|
|
30
|
+
*/
|
|
31
|
+
function toAgentyxIssues(error) {
|
|
32
|
+
return error.issues.map((issue) => ({
|
|
33
|
+
path: formatIssuePath(issue.path),
|
|
34
|
+
message: issue.message
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function formatIssuePath(path) {
|
|
38
|
+
if (path.length === 0) return "(root)";
|
|
39
|
+
return path.reduce((formatted, segment) => {
|
|
40
|
+
if (typeof segment === "number") return `${formatted}[${segment}]`;
|
|
41
|
+
return formatted === "" ? String(segment) : `${formatted}.${String(segment)}`;
|
|
42
|
+
}, "");
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
23
45
|
//#region src/config/errors.ts
|
|
24
46
|
/** Raised when the supplied directory has no `.agentyx.json`. */
|
|
25
47
|
var AgentyxConfigNotFoundError = class extends AgentyxError {
|
|
@@ -45,7 +67,7 @@ var AgentyxConfigValidationError = class extends AgentyxError {
|
|
|
45
67
|
/** The file the configuration came from, when it was read from disk. */
|
|
46
68
|
filePath;
|
|
47
69
|
constructor(error, filePath) {
|
|
48
|
-
const issues =
|
|
70
|
+
const issues = toAgentyxIssues(error);
|
|
49
71
|
const location = filePath === void 0 ? "" : ` in ${filePath}`;
|
|
50
72
|
const details = issues.map((issue) => ` - ${issue.path}: ${issue.message}`).join("\n");
|
|
51
73
|
super("agentyx_config_invalid", `Invalid Agentyx configuration${location}:\n${details}`);
|
|
@@ -65,19 +87,6 @@ var UnknownEnabledCapabilityError = class extends AgentyxError {
|
|
|
65
87
|
this.knownCapabilities = knownCapabilities;
|
|
66
88
|
}
|
|
67
89
|
};
|
|
68
|
-
function toConfigIssues(error) {
|
|
69
|
-
return error.issues.map((issue) => ({
|
|
70
|
-
path: formatIssuePath(issue.path),
|
|
71
|
-
message: issue.message
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
74
|
-
function formatIssuePath(path) {
|
|
75
|
-
if (path.length === 0) return "(root)";
|
|
76
|
-
return path.reduce((formatted, segment) => {
|
|
77
|
-
if (typeof segment === "number") return `${formatted}[${segment}]`;
|
|
78
|
-
return formatted === "" ? String(segment) : `${formatted}.${String(segment)}`;
|
|
79
|
-
}, "");
|
|
80
|
-
}
|
|
81
90
|
//#endregion
|
|
82
91
|
//#region src/mcp/schema.ts
|
|
83
92
|
const MCP_CAPABILITY_LEVELS = ["default", "optional"];
|
|
@@ -382,6 +391,49 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
|
|
|
382
391
|
contextCost: "high",
|
|
383
392
|
command: "codebase-memory-mcp"
|
|
384
393
|
})
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: "github",
|
|
397
|
+
load: () => ({
|
|
398
|
+
name: "github",
|
|
399
|
+
description: "Read repositories, issues, pull requests and workflow runs on GitHub.",
|
|
400
|
+
transport: "http",
|
|
401
|
+
contextCost: "high",
|
|
402
|
+
url: "https://api.githubcopilot.com/mcp/"
|
|
403
|
+
})
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
name: "sentry",
|
|
407
|
+
load: () => ({
|
|
408
|
+
name: "sentry",
|
|
409
|
+
description: "Inspect production issues, events and stack traces recorded by Sentry.",
|
|
410
|
+
transport: "http",
|
|
411
|
+
contextCost: "medium",
|
|
412
|
+
url: "https://mcp.sentry.dev/mcp"
|
|
413
|
+
})
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
name: "chrome-devtools",
|
|
417
|
+
load: () => ({
|
|
418
|
+
name: "chrome-devtools",
|
|
419
|
+
description: "Record performance traces and inspect pages through Chrome DevTools.",
|
|
420
|
+
transport: "stdio",
|
|
421
|
+
contextCost: "high",
|
|
422
|
+
command: "npx",
|
|
423
|
+
args: ["-y", "chrome-devtools-mcp@latest"]
|
|
424
|
+
})
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
name: "supabase",
|
|
428
|
+
load: () => ({
|
|
429
|
+
name: "supabase",
|
|
430
|
+
description: "Inspect and query Supabase project schemas, tables and logs.",
|
|
431
|
+
transport: "stdio",
|
|
432
|
+
contextCost: "high",
|
|
433
|
+
command: "npx",
|
|
434
|
+
args: ["-y", "@supabase/mcp-server-supabase@latest"],
|
|
435
|
+
env: { SUPABASE_ACCESS_TOKEN: { fromEnv: "SUPABASE_ACCESS_TOKEN" } }
|
|
436
|
+
})
|
|
385
437
|
}
|
|
386
438
|
]);
|
|
387
439
|
const builtInMcpServerNames = builtInMcpServerRegistry.names;
|
|
@@ -504,6 +556,133 @@ const builtInPacks = [
|
|
|
504
556
|
"subagent-driven-development",
|
|
505
557
|
"requesting-code-review"
|
|
506
558
|
]
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
name: "testing",
|
|
562
|
+
category: "engineering",
|
|
563
|
+
description: "Test design, isolation and stability at every level of the pyramid.",
|
|
564
|
+
skills: [
|
|
565
|
+
"test-strategy",
|
|
566
|
+
"test-doubles",
|
|
567
|
+
"e2e-testing",
|
|
568
|
+
"flaky-tests"
|
|
569
|
+
],
|
|
570
|
+
mcpServers: [{
|
|
571
|
+
name: "playwright",
|
|
572
|
+
activation: "optional"
|
|
573
|
+
}]
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
name: "security",
|
|
577
|
+
category: "engineering",
|
|
578
|
+
description: "Application security fundamentals for untrusted input, secrets and access.",
|
|
579
|
+
skills: [
|
|
580
|
+
"secure-coding",
|
|
581
|
+
"secrets-handling",
|
|
582
|
+
"dependency-security",
|
|
583
|
+
"auth-patterns"
|
|
584
|
+
]
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
name: "performance",
|
|
588
|
+
category: "engineering",
|
|
589
|
+
description: "Measure before optimizing, across application, browser and database.",
|
|
590
|
+
skills: [
|
|
591
|
+
"performance-profiling",
|
|
592
|
+
"web-vitals",
|
|
593
|
+
"query-performance"
|
|
594
|
+
],
|
|
595
|
+
mcpServers: [{
|
|
596
|
+
name: "chrome-devtools",
|
|
597
|
+
activation: "optional"
|
|
598
|
+
}]
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
name: "accessibility",
|
|
602
|
+
category: "engineering",
|
|
603
|
+
description: "Accessible markup, ARIA and keyboard interaction for web interfaces.",
|
|
604
|
+
skills: [
|
|
605
|
+
"semantic-html",
|
|
606
|
+
"aria-patterns",
|
|
607
|
+
"keyboard-navigation"
|
|
608
|
+
],
|
|
609
|
+
mcpServers: [{
|
|
610
|
+
name: "chrome-devtools",
|
|
611
|
+
activation: "optional"
|
|
612
|
+
}]
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
name: "refactoring",
|
|
616
|
+
category: "engineering",
|
|
617
|
+
description: "Change structure safely, including in legacy code with weak tests.",
|
|
618
|
+
skills: [
|
|
619
|
+
"refactoring-safely",
|
|
620
|
+
"legacy-code",
|
|
621
|
+
"dependency-hygiene"
|
|
622
|
+
]
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
name: "documentation",
|
|
626
|
+
category: "engineering",
|
|
627
|
+
description: "Documentation, interface reference and decision records that stay useful.",
|
|
628
|
+
skills: [
|
|
629
|
+
"technical-writing",
|
|
630
|
+
"api-documentation",
|
|
631
|
+
"decision-records"
|
|
632
|
+
]
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
name: "observability",
|
|
636
|
+
category: "engineering",
|
|
637
|
+
description: "Logging, metrics, tracing and incident response for running systems.",
|
|
638
|
+
skills: [
|
|
639
|
+
"structured-logging",
|
|
640
|
+
"metrics-and-tracing",
|
|
641
|
+
"incident-response"
|
|
642
|
+
],
|
|
643
|
+
mcpServers: [{
|
|
644
|
+
name: "sentry",
|
|
645
|
+
activation: "optional"
|
|
646
|
+
}]
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
name: "data",
|
|
650
|
+
category: "engineering",
|
|
651
|
+
description: "Schema design, migrations and transactional correctness.",
|
|
652
|
+
skills: [
|
|
653
|
+
"data-modeling",
|
|
654
|
+
"schema-migrations",
|
|
655
|
+
"transactions-and-consistency"
|
|
656
|
+
],
|
|
657
|
+
mcpServers: [{
|
|
658
|
+
name: "supabase",
|
|
659
|
+
activation: "optional"
|
|
660
|
+
}]
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
name: "git",
|
|
664
|
+
category: "workflow",
|
|
665
|
+
description: "Commit, branch and pull-request practice for reviewable history.",
|
|
666
|
+
skills: [
|
|
667
|
+
"commit-hygiene",
|
|
668
|
+
"branching-strategy",
|
|
669
|
+
"pull-requests"
|
|
670
|
+
],
|
|
671
|
+
mcpServers: [{
|
|
672
|
+
name: "github",
|
|
673
|
+
activation: "optional"
|
|
674
|
+
}]
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
name: "devops",
|
|
678
|
+
category: "workflow",
|
|
679
|
+
description: "Continuous integration, containers, deployment safety and infrastructure.",
|
|
680
|
+
skills: [
|
|
681
|
+
"ci-pipelines",
|
|
682
|
+
"containerization",
|
|
683
|
+
"deployment-safety",
|
|
684
|
+
"infrastructure-as-code"
|
|
685
|
+
]
|
|
507
686
|
}
|
|
508
687
|
];
|
|
509
688
|
/** The registry used by default when no explicit registry is supplied. */
|
|
@@ -779,7 +958,40 @@ const builtInSkillNames = [
|
|
|
779
958
|
"context-efficient-development",
|
|
780
959
|
"concise-output",
|
|
781
960
|
"targeted-exploration",
|
|
782
|
-
"focused-verification"
|
|
961
|
+
"focused-verification",
|
|
962
|
+
"test-strategy",
|
|
963
|
+
"test-doubles",
|
|
964
|
+
"e2e-testing",
|
|
965
|
+
"flaky-tests",
|
|
966
|
+
"secure-coding",
|
|
967
|
+
"secrets-handling",
|
|
968
|
+
"dependency-security",
|
|
969
|
+
"auth-patterns",
|
|
970
|
+
"performance-profiling",
|
|
971
|
+
"web-vitals",
|
|
972
|
+
"query-performance",
|
|
973
|
+
"semantic-html",
|
|
974
|
+
"aria-patterns",
|
|
975
|
+
"keyboard-navigation",
|
|
976
|
+
"refactoring-safely",
|
|
977
|
+
"legacy-code",
|
|
978
|
+
"dependency-hygiene",
|
|
979
|
+
"technical-writing",
|
|
980
|
+
"api-documentation",
|
|
981
|
+
"decision-records",
|
|
982
|
+
"structured-logging",
|
|
983
|
+
"metrics-and-tracing",
|
|
984
|
+
"incident-response",
|
|
985
|
+
"data-modeling",
|
|
986
|
+
"schema-migrations",
|
|
987
|
+
"transactions-and-consistency",
|
|
988
|
+
"commit-hygiene",
|
|
989
|
+
"branching-strategy",
|
|
990
|
+
"pull-requests",
|
|
991
|
+
"ci-pipelines",
|
|
992
|
+
"containerization",
|
|
993
|
+
"deployment-safety",
|
|
994
|
+
"infrastructure-as-code"
|
|
783
995
|
];
|
|
784
996
|
/** The absolute path of a built-in skill's `SKILL.md`. */
|
|
785
997
|
function builtInSkillPath(name) {
|
|
@@ -978,6 +1190,182 @@ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegis
|
|
|
978
1190
|
};
|
|
979
1191
|
}
|
|
980
1192
|
//#endregion
|
|
1193
|
+
//#region src/manifest/errors.ts
|
|
1194
|
+
/** Raised when `.agentyx.lock.json` is not valid JSON. */
|
|
1195
|
+
var AgentyxManifestParseError = class extends AgentyxError {
|
|
1196
|
+
filePath;
|
|
1197
|
+
constructor(filePath, reason, options) {
|
|
1198
|
+
super("agentyx_manifest_parse_error", `${filePath} is not valid JSON: ${reason}`, options);
|
|
1199
|
+
this.name = "AgentyxManifestParseError";
|
|
1200
|
+
this.filePath = filePath;
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
/**
|
|
1204
|
+
* Raised when the manifest parses as JSON but is not a manifest Agentyx
|
|
1205
|
+
* understands.
|
|
1206
|
+
*
|
|
1207
|
+
* This is never repaired. The manifest is what tells Agentyx which files it is
|
|
1208
|
+
* allowed to overwrite and delete, so guessing at a damaged one would be
|
|
1209
|
+
* guessing about destructive operations.
|
|
1210
|
+
*/
|
|
1211
|
+
var AgentyxManifestValidationError = class extends AgentyxError {
|
|
1212
|
+
issues;
|
|
1213
|
+
filePath;
|
|
1214
|
+
constructor(error, filePath) {
|
|
1215
|
+
const issues = toAgentyxIssues(error);
|
|
1216
|
+
const location = filePath === void 0 ? "" : ` in ${filePath}`;
|
|
1217
|
+
const details = issues.map((issue) => ` - ${issue.path}: ${issue.message}`).join("\n");
|
|
1218
|
+
super("agentyx_manifest_invalid", `Invalid Agentyx install manifest${location}:\n${details}\nDelete the file to start from a clean install record.`);
|
|
1219
|
+
this.name = "AgentyxManifestValidationError";
|
|
1220
|
+
this.issues = issues;
|
|
1221
|
+
this.filePath = filePath;
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
//#endregion
|
|
1225
|
+
//#region src/manifest/schema.ts
|
|
1226
|
+
/**
|
|
1227
|
+
* The manifest format version.
|
|
1228
|
+
*
|
|
1229
|
+
* A manifest written by a newer Agentyx fails validation instead of being
|
|
1230
|
+
* reinterpreted, because acting on a half-understood record of managed files is
|
|
1231
|
+
* how an installer deletes something it should not.
|
|
1232
|
+
*/
|
|
1233
|
+
const INSTALL_MANIFEST_VERSION = 1;
|
|
1234
|
+
/**
|
|
1235
|
+
* A path Agentyx manages, relative to the project root and always written with
|
|
1236
|
+
* `/` separators so a manifest reads the same on every platform.
|
|
1237
|
+
*/
|
|
1238
|
+
const managedPathSchema = z.string().min(1, "Managed paths must be non-empty strings.").refine((value) => !value.startsWith("/"), "Managed paths must be relative to the project root.").refine((value) => !value.includes("\\"), "Managed paths must use `/` separators.").refine((value) => !value.split("/").includes(".."), "Managed paths must not traverse outside the project root.");
|
|
1239
|
+
/** A SHA-256 digest of the exact bytes Agentyx last wrote to a managed path. */
|
|
1240
|
+
const contentHashSchema = z.string().regex(/^[0-9a-f]{64}$/, "Content hashes must be lowercase hexadecimal SHA-256 digests.");
|
|
1241
|
+
const targetsSchema = z.array(z.string().min(1, "Targets must be non-empty strings.")).min(1, "A manifest entry must record at least one target.");
|
|
1242
|
+
/** A `SKILL.md` file Agentyx wrote, owned entirely by Agentyx. */
|
|
1243
|
+
const skillManifestEntrySchema = z.strictObject({
|
|
1244
|
+
kind: z.literal("skill"),
|
|
1245
|
+
path: managedPathSchema,
|
|
1246
|
+
skill: z.string().min(1, "Skill names must be non-empty strings."),
|
|
1247
|
+
targets: targetsSchema,
|
|
1248
|
+
hash: contentHashSchema
|
|
1249
|
+
});
|
|
1250
|
+
/**
|
|
1251
|
+
* A provider MCP configuration file Agentyx contributed entries to.
|
|
1252
|
+
*
|
|
1253
|
+
* Unlike a skill file this one is shared with the user, so the entry records
|
|
1254
|
+
* the server keys Agentyx added rather than claiming the whole document.
|
|
1255
|
+
* `created` says whether the file existed before Agentyx first wrote it, which
|
|
1256
|
+
* is the only thing that makes removing the file itself safe.
|
|
1257
|
+
*/
|
|
1258
|
+
const mcpManifestEntrySchema = z.strictObject({
|
|
1259
|
+
kind: z.literal("mcp"),
|
|
1260
|
+
path: managedPathSchema,
|
|
1261
|
+
servers: z.array(z.string().min(1, "MCP server names must be non-empty strings.")),
|
|
1262
|
+
targets: targetsSchema,
|
|
1263
|
+
hash: contentHashSchema,
|
|
1264
|
+
created: z.boolean()
|
|
1265
|
+
});
|
|
1266
|
+
const installManifestEntrySchema = z.discriminatedUnion("kind", [skillManifestEntrySchema, mcpManifestEntrySchema]);
|
|
1267
|
+
/** The `.agentyx.lock.json` record of everything Agentyx installed into a project. */
|
|
1268
|
+
const installManifestSchema = z.strictObject({
|
|
1269
|
+
version: z.literal(1),
|
|
1270
|
+
entries: z.array(installManifestEntrySchema).default([])
|
|
1271
|
+
});
|
|
1272
|
+
//#endregion
|
|
1273
|
+
//#region src/manifest/io.ts
|
|
1274
|
+
const AGENTYX_MANIFEST_FILENAME = ".agentyx.lock.json";
|
|
1275
|
+
/** The absolute path `.agentyx.lock.json` is read from for a given project. */
|
|
1276
|
+
function agentyxManifestPath(projectPath = process.cwd()) {
|
|
1277
|
+
return resolve(projectPath, AGENTYX_MANIFEST_FILENAME);
|
|
1278
|
+
}
|
|
1279
|
+
/** A manifest that claims nothing — what a project has before its first install. */
|
|
1280
|
+
function emptyInstallManifest() {
|
|
1281
|
+
return {
|
|
1282
|
+
version: 1,
|
|
1283
|
+
entries: []
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* The SHA-256 digest Agentyx records for managed content.
|
|
1288
|
+
*
|
|
1289
|
+
* Comparing this digest with the file on disk is what separates "Agentyx wrote
|
|
1290
|
+
* this and may replace it" from "someone else owns this file", so it is
|
|
1291
|
+
* computed over the exact bytes written, never over a normalised form.
|
|
1292
|
+
*/
|
|
1293
|
+
function hashContent(content) {
|
|
1294
|
+
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Validates an already-parsed manifest document.
|
|
1298
|
+
*
|
|
1299
|
+
* @throws {AgentyxManifestValidationError} when the document violates the schema.
|
|
1300
|
+
*/
|
|
1301
|
+
function parseInstallManifest(value, filePath) {
|
|
1302
|
+
const result = installManifestSchema.safeParse(value);
|
|
1303
|
+
if (!result.success) throw new AgentyxManifestValidationError(result.error, filePath);
|
|
1304
|
+
return result.data;
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* Reads `.agentyx.lock.json` from `projectPath`.
|
|
1308
|
+
*
|
|
1309
|
+
* A missing manifest is a legitimate state — the project has simply never been
|
|
1310
|
+
* installed into — and yields an empty manifest. A manifest that exists but
|
|
1311
|
+
* cannot be understood is a hard failure: it governs which files Agentyx may
|
|
1312
|
+
* overwrite and delete, and a damaged one is never guessed at.
|
|
1313
|
+
*
|
|
1314
|
+
* @throws {AgentyxManifestParseError} when the file is not valid JSON.
|
|
1315
|
+
* @throws {AgentyxManifestValidationError} when the document violates the schema.
|
|
1316
|
+
*/
|
|
1317
|
+
async function loadInstallManifest(projectPath = process.cwd()) {
|
|
1318
|
+
const filePath = agentyxManifestPath(projectPath);
|
|
1319
|
+
let contents;
|
|
1320
|
+
try {
|
|
1321
|
+
contents = await readFile(filePath, "utf8");
|
|
1322
|
+
} catch (cause) {
|
|
1323
|
+
if (cause instanceof Error && cause.code === "ENOENT") return emptyInstallManifest();
|
|
1324
|
+
throw cause;
|
|
1325
|
+
}
|
|
1326
|
+
let document;
|
|
1327
|
+
try {
|
|
1328
|
+
document = JSON.parse(contents);
|
|
1329
|
+
} catch (cause) {
|
|
1330
|
+
throw new AgentyxManifestParseError(filePath, cause instanceof Error ? cause.message : String(cause), { cause });
|
|
1331
|
+
}
|
|
1332
|
+
return parseInstallManifest(document, filePath);
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Serialises a manifest for writing.
|
|
1336
|
+
*
|
|
1337
|
+
* Entries and their lists are sorted so that reinstalling an unchanged project
|
|
1338
|
+
* produces a byte-identical file and the manifest never shows up as noise in a
|
|
1339
|
+
* diff. Writing is deliberately not done here — only the install executor
|
|
1340
|
+
* touches the filesystem.
|
|
1341
|
+
*/
|
|
1342
|
+
function formatInstallManifest(manifest) {
|
|
1343
|
+
const entries = [...manifest.entries].map((entry) => entry.kind === "skill" ? {
|
|
1344
|
+
...entry,
|
|
1345
|
+
targets: sorted(entry.targets)
|
|
1346
|
+
} : {
|
|
1347
|
+
...entry,
|
|
1348
|
+
targets: sorted(entry.targets),
|
|
1349
|
+
servers: sorted(entry.servers)
|
|
1350
|
+
}).sort((left, right) => left.path.localeCompare(right.path));
|
|
1351
|
+
return `${JSON.stringify({
|
|
1352
|
+
version: manifest.version,
|
|
1353
|
+
entries
|
|
1354
|
+
}, null, 2)}\n`;
|
|
1355
|
+
}
|
|
1356
|
+
/**
|
|
1357
|
+
* Indexes manifest entries by managed path.
|
|
1358
|
+
*
|
|
1359
|
+
* Every ownership question — may this file be overwritten, may it be deleted —
|
|
1360
|
+
* is a lookup by path, so callers do not scan the list themselves.
|
|
1361
|
+
*/
|
|
1362
|
+
function manifestEntriesByPath(manifest) {
|
|
1363
|
+
return new Map(manifest.entries.map((entry) => [entry.path, entry]));
|
|
1364
|
+
}
|
|
1365
|
+
function sorted(values) {
|
|
1366
|
+
return [...values].sort();
|
|
1367
|
+
}
|
|
1368
|
+
//#endregion
|
|
981
1369
|
//#region src/meta.ts
|
|
982
1370
|
const agentyxCoreName = "agentyx-core";
|
|
983
1371
|
function getCoreStatus() {
|
|
@@ -1139,6 +1527,6 @@ function isNotFound(cause) {
|
|
|
1139
1527
|
return cause instanceof Error && cause.code === "ENOENT";
|
|
1140
1528
|
}
|
|
1141
1529
|
//#endregion
|
|
1142
|
-
export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, CircularPackDependencyError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, InvalidMcpServerError, InvalidSkillError, InvalidToolError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, TOOL_ACTIVATION_LEVELS, UnknownEnabledCapabilityError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, createMcpServerRegistry, createPackRegistry, createSkillRegistry, createToolRegistry, detectProject, enabledCapabilityNameSchema, filterEffectiveMcpServers, filterEffectiveTools, formatAgentyxConfig, formatSkillMarkdown, getCoreStatus, loadAgentyxConfig, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseSkillMarkdown, resolveAgentyxConfig, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, skillDefinitionSchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema };
|
|
1530
|
+
export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AGENTYX_MANIFEST_FILENAME, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, AgentyxManifestParseError, AgentyxManifestValidationError, CircularPackDependencyError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, INSTALL_MANIFEST_VERSION, InvalidMcpServerError, InvalidSkillError, InvalidToolError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, TOOL_ACTIVATION_LEVELS, UnknownEnabledCapabilityError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxManifestPath, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, createMcpServerRegistry, createPackRegistry, createSkillRegistry, createToolRegistry, detectProject, emptyInstallManifest, enabledCapabilityNameSchema, filterEffectiveMcpServers, filterEffectiveTools, formatAgentyxConfig, formatInstallManifest, formatSkillMarkdown, getCoreStatus, hashContent, installManifestEntrySchema, installManifestSchema, loadAgentyxConfig, loadInstallManifest, manifestEntriesByPath, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpManifestEntrySchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseInstallManifest, parseSkillMarkdown, resolveAgentyxConfig, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, skillDefinitionSchema, skillManifestEntrySchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema };
|
|
1143
1531
|
|
|
1144
1532
|
//# sourceMappingURL=index.mjs.map
|