@fro.bot/systematic 3.15.1 → 3.16.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/dist/cli.js +205 -36
- package/dist/{index-7cyxcwf5.js → index-ae6mhwth.js} +688 -160
- package/dist/index.js +42 -29
- package/dist/lib/agent-resolver.d.ts +7 -1
- package/dist/lib/capability-snapshot.d.ts +1 -1
- package/dist/lib/config-schema.d.ts +63 -1
- package/dist/lib/config.d.ts +59 -1
- package/dist/lib/pi-delegate-session.d.ts +2 -0
- package/dist/lib/pi-delegate-tool.d.ts +33 -1
- package/dist/lib/routing-resolver.d.ts +151 -0
- package/dist/pi.js +7496 -252
- package/dist/schemas/systematic-config.schema.json +1027 -185
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -23,14 +23,17 @@ import {
|
|
|
23
23
|
discriminatedUnion,
|
|
24
24
|
_enum,
|
|
25
25
|
literal,
|
|
26
|
+
extractString,
|
|
27
|
+
toSourcedPiSubagentsOverlays,
|
|
28
|
+
resolveRouting,
|
|
26
29
|
loadConfigWithSources,
|
|
30
|
+
collectRoutingTargets,
|
|
27
31
|
getConfigPaths,
|
|
28
|
-
extractString,
|
|
29
32
|
findAgentsInDir,
|
|
30
33
|
findCommandsInDir,
|
|
31
34
|
findSkillsInDir,
|
|
32
35
|
discoverSkills
|
|
33
|
-
} from "./index-
|
|
36
|
+
} from "./index-ae6mhwth.js";
|
|
34
37
|
var __defProp = Object.defineProperty;
|
|
35
38
|
var __returnValue = (v) => v;
|
|
36
39
|
function __exportSetter(name, newValue) {
|
|
@@ -59,7 +62,15 @@ function buildAgentCatalog(agentsDir) {
|
|
|
59
62
|
const entries = [];
|
|
60
63
|
for (const info of infos) {
|
|
61
64
|
const content = fs.readFileSync(info.file, "utf8");
|
|
62
|
-
const
|
|
65
|
+
const parsed = parseValidatedAgentEntry(content, info.file);
|
|
66
|
+
const category = info.category ?? "";
|
|
67
|
+
const key = info.name;
|
|
68
|
+
const entry = {
|
|
69
|
+
...parsed,
|
|
70
|
+
key,
|
|
71
|
+
category,
|
|
72
|
+
id: category ? `${category}/${key}` : key
|
|
73
|
+
};
|
|
63
74
|
try {
|
|
64
75
|
resolveToolAllowlist(entry.toolsSource);
|
|
65
76
|
} catch (error) {
|
|
@@ -68,9 +79,9 @@ function buildAgentCatalog(agentsDir) {
|
|
|
68
79
|
}
|
|
69
80
|
const existing = byName.get(entry.name);
|
|
70
81
|
if (existing) {
|
|
71
|
-
existing.push(
|
|
82
|
+
existing.push(category);
|
|
72
83
|
} else {
|
|
73
|
-
byName.set(entry.name, [
|
|
84
|
+
byName.set(entry.name, [category]);
|
|
74
85
|
}
|
|
75
86
|
entries.push(entry);
|
|
76
87
|
}
|
|
@@ -174,14 +185,19 @@ var CONFIG_AUTHORITY_FIELD_PATHS = [
|
|
|
174
185
|
];
|
|
175
186
|
var CONFIG_PROTECTED_FIELD_PATHS = [
|
|
176
187
|
"workflow_guard",
|
|
188
|
+
"profiles",
|
|
177
189
|
"agents.*.model",
|
|
178
190
|
"agents.*.permission",
|
|
179
191
|
"agents.*.skills",
|
|
180
192
|
"agents.*.variant",
|
|
193
|
+
"agents.*.opencode",
|
|
194
|
+
"agents.*.pi",
|
|
181
195
|
"categories.*.model",
|
|
182
196
|
"categories.*.permission",
|
|
183
197
|
"categories.*.skills",
|
|
184
|
-
"categories.*.variant"
|
|
198
|
+
"categories.*.variant",
|
|
199
|
+
"categories.*.opencode",
|
|
200
|
+
"categories.*.pi"
|
|
185
201
|
];
|
|
186
202
|
var CONFIG_SOURCE_ERROR_CODES = [
|
|
187
203
|
"parse-failed",
|
|
@@ -439,7 +455,14 @@ function configErrorCode(errorCode) {
|
|
|
439
455
|
}
|
|
440
456
|
function normalizeConfigObservation(config) {
|
|
441
457
|
assertRecord(config, "config");
|
|
442
|
-
assertAllowedKeys(config, [
|
|
458
|
+
assertAllowedKeys(config, [
|
|
459
|
+
"authorities",
|
|
460
|
+
"protectedFields",
|
|
461
|
+
"sources",
|
|
462
|
+
"activeProfile",
|
|
463
|
+
"profileSelectorSource",
|
|
464
|
+
"profileFallback"
|
|
465
|
+
], "config");
|
|
443
466
|
if (!Array.isArray(config.sources)) {
|
|
444
467
|
throw new TypeError("config.sources must be an array");
|
|
445
468
|
}
|
|
@@ -1496,21 +1519,19 @@ function lookupOverlay(map, category, agentKey) {
|
|
|
1496
1519
|
}
|
|
1497
1520
|
return map[agentKey];
|
|
1498
1521
|
}
|
|
1499
|
-
function
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
}
|
|
1510
|
-
return;
|
|
1522
|
+
function resolveRoutedFields(overlays, piSubagentsOverlays, category, agentKey) {
|
|
1523
|
+
const resolution = resolveRouting({
|
|
1524
|
+
overlays,
|
|
1525
|
+
piSubagentsOverlays,
|
|
1526
|
+
target: { agentKey, category: category ?? "" },
|
|
1527
|
+
harness: "pi"
|
|
1528
|
+
});
|
|
1529
|
+
return {
|
|
1530
|
+
model: typeof resolution.model === "string" ? resolution.model : undefined,
|
|
1531
|
+
thinking: resolution.qualifier
|
|
1532
|
+
};
|
|
1511
1533
|
}
|
|
1512
|
-
var
|
|
1513
|
-
"thinking",
|
|
1534
|
+
var OTHER_PI_SUBAGENTS_FRONTMATTER_FIELDS = [
|
|
1514
1535
|
"max_turns",
|
|
1515
1536
|
"tools",
|
|
1516
1537
|
"skills"
|
|
@@ -1519,7 +1540,7 @@ function resolvePiSubagentsFields(config, category, agentKey) {
|
|
|
1519
1540
|
const categoryOverlay = category ? config.pi_subagents?.categories?.[category] : undefined;
|
|
1520
1541
|
const agentOverlay = lookupOverlay(config.pi_subagents?.agents, category, agentKey);
|
|
1521
1542
|
const result = {};
|
|
1522
|
-
for (const field of
|
|
1543
|
+
for (const field of OTHER_PI_SUBAGENTS_FRONTMATTER_FIELDS) {
|
|
1523
1544
|
if (agentOverlay && Object.hasOwn(agentOverlay, field)) {
|
|
1524
1545
|
result[field] = agentOverlay[field];
|
|
1525
1546
|
} else if (categoryOverlay && Object.hasOwn(categoryOverlay, field)) {
|
|
@@ -1528,19 +1549,21 @@ function resolvePiSubagentsFields(config, category, agentKey) {
|
|
|
1528
1549
|
}
|
|
1529
1550
|
return result;
|
|
1530
1551
|
}
|
|
1531
|
-
function applyConfigToContent(content, config, category, agentKey) {
|
|
1552
|
+
function applyConfigToContent(content, config, overlays, piSubagentsOverlays, category, agentKey) {
|
|
1532
1553
|
const { data, body } = parseFrontmatter(content);
|
|
1533
|
-
const model =
|
|
1534
|
-
const
|
|
1554
|
+
const { model, thinking } = resolveRoutedFields(overlays, piSubagentsOverlays, category, agentKey);
|
|
1555
|
+
const otherFields = resolvePiSubagentsFields(config, category, agentKey);
|
|
1535
1556
|
const frontmatter = {};
|
|
1536
1557
|
if (typeof data.description === "string") {
|
|
1537
1558
|
frontmatter.description = data.description;
|
|
1538
1559
|
}
|
|
1539
1560
|
if (model !== undefined)
|
|
1540
1561
|
frontmatter.model = model;
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1562
|
+
if (thinking !== undefined)
|
|
1563
|
+
frontmatter.thinking = thinking;
|
|
1564
|
+
for (const field of OTHER_PI_SUBAGENTS_FRONTMATTER_FIELDS) {
|
|
1565
|
+
if (Object.hasOwn(otherFields, field)) {
|
|
1566
|
+
frontmatter[field] = otherFields[field];
|
|
1544
1567
|
}
|
|
1545
1568
|
}
|
|
1546
1569
|
let frontmatterBlock;
|
|
@@ -1559,12 +1582,12 @@ ${lines}
|
|
|
1559
1582
|
|
|
1560
1583
|
${trimmedBody}`;
|
|
1561
1584
|
}
|
|
1562
|
-
function applyConfigToEntries(entries, config) {
|
|
1585
|
+
function applyConfigToEntries(entries, config, overlays, piSubagentsOverlays) {
|
|
1563
1586
|
return entries.map((entry) => {
|
|
1564
1587
|
if (entry.status === "excluded-critical" || !entry.content)
|
|
1565
1588
|
return entry;
|
|
1566
1589
|
const { category, agentKey } = parseSourceCategoryAndKey(entry.sourceRelPath);
|
|
1567
|
-
const content = applyConfigToContent(entry.content, config, category, agentKey);
|
|
1590
|
+
const content = applyConfigToContent(entry.content, config, overlays, piSubagentsOverlays, category, agentKey);
|
|
1568
1591
|
const hash = crypto2.createHash("sha256").update(content).digest("hex");
|
|
1569
1592
|
return { ...entry, content, hash };
|
|
1570
1593
|
});
|
|
@@ -1573,10 +1596,11 @@ function generateEntries(repoRoot, configOptions) {
|
|
|
1573
1596
|
const entries = generateAll(repoRoot);
|
|
1574
1597
|
if (!configOptions)
|
|
1575
1598
|
return entries;
|
|
1576
|
-
const config = loadConfigWithSources(configOptions.cwd, {
|
|
1599
|
+
const { config, overlays } = loadConfigWithSources(configOptions.cwd, {
|
|
1577
1600
|
includeProject: configOptions.scope === "project"
|
|
1578
|
-
})
|
|
1579
|
-
|
|
1601
|
+
});
|
|
1602
|
+
const piSubagentsOverlays = toSourcedPiSubagentsOverlays(config.pi_subagents);
|
|
1603
|
+
return applyConfigToEntries(entries, config, overlays, piSubagentsOverlays);
|
|
1580
1604
|
}
|
|
1581
1605
|
function findPackageRoot() {
|
|
1582
1606
|
const thisFile = fileURLToPath(import.meta.url);
|
|
@@ -2703,7 +2727,7 @@ Commands:
|
|
|
2703
2727
|
Exit statuses: 0 valid artifact, 1 validation failure,
|
|
2704
2728
|
2 operational failure, 3 legacy artifact with no schema_version
|
|
2705
2729
|
config [subcommand] Configuration management
|
|
2706
|
-
show
|
|
2730
|
+
show [--json] Show configuration (--json for a machine-readable resolved view)
|
|
2707
2731
|
path Print config file locations
|
|
2708
2732
|
setup --harness opencode|pi Configure a harness to load Systematic (project-local only)
|
|
2709
2733
|
pi-subagents <subcommand> Manage Systematic persona export for pi-subagents
|
|
@@ -2722,6 +2746,7 @@ Examples:
|
|
|
2722
2746
|
systematic validate-review-artifact .context/systematic/ce-review/review-summary.json
|
|
2723
2747
|
systematic list agents
|
|
2724
2748
|
systematic config show
|
|
2749
|
+
systematic config show --json
|
|
2725
2750
|
systematic setup --harness opencode
|
|
2726
2751
|
systematic setup --harness pi
|
|
2727
2752
|
systematic pi-subagents preview
|
|
@@ -2730,6 +2755,13 @@ Examples:
|
|
|
2730
2755
|
systematic pi-subagents refresh
|
|
2731
2756
|
systematic pi-subagents cleanup
|
|
2732
2757
|
`;
|
|
2758
|
+
var CONFIG_SHOW_USAGE = `Usage: systematic config show [--json]
|
|
2759
|
+
|
|
2760
|
+
Options:
|
|
2761
|
+
--json Print a machine-readable resolved view (active profile, fallback,
|
|
2762
|
+
and per-agent/harness routing) instead of prose. No raw file
|
|
2763
|
+
contents in JSON mode.
|
|
2764
|
+
`;
|
|
2733
2765
|
var PI_SUBAGENTS_USAGE = `Usage: systematic pi-subagents <subcommand> [--scope project|global]
|
|
2734
2766
|
|
|
2735
2767
|
Subcommands:
|
|
@@ -3005,7 +3037,130 @@ function listItems(type) {
|
|
|
3005
3037
|
console.log(` ${item.name}`);
|
|
3006
3038
|
}
|
|
3007
3039
|
}
|
|
3008
|
-
function
|
|
3040
|
+
function formatRoutingModel(model) {
|
|
3041
|
+
if (model === undefined)
|
|
3042
|
+
return "(unset)";
|
|
3043
|
+
if (model === null)
|
|
3044
|
+
return "null (inherit)";
|
|
3045
|
+
return model;
|
|
3046
|
+
}
|
|
3047
|
+
function formatRoutingQualifier(qualifier) {
|
|
3048
|
+
return qualifier === undefined ? "(none)" : qualifier;
|
|
3049
|
+
}
|
|
3050
|
+
function formatRoutingSource(source) {
|
|
3051
|
+
return source === undefined ? "(n/a)" : `${source.level}/${source.form}`;
|
|
3052
|
+
}
|
|
3053
|
+
function printProfileSummary(metadata) {
|
|
3054
|
+
const activeLabel = metadata.activeProfile ?? "none";
|
|
3055
|
+
const selectedByLabel = metadata.profileSelectorSource ?? "(none)";
|
|
3056
|
+
console.log(` Active profile: ${activeLabel}`);
|
|
3057
|
+
console.log(` Selected by: ${selectedByLabel}`);
|
|
3058
|
+
if (metadata.profileFallback) {
|
|
3059
|
+
const usedLabel = metadata.profileFallback.usedDefault ? `your default profile "${metadata.profileFallback.usedDefault}"` : "base configuration (no default profile is set)";
|
|
3060
|
+
console.log(` Fallback: requested "${metadata.profileFallback.requested}" is not defined; used ${usedLabel}`);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
function disabledAgentsSet(loaded) {
|
|
3064
|
+
return new Set(loaded.config.disabled_agents ?? []);
|
|
3065
|
+
}
|
|
3066
|
+
function printRoutingTable(loaded) {
|
|
3067
|
+
const targets = collectRoutingTargets(loaded.overlays, disabledAgentsSet(loaded)).sort((left, right) => `${left.category}/${left.agentKey}`.localeCompare(`${right.category}/${right.agentKey}`));
|
|
3068
|
+
if (targets.length === 0) {
|
|
3069
|
+
console.log(" No per-agent or per-category overlays are defined.");
|
|
3070
|
+
return;
|
|
3071
|
+
}
|
|
3072
|
+
for (const target of targets) {
|
|
3073
|
+
console.log(` ${target.agentKey} (${target.category}):`);
|
|
3074
|
+
for (const harness of ["opencode", "pi"]) {
|
|
3075
|
+
const resolution = resolveRouting({
|
|
3076
|
+
harness,
|
|
3077
|
+
overlays: loaded.overlays,
|
|
3078
|
+
piSubagentsOverlays: loaded.piSubagentsOverlays,
|
|
3079
|
+
target
|
|
3080
|
+
});
|
|
3081
|
+
const qualifierName = harness === "opencode" ? "variant" : "thinking";
|
|
3082
|
+
console.log(` ${harness}: model=${formatRoutingModel(resolution.model)} (${formatRoutingSource(resolution.source.model)}), ` + `${qualifierName}=${formatRoutingQualifier(resolution.qualifier)} (${formatRoutingSource(resolution.source.qualifier)})`);
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
function printResolvedSection() {
|
|
3087
|
+
let loaded;
|
|
3088
|
+
try {
|
|
3089
|
+
loaded = loadConfigWithSources(process.cwd());
|
|
3090
|
+
} catch {
|
|
3091
|
+
console.log(`
|
|
3092
|
+
Resolved configuration: unavailable (the configuration failed to load).`);
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
const { metadata, overlays } = loaded;
|
|
3096
|
+
const hasProfileSelection = metadata.activeProfile !== null || metadata.profileSelectorSource !== null;
|
|
3097
|
+
const hasOverlays = Object.keys(overlays.agents).length > 0 || Object.keys(overlays.categories).length > 0;
|
|
3098
|
+
console.log(`
|
|
3099
|
+
Resolved configuration:`);
|
|
3100
|
+
if (!hasProfileSelection && !hasOverlays) {
|
|
3101
|
+
console.log(" No profiles are selected and no per-agent/category overlays are defined.");
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
printProfileSummary(metadata);
|
|
3105
|
+
console.log("");
|
|
3106
|
+
console.log(" Routing:");
|
|
3107
|
+
printRoutingTable(loaded);
|
|
3108
|
+
}
|
|
3109
|
+
function toJsonRoutingResolution(resolution) {
|
|
3110
|
+
return {
|
|
3111
|
+
model: resolution.model,
|
|
3112
|
+
qualifier: resolution.qualifier,
|
|
3113
|
+
source: resolution.source
|
|
3114
|
+
};
|
|
3115
|
+
}
|
|
3116
|
+
function buildConfigShowJson() {
|
|
3117
|
+
const paths = getConfigPaths(process.cwd());
|
|
3118
|
+
const locations = {
|
|
3119
|
+
user: paths.userConfig,
|
|
3120
|
+
project: paths.projectConfig,
|
|
3121
|
+
custom: paths.customConfig ?? null
|
|
3122
|
+
};
|
|
3123
|
+
let loaded;
|
|
3124
|
+
try {
|
|
3125
|
+
loaded = loadConfigWithSources(process.cwd());
|
|
3126
|
+
} catch (error) {
|
|
3127
|
+
return {
|
|
3128
|
+
locations,
|
|
3129
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3130
|
+
};
|
|
3131
|
+
}
|
|
3132
|
+
const targets = collectRoutingTargets(loaded.overlays, disabledAgentsSet(loaded)).sort((left, right) => `${left.category}/${left.agentKey}`.localeCompare(`${right.category}/${right.agentKey}`));
|
|
3133
|
+
const routing = targets.map((target) => ({
|
|
3134
|
+
target,
|
|
3135
|
+
opencode: toJsonRoutingResolution(resolveRouting({
|
|
3136
|
+
harness: "opencode",
|
|
3137
|
+
overlays: loaded.overlays,
|
|
3138
|
+
piSubagentsOverlays: loaded.piSubagentsOverlays,
|
|
3139
|
+
target
|
|
3140
|
+
})),
|
|
3141
|
+
pi: toJsonRoutingResolution(resolveRouting({
|
|
3142
|
+
harness: "pi",
|
|
3143
|
+
overlays: loaded.overlays,
|
|
3144
|
+
piSubagentsOverlays: loaded.piSubagentsOverlays,
|
|
3145
|
+
target
|
|
3146
|
+
}))
|
|
3147
|
+
}));
|
|
3148
|
+
return {
|
|
3149
|
+
locations,
|
|
3150
|
+
activeProfile: loaded.metadata.activeProfile,
|
|
3151
|
+
profileSelectorSource: loaded.metadata.profileSelectorSource,
|
|
3152
|
+
profileFallback: loaded.metadata.profileFallback,
|
|
3153
|
+
routing
|
|
3154
|
+
};
|
|
3155
|
+
}
|
|
3156
|
+
function configShow(options) {
|
|
3157
|
+
if (options.json) {
|
|
3158
|
+
const output = buildConfigShowJson();
|
|
3159
|
+
console.log(JSON.stringify(output, null, 2));
|
|
3160
|
+
if ("error" in output)
|
|
3161
|
+
process.exit(1);
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3009
3164
|
const paths = getConfigPaths(process.cwd());
|
|
3010
3165
|
console.log(`Configuration locations:
|
|
3011
3166
|
`);
|
|
@@ -3021,6 +3176,20 @@ Project configuration:`);
|
|
|
3021
3176
|
User configuration:`);
|
|
3022
3177
|
console.log(fs6.readFileSync(paths.userConfig, "utf-8"));
|
|
3023
3178
|
}
|
|
3179
|
+
printResolvedSection();
|
|
3180
|
+
}
|
|
3181
|
+
function parseConfigShowArgs(rest) {
|
|
3182
|
+
let json = false;
|
|
3183
|
+
for (const arg of rest) {
|
|
3184
|
+
if (arg === "--json") {
|
|
3185
|
+
json = true;
|
|
3186
|
+
} else {
|
|
3187
|
+
console.error(`Unknown argument: ${arg}`);
|
|
3188
|
+
console.error(CONFIG_SHOW_USAGE);
|
|
3189
|
+
process.exit(1);
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
return { json };
|
|
3024
3193
|
}
|
|
3025
3194
|
function configPath() {
|
|
3026
3195
|
const paths = getConfigPaths(process.cwd());
|
|
@@ -3219,7 +3388,7 @@ function runLegacyCli(args) {
|
|
|
3219
3388
|
switch (args[1]) {
|
|
3220
3389
|
case "show":
|
|
3221
3390
|
case undefined:
|
|
3222
|
-
configShow();
|
|
3391
|
+
configShow(parseConfigShowArgs(args.slice(2)));
|
|
3223
3392
|
break;
|
|
3224
3393
|
case "path":
|
|
3225
3394
|
configPath();
|