agent-shim 8.30.0 → 8.32.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 +151 -19
- package/dist/index.cjs +150 -13
- package/dist/index.mjs +143 -13
- package/dist/types/index.d.ts +125 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -48,6 +48,7 @@ __export(index_exports, {
|
|
|
48
48
|
CredentialSourceSchema: () => CredentialSourceSchema,
|
|
49
49
|
DOOR_EVENT_BUFFER_EVENTS: () => DOOR_EVENT_BUFFER_EVENTS,
|
|
50
50
|
DOOR_EVENT_SOURCE_RC: () => DOOR_EVENT_SOURCE_RC,
|
|
51
|
+
DOOR_HEALTH_EVENT_SOURCE: () => DOOR_HEALTH_EVENT_SOURCE,
|
|
51
52
|
DirectoryRuleAlreadyExistsError: () => DirectoryRuleAlreadyExistsError,
|
|
52
53
|
DirectoryRuleMissingTargetError: () => DirectoryRuleMissingTargetError,
|
|
53
54
|
DirectoryRuleNotFoundError: () => DirectoryRuleNotFoundError,
|
|
@@ -57,6 +58,7 @@ __export(index_exports, {
|
|
|
57
58
|
DoctorRunOutputSchema: () => DoctorRunOutputSchema,
|
|
58
59
|
DoorEventSchema: () => DoorEventSchema,
|
|
59
60
|
DoorEventSourceQuerySchema: () => DoorEventSourceQuerySchema,
|
|
61
|
+
DoorHealthEventSchema: () => DoorHealthEventSchema,
|
|
60
62
|
EXIT_FAILURE: () => EXIT_FAILURE,
|
|
61
63
|
EXIT_USAGE: () => EXIT_USAGE,
|
|
62
64
|
EffectiveWindowSchema: () => EffectiveWindowSchema,
|
|
@@ -93,6 +95,8 @@ __export(index_exports, {
|
|
|
93
95
|
ProviderKindMismatchError: () => ProviderKindMismatchError,
|
|
94
96
|
ProviderNotFoundError: () => ProviderNotFoundError,
|
|
95
97
|
ProviderSchema: () => ProviderSchema,
|
|
98
|
+
QUOTA_EXPIRING_EVENT_SOURCE: () => QUOTA_EXPIRING_EVENT_SOURCE,
|
|
99
|
+
QuotaExpiringEventSchema: () => QuotaExpiringEventSchema,
|
|
96
100
|
RC_CONTEXT_USAGE_DETAILS: () => RC_CONTEXT_USAGE_DETAILS,
|
|
97
101
|
RC_IDLE_EXPIRY_MS: () => RC_IDLE_EXPIRY_MS,
|
|
98
102
|
RC_ORPC_PATH_PREFIX: () => RC_ORPC_PATH_PREFIX,
|
|
@@ -120,6 +124,7 @@ __export(index_exports, {
|
|
|
120
124
|
RcRateLimitWindowSchema: () => RcRateLimitWindowSchema,
|
|
121
125
|
RcStreamEnvelopeSchema: () => RcStreamEnvelopeSchema,
|
|
122
126
|
RcStreamEventSchema: () => RcStreamEventSchema,
|
|
127
|
+
USAGE_EVENT_SOURCE: () => USAGE_EVENT_SOURCE,
|
|
123
128
|
UsageError: () => UsageError,
|
|
124
129
|
UsageListOutputSchema: () => UsageListOutputSchema,
|
|
125
130
|
UsageLiveOutputSchema: () => UsageLiveOutputSchema,
|
|
@@ -165,10 +170,12 @@ __export(index_exports, {
|
|
|
165
170
|
createDoorApiNodeHandler: () => createDoorApiNodeHandler,
|
|
166
171
|
createDoorApiRouter: () => createDoorApiRouter,
|
|
167
172
|
createDoorEventHub: () => createDoorEventHub,
|
|
173
|
+
createDoorHealthPublisher: () => createDoorHealthPublisher,
|
|
168
174
|
createEventsApiRouter: () => createEventsApiRouter,
|
|
169
175
|
createLaunchEventPublisher: () => createLaunchEventPublisher,
|
|
170
176
|
createLeafCache: () => createLeafCache,
|
|
171
177
|
createProfile: () => createProfile,
|
|
178
|
+
createQuotaExpiringPublisher: () => createQuotaExpiringPublisher,
|
|
172
179
|
createRcApiNodeHandler: () => createRcApiNodeHandler,
|
|
173
180
|
createRcApiRouter: () => createRcApiRouter,
|
|
174
181
|
createRcControlHandler: () => createRcControlHandler,
|
|
@@ -3034,6 +3041,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
3034
3041
|
try {
|
|
3035
3042
|
http3 = await ports.startProviderListener(lastPort);
|
|
3036
3043
|
} catch (error) {
|
|
3044
|
+
ports.doorHealth.listenerFailed("provider", error instanceof Error ? error.message : String(error));
|
|
3037
3045
|
return fail(`could not start the provider listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
3038
3046
|
}
|
|
3039
3047
|
if (previousSticky !== void 0 && http3.port !== previousSticky) {
|
|
@@ -3046,6 +3054,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
3046
3054
|
connect3 = await ports.startConnectListener(lastConnectPort);
|
|
3047
3055
|
} catch (error) {
|
|
3048
3056
|
await http3.close();
|
|
3057
|
+
ports.doorHealth.listenerFailed("connect", error instanceof Error ? error.message : String(error));
|
|
3049
3058
|
return fail(`could not start the CONNECT surface: ${error instanceof Error ? error.message : String(error)}`);
|
|
3050
3059
|
}
|
|
3051
3060
|
if (previousStickyConnect !== void 0 && connect3.port !== previousStickyConnect) {
|
|
@@ -3059,6 +3068,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
3059
3068
|
} catch (error) {
|
|
3060
3069
|
await connect3.close();
|
|
3061
3070
|
await http3.close();
|
|
3071
|
+
ports.doorHealth.listenerFailed("direct", error instanceof Error ? error.message : String(error));
|
|
3062
3072
|
return fail(`could not start the direct listener: ${error instanceof Error ? error.message : String(error)}`);
|
|
3063
3073
|
}
|
|
3064
3074
|
if (previousStickyDirect !== void 0 && direct.port !== previousStickyDirect) {
|
|
@@ -3066,6 +3076,7 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
3066
3076
|
}
|
|
3067
3077
|
lastDirectPort = direct.port;
|
|
3068
3078
|
writeFrontDoorState(fs12, paths.frontdoorStateFile, { protocol: FRONT_DOOR_PROTOCOL, supervisorPid: ports.ownPid, port: http3.port, connectPort: connect3.port, directPort: direct.port, ...sticky() });
|
|
3079
|
+
ports.doorHealth.generation({ providerPort: http3.port, connectPort: connect3.port, directPort: direct.port });
|
|
3069
3080
|
fs12.removeRecursive(paths.frontdoorLockFile);
|
|
3070
3081
|
ports.log(`agent-shim frontdoor supervisor ${String(ports.ownPid)}: front door on 127.0.0.1:${String(http3.port)}, CONNECT surface on 127.0.0.1:${String(connect3.port)}`);
|
|
3071
3082
|
let idleSince;
|
|
@@ -3078,11 +3089,13 @@ async function runFrontDoorSupervisor(idleShutdownMinutes, ports, options = {})
|
|
|
3078
3089
|
const listed = listFrontDoorSessions(fs12, paths.frontdoorSessionsDir);
|
|
3079
3090
|
const pruned = pruneDeadFrontDoorSessions(fs12, paths.frontdoorSessionsDir, ports.isRunning);
|
|
3080
3091
|
ports.observeLaunchRegistry(listed, pruned);
|
|
3092
|
+
ports.checkQuotaExpiry();
|
|
3081
3093
|
const prunedPids = new Set(pruned);
|
|
3082
3094
|
if (listed.filter((session) => !prunedPids.has(session.pid)).length === 0) {
|
|
3083
3095
|
idleSince ??= ports.now();
|
|
3084
3096
|
if (ports.now() - idleSince >= idleShutdownMinutes * MS_PER_MINUTE) {
|
|
3085
3097
|
ports.log(`agent-shim frontdoor supervisor: no sessions for ${String(idleShutdownMinutes)} minute(s); closing the front door and exiting`);
|
|
3098
|
+
ports.doorHealth.idleShutdown();
|
|
3086
3099
|
await direct.close();
|
|
3087
3100
|
await connect3.close();
|
|
3088
3101
|
await http3.close();
|
|
@@ -5342,7 +5355,7 @@ var import_undici = require("undici");
|
|
|
5342
5355
|
// package.json
|
|
5343
5356
|
var package_default = {
|
|
5344
5357
|
name: "agent-shim",
|
|
5345
|
-
version: "8.
|
|
5358
|
+
version: "8.32.0",
|
|
5346
5359
|
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.",
|
|
5347
5360
|
license: "MIT",
|
|
5348
5361
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -6524,10 +6537,10 @@ function windowBlockedUntil(windows) {
|
|
|
6524
6537
|
const resets = windows.flatMap((window) => window.status === "rejected" && window.resetsAtMs !== void 0 ? [window.resetsAtMs] : []);
|
|
6525
6538
|
return resets.length === 0 ? void 0 : Math.max(...resets);
|
|
6526
6539
|
}
|
|
6527
|
-
function
|
|
6540
|
+
function windowBurn(records, which) {
|
|
6528
6541
|
const points = [];
|
|
6529
6542
|
for (const record of records) {
|
|
6530
|
-
const window = record.rateLimitHeaders === void 0 ? void 0 : parseUnifiedRateLimit(record.rateLimitHeaders)?.
|
|
6543
|
+
const window = record.rateLimitHeaders === void 0 ? void 0 : parseUnifiedRateLimit(record.rateLimitHeaders)?.[which];
|
|
6531
6544
|
if (window?.utilization !== void 0 && window.resetsAt !== void 0) {
|
|
6532
6545
|
points.push({ resetsAt: window.resetsAt, point: { atMs: Date.parse(record.at), utilization: window.utilization } });
|
|
6533
6546
|
}
|
|
@@ -6621,11 +6634,16 @@ function assessIdentity(member, nowMs) {
|
|
|
6621
6634
|
const score = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR);
|
|
6622
6635
|
const fiveRemaining = five?.utilization === void 0 ? void 0 : Math.max(0, 1 - five.utilization);
|
|
6623
6636
|
const fiveUntil = five?.resetsAtMs === void 0 ? FIVE_HOUR_WINDOW_MS : Math.max(five.resetsAtMs - nowMs, MS_PER_SECOND4);
|
|
6624
|
-
const burn =
|
|
6637
|
+
const burn = windowBurn(member.records, "fiveHour");
|
|
6638
|
+
const sevenRemaining = seven?.utilization === void 0 ? void 0 : Math.max(0, 1 - seven.utilization);
|
|
6639
|
+
const sevenUntil = seven?.resetsAtMs === void 0 ? SEVEN_DAY_WINDOW_MS : Math.max(seven.resetsAtMs - nowMs, MS_PER_SECOND4);
|
|
6640
|
+
const sevenDayBurn = windowBurn(member.records, "sevenDay");
|
|
6625
6641
|
return {
|
|
6626
6642
|
candidate: { ...base, class: "scored", score, reasons: [...windowReasons.map((reason, index) => index === windowReasons.length - 1 ? `${reason}${observedAgo}` : reason), ...planReasons] },
|
|
6627
6643
|
...fiveRemaining === void 0 ? {} : { fiveHour: { remaining: fiveRemaining, untilResetMs: fiveUntil } },
|
|
6628
|
-
...burn === void 0 ? {} : { burn }
|
|
6644
|
+
...burn === void 0 ? {} : { burn },
|
|
6645
|
+
...sevenRemaining === void 0 ? {} : { sevenDay: { remaining: sevenRemaining, untilResetMs: sevenUntil } },
|
|
6646
|
+
...sevenDayBurn === void 0 ? {} : { sevenDayBurn }
|
|
6629
6647
|
};
|
|
6630
6648
|
}
|
|
6631
6649
|
function rankPool(input) {
|
|
@@ -6636,14 +6654,27 @@ function rankPool(input) {
|
|
|
6636
6654
|
const candidates = assessments.map((assessment) => {
|
|
6637
6655
|
const { candidate, fiveHour, burn } = assessment;
|
|
6638
6656
|
const pace = burn ?? (sharedDemand === void 0 ? void 0 : sharedDemand / capacityOf(candidate.plan));
|
|
6639
|
-
|
|
6657
|
+
const { sevenDay, sevenDayBurn } = assessment;
|
|
6658
|
+
if (candidate.class !== "scored") {
|
|
6640
6659
|
return { ...candidate, feasible: true };
|
|
6641
6660
|
}
|
|
6642
|
-
const
|
|
6643
|
-
if (
|
|
6661
|
+
const drySpots = [];
|
|
6662
|
+
if (fiveHour !== void 0 && pace !== void 0) {
|
|
6663
|
+
const runsDryInMs = fiveHour.remaining / pace;
|
|
6664
|
+
if (runsDryInMs < fiveHour.untilResetMs) {
|
|
6665
|
+
drySpots.push(`5h window would run dry in ${formatAge(runsDryInMs)}, before it resets in ${formatAge(fiveHour.untilResetMs)}`);
|
|
6666
|
+
}
|
|
6667
|
+
}
|
|
6668
|
+
if (sevenDay !== void 0 && sevenDayBurn !== void 0) {
|
|
6669
|
+
const runsDryInMs = sevenDay.remaining / sevenDayBurn;
|
|
6670
|
+
if (runsDryInMs < sevenDay.untilResetMs) {
|
|
6671
|
+
drySpots.push(`7d window would run dry in ${formatAge(runsDryInMs)}, before it resets in ${formatAge(sevenDay.untilResetMs)}`);
|
|
6672
|
+
}
|
|
6673
|
+
}
|
|
6674
|
+
if (drySpots.length === 0) {
|
|
6644
6675
|
return { ...candidate, feasible: true };
|
|
6645
6676
|
}
|
|
6646
|
-
return { ...candidate, feasible: false, reasons: [
|
|
6677
|
+
return { ...candidate, feasible: false, reasons: [...drySpots, ...candidate.reasons] };
|
|
6647
6678
|
});
|
|
6648
6679
|
const ordered = input.preference === "listed" ? [...candidates] : [...candidates].sort(
|
|
6649
6680
|
(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)
|
|
@@ -6651,7 +6682,8 @@ function rankPool(input) {
|
|
|
6651
6682
|
const sticky = input.sticky;
|
|
6652
6683
|
const stickyIndex = sticky === void 0 ? -1 : ordered.findIndex((candidate) => candidate.identity === sticky.identity);
|
|
6653
6684
|
const stickyCandidate = ordered[stickyIndex];
|
|
6654
|
-
|
|
6685
|
+
const keepSticky = stickyCandidate?.class === "scored" && stickyCandidate.feasible;
|
|
6686
|
+
if (sticky !== void 0 && keepSticky) {
|
|
6655
6687
|
const ageMs = nowMs - Date.parse(sticky.at);
|
|
6656
6688
|
const warm = ageMs <= PROMPT_CACHE_TTL_MS;
|
|
6657
6689
|
if (input.resuming || warm) {
|
|
@@ -6660,12 +6692,14 @@ function rankPool(input) {
|
|
|
6660
6692
|
ordered.unshift({ ...stickyCandidate, reasons: [why, ...stickyCandidate.reasons] });
|
|
6661
6693
|
}
|
|
6662
6694
|
}
|
|
6695
|
+
const movedOff = sticky !== void 0 && input.resuming && !keepSticky ? { identity: sticky.identity, reason: stickyCandidate?.reasons[0] ?? "no longer among the pool's members" } : void 0;
|
|
6663
6696
|
const pick = ordered.find((candidate) => candidate.class !== "ineligible");
|
|
6664
6697
|
const returns = ordered.flatMap((candidate) => candidate.blockedUntilMs === void 0 ? [] : [{ identity: candidate.identity, atMs: candidate.blockedUntilMs }]);
|
|
6665
6698
|
const earliestReturn = returns.length === 0 ? void 0 : returns.reduce((soonest, entry) => entry.atMs < soonest.atMs ? entry : soonest);
|
|
6666
6699
|
return {
|
|
6667
6700
|
candidates: ordered,
|
|
6668
|
-
...pick === void 0 ? { ...earliestReturn === void 0 ? {} : { earliestReturn } } : { pick }
|
|
6701
|
+
...pick === void 0 ? { ...earliestReturn === void 0 ? {} : { earliestReturn } } : { pick },
|
|
6702
|
+
...movedOff === void 0 || pick === void 0 ? {} : { movedOff }
|
|
6669
6703
|
};
|
|
6670
6704
|
}
|
|
6671
6705
|
|
|
@@ -6923,6 +6957,7 @@ function collectPoolPick(params) {
|
|
|
6923
6957
|
candidates: ranking.candidates.map(candidateView),
|
|
6924
6958
|
missing: missing.map(({ identity }) => identity),
|
|
6925
6959
|
...ranking.earliestReturn === void 0 ? {} : { earliestReturn: { identity: ranking.earliestReturn.identity, at: new Date(ranking.earliestReturn.atMs).toISOString() } },
|
|
6960
|
+
...ranking.movedOff === void 0 ? {} : { movedOff: ranking.movedOff },
|
|
6926
6961
|
...sticky.problem === void 0 ? {} : { stickyProblem: sticky.problem }
|
|
6927
6962
|
};
|
|
6928
6963
|
}
|
|
@@ -9194,6 +9229,8 @@ var PoolPickReportSchema = import_zod13.z.strictObject({
|
|
|
9194
9229
|
missing: import_zod13.z.array(import_zod13.z.string()),
|
|
9195
9230
|
/** When nothing can be picked, the soonest any member returns. */
|
|
9196
9231
|
earliestReturn: import_zod13.z.strictObject({ identity: import_zod13.z.string(), at: import_zod13.z.iso.datetime() }).optional(),
|
|
9232
|
+
/** The member a resumed conversation started on but moved off, and why, when the ranking could not keep it. */
|
|
9233
|
+
movedOff: import_zod13.z.strictObject({ identity: import_zod13.z.string(), reason: import_zod13.z.string() }).optional(),
|
|
9197
9234
|
/** Why the last-pick record could not be read, when that is the case. */
|
|
9198
9235
|
stickyProblem: import_zod13.z.string().optional()
|
|
9199
9236
|
});
|
|
@@ -10204,6 +10241,9 @@ var import_server3 = require("@orpc/server");
|
|
|
10204
10241
|
var import_zod20 = require("zod");
|
|
10205
10242
|
var DOOR_EVENT_SOURCE_RC = "rc";
|
|
10206
10243
|
var LAUNCH_EVENT_SOURCE = "launch";
|
|
10244
|
+
var USAGE_EVENT_SOURCE = "usage";
|
|
10245
|
+
var DOOR_HEALTH_EVENT_SOURCE = "door";
|
|
10246
|
+
var QUOTA_EXPIRING_EVENT_SOURCE = "quota-expiring";
|
|
10207
10247
|
var DoorEventSchema = import_zod20.z.strictObject({
|
|
10208
10248
|
source: import_zod20.z.string().min(1),
|
|
10209
10249
|
/** A positive integer because the backbone's counters start at one and only ever increase. */
|
|
@@ -10219,6 +10259,20 @@ var LaunchLifecycleEventSchema = import_zod20.z.strictObject({
|
|
|
10219
10259
|
startedAt: import_zod20.z.number(),
|
|
10220
10260
|
observedAt: import_zod20.z.number()
|
|
10221
10261
|
});
|
|
10262
|
+
var DoorHealthEventSchema = import_zod20.z.discriminatedUnion("kind", [
|
|
10263
|
+
import_zod20.z.strictObject({ kind: import_zod20.z.literal("generation"), pid: import_zod20.z.number().int().positive(), providerPort: import_zod20.z.number().int().positive(), connectPort: import_zod20.z.number().int().positive(), directPort: import_zod20.z.number().int().positive(), observedAt: import_zod20.z.number() }),
|
|
10264
|
+
import_zod20.z.strictObject({ kind: import_zod20.z.literal("listenerFailed"), pid: import_zod20.z.number().int().positive(), listener: import_zod20.z.enum(["provider", "connect", "direct"]), message: import_zod20.z.string(), observedAt: import_zod20.z.number() }),
|
|
10265
|
+
import_zod20.z.strictObject({ kind: import_zod20.z.literal("idleShutdown"), pid: import_zod20.z.number().int().positive(), observedAt: import_zod20.z.number() })
|
|
10266
|
+
]);
|
|
10267
|
+
var QuotaExpiringEventSchema = import_zod20.z.strictObject({
|
|
10268
|
+
identity: import_zod20.z.string().min(1),
|
|
10269
|
+
provider: import_zod20.z.string().min(1),
|
|
10270
|
+
window: import_zod20.z.enum(["fiveHour", "sevenDay"]),
|
|
10271
|
+
/** The fraction of the window already used when it was seen expiring, always below one because a fully used window has nothing left to spend. */
|
|
10272
|
+
utilization: import_zod20.z.number().min(0).max(1),
|
|
10273
|
+
resetsAt: import_zod20.z.iso.datetime(),
|
|
10274
|
+
observedAt: import_zod20.z.number()
|
|
10275
|
+
});
|
|
10222
10276
|
|
|
10223
10277
|
// src/frontdoor/eventsApi.ts
|
|
10224
10278
|
var EVENTS_API_TAG = "events";
|
|
@@ -10527,6 +10581,81 @@ function createLaunchEventPublisher(hub, now) {
|
|
|
10527
10581
|
};
|
|
10528
10582
|
}
|
|
10529
10583
|
|
|
10584
|
+
// src/frontdoor/doorHealthEvents.ts
|
|
10585
|
+
function createDoorHealthPublisher(hub, now, pid) {
|
|
10586
|
+
const publisher = hub.publisher(DOOR_HEALTH_EVENT_SOURCE);
|
|
10587
|
+
return {
|
|
10588
|
+
generation: (ports) => {
|
|
10589
|
+
publisher.publish({ kind: "generation", pid, providerPort: ports.providerPort, connectPort: ports.connectPort, directPort: ports.directPort, observedAt: now() });
|
|
10590
|
+
},
|
|
10591
|
+
listenerFailed: (listener, message) => {
|
|
10592
|
+
publisher.publish({ kind: "listenerFailed", pid, listener, message, observedAt: now() });
|
|
10593
|
+
},
|
|
10594
|
+
idleShutdown: () => {
|
|
10595
|
+
publisher.publish({ kind: "idleShutdown", pid, observedAt: now() });
|
|
10596
|
+
}
|
|
10597
|
+
};
|
|
10598
|
+
}
|
|
10599
|
+
|
|
10600
|
+
// src/frontdoor/quotaExpiringEvents.ts
|
|
10601
|
+
var MS_PER_HOUR2 = 36e5;
|
|
10602
|
+
var MS_PER_DAY2 = 864e5;
|
|
10603
|
+
var FIVE_HOUR_WINDOW_HOURS = 5;
|
|
10604
|
+
var SEVEN_DAY_WINDOW_DAYS = 7;
|
|
10605
|
+
var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR2;
|
|
10606
|
+
var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY2;
|
|
10607
|
+
var FINAL_SPAN_DENOMINATOR = 30;
|
|
10608
|
+
var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
|
|
10609
|
+
function createQuotaExpiringPublisher(hub, deps) {
|
|
10610
|
+
const publisher = hub.publisher(QUOTA_EXPIRING_EVENT_SOURCE);
|
|
10611
|
+
const latest = /* @__PURE__ */ new Map();
|
|
10612
|
+
for (const snapshot of deps.seed) {
|
|
10613
|
+
latest.set(snapshot.identity, snapshot);
|
|
10614
|
+
}
|
|
10615
|
+
hub.subscribe([USAGE_EVENT_SOURCE], (event) => {
|
|
10616
|
+
const snapshot = UsageSnapshotSchema.parse(event.payload);
|
|
10617
|
+
latest.set(snapshot.identity, snapshot);
|
|
10618
|
+
});
|
|
10619
|
+
const announced = /* @__PURE__ */ new Set();
|
|
10620
|
+
const windowsOf = (snapshot) => {
|
|
10621
|
+
const views = [];
|
|
10622
|
+
for (const provider of Object.keys(snapshot.providers).sort()) {
|
|
10623
|
+
const unified = snapshot.providers[provider]?.rateLimit?.unified;
|
|
10624
|
+
const fiveHour = unified?.fiveHour;
|
|
10625
|
+
if (fiveHour?.utilization !== void 0 && fiveHour.resetsAt !== void 0) {
|
|
10626
|
+
views.push({ provider, view: { window: "fiveHour", spanMs: FIVE_HOUR_WINDOW_MS2, utilization: fiveHour.utilization, resetsAtMs: Date.parse(fiveHour.resetsAt) } });
|
|
10627
|
+
}
|
|
10628
|
+
const sevenDay = unified?.sevenDay;
|
|
10629
|
+
if (sevenDay?.utilization !== void 0 && sevenDay.resetsAt !== void 0) {
|
|
10630
|
+
views.push({ provider, view: { window: "sevenDay", spanMs: SEVEN_DAY_WINDOW_MS2, utilization: sevenDay.utilization, resetsAtMs: Date.parse(sevenDay.resetsAt) } });
|
|
10631
|
+
}
|
|
10632
|
+
}
|
|
10633
|
+
return views;
|
|
10634
|
+
};
|
|
10635
|
+
return {
|
|
10636
|
+
check: () => {
|
|
10637
|
+
const now = deps.now();
|
|
10638
|
+
for (const identity of [...latest.keys()].sort()) {
|
|
10639
|
+
const snapshot = latest.get(identity);
|
|
10640
|
+
if (snapshot === void 0) {
|
|
10641
|
+
continue;
|
|
10642
|
+
}
|
|
10643
|
+
for (const { provider, view } of windowsOf(snapshot)) {
|
|
10644
|
+
if (view.utilization >= 1 || view.resetsAtMs <= now || view.resetsAtMs - now >= view.spanMs * QUOTA_EXPIRING_WINDOW_FRACTION) {
|
|
10645
|
+
continue;
|
|
10646
|
+
}
|
|
10647
|
+
const key = `${identity}:${provider}:${view.window}:${String(view.resetsAtMs)}`;
|
|
10648
|
+
if (announced.has(key)) {
|
|
10649
|
+
continue;
|
|
10650
|
+
}
|
|
10651
|
+
announced.add(key);
|
|
10652
|
+
publisher.publish({ identity, provider, window: view.window, utilization: view.utilization, resetsAt: new Date(view.resetsAtMs).toISOString(), observedAt: now });
|
|
10653
|
+
}
|
|
10654
|
+
}
|
|
10655
|
+
}
|
|
10656
|
+
};
|
|
10657
|
+
}
|
|
10658
|
+
|
|
10530
10659
|
// src/frontdoor/rcLiveUsage.ts
|
|
10531
10660
|
var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
|
|
10532
10661
|
function isRecord5(value) {
|
|
@@ -12848,10 +12977,11 @@ function resolvePoolLaunch(params) {
|
|
|
12848
12977
|
if (graph.ranking.candidates.length === 0) {
|
|
12849
12978
|
return { ok: false, message: `agent-shim: no member of pool "${poolName}" is an existing identity.` };
|
|
12850
12979
|
}
|
|
12851
|
-
const { pick, earliestReturn } = graph.ranking;
|
|
12980
|
+
const { pick, earliestReturn, movedOff } = graph.ranking;
|
|
12852
12981
|
if (pick !== void 0) {
|
|
12853
12982
|
recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
|
|
12854
|
-
|
|
12983
|
+
const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
|
|
12984
|
+
return { ok: true, identity: pick.identity, explanation: `pool ${poolName}: ${move}${pick.reasons.slice(0, REASONS_LOGGED).join("; ")}` };
|
|
12855
12985
|
}
|
|
12856
12986
|
if (earliestReturn === void 0) {
|
|
12857
12987
|
return { ok: false, message: `agent-shim: no member of pool "${poolName}" can be picked.` };
|
|
@@ -13520,6 +13650,7 @@ function prepareClaudeLaunch(options) {
|
|
|
13520
13650
|
CredentialSourceSchema,
|
|
13521
13651
|
DOOR_EVENT_BUFFER_EVENTS,
|
|
13522
13652
|
DOOR_EVENT_SOURCE_RC,
|
|
13653
|
+
DOOR_HEALTH_EVENT_SOURCE,
|
|
13523
13654
|
DirectoryRuleAlreadyExistsError,
|
|
13524
13655
|
DirectoryRuleMissingTargetError,
|
|
13525
13656
|
DirectoryRuleNotFoundError,
|
|
@@ -13529,6 +13660,7 @@ function prepareClaudeLaunch(options) {
|
|
|
13529
13660
|
DoctorRunOutputSchema,
|
|
13530
13661
|
DoorEventSchema,
|
|
13531
13662
|
DoorEventSourceQuerySchema,
|
|
13663
|
+
DoorHealthEventSchema,
|
|
13532
13664
|
EXIT_FAILURE,
|
|
13533
13665
|
EXIT_USAGE,
|
|
13534
13666
|
EffectiveWindowSchema,
|
|
@@ -13565,6 +13697,8 @@ function prepareClaudeLaunch(options) {
|
|
|
13565
13697
|
ProviderKindMismatchError,
|
|
13566
13698
|
ProviderNotFoundError,
|
|
13567
13699
|
ProviderSchema,
|
|
13700
|
+
QUOTA_EXPIRING_EVENT_SOURCE,
|
|
13701
|
+
QuotaExpiringEventSchema,
|
|
13568
13702
|
RC_CONTEXT_USAGE_DETAILS,
|
|
13569
13703
|
RC_IDLE_EXPIRY_MS,
|
|
13570
13704
|
RC_ORPC_PATH_PREFIX,
|
|
@@ -13592,6 +13726,7 @@ function prepareClaudeLaunch(options) {
|
|
|
13592
13726
|
RcRateLimitWindowSchema,
|
|
13593
13727
|
RcStreamEnvelopeSchema,
|
|
13594
13728
|
RcStreamEventSchema,
|
|
13729
|
+
USAGE_EVENT_SOURCE,
|
|
13595
13730
|
UsageError,
|
|
13596
13731
|
UsageListOutputSchema,
|
|
13597
13732
|
UsageLiveOutputSchema,
|
|
@@ -13637,10 +13772,12 @@ function prepareClaudeLaunch(options) {
|
|
|
13637
13772
|
createDoorApiNodeHandler,
|
|
13638
13773
|
createDoorApiRouter,
|
|
13639
13774
|
createDoorEventHub,
|
|
13775
|
+
createDoorHealthPublisher,
|
|
13640
13776
|
createEventsApiRouter,
|
|
13641
13777
|
createLaunchEventPublisher,
|
|
13642
13778
|
createLeafCache,
|
|
13643
13779
|
createProfile,
|
|
13780
|
+
createQuotaExpiringPublisher,
|
|
13644
13781
|
createRcApiNodeHandler,
|
|
13645
13782
|
createRcApiRouter,
|
|
13646
13783
|
createRcControlHandler,
|