@mostok/codexes 0.1.0 → 0.3.2

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.
Files changed (32) hide show
  1. package/README.md +10 -4
  2. package/dist/cli.js +2072 -1385
  3. package/dist/cli.js.map +4 -4
  4. package/dist/commands/account-list/run-account-list-command.js +36 -18
  5. package/dist/commands/account-list/run-account-list-command.js.map +1 -1
  6. package/dist/commands/root/run-root-command.js +54 -6
  7. package/dist/commands/root/run-root-command.js.map +1 -1
  8. package/dist/config/wrapper-config.d.ts +2 -1
  9. package/dist/config/wrapper-config.js +66 -17
  10. package/dist/config/wrapper-config.js.map +1 -1
  11. package/dist/core/context.d.ts +3 -0
  12. package/dist/core/context.js +3 -0
  13. package/dist/core/context.js.map +1 -1
  14. package/dist/selection/format-selection-summary.d.ts +12 -0
  15. package/dist/selection/format-selection-summary.js +182 -0
  16. package/dist/selection/format-selection-summary.js.map +1 -0
  17. package/dist/selection/select-account.js +7 -163
  18. package/dist/selection/select-account.js.map +1 -1
  19. package/dist/selection/selection-summary.d.ts +38 -0
  20. package/dist/selection/selection-summary.js +405 -0
  21. package/dist/selection/selection-summary.js.map +1 -0
  22. package/dist/selection/usage-cache.js +23 -0
  23. package/dist/selection/usage-cache.js.map +1 -1
  24. package/dist/selection/usage-normalize.js +182 -19
  25. package/dist/selection/usage-normalize.js.map +1 -1
  26. package/dist/selection/usage-probe-coordinator.js +13 -0
  27. package/dist/selection/usage-probe-coordinator.js.map +1 -1
  28. package/dist/selection/usage-types.d.ts +18 -2
  29. package/package.json +1 -1
  30. package/dist/accounts/resolve-active-account.d.ts +0 -6
  31. package/dist/accounts/resolve-active-account.js +0 -32
  32. package/dist/accounts/resolve-active-account.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-selection-summary.js","sourceRoot":"","sources":["../../src/selection/format-selection-summary.ts"],"names":[],"mappings":"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"}
@@ -1,168 +1,12 @@
1
- import { resolveAccountUsageSnapshots } from "./usage-probe-coordinator.js";
1
+ import { resolveSelectionSummary } from "./selection-summary.js";
2
2
  export async function selectAccountForExecution(input) {
3
- const accounts = await input.registry.listAccounts();
4
- input.logger.info("selection.start", {
5
- strategy: input.strategy,
6
- accountCount: accounts.length,
3
+ const summary = await resolveSelectionSummary({
4
+ ...input,
5
+ mode: "execution",
7
6
  });
8
- if (accounts.length === 0) {
9
- input.logger.warn("selection.none");
10
- throw new Error("No accounts configured. Add one with `codexes account add <label>`.");
7
+ if (!summary.selectedAccount) {
8
+ throw new Error(summary.executionBlockedReason ?? "Execution selection did not resolve an account.");
11
9
  }
12
- switch (input.strategy) {
13
- case "manual-default":
14
- return selectManualDefaultAccount(input.registry, input.logger, accounts);
15
- case "single-account":
16
- return selectSingleAccountOnly(input.registry, input.logger, accounts);
17
- case "remaining-limit-experimental":
18
- return selectExperimentalRemainingLimitAccount({
19
- accounts,
20
- experimentalSelection: input.experimentalSelection,
21
- fetchImpl: input.fetchImpl,
22
- logger: input.logger,
23
- registry: input.registry,
24
- selectionCacheFilePath: input.selectionCacheFilePath,
25
- });
26
- }
27
- }
28
- async function selectManualDefaultAccount(registry, logger, accounts) {
29
- const defaultAccount = await registry.getDefaultAccount();
30
- if (defaultAccount) {
31
- logger.info("selection.manual_default", {
32
- accountId: defaultAccount.id,
33
- label: defaultAccount.label,
34
- });
35
- return defaultAccount;
36
- }
37
- if (accounts.length === 1) {
38
- const [singleAccount] = accounts;
39
- if (!singleAccount) {
40
- throw new Error("No accounts configured.");
41
- }
42
- logger.info("selection.manual_default_fallback_single", {
43
- accountId: singleAccount.id,
44
- label: singleAccount.label,
45
- });
46
- return registry.selectAccount(singleAccount.id);
47
- }
48
- logger.warn("selection.manual_default_missing", {
49
- accountCount: accounts.length,
50
- });
51
- throw new Error("Multiple accounts are configured but no default account is selected. Use `codexes account use <account-id-or-label>` first.");
52
- }
53
- async function selectSingleAccountOnly(registry, logger, accounts) {
54
- if (accounts.length !== 1) {
55
- logger.warn("selection.single_account_invalid", {
56
- accountCount: accounts.length,
57
- });
58
- throw new Error("The single-account strategy requires exactly one configured account.");
59
- }
60
- const [singleAccount] = accounts;
61
- if (!singleAccount) {
62
- throw new Error("No accounts configured.");
63
- }
64
- logger.info("selection.single_account", {
65
- accountId: singleAccount.id,
66
- label: singleAccount.label,
67
- });
68
- const defaultAccount = await registry.getDefaultAccount();
69
- if (defaultAccount?.id === singleAccount.id) {
70
- return singleAccount;
71
- }
72
- return registry.selectAccount(singleAccount.id);
73
- }
74
- async function selectExperimentalRemainingLimitAccount(input) {
75
- if (!input.experimentalSelection?.enabled || !input.selectionCacheFilePath) {
76
- input.logger.warn("selection.experimental_config_missing", {
77
- enabled: input.experimentalSelection?.enabled ?? false,
78
- hasSelectionCacheFilePath: Boolean(input.selectionCacheFilePath),
79
- });
80
- return selectManualDefaultAccount(input.registry, input.logger, input.accounts);
81
- }
82
- const defaultAccount = await input.registry.getDefaultAccount();
83
- const probeResults = await resolveAccountUsageSnapshots({
84
- accounts: input.accounts,
85
- cacheFilePath: input.selectionCacheFilePath,
86
- fetchImpl: input.fetchImpl,
87
- logger: input.logger,
88
- probeConfig: input.experimentalSelection,
89
- });
90
- const failedProbes = probeResults.filter((entry) => !entry.ok);
91
- if (failedProbes.length > 0) {
92
- const eventName = failedProbes.length === probeResults.length
93
- ? "selection.experimental_fallback_all_probes_failed"
94
- : "selection.experimental_fallback_mixed_probe_outcomes";
95
- input.logger.warn(eventName, {
96
- failedAccountIds: failedProbes.map((entry) => entry.account.id),
97
- failureCategories: failedProbes.map((entry) => entry.category),
98
- successfulAccountIds: probeResults
99
- .filter((entry) => entry.ok)
100
- .map((entry) => entry.account.id),
101
- });
102
- return selectManualDefaultAccount(input.registry, input.logger, input.accounts);
103
- }
104
- const successfulProbes = probeResults.filter((entry) => entry.ok);
105
- const candidates = successfulProbes
106
- .filter((entry) => entry.snapshot.status === "usable")
107
- .sort((left, right) => compareExperimentalCandidates({
108
- defaultAccountId: defaultAccount?.id ?? null,
109
- left,
110
- right,
111
- registryOrder: input.accounts,
112
- }));
113
- input.logger.info("selection.experimental_ranked", {
114
- candidateOrder: candidates.map((entry) => ({
115
- accountId: entry.account.id,
116
- label: entry.account.label,
117
- dailyRemaining: entry.snapshot.dailyRemaining,
118
- weeklyRemaining: entry.snapshot.weeklyRemaining,
119
- source: entry.source,
120
- })),
121
- defaultAccountId: defaultAccount?.id ?? null,
122
- });
123
- const selected = candidates[0];
124
- if (!selected) {
125
- const allExhausted = successfulProbes.every((entry) => entry.snapshot.limitReached || entry.snapshot.status === "limit-reached");
126
- input.logger.warn(allExhausted
127
- ? "selection.experimental_fallback_all_accounts_exhausted"
128
- : "selection.experimental_fallback_ambiguous_usage", {
129
- usableProbeCount: candidates.length,
130
- probeStatuses: successfulProbes.map((entry) => ({
131
- accountId: entry.account.id,
132
- snapshotStatus: entry.snapshot.status,
133
- limitReached: entry.snapshot.limitReached,
134
- dailyRemaining: entry.snapshot.dailyRemaining,
135
- weeklyRemaining: entry.snapshot.weeklyRemaining,
136
- })),
137
- });
138
- return selectManualDefaultAccount(input.registry, input.logger, input.accounts);
139
- }
140
- input.logger.info("selection.experimental_selected", {
141
- accountId: selected.account.id,
142
- label: selected.account.label,
143
- dailyRemaining: selected.snapshot.dailyRemaining,
144
- weeklyRemaining: selected.snapshot.weeklyRemaining,
145
- source: selected.source,
146
- });
147
- return selected.account;
148
- }
149
- function compareExperimentalCandidates(input) {
150
- const dailyDelta = (input.right.snapshot.dailyRemaining ?? Number.NEGATIVE_INFINITY) -
151
- (input.left.snapshot.dailyRemaining ?? Number.NEGATIVE_INFINITY);
152
- if (dailyDelta !== 0) {
153
- return dailyDelta;
154
- }
155
- const weeklyDelta = (input.right.snapshot.weeklyRemaining ?? Number.NEGATIVE_INFINITY) -
156
- (input.left.snapshot.weeklyRemaining ?? Number.NEGATIVE_INFINITY);
157
- if (weeklyDelta !== 0) {
158
- return weeklyDelta;
159
- }
160
- const leftIsDefault = input.left.account.id === input.defaultAccountId;
161
- const rightIsDefault = input.right.account.id === input.defaultAccountId;
162
- if (leftIsDefault !== rightIsDefault) {
163
- return leftIsDefault ? -1 : 1;
164
- }
165
- return (input.registryOrder.findIndex((account) => account.id === input.left.account.id) -
166
- input.registryOrder.findIndex((account) => account.id === input.right.account.id));
10
+ return summary.selectedAccount;
167
11
  }
168
12
  //# sourceMappingURL=select-account.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-account.js","sourceRoot":"","sources":["../../src/selection/select-account.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select-account.js","sourceRoot":"","sources":["../../src/selection/select-account.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAO/C;IACC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC;QAC5C,GAAG,KAAK;QACR,IAAI,EAAE,WAAW;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,OAAO,CAAC,sBAAsB,IAAI,iDAAiD,CACpF,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,eAAe,CAAC;AACjC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { AccountRecord, AccountRegistry } from "../accounts/account-registry.js";
2
+ import type { AccountSelectionStrategy, ExperimentalSelectionConfig } from "../config/wrapper-config.js";
3
+ import type { Logger } from "../logging/logger.js";
4
+ import type { UsageProbeFailureCategory } from "./usage-client.js";
5
+ import type { NormalizedUsageSnapshot } from "./usage-types.js";
6
+ export type SelectionEntrySource = "cache" | "fresh" | "unavailable";
7
+ export type SelectionFallbackReason = "experimental-config-missing" | "all-probes-failed" | "mixed-probe-outcomes" | "all-accounts-exhausted" | "ambiguous-usage" | null;
8
+ export type SelectionDecisionMode = "manual-default" | "manual-default-fallback-single" | "single-account" | "experimental-ranked";
9
+ export type SelectionSummaryMode = "display-only" | "execution";
10
+ export interface SelectionSummaryEntry {
11
+ account: AccountRecord;
12
+ failureCategory: UsageProbeFailureCategory | null;
13
+ failureMessage: string | null;
14
+ isDefault: boolean;
15
+ isEligibleForRanking: boolean;
16
+ isSelected: boolean;
17
+ rankingPosition: number | null;
18
+ snapshot: NormalizedUsageSnapshot | null;
19
+ source: SelectionEntrySource;
20
+ }
21
+ export interface SelectionSummary {
22
+ entries: SelectionSummaryEntry[];
23
+ executionBlockedReason: string | null;
24
+ fallbackReason: SelectionFallbackReason;
25
+ mode: SelectionSummaryMode;
26
+ selectedAccount: AccountRecord | null;
27
+ selectedBy: SelectionDecisionMode | null;
28
+ strategy: AccountSelectionStrategy;
29
+ }
30
+ export declare function resolveSelectionSummary(input: {
31
+ experimentalSelection?: ExperimentalSelectionConfig;
32
+ fetchImpl?: typeof fetch;
33
+ logger: Logger;
34
+ mode?: SelectionSummaryMode;
35
+ registry: AccountRegistry;
36
+ selectionCacheFilePath?: string;
37
+ strategy: AccountSelectionStrategy;
38
+ }): Promise<SelectionSummary>;
@@ -0,0 +1,405 @@
1
+ import { resolveAccountUsageSnapshots } from "./usage-probe-coordinator.js";
2
+ export async function resolveSelectionSummary(input) {
3
+ const mode = input.mode ?? "execution";
4
+ const accounts = await input.registry.listAccounts();
5
+ input.logger.info("selection.summary.start", {
6
+ mode,
7
+ strategy: input.strategy,
8
+ accountCount: accounts.length,
9
+ });
10
+ if (accounts.length === 0) {
11
+ input.logger.warn("selection.none", {
12
+ mode,
13
+ strategy: input.strategy,
14
+ });
15
+ throw new Error("No accounts configured. Add one with `codexes account add <label>`.");
16
+ }
17
+ const defaultAccount = await input.registry.getDefaultAccount();
18
+ const summary = await resolveStrategySummary({
19
+ accounts,
20
+ defaultAccount,
21
+ experimentalSelection: input.experimentalSelection,
22
+ fetchImpl: input.fetchImpl,
23
+ logger: input.logger,
24
+ mode,
25
+ registry: input.registry,
26
+ selectionCacheFilePath: input.selectionCacheFilePath,
27
+ strategy: input.strategy,
28
+ });
29
+ input.logger.info("selection.summary.complete", {
30
+ mode: summary.mode,
31
+ strategy: summary.strategy,
32
+ selectedAccountId: summary.selectedAccount?.id ?? null,
33
+ selectedBy: summary.selectedBy,
34
+ fallbackReason: summary.fallbackReason,
35
+ executionBlockedReason: summary.executionBlockedReason,
36
+ entryCount: summary.entries.length,
37
+ });
38
+ return summary;
39
+ }
40
+ async function resolveStrategySummary(input) {
41
+ switch (input.strategy) {
42
+ case "manual-default":
43
+ return buildManualDefaultSummary(input.registry, input.logger, input.accounts, input.defaultAccount, input.mode);
44
+ case "single-account":
45
+ return buildSingleAccountSummary(input.registry, input.logger, input.accounts, input.defaultAccount, input.mode);
46
+ case "remaining-limit":
47
+ case "remaining-limit-experimental":
48
+ return buildExperimentalSummary(input);
49
+ }
50
+ }
51
+ async function buildManualDefaultSummary(registry, logger, accounts, defaultAccount, mode) {
52
+ const selection = await resolveManualDefaultSelection({
53
+ accounts,
54
+ logger,
55
+ mode,
56
+ registry,
57
+ strategy: "manual-default",
58
+ });
59
+ return {
60
+ entries: createUnavailableEntries(accounts, defaultAccount, selection.selectedAccount),
61
+ executionBlockedReason: selection.executionBlockedReason,
62
+ fallbackReason: null,
63
+ mode,
64
+ selectedAccount: selection.selectedAccount,
65
+ selectedBy: selection.selectedBy,
66
+ strategy: "manual-default",
67
+ };
68
+ }
69
+ async function buildSingleAccountSummary(registry, logger, accounts, defaultAccount, mode) {
70
+ const selectedAccount = await selectSingleAccountOnly(registry, logger, accounts, mode);
71
+ return {
72
+ entries: createUnavailableEntries(accounts, defaultAccount, selectedAccount),
73
+ executionBlockedReason: null,
74
+ fallbackReason: null,
75
+ mode,
76
+ selectedAccount,
77
+ selectedBy: "single-account",
78
+ strategy: "single-account",
79
+ };
80
+ }
81
+ async function buildExperimentalSummary(input) {
82
+ if (!input.experimentalSelection?.enabled || !input.selectionCacheFilePath) {
83
+ input.logger.warn("selection.experimental_config_missing", {
84
+ enabled: input.experimentalSelection?.enabled ?? false,
85
+ hasSelectionCacheFilePath: Boolean(input.selectionCacheFilePath),
86
+ mode: input.mode,
87
+ });
88
+ const fallbackSelection = await resolveManualDefaultSelection({
89
+ accounts: input.accounts,
90
+ fallbackReason: "experimental-config-missing",
91
+ logger: input.logger,
92
+ mode: input.mode,
93
+ registry: input.registry,
94
+ strategy: input.strategy,
95
+ });
96
+ return {
97
+ entries: createUnavailableEntries(input.accounts, input.defaultAccount, fallbackSelection.selectedAccount),
98
+ executionBlockedReason: fallbackSelection.executionBlockedReason,
99
+ fallbackReason: "experimental-config-missing",
100
+ mode: input.mode,
101
+ selectedAccount: fallbackSelection.selectedAccount,
102
+ selectedBy: fallbackSelection.selectedBy,
103
+ strategy: input.strategy,
104
+ };
105
+ }
106
+ const probeResults = await resolveAccountUsageSnapshots({
107
+ accounts: input.accounts,
108
+ cacheFilePath: input.selectionCacheFilePath,
109
+ fetchImpl: input.fetchImpl,
110
+ logger: input.logger,
111
+ probeConfig: input.experimentalSelection,
112
+ });
113
+ const failedProbes = probeResults.filter((entry) => !entry.ok);
114
+ if (failedProbes.length > 0) {
115
+ const fallbackReason = failedProbes.length === probeResults.length ? "all-probes-failed" : "mixed-probe-outcomes";
116
+ input.logger.warn(fallbackReason === "all-probes-failed"
117
+ ? "selection.experimental_fallback_all_probes_failed"
118
+ : "selection.experimental_fallback_mixed_probe_outcomes", {
119
+ failedAccountIds: failedProbes.map((entry) => entry.account.id),
120
+ failureCategories: failedProbes.map((entry) => entry.category),
121
+ mode: input.mode,
122
+ successfulAccountIds: probeResults
123
+ .filter((entry) => entry.ok)
124
+ .map((entry) => entry.account.id),
125
+ });
126
+ const fallbackSelection = await resolveManualDefaultSelection({
127
+ accounts: input.accounts,
128
+ fallbackReason,
129
+ logger: input.logger,
130
+ mode: input.mode,
131
+ registry: input.registry,
132
+ strategy: input.strategy,
133
+ });
134
+ logExperimentalFallbackSelection(input.logger, {
135
+ fallbackReason,
136
+ mode: input.mode,
137
+ selectedAccount: fallbackSelection.selectedAccount,
138
+ selectedBy: fallbackSelection.selectedBy,
139
+ });
140
+ return {
141
+ entries: createExperimentalEntries({
142
+ defaultAccount: input.defaultAccount,
143
+ probeResults,
144
+ selectedAccount: fallbackSelection.selectedAccount,
145
+ selectedCandidateIds: [],
146
+ }),
147
+ executionBlockedReason: fallbackSelection.executionBlockedReason,
148
+ fallbackReason,
149
+ mode: input.mode,
150
+ selectedAccount: fallbackSelection.selectedAccount,
151
+ selectedBy: fallbackSelection.selectedBy,
152
+ strategy: input.strategy,
153
+ };
154
+ }
155
+ const successfulProbes = probeResults.filter((entry) => entry.ok);
156
+ const candidates = successfulProbes
157
+ .filter((entry) => entry.snapshot.status === "usable")
158
+ .sort((left, right) => compareExperimentalCandidates({
159
+ defaultAccountId: input.defaultAccount?.id ?? null,
160
+ left,
161
+ registryOrder: input.accounts,
162
+ right,
163
+ }));
164
+ input.logger.info("selection.experimental_ranked", {
165
+ candidateOrder: candidates.map((entry) => ({
166
+ accountId: entry.account.id,
167
+ label: entry.account.label,
168
+ primaryRemainingPercent: entry.snapshot.dailyRemaining,
169
+ secondaryRemainingPercent: entry.snapshot.weeklyRemaining,
170
+ source: entry.source,
171
+ })),
172
+ defaultAccountId: input.defaultAccount?.id ?? null,
173
+ mode: input.mode,
174
+ rankingSignal: "remaining-percent",
175
+ tieBreakOrder: [
176
+ "primary_remaining_percent_desc",
177
+ "secondary_remaining_percent_desc",
178
+ "default_account",
179
+ "registry_order",
180
+ ],
181
+ });
182
+ const selected = candidates[0];
183
+ if (!selected) {
184
+ const allExhausted = successfulProbes.every((entry) => entry.snapshot.limitReached || entry.snapshot.status === "limit-reached");
185
+ const fallbackReason = allExhausted ? "all-accounts-exhausted" : "ambiguous-usage";
186
+ input.logger.warn(allExhausted
187
+ ? "selection.experimental_fallback_all_accounts_exhausted"
188
+ : "selection.experimental_fallback_ambiguous_usage", {
189
+ mode: input.mode,
190
+ usableProbeCount: candidates.length,
191
+ probeStatuses: successfulProbes.map((entry) => ({
192
+ accountId: entry.account.id,
193
+ snapshotStatus: entry.snapshot.status,
194
+ limitReached: entry.snapshot.limitReached,
195
+ dailyRemaining: entry.snapshot.dailyRemaining,
196
+ weeklyRemaining: entry.snapshot.weeklyRemaining,
197
+ })),
198
+ });
199
+ const fallbackSelection = await resolveManualDefaultSelection({
200
+ accounts: input.accounts,
201
+ fallbackReason,
202
+ logger: input.logger,
203
+ mode: input.mode,
204
+ registry: input.registry,
205
+ strategy: input.strategy,
206
+ });
207
+ logExperimentalFallbackSelection(input.logger, {
208
+ fallbackReason,
209
+ mode: input.mode,
210
+ selectedAccount: fallbackSelection.selectedAccount,
211
+ selectedBy: fallbackSelection.selectedBy,
212
+ });
213
+ return {
214
+ entries: createExperimentalEntries({
215
+ defaultAccount: input.defaultAccount,
216
+ probeResults,
217
+ selectedAccount: fallbackSelection.selectedAccount,
218
+ selectedCandidateIds: [],
219
+ }),
220
+ executionBlockedReason: fallbackSelection.executionBlockedReason,
221
+ fallbackReason,
222
+ mode: input.mode,
223
+ selectedAccount: fallbackSelection.selectedAccount,
224
+ selectedBy: fallbackSelection.selectedBy,
225
+ strategy: input.strategy,
226
+ };
227
+ }
228
+ input.logger.info("selection.experimental_selected", {
229
+ accountId: selected.account.id,
230
+ label: selected.account.label,
231
+ primaryRemainingPercent: selected.snapshot.dailyRemaining,
232
+ secondaryRemainingPercent: selected.snapshot.weeklyRemaining,
233
+ source: selected.source,
234
+ mode: input.mode,
235
+ selectedBy: "experimental-ranked",
236
+ rankingSignal: "remaining-percent",
237
+ });
238
+ return {
239
+ entries: createExperimentalEntries({
240
+ defaultAccount: input.defaultAccount,
241
+ probeResults,
242
+ selectedAccount: selected.account,
243
+ selectedCandidateIds: candidates.map((entry) => entry.account.id),
244
+ }),
245
+ executionBlockedReason: null,
246
+ fallbackReason: null,
247
+ mode: input.mode,
248
+ selectedAccount: selected.account,
249
+ selectedBy: "experimental-ranked",
250
+ strategy: input.strategy,
251
+ };
252
+ }
253
+ async function resolveManualDefaultSelection(input) {
254
+ input.logger.debug("selection.manual_default.requirement", {
255
+ mode: input.mode,
256
+ strategy: input.strategy,
257
+ fallbackReason: input.fallbackReason ?? null,
258
+ accountCount: input.accounts.length,
259
+ });
260
+ const defaultAccount = await input.registry.getDefaultAccount();
261
+ if (defaultAccount) {
262
+ input.logger.info("selection.manual_default", {
263
+ accountId: defaultAccount.id,
264
+ label: defaultAccount.label,
265
+ mode: input.mode,
266
+ strategy: input.strategy,
267
+ });
268
+ return {
269
+ executionBlockedReason: null,
270
+ selectedAccount: defaultAccount,
271
+ selectedBy: "manual-default",
272
+ };
273
+ }
274
+ if (input.accounts.length === 1) {
275
+ const [singleAccount] = input.accounts;
276
+ if (!singleAccount) {
277
+ throw new Error("No accounts configured.");
278
+ }
279
+ input.logger.info("selection.manual_default_fallback_single", {
280
+ accountId: singleAccount.id,
281
+ label: singleAccount.label,
282
+ mode: input.mode,
283
+ strategy: input.strategy,
284
+ });
285
+ return {
286
+ executionBlockedReason: null,
287
+ selectedAccount: await input.registry.selectAccount(singleAccount.id),
288
+ selectedBy: "manual-default-fallback-single",
289
+ };
290
+ }
291
+ const executionBlockedReason = "Multiple accounts are configured but no default account is selected. Use `codexes account use <account-id-or-label>` first.";
292
+ input.logger.warn("selection.manual_default_missing", {
293
+ accountCount: input.accounts.length,
294
+ mode: input.mode,
295
+ strategy: input.strategy,
296
+ fallbackReason: input.fallbackReason ?? null,
297
+ });
298
+ if (input.mode === "display-only") {
299
+ input.logger.info("selection.display_only_missing_execution_account", {
300
+ accountCount: input.accounts.length,
301
+ strategy: input.strategy,
302
+ fallbackReason: input.fallbackReason ?? null,
303
+ });
304
+ return {
305
+ executionBlockedReason,
306
+ selectedAccount: null,
307
+ selectedBy: null,
308
+ };
309
+ }
310
+ input.logger.warn("selection.execution_blocked_missing_default", {
311
+ accountCount: input.accounts.length,
312
+ strategy: input.strategy,
313
+ fallbackReason: input.fallbackReason ?? null,
314
+ });
315
+ throw new Error(executionBlockedReason);
316
+ }
317
+ async function selectSingleAccountOnly(registry, logger, accounts, mode) {
318
+ logger.debug("selection.single_account.requirement", {
319
+ mode,
320
+ accountCount: accounts.length,
321
+ });
322
+ if (accounts.length !== 1) {
323
+ logger.warn("selection.single_account_invalid", {
324
+ accountCount: accounts.length,
325
+ mode,
326
+ });
327
+ throw new Error("The single-account strategy requires exactly one configured account.");
328
+ }
329
+ const [singleAccount] = accounts;
330
+ if (!singleAccount) {
331
+ throw new Error("No accounts configured.");
332
+ }
333
+ logger.info("selection.single_account", {
334
+ accountId: singleAccount.id,
335
+ label: singleAccount.label,
336
+ mode,
337
+ });
338
+ const defaultAccount = await registry.getDefaultAccount();
339
+ if (defaultAccount?.id === singleAccount.id) {
340
+ return singleAccount;
341
+ }
342
+ return registry.selectAccount(singleAccount.id);
343
+ }
344
+ function createUnavailableEntries(accounts, defaultAccount, selectedAccount) {
345
+ return accounts.map((account) => ({
346
+ account,
347
+ failureCategory: null,
348
+ failureMessage: null,
349
+ isDefault: account.id === defaultAccount?.id,
350
+ isEligibleForRanking: false,
351
+ isSelected: account.id === selectedAccount?.id,
352
+ rankingPosition: null,
353
+ snapshot: null,
354
+ source: "unavailable",
355
+ }));
356
+ }
357
+ function createExperimentalEntries(input) {
358
+ return input.probeResults.map((entry) => ({
359
+ account: entry.account,
360
+ failureCategory: entry.ok ? null : entry.category,
361
+ failureMessage: entry.ok ? null : entry.message,
362
+ isDefault: entry.account.id === input.defaultAccount?.id,
363
+ isEligibleForRanking: entry.ok && entry.snapshot.status === "usable",
364
+ isSelected: entry.account.id === input.selectedAccount?.id,
365
+ rankingPosition: entry.ok ? resolveRankingPosition(input.selectedCandidateIds, entry.account.id) : null,
366
+ snapshot: entry.ok ? entry.snapshot : null,
367
+ source: entry.ok ? entry.source : "fresh",
368
+ }));
369
+ }
370
+ function resolveRankingPosition(selectedCandidateIds, accountId) {
371
+ const index = selectedCandidateIds.indexOf(accountId);
372
+ if (index < 0) {
373
+ return null;
374
+ }
375
+ return index + 1;
376
+ }
377
+ function compareExperimentalCandidates(input) {
378
+ const dailyDelta = (input.right.snapshot.dailyRemaining ?? Number.NEGATIVE_INFINITY) -
379
+ (input.left.snapshot.dailyRemaining ?? Number.NEGATIVE_INFINITY);
380
+ if (dailyDelta !== 0) {
381
+ return dailyDelta;
382
+ }
383
+ const weeklyDelta = (input.right.snapshot.weeklyRemaining ?? Number.NEGATIVE_INFINITY) -
384
+ (input.left.snapshot.weeklyRemaining ?? Number.NEGATIVE_INFINITY);
385
+ if (weeklyDelta !== 0) {
386
+ return weeklyDelta;
387
+ }
388
+ const leftIsDefault = input.left.account.id === input.defaultAccountId;
389
+ const rightIsDefault = input.right.account.id === input.defaultAccountId;
390
+ if (leftIsDefault !== rightIsDefault) {
391
+ return leftIsDefault ? -1 : 1;
392
+ }
393
+ return (input.registryOrder.findIndex((account) => account.id === input.left.account.id) -
394
+ input.registryOrder.findIndex((account) => account.id === input.right.account.id));
395
+ }
396
+ function logExperimentalFallbackSelection(logger, input) {
397
+ logger.info("selection.experimental_fallback_selected", {
398
+ fallbackReason: input.fallbackReason,
399
+ mode: input.mode,
400
+ selectedAccountId: input.selectedAccount?.id ?? null,
401
+ selectedBy: input.selectedBy,
402
+ rankingSignal: input.selectedBy === null ? null : "manual-default-fallback",
403
+ });
404
+ }
405
+ //# sourceMappingURL=selection-summary.js.map