agent-shim 8.33.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 +73 -27
- package/dist/index.cjs +69 -23
- package/dist/index.mjs +69 -23
- package/dist/types/index.d.ts +182 -8
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -57135,11 +57135,14 @@ var IDENTITY_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._@-]*";
|
|
|
57135
57135
|
var PoolNameSchema = external_exports.string().min(1).regex(new RegExp(`^${POOL_NAME_PATTERN}$`));
|
|
57136
57136
|
var SELECTOR_RE = new RegExp(`^(${POOL_SELECTOR_PREFIX}${POOL_NAME_PATTERN}|${IDENTITY_NAME_PATTERN})$`);
|
|
57137
57137
|
var IdentitySelectorSchema = external_exports.string().min(1).regex(SELECTOR_RE);
|
|
57138
|
-
var PoolMemberSchema = external_exports.string().min(1).regex(SELECTOR_RE);
|
|
57138
|
+
var PoolMemberSchema = external_exports.union([external_exports.string().min(1).regex(SELECTOR_RE), external_exports.strictObject({ identity: external_exports.string().min(1).regex(SELECTOR_RE), when: WhenSchema })]);
|
|
57139
|
+
function poolMemberIdentity(member) {
|
|
57140
|
+
return typeof member === "string" ? member : member.identity;
|
|
57141
|
+
}
|
|
57139
57142
|
var POOL_PREFERENCES = ["score", "listed"];
|
|
57140
57143
|
var PoolPreferenceSchema = external_exports.enum(POOL_PREFERENCES);
|
|
57141
57144
|
var PoolSchema = external_exports.strictObject({
|
|
57142
|
-
identities: external_exports.array(PoolMemberSchema).min(1).refine((members2) => new Set(members2).size === members2.length, { message: "pool members must be unique" }),
|
|
57145
|
+
identities: external_exports.array(PoolMemberSchema).min(1).refine((members2) => new Set(members2.map(poolMemberIdentity)).size === members2.length, { message: "pool members must be unique" }),
|
|
57143
57146
|
preference: PoolPreferenceSchema.optional()
|
|
57144
57147
|
});
|
|
57145
57148
|
var DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
|
|
@@ -60153,7 +60156,7 @@ function writePools(paths, pools) {
|
|
|
60153
60156
|
function poolCycleOf(pools, name) {
|
|
60154
60157
|
const walk = (current, path46) => {
|
|
60155
60158
|
for (const entry of pools[current]?.identities ?? []) {
|
|
60156
|
-
const nested = poolNameOf(entry);
|
|
60159
|
+
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
60157
60160
|
if (nested === void 0) {
|
|
60158
60161
|
continue;
|
|
60159
60162
|
}
|
|
@@ -60174,9 +60177,10 @@ function poolCycleOf(pools, name) {
|
|
|
60174
60177
|
}
|
|
60175
60178
|
function validateMembers(pools, name, members2) {
|
|
60176
60179
|
for (const entry of members2) {
|
|
60177
|
-
const
|
|
60180
|
+
const identity = poolMemberIdentity(entry);
|
|
60181
|
+
const nested = poolNameOf(identity);
|
|
60178
60182
|
if (nested !== void 0 && nested !== name && pools[nested] === void 0) {
|
|
60179
|
-
throw new UsageError(`Member "${
|
|
60183
|
+
throw new UsageError(`Member "${identity}" of pool "${name}" names a pool that is not defined. Run \`agent-shim pool add ${nested} --identity <name>...\` first.`);
|
|
60180
60184
|
}
|
|
60181
60185
|
}
|
|
60182
60186
|
const cycle = poolCycleOf({ ...pools, [name]: { identities: [...members2] } }, name);
|
|
@@ -60915,12 +60919,18 @@ function parseDuration(value2) {
|
|
|
60915
60919
|
}
|
|
60916
60920
|
var evaluator = createSyncEvaluator({});
|
|
60917
60921
|
function resolversOf(context) {
|
|
60922
|
+
const pool = context.pool;
|
|
60918
60923
|
const values = {
|
|
60919
60924
|
now: context.nowMs,
|
|
60920
60925
|
...context.fact?.latestMtimeMs === void 0 ? {} : { "entry.latestMtimeMs": context.fact.latestMtimeMs },
|
|
60921
60926
|
...context.fact?.totalSizeBytes === void 0 ? {} : { "entry.totalSizeBytes": context.fact.totalSizeBytes },
|
|
60922
60927
|
...context.branch === void 0 ? {} : { "repo.branch": context.branch },
|
|
60923
|
-
"repo.detached": context.branchDetached ?? false
|
|
60928
|
+
"repo.detached": context.branchDetached ?? false,
|
|
60929
|
+
...pool?.fiveHour === void 0 ? {} : { "quota.fiveHour.remaining": pool.fiveHour.remaining, "quota.fiveHour.utilization": pool.fiveHour.utilization, "quota.fiveHour.hoursUntilReset": pool.fiveHour.hoursUntilReset },
|
|
60930
|
+
...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
|
|
60931
|
+
...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
|
|
60932
|
+
...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
|
|
60933
|
+
...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
|
|
60924
60934
|
};
|
|
60925
60935
|
return {
|
|
60926
60936
|
resolveValue: (key) => {
|
|
@@ -63655,7 +63665,7 @@ function registerIdentityCommand(program2, deps) {
|
|
|
63655
63665
|
// package.json
|
|
63656
63666
|
var package_default = {
|
|
63657
63667
|
name: "agent-shim",
|
|
63658
|
-
version: "8.
|
|
63668
|
+
version: "8.34.0",
|
|
63659
63669
|
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.",
|
|
63660
63670
|
license: "MIT",
|
|
63661
63671
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -64744,12 +64754,48 @@ function assessIdentity(member, nowMs) {
|
|
|
64744
64754
|
...sevenDayBurn === void 0 ? {} : { sevenDayBurn }
|
|
64745
64755
|
};
|
|
64746
64756
|
}
|
|
64757
|
+
function poolFactsOf(member, nowMs, resuming, sticky) {
|
|
64758
|
+
const unified = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
|
|
64759
|
+
const window = (which) => {
|
|
64760
|
+
const raw = unified?.[which];
|
|
64761
|
+
if (raw?.utilization === void 0) {
|
|
64762
|
+
return void 0;
|
|
64763
|
+
}
|
|
64764
|
+
if (raw.resetsAt === void 0) {
|
|
64765
|
+
return void 0;
|
|
64766
|
+
}
|
|
64767
|
+
return { remaining: Math.max(0, 1 - raw.utilization), utilization: raw.utilization, hoursUntilReset: Math.max(0, (Date.parse(raw.resetsAt) - nowMs) / MS_PER_HOUR) };
|
|
64768
|
+
};
|
|
64769
|
+
const burn = windowBurn(member.records, "fiveHour");
|
|
64770
|
+
return {
|
|
64771
|
+
...window("fiveHour") === void 0 ? {} : { fiveHour: window("fiveHour") },
|
|
64772
|
+
...window("sevenDay") === void 0 ? {} : { sevenDay: window("sevenDay") },
|
|
64773
|
+
...burn === void 0 ? {} : { burnPerHour: burn * MS_PER_HOUR },
|
|
64774
|
+
resuming,
|
|
64775
|
+
...sticky?.identity === member.identity ? { lastPickHoursAgo: Math.max(0, (nowMs - Date.parse(sticky.at)) / MS_PER_HOUR) } : {}
|
|
64776
|
+
};
|
|
64777
|
+
}
|
|
64747
64778
|
function rankPool(input2) {
|
|
64748
64779
|
const { members: members2, nowMs } = input2;
|
|
64749
|
-
const assessments = members2.map((member) => assess(member, nowMs));
|
|
64780
|
+
const assessments = members2.map((member) => ({ member, ...assess(member, nowMs) }));
|
|
64750
64781
|
const demands = assessments.flatMap(({ candidate, burn }) => burn === void 0 ? [] : [burn * capacityOf(candidate.plan)]);
|
|
64751
64782
|
const sharedDemand = demands.length === 0 ? void 0 : Math.max(...demands);
|
|
64752
|
-
const
|
|
64783
|
+
const guarded = assessments.map((assessment) => {
|
|
64784
|
+
const { candidate } = assessment;
|
|
64785
|
+
if (candidate.class === "ineligible" || assessment.member.policy === void 0) {
|
|
64786
|
+
return assessment;
|
|
64787
|
+
}
|
|
64788
|
+
const context = { nowMs, env: {}, pool: poolFactsOf(assessment.member, nowMs, input2.resuming, input2.sticky) };
|
|
64789
|
+
const verdict = evaluateWhen(assessment.member.policy, context);
|
|
64790
|
+
if (verdict.status === "indeterminate") {
|
|
64791
|
+
return { ...assessment, candidate: { ...candidate, policyDemoted: true, reasons: [`policy undecided (${verdict.checked.join(", ") === "predicate" ? "predicate" : verdict.checked.join(", ")}): ${verdict.reason}`, ...candidate.reasons] } };
|
|
64792
|
+
}
|
|
64793
|
+
if (verdict.passed) {
|
|
64794
|
+
return assessment;
|
|
64795
|
+
}
|
|
64796
|
+
return { ...assessment, candidate: { ...candidate, class: "ineligible", reasons: [`skipped by policy (${verdict.checked.join(", ")}: did not hold)`, ...candidate.reasons] } };
|
|
64797
|
+
});
|
|
64798
|
+
const candidates = guarded.map((assessment) => {
|
|
64753
64799
|
const { candidate, fiveHour, burn } = assessment;
|
|
64754
64800
|
const pace = burn ?? (sharedDemand === void 0 ? void 0 : sharedDemand / capacityOf(candidate.plan));
|
|
64755
64801
|
const { sevenDay, sevenDayBurn } = assessment;
|
|
@@ -64775,7 +64821,7 @@ function rankPool(input2) {
|
|
|
64775
64821
|
return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
|
|
64776
64822
|
});
|
|
64777
64823
|
const ordered = input2.preference === "listed" ? [...candidates] : [...candidates].sort(
|
|
64778
|
-
(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)
|
|
64824
|
+
(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)
|
|
64779
64825
|
);
|
|
64780
64826
|
const sticky = input2.sticky;
|
|
64781
64827
|
const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
|
|
@@ -65104,27 +65150,27 @@ function rankNamedPool(input2, poolName, stack, sticky) {
|
|
|
65104
65150
|
throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
65105
65151
|
}
|
|
65106
65152
|
const childStack = [...stack, poolName];
|
|
65107
|
-
const direct = pool.identities.filter((entry) => poolNameOf(entry) === void 0);
|
|
65108
|
-
const missing = direct.filter((entry) => !input2.identityExists(entry)).map((
|
|
65109
|
-
const loaded = new Map(loadPoolMembers(input2.fs, input2.paths, direct.filter(input2.identityExists), input2.nowMs).map((member) => [member.identity, member]));
|
|
65153
|
+
const direct = pool.identities.filter((entry) => poolNameOf(poolMemberIdentity(entry)) === void 0);
|
|
65154
|
+
const missing = direct.filter((entry) => !input2.identityExists(poolMemberIdentity(entry))).map((entry) => ({ pool: poolName, identity: poolMemberIdentity(entry) }));
|
|
65155
|
+
const loaded = new Map(loadPoolMembers(input2.fs, input2.paths, direct.filter((entry) => input2.identityExists(poolMemberIdentity(entry))).map(poolMemberIdentity), input2.nowMs).map((member) => [member.identity, member]));
|
|
65110
65156
|
const members2 = [];
|
|
65111
65157
|
for (const entry of pool.identities) {
|
|
65112
|
-
const nestedName = poolNameOf(entry);
|
|
65158
|
+
const nestedName = poolNameOf(poolMemberIdentity(entry));
|
|
65113
65159
|
if (nestedName === void 0) {
|
|
65114
|
-
const member = loaded.get(entry);
|
|
65160
|
+
const member = loaded.get(poolMemberIdentity(entry));
|
|
65115
65161
|
if (member !== void 0) {
|
|
65116
|
-
members2.push(member);
|
|
65162
|
+
members2.push(typeof entry === "string" ? member : { ...member, policy: entry.when });
|
|
65117
65163
|
}
|
|
65118
65164
|
continue;
|
|
65119
65165
|
}
|
|
65120
65166
|
if (input2.pools[nestedName] === void 0) {
|
|
65121
|
-
throw new PoolGraphError(`Pool "${poolName}" member "${entry}" names a pool that is not defined.`);
|
|
65167
|
+
throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
|
|
65122
65168
|
}
|
|
65123
65169
|
if (childStack.includes(nestedName)) {
|
|
65124
|
-
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.`);
|
|
65170
|
+
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.`);
|
|
65125
65171
|
}
|
|
65126
65172
|
const nested = nestedMember(input2, nestedName, childStack, sticky);
|
|
65127
|
-
members2.push(nested.member);
|
|
65173
|
+
members2.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
|
|
65128
65174
|
missing.push(...nested.missing);
|
|
65129
65175
|
}
|
|
65130
65176
|
const ranking = rankPool({
|
|
@@ -70139,16 +70185,16 @@ function runDoctor(params) {
|
|
|
70139
70185
|
const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
|
|
70140
70186
|
const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
|
|
70141
70187
|
for (const [poolName, pool] of Object.entries(pools)) {
|
|
70142
|
-
const missing = pool.identities.filter((member) => poolNameOf(member) === void 0 && !validIdentityNames.has(member));
|
|
70188
|
+
const missing = pool.identities.filter((member) => poolNameOf(poolMemberIdentity(member)) === void 0 && !validIdentityNames.has(poolMemberIdentity(member)));
|
|
70143
70189
|
const undefinedPools = pool.identities.flatMap((member) => {
|
|
70144
|
-
const nested = poolNameOf(member);
|
|
70190
|
+
const nested = poolNameOf(poolMemberIdentity(member));
|
|
70145
70191
|
return nested === void 0 || nested in pools ? [] : [nested];
|
|
70146
70192
|
});
|
|
70147
70193
|
if (missing.length === 0 && undefinedPools.length === 0) {
|
|
70148
|
-
push("pool", "pass", `${poolName} is valid (${pool.identities.join(", ")}).`, poolName);
|
|
70194
|
+
push("pool", "pass", `${poolName} is valid (${pool.identities.map(poolMemberIdentity).join(", ")}).`, poolName);
|
|
70149
70195
|
} else {
|
|
70150
70196
|
const problems = [
|
|
70151
|
-
...missing.map((member) => `identity "${member}", which does not exist`),
|
|
70197
|
+
...missing.map((member) => `identity "${poolMemberIdentity(member)}", which does not exist`),
|
|
70152
70198
|
...undefinedPools.map((nested) => `pool "${nested}", which is not defined`)
|
|
70153
70199
|
];
|
|
70154
70200
|
push("pool", "fail", `Pool "${poolName}" names ${problems.join(" and ")}.`, poolName);
|
|
@@ -81780,12 +81826,12 @@ function registerPoolCommand(program2, deps) {
|
|
|
81780
81826
|
}
|
|
81781
81827
|
const members2 = options.identity === void 0 ? existing.identities : membersOf(options);
|
|
81782
81828
|
if (options.identity !== void 0) {
|
|
81783
|
-
requireIdentities(paths,
|
|
81829
|
+
requireIdentities(paths, membersOf(options));
|
|
81784
81830
|
}
|
|
81785
81831
|
const preference = options.preference === void 0 ? existing.preference : options.preference === false ? void 0 : options.preference;
|
|
81786
81832
|
const updated = setPool(paths, name, members2, preference);
|
|
81787
81833
|
reportMutation(options.json, { action: "updated", kind: "pool", name, value: updated }, () => {
|
|
81788
|
-
console.log(`Pool "${name}" now has ${members2.join(", ")}.`);
|
|
81834
|
+
console.log(`Pool "${name}" now has ${members2.map(poolMemberIdentity).join(", ")}.`);
|
|
81789
81835
|
});
|
|
81790
81836
|
}),
|
|
81791
81837
|
["agent-shim pool set subs --identity work --identity personal --identity spare", "agent-shim pool set subs --preference listed"]
|
|
@@ -81805,7 +81851,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
81805
81851
|
}
|
|
81806
81852
|
for (const name of names) {
|
|
81807
81853
|
const entry = pools[name];
|
|
81808
|
-
console.log(`${active === `${POOL_SELECTOR_PREFIX}${name}` ? "*" : " "} ${name}: ${(entry?.identities ?? []).join(", ")}${entry?.preference === void 0 ? "" : " (preference: listed)"}`);
|
|
81854
|
+
console.log(`${active === `${POOL_SELECTOR_PREFIX}${name}` ? "*" : " "} ${name}: ${(entry?.identities ?? []).map(poolMemberIdentity).join(", ")}${entry?.preference === void 0 ? "" : " (preference: listed)"}`);
|
|
81809
81855
|
}
|
|
81810
81856
|
}),
|
|
81811
81857
|
["agent-shim pool list", "agent-shim pool list --json"]
|
|
@@ -81818,7 +81864,7 @@ function registerPoolCommand(program2, deps) {
|
|
|
81818
81864
|
return;
|
|
81819
81865
|
}
|
|
81820
81866
|
console.log(`Pool: ${name}`);
|
|
81821
|
-
console.log(`Members: ${entry.identities.join(", ")}`);
|
|
81867
|
+
console.log(`Members: ${entry.identities.map(poolMemberIdentity).join(", ")}`);
|
|
81822
81868
|
if (entry.preference !== void 0) {
|
|
81823
81869
|
console.log(`Preference: ${entry.preference}`);
|
|
81824
81870
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -623,11 +623,14 @@ var IDENTITY_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._@-]*";
|
|
|
623
623
|
var PoolNameSchema = import_zod.z.string().min(1).regex(new RegExp(`^${POOL_NAME_PATTERN}$`));
|
|
624
624
|
var SELECTOR_RE = new RegExp(`^(${POOL_SELECTOR_PREFIX}${POOL_NAME_PATTERN}|${IDENTITY_NAME_PATTERN})$`);
|
|
625
625
|
var IdentitySelectorSchema = import_zod.z.string().min(1).regex(SELECTOR_RE);
|
|
626
|
-
var PoolMemberSchema = import_zod.z.string().min(1).regex(SELECTOR_RE);
|
|
626
|
+
var PoolMemberSchema = import_zod.z.union([import_zod.z.string().min(1).regex(SELECTOR_RE), import_zod.z.strictObject({ identity: import_zod.z.string().min(1).regex(SELECTOR_RE), when: WhenSchema })]);
|
|
627
|
+
function poolMemberIdentity(member) {
|
|
628
|
+
return typeof member === "string" ? member : member.identity;
|
|
629
|
+
}
|
|
627
630
|
var POOL_PREFERENCES = ["score", "listed"];
|
|
628
631
|
var PoolPreferenceSchema = import_zod.z.enum(POOL_PREFERENCES);
|
|
629
632
|
var PoolSchema = import_zod.z.strictObject({
|
|
630
|
-
identities: import_zod.z.array(PoolMemberSchema).min(1).refine((members) => new Set(members).size === members.length, { message: "pool members must be unique" }),
|
|
633
|
+
identities: import_zod.z.array(PoolMemberSchema).min(1).refine((members) => new Set(members.map(poolMemberIdentity)).size === members.length, { message: "pool members must be unique" }),
|
|
631
634
|
preference: PoolPreferenceSchema.optional()
|
|
632
635
|
});
|
|
633
636
|
var DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
|
|
@@ -1004,12 +1007,18 @@ function matchBranch(pattern, branch, detached = false) {
|
|
|
1004
1007
|
}
|
|
1005
1008
|
var evaluator = (0, import_trilean2.createSyncEvaluator)({});
|
|
1006
1009
|
function resolversOf(context) {
|
|
1010
|
+
const pool = context.pool;
|
|
1007
1011
|
const values = {
|
|
1008
1012
|
now: context.nowMs,
|
|
1009
1013
|
...context.fact?.latestMtimeMs === void 0 ? {} : { "entry.latestMtimeMs": context.fact.latestMtimeMs },
|
|
1010
1014
|
...context.fact?.totalSizeBytes === void 0 ? {} : { "entry.totalSizeBytes": context.fact.totalSizeBytes },
|
|
1011
1015
|
...context.branch === void 0 ? {} : { "repo.branch": context.branch },
|
|
1012
|
-
"repo.detached": context.branchDetached ?? false
|
|
1016
|
+
"repo.detached": context.branchDetached ?? false,
|
|
1017
|
+
...pool?.fiveHour === void 0 ? {} : { "quota.fiveHour.remaining": pool.fiveHour.remaining, "quota.fiveHour.utilization": pool.fiveHour.utilization, "quota.fiveHour.hoursUntilReset": pool.fiveHour.hoursUntilReset },
|
|
1018
|
+
...pool?.sevenDay === void 0 ? {} : { "quota.sevenDay.remaining": pool.sevenDay.remaining, "quota.sevenDay.utilization": pool.sevenDay.utilization, "quota.sevenDay.hoursUntilReset": pool.sevenDay.hoursUntilReset },
|
|
1019
|
+
...pool?.burnPerHour === void 0 ? {} : { "quota.burnPerHour": pool.burnPerHour },
|
|
1020
|
+
...pool?.resuming === void 0 ? {} : { "session.resuming": pool.resuming },
|
|
1021
|
+
...pool?.lastPickHoursAgo === void 0 ? {} : { "session.lastPickHoursAgo": pool.lastPickHoursAgo }
|
|
1013
1022
|
};
|
|
1014
1023
|
return {
|
|
1015
1024
|
resolveValue: (key) => {
|
|
@@ -5390,7 +5399,7 @@ var import_undici = require("undici");
|
|
|
5390
5399
|
// package.json
|
|
5391
5400
|
var package_default = {
|
|
5392
5401
|
name: "agent-shim",
|
|
5393
|
-
version: "8.
|
|
5402
|
+
version: "8.34.0",
|
|
5394
5403
|
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.",
|
|
5395
5404
|
license: "MIT",
|
|
5396
5405
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -6682,12 +6691,48 @@ function assessIdentity(member, nowMs) {
|
|
|
6682
6691
|
...sevenDayBurn === void 0 ? {} : { sevenDayBurn }
|
|
6683
6692
|
};
|
|
6684
6693
|
}
|
|
6694
|
+
function poolFactsOf(member, nowMs, resuming, sticky) {
|
|
6695
|
+
const unified = member.snapshot?.providers[ANTHROPIC_PROVIDER]?.rateLimit?.unified;
|
|
6696
|
+
const window = (which) => {
|
|
6697
|
+
const raw = unified?.[which];
|
|
6698
|
+
if (raw?.utilization === void 0) {
|
|
6699
|
+
return void 0;
|
|
6700
|
+
}
|
|
6701
|
+
if (raw.resetsAt === void 0) {
|
|
6702
|
+
return void 0;
|
|
6703
|
+
}
|
|
6704
|
+
return { remaining: Math.max(0, 1 - raw.utilization), utilization: raw.utilization, hoursUntilReset: Math.max(0, (Date.parse(raw.resetsAt) - nowMs) / MS_PER_HOUR) };
|
|
6705
|
+
};
|
|
6706
|
+
const burn = windowBurn(member.records, "fiveHour");
|
|
6707
|
+
return {
|
|
6708
|
+
...window("fiveHour") === void 0 ? {} : { fiveHour: window("fiveHour") },
|
|
6709
|
+
...window("sevenDay") === void 0 ? {} : { sevenDay: window("sevenDay") },
|
|
6710
|
+
...burn === void 0 ? {} : { burnPerHour: burn * MS_PER_HOUR },
|
|
6711
|
+
resuming,
|
|
6712
|
+
...sticky?.identity === member.identity ? { lastPickHoursAgo: Math.max(0, (nowMs - Date.parse(sticky.at)) / MS_PER_HOUR) } : {}
|
|
6713
|
+
};
|
|
6714
|
+
}
|
|
6685
6715
|
function rankPool(input) {
|
|
6686
6716
|
const { members, nowMs } = input;
|
|
6687
|
-
const assessments = members.map((member) => assess(member, nowMs));
|
|
6717
|
+
const assessments = members.map((member) => ({ member, ...assess(member, nowMs) }));
|
|
6688
6718
|
const demands = assessments.flatMap(({ candidate, burn }) => burn === void 0 ? [] : [burn * capacityOf(candidate.plan)]);
|
|
6689
6719
|
const sharedDemand = demands.length === 0 ? void 0 : Math.max(...demands);
|
|
6690
|
-
const
|
|
6720
|
+
const guarded = assessments.map((assessment) => {
|
|
6721
|
+
const { candidate } = assessment;
|
|
6722
|
+
if (candidate.class === "ineligible" || assessment.member.policy === void 0) {
|
|
6723
|
+
return assessment;
|
|
6724
|
+
}
|
|
6725
|
+
const context = { nowMs, env: {}, pool: poolFactsOf(assessment.member, nowMs, input.resuming, input.sticky) };
|
|
6726
|
+
const verdict = evaluateWhen(assessment.member.policy, context);
|
|
6727
|
+
if (verdict.status === "indeterminate") {
|
|
6728
|
+
return { ...assessment, candidate: { ...candidate, policyDemoted: true, reasons: [`policy undecided (${verdict.checked.join(", ") === "predicate" ? "predicate" : verdict.checked.join(", ")}): ${verdict.reason}`, ...candidate.reasons] } };
|
|
6729
|
+
}
|
|
6730
|
+
if (verdict.passed) {
|
|
6731
|
+
return assessment;
|
|
6732
|
+
}
|
|
6733
|
+
return { ...assessment, candidate: { ...candidate, class: "ineligible", reasons: [`skipped by policy (${verdict.checked.join(", ")}: did not hold)`, ...candidate.reasons] } };
|
|
6734
|
+
});
|
|
6735
|
+
const candidates = guarded.map((assessment) => {
|
|
6691
6736
|
const { candidate, fiveHour, burn } = assessment;
|
|
6692
6737
|
const pace = burn ?? (sharedDemand === void 0 ? void 0 : sharedDemand / capacityOf(candidate.plan));
|
|
6693
6738
|
const { sevenDay, sevenDayBurn } = assessment;
|
|
@@ -6713,7 +6758,7 @@ function rankPool(input) {
|
|
|
6713
6758
|
return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
|
|
6714
6759
|
});
|
|
6715
6760
|
const ordered = input.preference === "listed" ? [...candidates] : [...candidates].sort(
|
|
6716
|
-
(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)
|
|
6761
|
+
(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)
|
|
6717
6762
|
);
|
|
6718
6763
|
const sticky = input.sticky;
|
|
6719
6764
|
const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
|
|
@@ -6884,27 +6929,27 @@ function rankNamedPool(input, poolName, stack, sticky) {
|
|
|
6884
6929
|
throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
6885
6930
|
}
|
|
6886
6931
|
const childStack = [...stack, poolName];
|
|
6887
|
-
const direct = pool.identities.filter((entry) => poolNameOf(entry) === void 0);
|
|
6888
|
-
const missing = direct.filter((entry) => !input.identityExists(entry)).map((
|
|
6889
|
-
const loaded = new Map(loadPoolMembers(input.fs, input.paths, direct.filter(input.identityExists), input.nowMs).map((member) => [member.identity, member]));
|
|
6932
|
+
const direct = pool.identities.filter((entry) => poolNameOf(poolMemberIdentity(entry)) === void 0);
|
|
6933
|
+
const missing = direct.filter((entry) => !input.identityExists(poolMemberIdentity(entry))).map((entry) => ({ pool: poolName, identity: poolMemberIdentity(entry) }));
|
|
6934
|
+
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]));
|
|
6890
6935
|
const members = [];
|
|
6891
6936
|
for (const entry of pool.identities) {
|
|
6892
|
-
const nestedName = poolNameOf(entry);
|
|
6937
|
+
const nestedName = poolNameOf(poolMemberIdentity(entry));
|
|
6893
6938
|
if (nestedName === void 0) {
|
|
6894
|
-
const member = loaded.get(entry);
|
|
6939
|
+
const member = loaded.get(poolMemberIdentity(entry));
|
|
6895
6940
|
if (member !== void 0) {
|
|
6896
|
-
members.push(member);
|
|
6941
|
+
members.push(typeof entry === "string" ? member : { ...member, policy: entry.when });
|
|
6897
6942
|
}
|
|
6898
6943
|
continue;
|
|
6899
6944
|
}
|
|
6900
6945
|
if (input.pools[nestedName] === void 0) {
|
|
6901
|
-
throw new PoolGraphError(`Pool "${poolName}" member "${entry}" names a pool that is not defined.`);
|
|
6946
|
+
throw new PoolGraphError(`Pool "${poolName}" member "${poolMemberIdentity(entry)}" names a pool that is not defined.`);
|
|
6902
6947
|
}
|
|
6903
6948
|
if (childStack.includes(nestedName)) {
|
|
6904
|
-
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.`);
|
|
6949
|
+
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.`);
|
|
6905
6950
|
}
|
|
6906
6951
|
const nested = nestedMember(input, nestedName, childStack, sticky);
|
|
6907
|
-
members.push(nested.member);
|
|
6952
|
+
members.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
|
|
6908
6953
|
missing.push(...nested.missing);
|
|
6909
6954
|
}
|
|
6910
6955
|
const ranking = rankPool({
|
|
@@ -7165,7 +7210,7 @@ function writePools(paths, pools) {
|
|
|
7165
7210
|
function poolCycleOf(pools, name) {
|
|
7166
7211
|
const walk = (current, path32) => {
|
|
7167
7212
|
for (const entry of pools[current]?.identities ?? []) {
|
|
7168
|
-
const nested = poolNameOf(entry);
|
|
7213
|
+
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
7169
7214
|
if (nested === void 0) {
|
|
7170
7215
|
continue;
|
|
7171
7216
|
}
|
|
@@ -7186,9 +7231,10 @@ function poolCycleOf(pools, name) {
|
|
|
7186
7231
|
}
|
|
7187
7232
|
function validateMembers(pools, name, members) {
|
|
7188
7233
|
for (const entry of members) {
|
|
7189
|
-
const
|
|
7234
|
+
const identity = poolMemberIdentity(entry);
|
|
7235
|
+
const nested = poolNameOf(identity);
|
|
7190
7236
|
if (nested !== void 0 && nested !== name && pools[nested] === void 0) {
|
|
7191
|
-
throw new UsageError(`Member "${
|
|
7237
|
+
throw new UsageError(`Member "${identity}" of pool "${name}" names a pool that is not defined. Run \`agent-shim pool add ${nested} --identity <name>...\` first.`);
|
|
7192
7238
|
}
|
|
7193
7239
|
}
|
|
7194
7240
|
const cycle = poolCycleOf({ ...pools, [name]: { identities: [...members] } }, name);
|
|
@@ -9893,16 +9939,16 @@ function runDoctor(params) {
|
|
|
9893
9939
|
const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
|
|
9894
9940
|
const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
|
|
9895
9941
|
for (const [poolName, pool] of Object.entries(pools)) {
|
|
9896
|
-
const missing = pool.identities.filter((member) => poolNameOf(member) === void 0 && !validIdentityNames.has(member));
|
|
9942
|
+
const missing = pool.identities.filter((member) => poolNameOf(poolMemberIdentity(member)) === void 0 && !validIdentityNames.has(poolMemberIdentity(member)));
|
|
9897
9943
|
const undefinedPools = pool.identities.flatMap((member) => {
|
|
9898
|
-
const nested = poolNameOf(member);
|
|
9944
|
+
const nested = poolNameOf(poolMemberIdentity(member));
|
|
9899
9945
|
return nested === void 0 || nested in pools ? [] : [nested];
|
|
9900
9946
|
});
|
|
9901
9947
|
if (missing.length === 0 && undefinedPools.length === 0) {
|
|
9902
|
-
push("pool", "pass", `${poolName} is valid (${pool.identities.join(", ")}).`, poolName);
|
|
9948
|
+
push("pool", "pass", `${poolName} is valid (${pool.identities.map(poolMemberIdentity).join(", ")}).`, poolName);
|
|
9903
9949
|
} else {
|
|
9904
9950
|
const problems = [
|
|
9905
|
-
...missing.map((member) => `identity "${member}", which does not exist`),
|
|
9951
|
+
...missing.map((member) => `identity "${poolMemberIdentity(member)}", which does not exist`),
|
|
9906
9952
|
...undefinedPools.map((nested) => `pool "${nested}", which is not defined`)
|
|
9907
9953
|
];
|
|
9908
9954
|
push("pool", "fail", `Pool "${poolName}" names ${problems.join(" and ")}.`, poolName);
|
package/dist/index.mjs
CHANGED
|
@@ -311,11 +311,14 @@ var IDENTITY_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9._@-]*";
|
|
|
311
311
|
var PoolNameSchema = z.string().min(1).regex(new RegExp(`^${POOL_NAME_PATTERN}$`));
|
|
312
312
|
var SELECTOR_RE = new RegExp(`^(${POOL_SELECTOR_PREFIX}${POOL_NAME_PATTERN}|${IDENTITY_NAME_PATTERN})$`);
|
|
313
313
|
var IdentitySelectorSchema = z.string().min(1).regex(SELECTOR_RE);
|
|
314
|
-
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
|
+
}
|
|
315
318
|
var POOL_PREFERENCES = ["score", "listed"];
|
|
316
319
|
var PoolPreferenceSchema = z.enum(POOL_PREFERENCES);
|
|
317
320
|
var PoolSchema = z.strictObject({
|
|
318
|
-
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" }),
|
|
319
322
|
preference: PoolPreferenceSchema.optional()
|
|
320
323
|
});
|
|
321
324
|
var DirectoryRuleSchema = ConfigProfileSchema.omit({ description: true }).extend({
|
|
@@ -692,12 +695,18 @@ function matchBranch(pattern, branch, detached = false) {
|
|
|
692
695
|
}
|
|
693
696
|
var evaluator = createSyncEvaluator({});
|
|
694
697
|
function resolversOf(context) {
|
|
698
|
+
const pool = context.pool;
|
|
695
699
|
const values = {
|
|
696
700
|
now: context.nowMs,
|
|
697
701
|
...context.fact?.latestMtimeMs === void 0 ? {} : { "entry.latestMtimeMs": context.fact.latestMtimeMs },
|
|
698
702
|
...context.fact?.totalSizeBytes === void 0 ? {} : { "entry.totalSizeBytes": context.fact.totalSizeBytes },
|
|
699
703
|
...context.branch === void 0 ? {} : { "repo.branch": context.branch },
|
|
700
|
-
"repo.detached": context.branchDetached ?? false
|
|
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 }
|
|
701
710
|
};
|
|
702
711
|
return {
|
|
703
712
|
resolveValue: (key) => {
|
|
@@ -5078,7 +5087,7 @@ import { Agent as Agent3, fetch as undiciFetch } from "undici";
|
|
|
5078
5087
|
// package.json
|
|
5079
5088
|
var package_default = {
|
|
5080
5089
|
name: "agent-shim",
|
|
5081
|
-
version: "8.
|
|
5090
|
+
version: "8.34.0",
|
|
5082
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.",
|
|
5083
5092
|
license: "MIT",
|
|
5084
5093
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -6370,12 +6379,48 @@ function assessIdentity(member, nowMs) {
|
|
|
6370
6379
|
...sevenDayBurn === void 0 ? {} : { sevenDayBurn }
|
|
6371
6380
|
};
|
|
6372
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
|
+
}
|
|
6373
6403
|
function rankPool(input) {
|
|
6374
6404
|
const { members, nowMs } = input;
|
|
6375
|
-
const assessments = members.map((member) => assess(member, nowMs));
|
|
6405
|
+
const assessments = members.map((member) => ({ member, ...assess(member, nowMs) }));
|
|
6376
6406
|
const demands = assessments.flatMap(({ candidate, burn }) => burn === void 0 ? [] : [burn * capacityOf(candidate.plan)]);
|
|
6377
6407
|
const sharedDemand = demands.length === 0 ? void 0 : Math.max(...demands);
|
|
6378
|
-
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) => {
|
|
6379
6424
|
const { candidate, fiveHour, burn } = assessment;
|
|
6380
6425
|
const pace = burn ?? (sharedDemand === void 0 ? void 0 : sharedDemand / capacityOf(candidate.plan));
|
|
6381
6426
|
const { sevenDay, sevenDayBurn } = assessment;
|
|
@@ -6401,7 +6446,7 @@ function rankPool(input) {
|
|
|
6401
6446
|
return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
|
|
6402
6447
|
});
|
|
6403
6448
|
const ordered = input.preference === "listed" ? [...candidates] : [...candidates].sort(
|
|
6404
|
-
(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)
|
|
6405
6450
|
);
|
|
6406
6451
|
const sticky = input.sticky;
|
|
6407
6452
|
const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
|
|
@@ -6572,27 +6617,27 @@ function rankNamedPool(input, poolName, stack, sticky) {
|
|
|
6572
6617
|
throw new PoolGraphError(`No pool named "${poolName}". Run \`agent-shim pool add ${poolName} --identity <name>...\` first.`);
|
|
6573
6618
|
}
|
|
6574
6619
|
const childStack = [...stack, poolName];
|
|
6575
|
-
const direct = pool.identities.filter((entry) => poolNameOf(entry) === void 0);
|
|
6576
|
-
const missing = direct.filter((entry) => !input.identityExists(entry)).map((
|
|
6577
|
-
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]));
|
|
6578
6623
|
const members = [];
|
|
6579
6624
|
for (const entry of pool.identities) {
|
|
6580
|
-
const nestedName = poolNameOf(entry);
|
|
6625
|
+
const nestedName = poolNameOf(poolMemberIdentity(entry));
|
|
6581
6626
|
if (nestedName === void 0) {
|
|
6582
|
-
const member = loaded.get(entry);
|
|
6627
|
+
const member = loaded.get(poolMemberIdentity(entry));
|
|
6583
6628
|
if (member !== void 0) {
|
|
6584
|
-
members.push(member);
|
|
6629
|
+
members.push(typeof entry === "string" ? member : { ...member, policy: entry.when });
|
|
6585
6630
|
}
|
|
6586
6631
|
continue;
|
|
6587
6632
|
}
|
|
6588
6633
|
if (input.pools[nestedName] === void 0) {
|
|
6589
|
-
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.`);
|
|
6590
6635
|
}
|
|
6591
6636
|
if (childStack.includes(nestedName)) {
|
|
6592
|
-
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.`);
|
|
6593
6638
|
}
|
|
6594
6639
|
const nested = nestedMember(input, nestedName, childStack, sticky);
|
|
6595
|
-
members.push(nested.member);
|
|
6640
|
+
members.push(typeof entry === "string" ? nested.member : { ...nested.member, policy: entry.when });
|
|
6596
6641
|
missing.push(...nested.missing);
|
|
6597
6642
|
}
|
|
6598
6643
|
const ranking = rankPool({
|
|
@@ -6853,7 +6898,7 @@ function writePools(paths, pools) {
|
|
|
6853
6898
|
function poolCycleOf(pools, name) {
|
|
6854
6899
|
const walk = (current, path32) => {
|
|
6855
6900
|
for (const entry of pools[current]?.identities ?? []) {
|
|
6856
|
-
const nested = poolNameOf(entry);
|
|
6901
|
+
const nested = poolNameOf(poolMemberIdentity(entry));
|
|
6857
6902
|
if (nested === void 0) {
|
|
6858
6903
|
continue;
|
|
6859
6904
|
}
|
|
@@ -6874,9 +6919,10 @@ function poolCycleOf(pools, name) {
|
|
|
6874
6919
|
}
|
|
6875
6920
|
function validateMembers(pools, name, members) {
|
|
6876
6921
|
for (const entry of members) {
|
|
6877
|
-
const
|
|
6922
|
+
const identity = poolMemberIdentity(entry);
|
|
6923
|
+
const nested = poolNameOf(identity);
|
|
6878
6924
|
if (nested !== void 0 && nested !== name && pools[nested] === void 0) {
|
|
6879
|
-
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.`);
|
|
6880
6926
|
}
|
|
6881
6927
|
}
|
|
6882
6928
|
const cycle = poolCycleOf({ ...pools, [name]: { identities: [...members] } }, name);
|
|
@@ -9581,16 +9627,16 @@ function runDoctor(params) {
|
|
|
9581
9627
|
const validatedGlobalConfig = params.globalConfig.raw === void 0 ? void 0 : validateJson(GlobalConfigSchema, params.globalConfig);
|
|
9582
9628
|
const pools = validatedGlobalConfig?.ok === true ? validatedGlobalConfig.data.pools ?? {} : {};
|
|
9583
9629
|
for (const [poolName, pool] of Object.entries(pools)) {
|
|
9584
|
-
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)));
|
|
9585
9631
|
const undefinedPools = pool.identities.flatMap((member) => {
|
|
9586
|
-
const nested = poolNameOf(member);
|
|
9632
|
+
const nested = poolNameOf(poolMemberIdentity(member));
|
|
9587
9633
|
return nested === void 0 || nested in pools ? [] : [nested];
|
|
9588
9634
|
});
|
|
9589
9635
|
if (missing.length === 0 && undefinedPools.length === 0) {
|
|
9590
|
-
push("pool", "pass", `${poolName} is valid (${pool.identities.join(", ")}).`, poolName);
|
|
9636
|
+
push("pool", "pass", `${poolName} is valid (${pool.identities.map(poolMemberIdentity).join(", ")}).`, poolName);
|
|
9591
9637
|
} else {
|
|
9592
9638
|
const problems = [
|
|
9593
|
-
...missing.map((member) => `identity "${member}", which does not exist`),
|
|
9639
|
+
...missing.map((member) => `identity "${poolMemberIdentity(member)}", which does not exist`),
|
|
9594
9640
|
...undefinedPools.map((nested) => `pool "${nested}", which is not defined`)
|
|
9595
9641
|
];
|
|
9596
9642
|
push("pool", "fail", `Pool "${poolName}" names ${problems.join(" and ")}.`, poolName);
|
package/dist/types/index.d.ts
CHANGED
|
@@ -630,7 +630,81 @@ type PoolPreference = z.infer<typeof PoolPreferenceSchema>;
|
|
|
630
630
|
* `preference` decides how the member is chosen, and an absent field means "score". "score" ranks members by plan-size-weighted remaining quota per hour until reset, so the quota closest to expiring is spent first (use-it-or-lose-it). "listed" ranks members strictly in the order the pool lists them, skipping only a member that is currently refused, so a pool can pin one identity first and fall back to the others only while that one is refused.
|
|
631
631
|
*/
|
|
632
632
|
declare const PoolSchema: z.ZodObject<{
|
|
633
|
-
identities: z.ZodArray<z.ZodString
|
|
633
|
+
identities: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
634
|
+
identity: z.ZodString;
|
|
635
|
+
when: z.ZodUnion<readonly [z.ZodObject<{
|
|
636
|
+
newerThan: z.ZodOptional<z.ZodString>;
|
|
637
|
+
olderThan: z.ZodOptional<z.ZodString>;
|
|
638
|
+
maxSizeBytes: z.ZodOptional<z.ZodInt>;
|
|
639
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
640
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
641
|
+
}, z.core.$strict>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
642
|
+
kind: z.ZodLiteral<"not">;
|
|
643
|
+
operand: typeof PredicateNodeSchema;
|
|
644
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
645
|
+
kind: z.ZodLiteral<"and">;
|
|
646
|
+
left: typeof PredicateNodeSchema;
|
|
647
|
+
right: typeof PredicateNodeSchema;
|
|
648
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
649
|
+
kind: z.ZodLiteral<"or">;
|
|
650
|
+
left: typeof PredicateNodeSchema;
|
|
651
|
+
right: typeof PredicateNodeSchema;
|
|
652
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
653
|
+
kind: z.ZodLiteral<"allOf">;
|
|
654
|
+
operands: z.ZodArray<typeof PredicateNodeSchema>;
|
|
655
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
656
|
+
kind: z.ZodLiteral<"anyOf">;
|
|
657
|
+
operands: z.ZodArray<typeof PredicateNodeSchema>;
|
|
658
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
659
|
+
kind: z.ZodLiteral<"compare">;
|
|
660
|
+
op: z.ZodEnum<{
|
|
661
|
+
gt: "gt";
|
|
662
|
+
gte: "gte";
|
|
663
|
+
lt: "lt";
|
|
664
|
+
lte: "lte";
|
|
665
|
+
eq: "eq";
|
|
666
|
+
neq: "neq";
|
|
667
|
+
}>;
|
|
668
|
+
left: typeof trilean.ExpressionNodeSchema;
|
|
669
|
+
right: typeof trilean.ExpressionNodeSchema;
|
|
670
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
671
|
+
kind: z.ZodLiteral<"textCompare">;
|
|
672
|
+
op: z.ZodEnum<{
|
|
673
|
+
equals: "equals";
|
|
674
|
+
notEquals: "notEquals";
|
|
675
|
+
matches: "matches";
|
|
676
|
+
notMatches: "notMatches";
|
|
677
|
+
portableMatches: "portableMatches";
|
|
678
|
+
portableNotMatches: "portableNotMatches";
|
|
679
|
+
}>;
|
|
680
|
+
left: typeof trilean.ExpressionNodeSchema;
|
|
681
|
+
right: typeof trilean.ExpressionNodeSchema;
|
|
682
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
683
|
+
kind: z.ZodLiteral<"memberOf">;
|
|
684
|
+
op: z.ZodEnum<{
|
|
685
|
+
in: "in";
|
|
686
|
+
notIn: "notIn";
|
|
687
|
+
}>;
|
|
688
|
+
operand: typeof trilean.ExpressionNodeSchema;
|
|
689
|
+
candidates: z.ZodArray<typeof trilean.ExpressionNodeSchema>;
|
|
690
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
691
|
+
kind: z.ZodLiteral<"exists">;
|
|
692
|
+
operand: typeof trilean.ExpressionNodeSchema;
|
|
693
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
694
|
+
kind: z.ZodLiteral<"some">;
|
|
695
|
+
collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
696
|
+
item: typeof PredicateNodeSchema;
|
|
697
|
+
filter: z.ZodOptional<typeof PredicateNodeSchema>;
|
|
698
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
699
|
+
kind: z.ZodLiteral<"every">;
|
|
700
|
+
collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
701
|
+
item: typeof PredicateNodeSchema;
|
|
702
|
+
filter: z.ZodOptional<typeof PredicateNodeSchema>;
|
|
703
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
704
|
+
kind: z.ZodLiteral<"treeReference">;
|
|
705
|
+
key: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
706
|
+
}, z.core.$strip>], "kind">]>;
|
|
707
|
+
}, z.core.$strict>]>>;
|
|
634
708
|
preference: z.ZodOptional<z.ZodEnum<{
|
|
635
709
|
score: "score";
|
|
636
710
|
listed: "listed";
|
|
@@ -1332,7 +1406,81 @@ declare const GlobalConfigSchema: z.ZodObject<{
|
|
|
1332
1406
|
}>>;
|
|
1333
1407
|
}, z.core.$strict>>;
|
|
1334
1408
|
pools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1335
|
-
identities: z.ZodArray<z.ZodString
|
|
1409
|
+
identities: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
1410
|
+
identity: z.ZodString;
|
|
1411
|
+
when: z.ZodUnion<readonly [z.ZodObject<{
|
|
1412
|
+
newerThan: z.ZodOptional<z.ZodString>;
|
|
1413
|
+
olderThan: z.ZodOptional<z.ZodString>;
|
|
1414
|
+
maxSizeBytes: z.ZodOptional<z.ZodInt>;
|
|
1415
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
1416
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1417
|
+
}, z.core.$strict>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1418
|
+
kind: z.ZodLiteral<"not">;
|
|
1419
|
+
operand: typeof PredicateNodeSchema;
|
|
1420
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1421
|
+
kind: z.ZodLiteral<"and">;
|
|
1422
|
+
left: typeof PredicateNodeSchema;
|
|
1423
|
+
right: typeof PredicateNodeSchema;
|
|
1424
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1425
|
+
kind: z.ZodLiteral<"or">;
|
|
1426
|
+
left: typeof PredicateNodeSchema;
|
|
1427
|
+
right: typeof PredicateNodeSchema;
|
|
1428
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1429
|
+
kind: z.ZodLiteral<"allOf">;
|
|
1430
|
+
operands: z.ZodArray<typeof PredicateNodeSchema>;
|
|
1431
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1432
|
+
kind: z.ZodLiteral<"anyOf">;
|
|
1433
|
+
operands: z.ZodArray<typeof PredicateNodeSchema>;
|
|
1434
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1435
|
+
kind: z.ZodLiteral<"compare">;
|
|
1436
|
+
op: z.ZodEnum<{
|
|
1437
|
+
gt: "gt";
|
|
1438
|
+
gte: "gte";
|
|
1439
|
+
lt: "lt";
|
|
1440
|
+
lte: "lte";
|
|
1441
|
+
eq: "eq";
|
|
1442
|
+
neq: "neq";
|
|
1443
|
+
}>;
|
|
1444
|
+
left: typeof trilean.ExpressionNodeSchema;
|
|
1445
|
+
right: typeof trilean.ExpressionNodeSchema;
|
|
1446
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1447
|
+
kind: z.ZodLiteral<"textCompare">;
|
|
1448
|
+
op: z.ZodEnum<{
|
|
1449
|
+
equals: "equals";
|
|
1450
|
+
notEquals: "notEquals";
|
|
1451
|
+
matches: "matches";
|
|
1452
|
+
notMatches: "notMatches";
|
|
1453
|
+
portableMatches: "portableMatches";
|
|
1454
|
+
portableNotMatches: "portableNotMatches";
|
|
1455
|
+
}>;
|
|
1456
|
+
left: typeof trilean.ExpressionNodeSchema;
|
|
1457
|
+
right: typeof trilean.ExpressionNodeSchema;
|
|
1458
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1459
|
+
kind: z.ZodLiteral<"memberOf">;
|
|
1460
|
+
op: z.ZodEnum<{
|
|
1461
|
+
in: "in";
|
|
1462
|
+
notIn: "notIn";
|
|
1463
|
+
}>;
|
|
1464
|
+
operand: typeof trilean.ExpressionNodeSchema;
|
|
1465
|
+
candidates: z.ZodArray<typeof trilean.ExpressionNodeSchema>;
|
|
1466
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1467
|
+
kind: z.ZodLiteral<"exists">;
|
|
1468
|
+
operand: typeof trilean.ExpressionNodeSchema;
|
|
1469
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1470
|
+
kind: z.ZodLiteral<"some">;
|
|
1471
|
+
collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
1472
|
+
item: typeof PredicateNodeSchema;
|
|
1473
|
+
filter: z.ZodOptional<typeof PredicateNodeSchema>;
|
|
1474
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1475
|
+
kind: z.ZodLiteral<"every">;
|
|
1476
|
+
collection: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
1477
|
+
item: typeof PredicateNodeSchema;
|
|
1478
|
+
filter: z.ZodOptional<typeof PredicateNodeSchema>;
|
|
1479
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1480
|
+
kind: z.ZodLiteral<"treeReference">;
|
|
1481
|
+
key: z.ZodType<trilean.JsonValue, unknown, z.core.$ZodTypeInternals<trilean.JsonValue, unknown>>;
|
|
1482
|
+
}, z.core.$strip>], "kind">]>;
|
|
1483
|
+
}, z.core.$strict>]>>;
|
|
1336
1484
|
preference: z.ZodOptional<z.ZodEnum<{
|
|
1337
1485
|
score: "score";
|
|
1338
1486
|
listed: "listed";
|
|
@@ -5230,12 +5378,12 @@ declare function createControlApiRouter(deps: ControlApiDeps): {
|
|
|
5230
5378
|
identity: "identity";
|
|
5231
5379
|
provider: "provider";
|
|
5232
5380
|
pool: "pool";
|
|
5233
|
-
keychain: "keychain";
|
|
5234
5381
|
"ambient-credential": "ambient-credential";
|
|
5235
5382
|
"binary-discovery": "binary-discovery";
|
|
5236
5383
|
"claude-shim": "claude-shim";
|
|
5237
5384
|
"path-resolution": "path-resolution";
|
|
5238
5385
|
"legacy-name": "legacy-name";
|
|
5386
|
+
keychain: "keychain";
|
|
5239
5387
|
"directory-rules": "directory-rules";
|
|
5240
5388
|
"categories-local": "categories-local";
|
|
5241
5389
|
"active-identity": "active-identity";
|
|
@@ -5811,12 +5959,12 @@ declare function createDoorApiRouter(deps: DoorApiDeps): {
|
|
|
5811
5959
|
identity: "identity";
|
|
5812
5960
|
provider: "provider";
|
|
5813
5961
|
pool: "pool";
|
|
5814
|
-
keychain: "keychain";
|
|
5815
5962
|
"ambient-credential": "ambient-credential";
|
|
5816
5963
|
"binary-discovery": "binary-discovery";
|
|
5817
5964
|
"claude-shim": "claude-shim";
|
|
5818
5965
|
"path-resolution": "path-resolution";
|
|
5819
5966
|
"legacy-name": "legacy-name";
|
|
5967
|
+
keychain: "keychain";
|
|
5820
5968
|
"directory-rules": "directory-rules";
|
|
5821
5969
|
"categories-local": "categories-local";
|
|
5822
5970
|
"active-identity": "active-identity";
|
|
@@ -6301,12 +6449,12 @@ declare const DoctorFindingSchema: z.ZodObject<{
|
|
|
6301
6449
|
identity: "identity";
|
|
6302
6450
|
provider: "provider";
|
|
6303
6451
|
pool: "pool";
|
|
6304
|
-
keychain: "keychain";
|
|
6305
6452
|
"ambient-credential": "ambient-credential";
|
|
6306
6453
|
"binary-discovery": "binary-discovery";
|
|
6307
6454
|
"claude-shim": "claude-shim";
|
|
6308
6455
|
"path-resolution": "path-resolution";
|
|
6309
6456
|
"legacy-name": "legacy-name";
|
|
6457
|
+
keychain: "keychain";
|
|
6310
6458
|
"directory-rules": "directory-rules";
|
|
6311
6459
|
"categories-local": "categories-local";
|
|
6312
6460
|
"active-identity": "active-identity";
|
|
@@ -6330,12 +6478,12 @@ declare const DoctorRunOutputSchema: z.ZodObject<{
|
|
|
6330
6478
|
identity: "identity";
|
|
6331
6479
|
provider: "provider";
|
|
6332
6480
|
pool: "pool";
|
|
6333
|
-
keychain: "keychain";
|
|
6334
6481
|
"ambient-credential": "ambient-credential";
|
|
6335
6482
|
"binary-discovery": "binary-discovery";
|
|
6336
6483
|
"claude-shim": "claude-shim";
|
|
6337
6484
|
"path-resolution": "path-resolution";
|
|
6338
6485
|
"legacy-name": "legacy-name";
|
|
6486
|
+
keychain: "keychain";
|
|
6339
6487
|
"directory-rules": "directory-rules";
|
|
6340
6488
|
"categories-local": "categories-local";
|
|
6341
6489
|
"active-identity": "active-identity";
|
|
@@ -6784,6 +6932,8 @@ interface PoolMember {
|
|
|
6784
6932
|
readonly records: readonly UsageRecord[];
|
|
6785
6933
|
/** Present when this member stands for a nested `pool:<name>` entry rather than a direct identity. */
|
|
6786
6934
|
readonly nested?: NestedContribution;
|
|
6935
|
+
/** The member entry's policy condition, from the object form of a pool member: definite false skips the member as ineligible by policy, indeterminate demotes it to last within its class, naming the missing fact either way. */
|
|
6936
|
+
readonly policy?: WhenCondition;
|
|
6787
6937
|
}
|
|
6788
6938
|
/** The member last picked for this directory, kept so a conversation stays on the account whose prompt cache is warm. */
|
|
6789
6939
|
interface StickyPick {
|
|
@@ -6811,6 +6961,8 @@ interface Candidate {
|
|
|
6811
6961
|
/** When an `ineligible` candidate can be used again. */
|
|
6812
6962
|
readonly blockedUntilMs?: number;
|
|
6813
6963
|
readonly plan: PlanClass;
|
|
6964
|
+
/** True when the member's policy condition could not be decided and it is ranked last within its class, naming the missing fact in its reasons. */
|
|
6965
|
+
readonly policyDemoted?: boolean;
|
|
6814
6966
|
/** Human-readable facts behind the class and score, in the order they matter. */
|
|
6815
6967
|
readonly reasons: readonly string[];
|
|
6816
6968
|
}
|
|
@@ -6852,6 +7004,15 @@ declare function collectPoolPick(params: Readonly<{
|
|
|
6852
7004
|
nowMs: number;
|
|
6853
7005
|
}>): PoolPickReport;
|
|
6854
7006
|
|
|
7007
|
+
/** One quota window's pool-selection facts, in the units a policy reads: fractions of the window, and hours until it resets. */
|
|
7008
|
+
interface PoolWindowFacts {
|
|
7009
|
+
/** The fraction of the window still unused, between zero and one. */
|
|
7010
|
+
readonly remaining: number;
|
|
7011
|
+
/** The fraction of the window already used, between zero and one. */
|
|
7012
|
+
readonly utilization: number;
|
|
7013
|
+
/** How long until the window resets, in hours. */
|
|
7014
|
+
readonly hoursUntilReset: number;
|
|
7015
|
+
}
|
|
6855
7016
|
/** Everything a `when` condition can be evaluated against, injected rather than read. */
|
|
6856
7017
|
interface ConditionContext {
|
|
6857
7018
|
readonly nowMs: number;
|
|
@@ -6862,6 +7023,16 @@ interface ConditionContext {
|
|
|
6862
7023
|
/** True when the repository is in detached-HEAD state, in which case no `branch` condition can match. */
|
|
6863
7024
|
readonly branchDetached?: boolean;
|
|
6864
7025
|
readonly env: Readonly<Record<string, string | undefined>>;
|
|
7026
|
+
/**
|
|
7027
|
+
* The pool-selection facts a member entry's policy condition reads. Present only when the condition guards a pool member, so the same reference namespace serves the cascade and the pool: `quota.fiveHour.remaining`, `quota.fiveHour.utilization`, `quota.fiveHour.hoursUntilReset`, the same three under `quota.sevenDay`, `quota.burnPerHour` (the five-hour window's observed utilisation pace, in fractions per hour), `session.resuming` (this launch resumes or continues a conversation) and `session.lastPickHoursAgo` (how long ago this directory last picked this member). Conversation context is deliberately not provided: nothing the door holds knows it, so a condition referencing it is indeterminate, naming the missing fact, rather than guessed.
|
|
7028
|
+
*/
|
|
7029
|
+
readonly pool?: {
|
|
7030
|
+
readonly fiveHour?: PoolWindowFacts;
|
|
7031
|
+
readonly sevenDay?: PoolWindowFacts;
|
|
7032
|
+
readonly burnPerHour?: number;
|
|
7033
|
+
readonly resuming?: boolean;
|
|
7034
|
+
readonly lastPickHoursAgo?: number;
|
|
7035
|
+
};
|
|
6865
7036
|
}
|
|
6866
7037
|
/**
|
|
6867
7038
|
* The result of evaluating one `when`: definite, with which condition fields were present and which of those did not hold, or indeterminate, when a datum the condition needed is missing. Indeterminate is not false: a missing fact has not failed the condition, it has left it undecided, and the consumer decides what an undecided entry does (the resolver keeps today's behaviour of not passing it, so nothing changes for existing configurations; the pool ranking of #258 instead keeps such a member but ranks it last, naming the missing fact).
|
|
@@ -7215,6 +7386,9 @@ declare function updateProvider(paths: LayoutPaths, name: string, input: UpdateP
|
|
|
7215
7386
|
/** Deletes a provider definition. Throws `ProviderNotFoundError` when it does not exist. */
|
|
7216
7387
|
declare function removeProvider(paths: LayoutPaths, name: string): void;
|
|
7217
7388
|
|
|
7389
|
+
/** One pool member entry, whichever form it takes: the plain selector string, or the object form carrying its policy condition. */
|
|
7390
|
+
type PoolMemberEntry = Pool["identities"][number];
|
|
7391
|
+
|
|
7218
7392
|
/** Raised when a command names a pool that is not defined in the global config. */
|
|
7219
7393
|
declare class PoolNotFoundError extends CliError {
|
|
7220
7394
|
readonly poolName: string;
|
|
@@ -7225,9 +7399,9 @@ declare function readPools(paths: LayoutPaths): Readonly<Record<string, Pool>>;
|
|
|
7225
7399
|
/** The pool named `name`; throws `PoolNotFoundError` when none is defined. */
|
|
7226
7400
|
declare function requirePool(paths: LayoutPaths, name: string): Pool;
|
|
7227
7401
|
/** Defines a new pool. Throws `InvalidPoolNameError` for a name `PoolNameSchema` rejects, `PoolAlreadyExistsError` for one already defined, and `UsageError` for a nested member that names an undefined pool or a cycle. */
|
|
7228
|
-
declare function addPool(paths: LayoutPaths, name: string, identities: readonly
|
|
7402
|
+
declare function addPool(paths: LayoutPaths, name: string, identities: readonly PoolMemberEntry[], preference?: PoolPreference): Pool;
|
|
7229
7403
|
/** Replaces an existing pool's members and preference. Throws `PoolNotFoundError` when it is not defined, and `UsageError` for a nested member that names an undefined pool or a cycle. */
|
|
7230
|
-
declare function setPool(paths: LayoutPaths, name: string, identities: readonly
|
|
7404
|
+
declare function setPool(paths: LayoutPaths, name: string, identities: readonly PoolMemberEntry[], preference?: PoolPreference): Pool;
|
|
7231
7405
|
/** Removes a pool. Throws `PoolNotFoundError` when it is not defined. Anything that selected it (an active-identity file, a directory rule) is left for `doctor` to report, as with a removed identity. */
|
|
7232
7406
|
declare function removePool(paths: LayoutPaths, name: string): void;
|
|
7233
7407
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-shim",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.34.0",
|
|
4
4
|
"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.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|