agent-shim 8.32.0 → 8.34.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.cjs +2054 -148
- package/dist/index.cjs +143 -61
- package/dist/index.mjs +143 -61
- package/dist/types/index.d.ts +939 -41
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -56,6 +56,7 @@ var categories_default_default = {
|
|
|
56
56
|
// src/config/schema.ts
|
|
57
57
|
import path2 from "node:path";
|
|
58
58
|
import { z } from "zod";
|
|
59
|
+
import { PredicateNodeSchema } from "trilean";
|
|
59
60
|
|
|
60
61
|
// src/versionDiscovery.ts
|
|
61
62
|
import os from "node:os";
|
|
@@ -186,13 +187,14 @@ var CategoryMapSchema = z.strictObject({
|
|
|
186
187
|
}).transform((input) => expandAllCategoryKey(input));
|
|
187
188
|
var DURATION_RE = /^(?:0|[1-9][0-9]*)(?:ms|s|m|h|d|w)$/;
|
|
188
189
|
var DurationSchema = z.string().regex(DURATION_RE);
|
|
189
|
-
var
|
|
190
|
+
var WhenConditionObjectSchema = z.strictObject({
|
|
190
191
|
newerThan: DurationSchema.optional(),
|
|
191
192
|
olderThan: DurationSchema.optional(),
|
|
192
193
|
maxSizeBytes: z.int().positive().optional(),
|
|
193
194
|
branch: z.string().min(1).optional(),
|
|
194
195
|
env: z.record(z.string().min(1), z.string()).optional()
|
|
195
196
|
});
|
|
197
|
+
var WhenSchema = z.union([WhenConditionObjectSchema, PredicateNodeSchema]);
|
|
196
198
|
var EntryValueSchema = z.union([
|
|
197
199
|
z.boolean(),
|
|
198
200
|
z.strictObject({ value: z.boolean(), when: WhenSchema })
|
|
@@ -309,11 +311,14 @@ var IDENTITY_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._@-]*";
|
|
|
309
311
|
var PoolNameSchema = z.string().min(1).regex(new RegExp(`^${POOL_NAME_PATTERN}$`));
|
|
310
312
|
var SELECTOR_RE = new RegExp(`^(${POOL_SELECTOR_PREFIX}${POOL_NAME_PATTERN}|${IDENTITY_NAME_PATTERN})$`);
|
|
311
313
|
var IdentitySelectorSchema = z.string().min(1).regex(SELECTOR_RE);
|
|
312
|
-
var PoolMemberSchema = z.string().min(1).regex(SELECTOR_RE);
|
|
314
|
+
var PoolMemberSchema = z.union([z.string().min(1).regex(SELECTOR_RE), z.strictObject({ identity: z.string().min(1).regex(SELECTOR_RE), when: WhenSchema })]);
|
|
315
|
+
function poolMemberIdentity(member) {
|
|
316
|
+
return typeof member === "string" ? member : member.identity;
|
|
317
|
+
}
|
|
313
318
|
var POOL_PREFERENCES = ["score", "listed"];
|
|
314
319
|
var PoolPreferenceSchema = z.enum(POOL_PREFERENCES);
|
|
315
320
|
var PoolSchema = z.strictObject({
|
|
316
|
-
identities: z.array(PoolMemberSchema).min(1).refine((members) => new Set(members).size === members.length, { message: "pool members must be unique" }),
|
|
321
|
+
identities: z.array(PoolMemberSchema).min(1).refine((members) => new Set(members.map(poolMemberIdentity)).size === members.length, { message: "pool members must be unique" }),
|
|
317
322
|
preference: PoolPreferenceSchema.optional()
|
|
318
323
|
});
|
|
319
324
|
var DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
|
|
@@ -657,6 +662,7 @@ function classifyEntries(names, options) {
|
|
|
657
662
|
|
|
658
663
|
// src/resolve/conditions.ts
|
|
659
664
|
import picomatch2 from "picomatch";
|
|
665
|
+
import { createSyncEvaluator } from "trilean";
|
|
660
666
|
var MILLISECONDS_PER_UNIT = Object.freeze({
|
|
661
667
|
ms: 1,
|
|
662
668
|
s: 1e3,
|
|
@@ -687,52 +693,87 @@ function matchBranch(pattern, branch, detached = false) {
|
|
|
687
693
|
}
|
|
688
694
|
return picomatch2(pattern, { dot: true, nocase: false })(branch);
|
|
689
695
|
}
|
|
696
|
+
var evaluator = createSyncEvaluator({});
|
|
697
|
+
function resolversOf(context) {
|
|
698
|
+
const pool = context.pool;
|
|
699
|
+
const values = {
|
|
700
|
+
now: context.nowMs,
|
|
701
|
+
...context.fact?.latestMtimeMs === void 0 ? {} : { "entry.latestMtimeMs": context.fact.latestMtimeMs },
|
|
702
|
+
...context.fact?.totalSizeBytes === void 0 ? {} : { "entry.totalSizeBytes": context.fact.totalSizeBytes },
|
|
703
|
+
...context.branch === void 0 ? {} : { "repo.branch": context.branch },
|
|
704
|
+
"repo.detached": context.branchDetached ?? false,
|
|
705
|
+
...pool?.fiveHour === void 0 ? {} : { "quota.fiveHour.remaining": pool.fiveHour.remaining, "quota.fiveHour.utilization": pool.fiveHour.utilization, "quota.fiveHour.hoursUntilReset": pool.fiveHour.hoursUntilReset },
|
|
706
|
+
...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
|
|
707
|
+
...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
|
|
708
|
+
...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
|
|
709
|
+
...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
|
|
710
|
+
};
|
|
711
|
+
return {
|
|
712
|
+
resolveValue: (key) => {
|
|
713
|
+
const wrap = (value2) => ({ found: true, value: typeof value2 === "number" ? { kind: "number", value: value2 } : typeof value2 === "string" ? { kind: "text", value: value2 } : { kind: "boolean", value: value2 } });
|
|
714
|
+
if (typeof key !== "string") {
|
|
715
|
+
return { found: false };
|
|
716
|
+
}
|
|
717
|
+
if (key.startsWith("env.")) {
|
|
718
|
+
const value2 = context.env[key.slice("env.".length)];
|
|
719
|
+
return value2 === void 0 ? { found: false } : wrap(value2);
|
|
720
|
+
}
|
|
721
|
+
const value = values[key];
|
|
722
|
+
return value === void 0 ? { found: false } : wrap(value);
|
|
723
|
+
},
|
|
724
|
+
// This embedding provides the reference namespace only: a tree that asks for a lookup or a collection finds neither, which the evaluator carries as indeterminate rather than letting the tree pretend an answer.
|
|
725
|
+
resolveLookup: () => ({ found: false }),
|
|
726
|
+
resolveCollection: () => []
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function fieldPredicate(field, when, context) {
|
|
730
|
+
switch (field) {
|
|
731
|
+
case "newerThan": {
|
|
732
|
+
const window = parseDuration(when.newerThan ?? "");
|
|
733
|
+
return { kind: "compare", op: "gte", left: { kind: "reference", key: "entry.latestMtimeMs" }, right: { kind: "numberLiteral", value: context.nowMs - window } };
|
|
734
|
+
}
|
|
735
|
+
case "olderThan": {
|
|
736
|
+
const window = parseDuration(when.olderThan ?? "");
|
|
737
|
+
return { kind: "compare", op: "lt", left: { kind: "reference", key: "entry.latestMtimeMs" }, right: { kind: "numberLiteral", value: context.nowMs - window } };
|
|
738
|
+
}
|
|
739
|
+
case "maxSizeBytes":
|
|
740
|
+
return { kind: "compare", op: "lte", left: { kind: "reference", key: "entry.totalSizeBytes" }, right: { kind: "numberLiteral", value: when.maxSizeBytes ?? 0 } };
|
|
741
|
+
case "branch":
|
|
742
|
+
return { kind: "allOf", operands: [{ kind: "textCompare", op: "portableMatches", left: { kind: "reference", key: "repo.branch" }, right: { kind: "textLiteral", value: when.branch ?? "" } }, { kind: "compare", op: "eq", left: { kind: "reference", key: "repo.detached" }, right: { kind: "booleanLiteral", value: false } }] };
|
|
743
|
+
case "env": {
|
|
744
|
+
const entries = Object.entries(when.env ?? {});
|
|
745
|
+
return { kind: "allOf", operands: entries.map(([name, expected]) => ({ kind: "textCompare", op: "equals", left: { kind: "reference", key: `env.${name}` }, right: { kind: "textLiteral", value: expected } })) };
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
return { kind: "allOf", operands: [] };
|
|
749
|
+
}
|
|
690
750
|
function evaluateWhen(when, context) {
|
|
691
751
|
if (when === void 0) {
|
|
692
|
-
return { passed: true, checked: [], failed: [] };
|
|
752
|
+
return { status: "definite", passed: true, checked: [], failed: [] };
|
|
753
|
+
}
|
|
754
|
+
if ("kind" in when) {
|
|
755
|
+
const result = evaluator.evaluatePredicate(when, void 0, resolversOf(context));
|
|
756
|
+
return result.status === "indeterminate" ? { status: "indeterminate", reason: result.reason.message, checked: ["predicate"] } : { status: "definite", passed: result.value, checked: ["predicate"], failed: result.value ? [] : ["predicate"] };
|
|
693
757
|
}
|
|
694
758
|
const checked = [];
|
|
695
759
|
const failed = [];
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
const latest = context.fact?.latestMtimeMs;
|
|
700
|
-
if (latest === void 0 || context.nowMs - latest > window) {
|
|
701
|
-
failed.push("newerThan");
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
if (when.olderThan !== void 0) {
|
|
705
|
-
checked.push("olderThan");
|
|
706
|
-
const window = parseDuration(when.olderThan);
|
|
707
|
-
const latest = context.fact?.latestMtimeMs;
|
|
708
|
-
if (latest === void 0 || context.nowMs - latest <= window) {
|
|
709
|
-
failed.push("olderThan");
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
if (when.maxSizeBytes !== void 0) {
|
|
713
|
-
checked.push("maxSizeBytes");
|
|
714
|
-
const total = context.fact?.totalSizeBytes;
|
|
715
|
-
if (total === void 0 || total > when.maxSizeBytes) {
|
|
716
|
-
failed.push("maxSizeBytes");
|
|
760
|
+
for (const field of ["newerThan", "olderThan", "maxSizeBytes", "branch", "env"]) {
|
|
761
|
+
if (when[field] === void 0) {
|
|
762
|
+
continue;
|
|
717
763
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
failed.push("branch");
|
|
764
|
+
checked.push(field);
|
|
765
|
+
const result = evaluator.evaluatePredicate(fieldPredicate(field, when, context), void 0, resolversOf(context));
|
|
766
|
+
if (result.status === "indeterminate") {
|
|
767
|
+
return { status: "indeterminate", reason: result.reason.message, checked };
|
|
723
768
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
checked.push("env");
|
|
727
|
-
const mismatch = Object.entries(when.env).some(([name, expected]) => context.env[name] !== expected);
|
|
728
|
-
if (mismatch) {
|
|
729
|
-
failed.push("env");
|
|
769
|
+
if (!result.value) {
|
|
770
|
+
failed.push(field);
|
|
730
771
|
}
|
|
731
772
|
}
|
|
732
|
-
return { passed: failed.length === 0, checked, failed };
|
|
773
|
+
return { status: "definite", passed: failed.length === 0, checked, failed };
|
|
733
774
|
}
|
|
734
775
|
function isVacuousWhen(when) {
|
|
735
|
-
return when !== void 0 && Object.keys(when).length === 0;
|
|
776
|
+
return when !== void 0 && !("kind" in when) && Object.keys(when).length === 0;
|
|
736
777
|
}
|
|
737
778
|
|
|
738
779
|
// src/resolve/match.ts
|
|
@@ -1103,10 +1144,10 @@ function selectRule(relPath, flattened, context) {
|
|
|
1103
1144
|
...context.branchDetached === void 0 ? {} : { branchDetached: context.branchDetached },
|
|
1104
1145
|
env: context.env
|
|
1105
1146
|
});
|
|
1106
|
-
if (evaluation.passed) {
|
|
1147
|
+
if (evaluation.status === "definite" && evaluation.passed) {
|
|
1107
1148
|
return { rule, eliminated };
|
|
1108
1149
|
}
|
|
1109
|
-
eliminated.push({ rule, failed: evaluation.failed });
|
|
1150
|
+
eliminated.push({ rule, failed: evaluation.status === "definite" ? evaluation.failed : [`${evaluation.checked.join(", ")} could not be decided: ${evaluation.reason}`] });
|
|
1110
1151
|
}
|
|
1111
1152
|
return { eliminated };
|
|
1112
1153
|
}
|
|
@@ -1340,7 +1381,10 @@ function planFarm(params) {
|
|
|
1340
1381
|
var ENTER_EVERYTHING = () => true;
|
|
1341
1382
|
function readsSubtreeAggregates(rule) {
|
|
1342
1383
|
const when = rule.when;
|
|
1343
|
-
|
|
1384
|
+
if (when === void 0) {
|
|
1385
|
+
return false;
|
|
1386
|
+
}
|
|
1387
|
+
return "kind" in when || when.newerThan !== void 0 || when.olderThan !== void 0 || when.maxSizeBytes !== void 0;
|
|
1344
1388
|
}
|
|
1345
1389
|
function hasUnboundedDepth(pattern) {
|
|
1346
1390
|
return pattern.includes("**") || /[{(]/.test(pattern);
|
|
@@ -5043,7 +5087,7 @@ import { Agent as Agent3, fetch as undiciFetch } from "undici";
|
|
|
5043
5087
|
// package.json
|
|
5044
5088
|
var package_default = {
|
|
5045
5089
|
name: "agent-shim",
|
|
5046
|
-
version: "8.
|
|
5090
|
+
version: "8.34.0",
|
|
5047
5091
|
description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
5048
5092
|
license: "MIT",
|
|
5049
5093
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -5099,6 +5143,7 @@ var package_default = {
|
|
|
5099
5143
|
commander: "^15.0.0",
|
|
5100
5144
|
cosmiconfig: "^10.0.1",
|
|
5101
5145
|
picomatch: "^4.0.7",
|
|
5146
|
+
trilean: "1.7.1",
|
|
5102
5147
|
undici: "7.29.1",
|
|
5103
5148
|
zod: "^4.6.1"
|
|
5104
5149
|
},
|
|
@@ -6334,12 +6379,48 @@ function assessIdentity(member, nowMs) {
|
|
|
6334
6379
|
...sevenDayBurn === void 0 ? {} : { sevenDayBurn }
|
|
6335
6380
|
};
|
|
6336
6381
|
}
|
|
6382
|
+
function poolFactsOf(member, nowMs, resuming, sticky) {
|
|
6383
|
+
const unified = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
|
|
6384
|
+
const window = (which) => {
|
|
6385
|
+
const raw = unified?.[which];
|
|
6386
|
+
if (raw?.utilization === void 0) {
|
|
6387
|
+
return void 0;
|
|
6388
|
+
}
|
|
6389
|
+
if (raw.resetsAt === void 0) {
|
|
6390
|
+
return void 0;
|
|
6391
|
+
}
|
|
6392
|
+
return { remaining: Math.max(0, 1 - raw.utilization), utilization: raw.utilization, hoursUntilReset: Math.max(0, (Date.parse(raw.resetsAt) - nowMs) / MS_PER_HOUR) };
|
|
6393
|
+
};
|
|
6394
|
+
const burn = windowBurn(member.records, "fiveHour");
|
|
6395
|
+
return {
|
|
6396
|
+
...window("fiveHour") === void 0 ? {} : { fiveHour: window("fiveHour") },
|
|
6397
|
+
...window("sevenDay") === void 0 ? {} : { sevenDay: window("sevenDay") },
|
|
6398
|
+
...burn === void 0 ? {} : { burnPerHour: burn * MS_PER_HOUR },
|
|
6399
|
+
resuming,
|
|
6400
|
+
...sticky?.identity === member.identity ? { lastPickHoursAgo: Math.max(0, (nowMs - Date.parse(sticky.at)) / MS_PER_HOUR) } : {}
|
|
6401
|
+
};
|
|
6402
|
+
}
|
|
6337
6403
|
function rankPool(input) {
|
|
6338
6404
|
const { members, nowMs } = input;
|
|
6339
|
-
const assessments = members.map((member) => assess(member, nowMs));
|
|
6405
|
+
const assessments = members.map((member) => ({ member, ...assess(member, nowMs) }));
|
|
6340
6406
|
const demands = assessments.flatMap(({ candidate, burn }) => burn === void 0 ? [] : [burn * capacityOf(candidate.plan)]);
|
|
6341
6407
|
const sharedDemand = demands.length === 0 ? void 0 : Math.max(...demands);
|
|
6342
|
-
const
|
|
6408
|
+
const guarded = assessments.map((assessment) => {
|
|
6409
|
+
const { candidate } = assessment;
|
|
6410
|
+
if (candidate.class === "ineligible" || assessment.member.policy === void 0) {
|
|
6411
|
+
return assessment;
|
|
6412
|
+
}
|
|
6413
|
+
const context = { nowMs, env: {}, pool: poolFactsOf(assessment.member, nowMs, input.resuming, input.sticky) };
|
|
6414
|
+
const verdict = evaluateWhen(assessment.member.policy, context);
|
|
6415
|
+
if (verdict.status === "indeterminate") {
|
|
6416
|
+
return { ...assessment, candidate: { ...candidate, policyDemoted: true, reasons: [`policy undecided (${verdict.checked.join(", ") === "predicate" ? "predicate" : verdict.checked.join(", ")}): ${verdict.reason}`, ...candidate.reasons] } };
|
|
6417
|
+
}
|
|
6418
|
+
if (verdict.passed) {
|
|
6419
|
+
return assessment;
|
|
6420
|
+
}
|
|
6421
|
+
return { ...assessment, candidate: { ...candidate, class: "ineligible", reasons: [`skipped by policy (${verdict.checked.join(", ")}: did not hold)`, ...candidate.reasons] } };
|
|
6422
|
+
});
|
|
6423
|
+
const candidates = guarded.map((assessment) => {
|
|
6343
6424
|
const { candidate, fiveHour, burn } = assessment;
|
|
6344
6425
|
const pace = burn ?? (sharedDemand === void 0 ? void 0 : sharedDemand / capacityOf(candidate.plan));
|
|
6345
6426
|
const { sevenDay, sevenDayBurn } = assessment;
|
|
@@ -6365,7 +6446,7 @@ function rankPool(input) {
|
|
|
6365
6446
|
return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
|
|
6366
6447
|
});
|
|
6367
6448
|
const ordered = input.preference === "listed" ? [...candidates] : [...candidates].sort(
|
|
6368
|
-
(left, right) => CLASS_ORDER[left.class] - CLASS_ORDER[right.class] || Number(right.feasible) - Number(left.feasible) || (right.score ?? 0) - (left.score ?? 0) || left.identity.localeCompare(right.identity)
|
|
6449
|
+
(left, right) => CLASS_ORDER[left.class] - CLASS_ORDER[right.class] || Number(left.policyDemoted ?? false) - Number(right.policyDemoted ?? false) || Number(right.feasible) - Number(left.feasible) || (right.score ?? 0) - (left.score ?? 0) || left.identity.localeCompare(right.identity)
|
|
6369
6450
|
);
|
|
6370
6451
|
const sticky = input.sticky;
|
|
6371
6452
|
const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
|
|
@@ -6536,27 +6617,27 @@ function rankNamedPool(input, poolName, stack, sticky) {
|
|
|
6536
6617
|
throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
6537
6618
|
}
|
|
6538
6619
|
const childStack = [...stack, poolName];
|
|
6539
|
-
const direct = pool.identities.filter((entry) => poolNameOf(entry) === void 0);
|
|
6540
|
-
const missing = direct.filter((entry) => !input.identityExists(entry)).map((
|
|
6541
|
-
const loaded = new Map(loadPoolMembers(input.fs, input.paths, direct.filter(input.identityExists), input.nowMs).map((member) => [member.identity, member]));
|
|
6620
|
+
const direct = pool.identities.filter((entry) => poolNameOf(poolMemberIdentity(entry)) === void 0);
|
|
6621
|
+
const missing = direct.filter((entry) => !input.identityExists(poolMemberIdentity(entry))).map((entry) => ({ pool: poolName, identity: poolMemberIdentity(entry) }));
|
|
6622
|
+
const loaded = new Map(loadPoolMembers(input.fs, input.paths, direct.filter((entry) => input.identityExists(poolMemberIdentity(entry))).map(poolMemberIdentity), input.nowMs).map((member) => [member.identity, member]));
|
|
6542
6623
|
const members = [];
|
|
6543
6624
|
for (const entry of pool.identities) {
|
|
6544
|
-
const nestedName = poolNameOf(entry);
|
|
6625
|
+
const nestedName = poolNameOf(poolMemberIdentity(entry));
|
|
6545
6626
|
if (nestedName === void 0) {
|
|
6546
|
-
const member = loaded.get(entry);
|
|
6627
|
+
const member = loaded.get(poolMemberIdentity(entry));
|
|
6547
6628
|
if (member !== void 0) {
|
|
6548
|
-
members.push(member);
|
|
6629
|
+
members.push(typeof entry === "string" ? member : { ...member, policy: entry.when });
|
|
6549
6630
|
}
|
|
6550
6631
|
continue;
|
|
6551
6632
|
}
|
|
6552
6633
|
if (input.pools[nestedName] === void 0) {
|
|
6553
|
-
throw new PoolGraphError(`Pool "${poolName}" member "${entry}" names a pool that is not defined.`);
|
|
6634
|
+
throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
|
|
6554
6635
|
}
|
|
6555
6636
|
if (childStack.includes(nestedName)) {
|
|
6556
|
-
throw new PoolGraphError(`Pool "${poolName}" member "${entry}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
|
|
6637
|
+
throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" closes a cycle: ${[...childStack.slice(childStack.indexOf(nestedName)), nestedName].join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
|
|
6557
6638
|
}
|
|
6558
6639
|
const nested = nestedMember(input, nestedName, childStack, sticky);
|
|
6559
|
-
members.push(nested.member);
|
|
6640
|
+
members.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
|
|
6560
6641
|
missing.push(...nested.missing);
|
|
6561
6642
|
}
|
|
6562
6643
|
const ranking = rankPool({
|
|
@@ -6817,7 +6898,7 @@ function writePools(paths, pools) {
|
|
|
6817
6898
|
function poolCycleOf(pools, name) {
|
|
6818
6899
|
const walk = (current, path32) => {
|
|
6819
6900
|
for (const entry of pools[current]?.identities ?? []) {
|
|
6820
|
-
const nested = poolNameOf(entry);
|
|
6901
|
+
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
6821
6902
|
if (nested === void 0) {
|
|
6822
6903
|
continue;
|
|
6823
6904
|
}
|
|
@@ -6838,9 +6919,10 @@ function poolCycleOf(pools, name) {
|
|
|
6838
6919
|
}
|
|
6839
6920
|
function validateMembers(pools, name, members) {
|
|
6840
6921
|
for (const entry of members) {
|
|
6841
|
-
const
|
|
6922
|
+
const identity = poolMemberIdentity(entry);
|
|
6923
|
+
const nested = poolNameOf(identity);
|
|
6842
6924
|
if (nested !== void 0 && nested !== name && pools[nested] === void 0) {
|
|
6843
|
-
throw new UsageError(`Member "${
|
|
6925
|
+
throw new UsageError(`Member "${identity}" of pool "${name}" names a pool that is not defined. Run \`agent-shim pool add ${nested} --identity <name>...\` first.`);
|
|
6844
6926
|
}
|
|
6845
6927
|
}
|
|
6846
6928
|
const cycle = poolCycleOf({ ...pools, [name]: { identities: [...members] } }, name);
|
|
@@ -9545,16 +9627,16 @@ function runDoctor(params) {
|
|
|
9545
9627
|
const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
|
|
9546
9628
|
const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
|
|
9547
9629
|
for (const [poolName, pool] of Object.entries(pools)) {
|
|
9548
|
-
const missing = pool.identities.filter((member) => poolNameOf(member) === void 0 && !validIdentityNames.has(member));
|
|
9630
|
+
const missing = pool.identities.filter((member) => poolNameOf(poolMemberIdentity(member)) === void 0 && !validIdentityNames.has(poolMemberIdentity(member)));
|
|
9549
9631
|
const undefinedPools = pool.identities.flatMap((member) => {
|
|
9550
|
-
const nested = poolNameOf(member);
|
|
9632
|
+
const nested = poolNameOf(poolMemberIdentity(member));
|
|
9551
9633
|
return nested === void 0 || nested in pools ? [] : [nested];
|
|
9552
9634
|
});
|
|
9553
9635
|
if (missing.length === 0 && undefinedPools.length === 0) {
|
|
9554
|
-
push("pool", "pass", `${poolName} is valid (${pool.identities.join(", ")}).`, poolName);
|
|
9636
|
+
push("pool", "pass", `${poolName} is valid (${pool.identities.map(poolMemberIdentity).join(", ")}).`, poolName);
|
|
9555
9637
|
} else {
|
|
9556
9638
|
const problems = [
|
|
9557
|
-
...missing.map((member) => `identity "${member}", which does not exist`),
|
|
9639
|
+
...missing.map((member) => `identity "${poolMemberIdentity(member)}", which does not exist`),
|
|
9558
9640
|
...undefinedPools.map((nested) => `pool "${nested}", which is not defined`)
|
|
9559
9641
|
];
|
|
9560
9642
|
push("pool", "fail", `Pool "${poolName}" names ${problems.join(" and ")}.`, poolName);
|