@mostok/codexes 0.1.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/LICENSE +15 -0
- package/README.md +88 -0
- package/dist/accounts/account-registry.d.ts +30 -0
- package/dist/accounts/account-registry.js +263 -0
- package/dist/accounts/account-registry.js.map +1 -0
- package/dist/accounts/account-resolution.d.ts +16 -0
- package/dist/accounts/account-resolution.js +71 -0
- package/dist/accounts/account-resolution.js.map +1 -0
- package/dist/accounts/resolve-active-account.d.ts +6 -0
- package/dist/accounts/resolve-active-account.js +32 -0
- package/dist/accounts/resolve-active-account.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3426 -0
- package/dist/cli.js.map +7 -0
- package/dist/commands/account-add/run-account-add-command.d.ts +2 -0
- package/dist/commands/account-add/run-account-add-command.js +296 -0
- package/dist/commands/account-add/run-account-add-command.js.map +1 -0
- package/dist/commands/account-list/run-account-list-command.d.ts +2 -0
- package/dist/commands/account-list/run-account-list-command.js +48 -0
- package/dist/commands/account-list/run-account-list-command.js.map +1 -0
- package/dist/commands/account-remove/run-account-remove-command.d.ts +2 -0
- package/dist/commands/account-remove/run-account-remove-command.js +52 -0
- package/dist/commands/account-remove/run-account-remove-command.js.map +1 -0
- package/dist/commands/account-use/run-account-use-command.d.ts +2 -0
- package/dist/commands/account-use/run-account-use-command.js +78 -0
- package/dist/commands/account-use/run-account-use-command.js.map +1 -0
- package/dist/commands/root/run-root-command.d.ts +2 -0
- package/dist/commands/root/run-root-command.js +175 -0
- package/dist/commands/root/run-root-command.js.map +1 -0
- package/dist/config/wrapper-config.d.ts +24 -0
- package/dist/config/wrapper-config.js +145 -0
- package/dist/config/wrapper-config.js.map +1 -0
- package/dist/core/bootstrap.d.ts +8 -0
- package/dist/core/bootstrap.js +32 -0
- package/dist/core/bootstrap.js.map +1 -0
- package/dist/core/context.d.ts +33 -0
- package/dist/core/context.js +72 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/paths.d.ts +12 -0
- package/dist/core/paths.js +30 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/logging/logger.d.ts +18 -0
- package/dist/logging/logger.js +56 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/process/codex-launch-spec.d.ts +5 -0
- package/dist/process/codex-launch-spec.js +80 -0
- package/dist/process/codex-launch-spec.js.map +1 -0
- package/dist/process/find-codex-binary.d.ts +14 -0
- package/dist/process/find-codex-binary.js +73 -0
- package/dist/process/find-codex-binary.js.map +1 -0
- package/dist/process/run-codex-login.d.ts +14 -0
- package/dist/process/run-codex-login.js +97 -0
- package/dist/process/run-codex-login.js.map +1 -0
- package/dist/process/spawn-codex-command.d.ts +7 -0
- package/dist/process/spawn-codex-command.js +69 -0
- package/dist/process/spawn-codex-command.js.map +1 -0
- package/dist/runtime/activate-account/activate-account.d.ts +27 -0
- package/dist/runtime/activate-account/activate-account.js +298 -0
- package/dist/runtime/activate-account/activate-account.js.map +1 -0
- package/dist/runtime/auth-state-probe.d.ts +57 -0
- package/dist/runtime/auth-state-probe.js +394 -0
- package/dist/runtime/auth-state-probe.js.map +1 -0
- package/dist/runtime/init/initialize-runtime.d.ts +19 -0
- package/dist/runtime/init/initialize-runtime.js +275 -0
- package/dist/runtime/init/initialize-runtime.js.map +1 -0
- package/dist/runtime/lock/runtime-lock.d.ts +11 -0
- package/dist/runtime/lock/runtime-lock.js +99 -0
- package/dist/runtime/lock/runtime-lock.js.map +1 -0
- package/dist/runtime/login-workspace.d.ts +18 -0
- package/dist/runtime/login-workspace.js +171 -0
- package/dist/runtime/login-workspace.js.map +1 -0
- package/dist/runtime/runtime-contract.d.ts +44 -0
- package/dist/runtime/runtime-contract.js +79 -0
- package/dist/runtime/runtime-contract.js.map +1 -0
- package/dist/selection/account-auth-state.d.ts +23 -0
- package/dist/selection/account-auth-state.js +132 -0
- package/dist/selection/account-auth-state.js.map +1 -0
- package/dist/selection/select-account.d.ts +11 -0
- package/dist/selection/select-account.js +168 -0
- package/dist/selection/select-account.js.map +1 -0
- package/dist/selection/usage-cache.d.ts +24 -0
- package/dist/selection/usage-cache.js +106 -0
- package/dist/selection/usage-cache.js.map +1 -0
- package/dist/selection/usage-client.d.ts +23 -0
- package/dist/selection/usage-client.js +143 -0
- package/dist/selection/usage-client.js.map +1 -0
- package/dist/selection/usage-normalize.d.ts +7 -0
- package/dist/selection/usage-normalize.js +209 -0
- package/dist/selection/usage-normalize.js.map +1 -0
- package/dist/selection/usage-probe-coordinator.d.ts +18 -0
- package/dist/selection/usage-probe-coordinator.js +69 -0
- package/dist/selection/usage-probe-coordinator.js.map +1 -0
- package/dist/selection/usage-types.d.ts +59 -0
- package/dist/selection/usage-types.js +2 -0
- package/dist/selection/usage-types.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function createRuntimeContract(input) {
|
|
3
|
+
const contract = {
|
|
4
|
+
credentialStoreMode: input.credentialStoreMode,
|
|
5
|
+
sharedCodexHome: input.sharedCodexHome,
|
|
6
|
+
runtimeRoot: input.runtimeRoot,
|
|
7
|
+
perAccountRoot: input.accountRoot,
|
|
8
|
+
supported: input.credentialStoreMode === "file",
|
|
9
|
+
fileRules: [
|
|
10
|
+
createRule("config.toml", "shared", "never", "Shared CLI behavior and MCP config should remain common."),
|
|
11
|
+
createRule("mcp.json", "shared", "never", "MCP topology is shared across accounts."),
|
|
12
|
+
createRule("trust/**", "shared", "never", "Trust metadata should not be overwritten per account."),
|
|
13
|
+
createRule("auth.json", "account", "if-changed", "Windows probe evidence shows auth.json is sufficient for `codex login status`, so it belongs to the active account profile."),
|
|
14
|
+
createRule("sessions/**", "account", "if-changed", "Session refresh artifacts are still treated as account-scoped until a real token-refresh probe proves otherwise."),
|
|
15
|
+
createRule("cache/**", "ephemeral", "never", "Transient caches should be recreated instead of copied."),
|
|
16
|
+
createRule("logs/**", "ephemeral", "never", "Runtime logs are diagnostic and should not sync back."),
|
|
17
|
+
createRule("history.jsonl", "ephemeral", "never", "Conversation history should stay local to each runtime session."),
|
|
18
|
+
createRule("models_cache.json", "ephemeral", "never", "Model cache data can be rebuilt and should not drive account switching."),
|
|
19
|
+
createRule("tmp/**", "ephemeral", "never", "Temporary files should be discarded after each run."),
|
|
20
|
+
createRule("state_*.sqlite*", "protected", "never", "Observed SQLite runtime state exists in the live Codex home and remains unproven for cross-account merge or sync-back."),
|
|
21
|
+
createRule("logs_*.sqlite*", "protected", "never", "SQLite-backed log databases should stay isolated until a dedicated write-heavy probe proves they are safe to discard or share."),
|
|
22
|
+
createRule("keyring/**", "protected", "never", "External credential stores are explicitly unsupported for MVP."),
|
|
23
|
+
],
|
|
24
|
+
syncBackStrategy: {
|
|
25
|
+
whenChildProcessSucceeds: "Compare allowed account-classified files and sync only changed files back to the owning account profile.",
|
|
26
|
+
whenChildProcessFails: "Restore pre-launch runtime state and avoid syncing ambiguous mutations unless the failure is known-safe.",
|
|
27
|
+
compareStrategy: "Use file existence, modified time, and content hash checks before any sync-back write.",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
input.logger.info("runtime.contract_created", {
|
|
31
|
+
sharedCodexHome: contract.sharedCodexHome,
|
|
32
|
+
runtimeRoot: contract.runtimeRoot,
|
|
33
|
+
perAccountRoot: contract.perAccountRoot,
|
|
34
|
+
credentialStoreMode: contract.credentialStoreMode,
|
|
35
|
+
supported: contract.supported,
|
|
36
|
+
});
|
|
37
|
+
input.logger.debug("runtime.file_rules", {
|
|
38
|
+
fileRules: contract.fileRules,
|
|
39
|
+
syncBackStrategy: contract.syncBackStrategy,
|
|
40
|
+
});
|
|
41
|
+
return contract;
|
|
42
|
+
}
|
|
43
|
+
export function resolveAccountRuntimePaths(contract, accountId) {
|
|
44
|
+
const accountDirectory = path.join(contract.perAccountRoot, accountId);
|
|
45
|
+
return {
|
|
46
|
+
accountDirectory,
|
|
47
|
+
accountStateDirectory: path.join(accountDirectory, "state"),
|
|
48
|
+
accountMetadataFile: path.join(accountDirectory, "account.json"),
|
|
49
|
+
runtimeBackupDirectory: path.join(contract.runtimeRoot, "backups", accountId),
|
|
50
|
+
runtimeTempDirectory: path.join(contract.runtimeRoot, "tmp", accountId),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function summarizeRuntimeContract(contract) {
|
|
54
|
+
return {
|
|
55
|
+
supported: contract.supported,
|
|
56
|
+
credentialStoreMode: contract.credentialStoreMode,
|
|
57
|
+
sharedCodexHome: contract.sharedCodexHome,
|
|
58
|
+
runtimeRoot: contract.runtimeRoot,
|
|
59
|
+
perAccountRoot: contract.perAccountRoot,
|
|
60
|
+
classifications: contract.fileRules.reduce((accumulator, rule) => {
|
|
61
|
+
accumulator[rule.classification] += 1;
|
|
62
|
+
return accumulator;
|
|
63
|
+
}, {
|
|
64
|
+
shared: 0,
|
|
65
|
+
account: 0,
|
|
66
|
+
ephemeral: 0,
|
|
67
|
+
protected: 0,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function createRule(pathPattern, classification, syncBack, reason) {
|
|
72
|
+
return {
|
|
73
|
+
pathPattern,
|
|
74
|
+
classification,
|
|
75
|
+
syncBack,
|
|
76
|
+
reason,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=runtime-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-contract.js","sourceRoot":"","sources":["../../src/runtime/runtime-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AccountRecord } from "../accounts/account-registry.js";
|
|
2
|
+
import type { Logger } from "../logging/logger.js";
|
|
3
|
+
export type AccountAuthStateFailureCategory = "missing-file" | "malformed-json" | "missing-access-token" | "unsupported-auth-shape";
|
|
4
|
+
export interface AccountAuthState {
|
|
5
|
+
accessToken: string;
|
|
6
|
+
accountId: string | null;
|
|
7
|
+
authMode: string | null;
|
|
8
|
+
lastRefresh: string | null;
|
|
9
|
+
}
|
|
10
|
+
export type AccountAuthStateReadResult = {
|
|
11
|
+
ok: true;
|
|
12
|
+
filePath: string;
|
|
13
|
+
state: AccountAuthState;
|
|
14
|
+
} | {
|
|
15
|
+
ok: false;
|
|
16
|
+
category: AccountAuthStateFailureCategory;
|
|
17
|
+
filePath: string;
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function readAccountAuthState(input: {
|
|
21
|
+
account: AccountRecord;
|
|
22
|
+
logger: Logger;
|
|
23
|
+
}): Promise<AccountAuthStateReadResult>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function readAccountAuthState(input) {
|
|
4
|
+
const filePath = path.join(input.account.authDirectory, "state", "auth.json");
|
|
5
|
+
input.logger.debug("selection.account_auth_state.read_start", {
|
|
6
|
+
accountId: input.account.id,
|
|
7
|
+
label: input.account.label,
|
|
8
|
+
filePath,
|
|
9
|
+
});
|
|
10
|
+
try {
|
|
11
|
+
const raw = await readFile(filePath, "utf8");
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
if (!isRecord(parsed)) {
|
|
14
|
+
input.logger.warn("selection.account_auth_state.unsupported_shape", {
|
|
15
|
+
accountId: input.account.id,
|
|
16
|
+
label: input.account.label,
|
|
17
|
+
filePath,
|
|
18
|
+
topLevelType: typeof parsed,
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
category: "unsupported-auth-shape",
|
|
23
|
+
filePath,
|
|
24
|
+
message: "auth.json is not a JSON object.",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const accessToken = resolveString(parsed.access_token, getNestedString(parsed, ["tokens", "access_token"]), getNestedString(parsed, ["tokens", "accessToken"]));
|
|
28
|
+
if (!accessToken) {
|
|
29
|
+
input.logger.warn("selection.account_auth_state.access_token_missing", {
|
|
30
|
+
accountId: input.account.id,
|
|
31
|
+
label: input.account.label,
|
|
32
|
+
filePath,
|
|
33
|
+
hasTokensObject: isRecord(parsed.tokens),
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
category: "missing-access-token",
|
|
38
|
+
filePath,
|
|
39
|
+
message: "auth.json does not contain an access_token.",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const result = {
|
|
43
|
+
ok: true,
|
|
44
|
+
filePath,
|
|
45
|
+
state: {
|
|
46
|
+
accessToken,
|
|
47
|
+
accountId: resolveString(parsed.account_id, parsed.accountId, getNestedString(parsed, ["tokens", "account_id"]), getNestedString(parsed, ["tokens", "accountId"])),
|
|
48
|
+
authMode: resolveString(parsed.auth_mode, parsed.authMode, getNestedString(parsed, ["tokens", "auth_mode"]), getNestedString(parsed, ["tokens", "authMode"])),
|
|
49
|
+
lastRefresh: resolveString(parsed.last_refresh, parsed.lastRefresh, parsed.refresh_at, parsed.refreshAt),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
input.logger.debug("selection.account_auth_state.read_complete", {
|
|
53
|
+
accountId: input.account.id,
|
|
54
|
+
label: input.account.label,
|
|
55
|
+
filePath,
|
|
56
|
+
hasAccessToken: true,
|
|
57
|
+
authAccountId: result.state.accountId,
|
|
58
|
+
authMode: result.state.authMode,
|
|
59
|
+
hasRefreshMetadata: result.state.lastRefresh !== null,
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (isNodeErrorWithCode(error, "ENOENT")) {
|
|
65
|
+
input.logger.warn("selection.account_auth_state.missing_file", {
|
|
66
|
+
accountId: input.account.id,
|
|
67
|
+
label: input.account.label,
|
|
68
|
+
filePath,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
category: "missing-file",
|
|
73
|
+
filePath,
|
|
74
|
+
message: "auth.json was not found for the account profile.",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (error instanceof SyntaxError) {
|
|
78
|
+
input.logger.warn("selection.account_auth_state.malformed_json", {
|
|
79
|
+
accountId: input.account.id,
|
|
80
|
+
label: input.account.label,
|
|
81
|
+
filePath,
|
|
82
|
+
message: error.message,
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
category: "malformed-json",
|
|
87
|
+
filePath,
|
|
88
|
+
message: error.message,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
input.logger.warn("selection.account_auth_state.unsupported_shape", {
|
|
92
|
+
accountId: input.account.id,
|
|
93
|
+
label: input.account.label,
|
|
94
|
+
filePath,
|
|
95
|
+
message: error instanceof Error ? error.message : String(error),
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
category: "unsupported-auth-shape",
|
|
100
|
+
filePath,
|
|
101
|
+
message: error instanceof Error ? error.message : String(error),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function getNestedString(value, pathParts) {
|
|
106
|
+
let current = value;
|
|
107
|
+
for (const part of pathParts) {
|
|
108
|
+
if (!isRecord(current) || typeof current[part] === "undefined") {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
current = current[part];
|
|
112
|
+
}
|
|
113
|
+
return typeof current === "string" && current.trim().length > 0 ? current : null;
|
|
114
|
+
}
|
|
115
|
+
function resolveString(...values) {
|
|
116
|
+
for (const value of values) {
|
|
117
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
function isRecord(value) {
|
|
124
|
+
return typeof value === "object" && value !== null;
|
|
125
|
+
}
|
|
126
|
+
function isNodeErrorWithCode(error, code) {
|
|
127
|
+
return (typeof error === "object" &&
|
|
128
|
+
error !== null &&
|
|
129
|
+
"code" in error &&
|
|
130
|
+
error.code === code);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=account-auth-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-auth-state.js","sourceRoot":"","sources":["../../src/selection/account-auth-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AccountRegistry, AccountRecord } from "../accounts/account-registry.js";
|
|
2
|
+
import type { AccountSelectionStrategy, ExperimentalSelectionConfig } from "../config/wrapper-config.js";
|
|
3
|
+
import type { Logger } from "../logging/logger.js";
|
|
4
|
+
export declare function selectAccountForExecution(input: {
|
|
5
|
+
experimentalSelection?: ExperimentalSelectionConfig;
|
|
6
|
+
fetchImpl?: typeof fetch;
|
|
7
|
+
logger: Logger;
|
|
8
|
+
registry: AccountRegistry;
|
|
9
|
+
selectionCacheFilePath?: string;
|
|
10
|
+
strategy: AccountSelectionStrategy;
|
|
11
|
+
}): Promise<AccountRecord>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { resolveAccountUsageSnapshots } from "./usage-probe-coordinator.js";
|
|
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,
|
|
7
|
+
});
|
|
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>`.");
|
|
11
|
+
}
|
|
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));
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=select-account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-account.js","sourceRoot":"","sources":["../../src/selection/select-account.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Logger } from "../logging/logger.js";
|
|
2
|
+
import type { NormalizedUsageSnapshot } from "./usage-types.js";
|
|
3
|
+
export interface UsageCacheEntry {
|
|
4
|
+
accountId: string;
|
|
5
|
+
accountLabel: string;
|
|
6
|
+
cachedAt: string;
|
|
7
|
+
snapshot: NormalizedUsageSnapshot;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadUsageCache(input: {
|
|
10
|
+
cacheFilePath: string;
|
|
11
|
+
logger: Logger;
|
|
12
|
+
}): Promise<UsageCacheEntry[]>;
|
|
13
|
+
export declare function persistUsageCache(input: {
|
|
14
|
+
cacheFilePath: string;
|
|
15
|
+
entries: UsageCacheEntry[];
|
|
16
|
+
logger: Logger;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function resolveFreshUsageCacheEntry(input: {
|
|
19
|
+
accountId: string;
|
|
20
|
+
entries: UsageCacheEntry[];
|
|
21
|
+
logger: Logger;
|
|
22
|
+
now: number;
|
|
23
|
+
ttlMs: number;
|
|
24
|
+
}): UsageCacheEntry | null;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const USAGE_CACHE_SCHEMA_VERSION = 1;
|
|
4
|
+
export async function loadUsageCache(input) {
|
|
5
|
+
try {
|
|
6
|
+
const raw = await readFile(input.cacheFilePath, "utf8");
|
|
7
|
+
const parsed = JSON.parse(raw);
|
|
8
|
+
const normalized = normalizeUsageCacheDocument(parsed);
|
|
9
|
+
input.logger.debug("selection.usage_cache.load_success", {
|
|
10
|
+
cacheFilePath: input.cacheFilePath,
|
|
11
|
+
entryCount: normalized.entries.length,
|
|
12
|
+
});
|
|
13
|
+
return normalized.entries;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (isNodeErrorWithCode(error, "ENOENT")) {
|
|
17
|
+
input.logger.debug("selection.usage_cache.missing", {
|
|
18
|
+
cacheFilePath: input.cacheFilePath,
|
|
19
|
+
});
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
const backupPath = `${input.cacheFilePath}.corrupt-${Date.now()}`;
|
|
23
|
+
await rename(input.cacheFilePath, backupPath).catch(() => undefined);
|
|
24
|
+
input.logger.warn("selection.usage_cache.corrupt", {
|
|
25
|
+
cacheFilePath: input.cacheFilePath,
|
|
26
|
+
backupPath,
|
|
27
|
+
message: error instanceof Error ? error.message : String(error),
|
|
28
|
+
});
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function persistUsageCache(input) {
|
|
33
|
+
await mkdir(path.dirname(input.cacheFilePath), { recursive: true });
|
|
34
|
+
const document = {
|
|
35
|
+
schemaVersion: USAGE_CACHE_SCHEMA_VERSION,
|
|
36
|
+
entries: input.entries,
|
|
37
|
+
};
|
|
38
|
+
const tempFile = `${input.cacheFilePath}.tmp`;
|
|
39
|
+
const serialized = JSON.stringify(document, null, 2);
|
|
40
|
+
await writeFile(tempFile, serialized, "utf8");
|
|
41
|
+
await rename(tempFile, input.cacheFilePath);
|
|
42
|
+
input.logger.debug("selection.usage_cache.persisted", {
|
|
43
|
+
cacheFilePath: input.cacheFilePath,
|
|
44
|
+
entryCount: input.entries.length,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
export function resolveFreshUsageCacheEntry(input) {
|
|
48
|
+
const entry = input.entries.find((candidate) => candidate.accountId === input.accountId) ?? null;
|
|
49
|
+
if (!entry) {
|
|
50
|
+
input.logger.debug("selection.usage_cache.miss", {
|
|
51
|
+
accountId: input.accountId,
|
|
52
|
+
ttlMs: input.ttlMs,
|
|
53
|
+
});
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const ageMs = input.now - new Date(entry.cachedAt).valueOf();
|
|
57
|
+
if (!Number.isFinite(ageMs) || ageMs > input.ttlMs) {
|
|
58
|
+
input.logger.debug("selection.usage_cache.expired", {
|
|
59
|
+
accountId: input.accountId,
|
|
60
|
+
cachedAt: entry.cachedAt,
|
|
61
|
+
ageMs: Number.isFinite(ageMs) ? ageMs : null,
|
|
62
|
+
ttlMs: input.ttlMs,
|
|
63
|
+
});
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
input.logger.debug("selection.usage_cache.hit", {
|
|
67
|
+
accountId: input.accountId,
|
|
68
|
+
cachedAt: entry.cachedAt,
|
|
69
|
+
ageMs,
|
|
70
|
+
ttlMs: input.ttlMs,
|
|
71
|
+
});
|
|
72
|
+
return entry;
|
|
73
|
+
}
|
|
74
|
+
function normalizeUsageCacheDocument(value) {
|
|
75
|
+
if (!isRecord(value)) {
|
|
76
|
+
throw new Error("Usage cache document is not an object.");
|
|
77
|
+
}
|
|
78
|
+
const schemaVersion = typeof value.schemaVersion === "number" ? value.schemaVersion : USAGE_CACHE_SCHEMA_VERSION;
|
|
79
|
+
if (schemaVersion !== USAGE_CACHE_SCHEMA_VERSION) {
|
|
80
|
+
throw new Error(`Unsupported usage cache schema version ${schemaVersion}.`);
|
|
81
|
+
}
|
|
82
|
+
const entries = Array.isArray(value.entries)
|
|
83
|
+
? value.entries.filter(isUsageCacheEntry)
|
|
84
|
+
: [];
|
|
85
|
+
return {
|
|
86
|
+
schemaVersion: USAGE_CACHE_SCHEMA_VERSION,
|
|
87
|
+
entries,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function isUsageCacheEntry(value) {
|
|
91
|
+
return (isRecord(value) &&
|
|
92
|
+
typeof value.accountId === "string" &&
|
|
93
|
+
typeof value.accountLabel === "string" &&
|
|
94
|
+
typeof value.cachedAt === "string" &&
|
|
95
|
+
isRecord(value.snapshot));
|
|
96
|
+
}
|
|
97
|
+
function isRecord(value) {
|
|
98
|
+
return typeof value === "object" && value !== null;
|
|
99
|
+
}
|
|
100
|
+
function isNodeErrorWithCode(error, code) {
|
|
101
|
+
return (typeof error === "object" &&
|
|
102
|
+
error !== null &&
|
|
103
|
+
"code" in error &&
|
|
104
|
+
error.code === code);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=usage-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-cache.js","sourceRoot":"","sources":["../../src/selection/usage-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AccountRecord } from "../accounts/account-registry.js";
|
|
2
|
+
import type { ExperimentalSelectionConfig } from "../config/wrapper-config.js";
|
|
3
|
+
import type { Logger } from "../logging/logger.js";
|
|
4
|
+
import type { NormalizedUsageSnapshot } from "./usage-types.js";
|
|
5
|
+
export type UsageProbeFailureCategory = "auth-missing" | "timeout" | "http-error" | "invalid-response";
|
|
6
|
+
export type AccountUsageProbeResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
account: AccountRecord;
|
|
9
|
+
snapshot: NormalizedUsageSnapshot;
|
|
10
|
+
source: "fresh";
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
account: AccountRecord;
|
|
14
|
+
category: UsageProbeFailureCategory;
|
|
15
|
+
message: string;
|
|
16
|
+
source: "fresh";
|
|
17
|
+
};
|
|
18
|
+
export declare function probeAccountUsage(input: {
|
|
19
|
+
account: AccountRecord;
|
|
20
|
+
fetchImpl?: typeof fetch;
|
|
21
|
+
logger: Logger;
|
|
22
|
+
probeConfig: ExperimentalSelectionConfig;
|
|
23
|
+
}): Promise<AccountUsageProbeResult>;
|