oc-codex-multi-auth 6.0.0 → 6.1.1
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 +1 -1
- package/README.md +56 -18
- package/assets/readme-hero.svg +10 -10
- package/config/README.md +1 -1
- package/config/minimal-opencode.json +1 -1
- package/config/opencode-legacy.json +1 -1
- package/config/opencode-modern.json +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -2525
- package/dist/index.js.map +1 -1
- package/dist/lib/accounts/persistence.d.ts +34 -0
- package/dist/lib/accounts/persistence.d.ts.map +1 -0
- package/dist/lib/accounts/persistence.js +153 -0
- package/dist/lib/accounts/persistence.js.map +1 -0
- package/dist/lib/accounts/recovery.d.ts +59 -0
- package/dist/lib/accounts/recovery.d.ts.map +1 -0
- package/dist/lib/accounts/recovery.js +229 -0
- package/dist/lib/accounts/recovery.js.map +1 -0
- package/dist/lib/accounts/rotation.d.ts +40 -0
- package/dist/lib/accounts/rotation.d.ts.map +1 -0
- package/dist/lib/accounts/rotation.js +204 -0
- package/dist/lib/accounts/rotation.js.map +1 -0
- package/dist/lib/accounts/state.d.ts +92 -0
- package/dist/lib/accounts/state.d.ts.map +1 -0
- package/dist/lib/accounts/state.js +366 -0
- package/dist/lib/accounts/state.js.map +1 -0
- package/dist/lib/accounts.d.ts +48 -91
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +121 -699
- package/dist/lib/accounts.js.map +1 -1
- package/dist/lib/auth/auth.d.ts +1 -1
- package/dist/lib/auth/auth.d.ts.map +1 -1
- package/dist/lib/auth/auth.js +5 -2
- package/dist/lib/auth/auth.js.map +1 -1
- package/dist/lib/auth/login-runner.d.ts +32 -0
- package/dist/lib/auth/login-runner.d.ts.map +1 -1
- package/dist/lib/auth/login-runner.js +79 -64
- package/dist/lib/auth/login-runner.js.map +1 -1
- package/dist/lib/auth/server.d.ts.map +1 -1
- package/dist/lib/auth/server.js +3 -8
- package/dist/lib/auth/server.js.map +1 -1
- package/dist/lib/circuit-breaker.d.ts +53 -2
- package/dist/lib/circuit-breaker.d.ts.map +1 -1
- package/dist/lib/circuit-breaker.js +65 -6
- package/dist/lib/circuit-breaker.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +77 -32
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/error-sentinels.d.ts +20 -0
- package/dist/lib/error-sentinels.d.ts.map +1 -0
- package/dist/lib/error-sentinels.js +28 -0
- package/dist/lib/error-sentinels.js.map +1 -0
- package/dist/lib/errors.d.ts +100 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +116 -1
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/logger.d.ts +14 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +65 -5
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/oauth-constants.d.ts +18 -0
- package/dist/lib/oauth-constants.d.ts.map +1 -0
- package/dist/lib/oauth-constants.js +18 -0
- package/dist/lib/oauth-constants.js.map +1 -0
- package/dist/lib/oauth-success.d.ts +2 -0
- package/dist/lib/oauth-success.d.ts.map +1 -0
- package/dist/lib/oauth-success.html +711 -711
- package/dist/lib/oauth-success.js +714 -0
- package/dist/lib/oauth-success.js.map +1 -0
- package/dist/lib/prompts/codex.d.ts.map +1 -1
- package/dist/lib/prompts/codex.js +12 -3
- package/dist/lib/prompts/codex.js.map +1 -1
- package/dist/lib/prompts/opencode-codex.d.ts.map +1 -1
- package/dist/lib/prompts/opencode-codex.js +3 -2
- package/dist/lib/prompts/opencode-codex.js.map +1 -1
- package/dist/lib/recovery/hook.d.ts +43 -0
- package/dist/lib/recovery/hook.d.ts.map +1 -0
- package/dist/lib/recovery/hook.js +325 -0
- package/dist/lib/recovery/hook.js.map +1 -0
- package/dist/lib/recovery/index.d.ts +1 -0
- package/dist/lib/recovery/index.d.ts.map +1 -1
- package/dist/lib/recovery/index.js +1 -0
- package/dist/lib/recovery/index.js.map +1 -1
- package/dist/lib/recovery/storage.d.ts.map +1 -1
- package/dist/lib/recovery/storage.js +5 -1
- package/dist/lib/recovery/storage.js.map +1 -1
- package/dist/lib/recovery.d.ts +15 -30
- package/dist/lib/recovery.d.ts.map +1 -1
- package/dist/lib/recovery.js +14 -312
- package/dist/lib/recovery.js.map +1 -1
- package/dist/lib/request/fetch-helpers.d.ts +1 -0
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
- package/dist/lib/request/fetch-helpers.js +58 -10
- package/dist/lib/request/fetch-helpers.js.map +1 -1
- package/dist/lib/request/response-handler.d.ts.map +1 -1
- package/dist/lib/request/response-handler.js +8 -2
- package/dist/lib/request/response-handler.js.map +1 -1
- package/dist/lib/runtime.d.ts +101 -0
- package/dist/lib/runtime.d.ts.map +1 -0
- package/dist/lib/runtime.js +77 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/schemas.d.ts +164 -1
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +251 -0
- package/dist/lib/schemas.js.map +1 -1
- package/dist/lib/storage/atomic-write.d.ts +31 -0
- package/dist/lib/storage/atomic-write.d.ts.map +1 -0
- package/dist/lib/storage/atomic-write.js +75 -0
- package/dist/lib/storage/atomic-write.js.map +1 -0
- package/dist/lib/storage/backup.d.ts +13 -0
- package/dist/lib/storage/backup.d.ts.map +1 -0
- package/dist/lib/storage/backup.js +59 -0
- package/dist/lib/storage/backup.js.map +1 -0
- package/dist/lib/storage/errors.d.ts +17 -0
- package/dist/lib/storage/errors.d.ts.map +1 -0
- package/dist/lib/storage/errors.js +38 -0
- package/dist/lib/storage/errors.js.map +1 -0
- package/dist/lib/storage/export-import.d.ts +84 -0
- package/dist/lib/storage/export-import.d.ts.map +1 -0
- package/dist/lib/storage/export-import.js +222 -0
- package/dist/lib/storage/export-import.js.map +1 -0
- package/dist/lib/storage/flagged.d.ts +29 -0
- package/dist/lib/storage/flagged.d.ts.map +1 -0
- package/dist/lib/storage/flagged.js +207 -0
- package/dist/lib/storage/flagged.js.map +1 -0
- package/dist/lib/storage/identity.d.ts +72 -0
- package/dist/lib/storage/identity.d.ts.map +1 -0
- package/dist/lib/storage/identity.js +230 -0
- package/dist/lib/storage/identity.js.map +1 -0
- package/dist/lib/storage/keychain.d.ts +146 -0
- package/dist/lib/storage/keychain.d.ts.map +1 -0
- package/dist/lib/storage/keychain.js +278 -0
- package/dist/lib/storage/keychain.js.map +1 -0
- package/dist/lib/storage/load-save.d.ts +61 -0
- package/dist/lib/storage/load-save.d.ts.map +1 -0
- package/dist/lib/storage/load-save.js +606 -0
- package/dist/lib/storage/load-save.js.map +1 -0
- package/dist/lib/storage/migrations.d.ts +35 -0
- package/dist/lib/storage/migrations.d.ts.map +1 -1
- package/dist/lib/storage/migrations.js +37 -0
- package/dist/lib/storage/migrations.js.map +1 -1
- package/dist/lib/storage/normalize.d.ts +22 -0
- package/dist/lib/storage/normalize.d.ts.map +1 -0
- package/dist/lib/storage/normalize.js +114 -0
- package/dist/lib/storage/normalize.js.map +1 -0
- package/dist/lib/storage/paths.d.ts.map +1 -1
- package/dist/lib/storage/paths.js +2 -1
- package/dist/lib/storage/paths.js.map +1 -1
- package/dist/lib/storage/state.d.ts +46 -0
- package/dist/lib/storage/state.d.ts.map +1 -0
- package/dist/lib/storage/state.js +100 -0
- package/dist/lib/storage/state.js.map +1 -0
- package/dist/lib/storage/worktree-lock.d.ts +79 -0
- package/dist/lib/storage/worktree-lock.d.ts.map +1 -0
- package/dist/lib/storage/worktree-lock.js +265 -0
- package/dist/lib/storage/worktree-lock.js.map +1 -0
- package/dist/lib/storage.d.ts +21 -155
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +24 -1167
- package/dist/lib/storage.js.map +1 -1
- package/dist/lib/tools/_shared.d.ts +16 -0
- package/dist/lib/tools/_shared.d.ts.map +1 -0
- package/dist/lib/tools/_shared.js +21 -0
- package/dist/lib/tools/_shared.js.map +1 -0
- package/dist/lib/tools/codex-dashboard.d.ts +8 -0
- package/dist/lib/tools/codex-dashboard.d.ts.map +1 -0
- package/dist/lib/tools/codex-dashboard.js +176 -0
- package/dist/lib/tools/codex-dashboard.js.map +1 -0
- package/dist/lib/tools/codex-diag.d.ts +19 -0
- package/dist/lib/tools/codex-diag.d.ts.map +1 -0
- package/dist/lib/tools/codex-diag.js +139 -0
- package/dist/lib/tools/codex-diag.js.map +1 -0
- package/dist/lib/tools/codex-diff.d.ts +44 -0
- package/dist/lib/tools/codex-diff.d.ts.map +1 -0
- package/dist/lib/tools/codex-diff.js +284 -0
- package/dist/lib/tools/codex-diff.js.map +1 -0
- package/dist/lib/tools/codex-doctor.d.ts +8 -0
- package/dist/lib/tools/codex-doctor.d.ts.map +1 -0
- package/dist/lib/tools/codex-doctor.js +284 -0
- package/dist/lib/tools/codex-doctor.js.map +1 -0
- package/dist/lib/tools/codex-export.d.ts +8 -0
- package/dist/lib/tools/codex-export.d.ts.map +1 -0
- package/dist/lib/tools/codex-export.js +63 -0
- package/dist/lib/tools/codex-export.js.map +1 -0
- package/dist/lib/tools/codex-health.d.ts +8 -0
- package/dist/lib/tools/codex-health.d.ts.map +1 -0
- package/dist/lib/tools/codex-health.js +124 -0
- package/dist/lib/tools/codex-health.js.map +1 -0
- package/dist/lib/tools/codex-help.d.ts +8 -0
- package/dist/lib/tools/codex-help.d.ts.map +1 -0
- package/dist/lib/tools/codex-help.js +127 -0
- package/dist/lib/tools/codex-help.js.map +1 -0
- package/dist/lib/tools/codex-import.d.ts +8 -0
- package/dist/lib/tools/codex-import.d.ts.map +1 -0
- package/dist/lib/tools/codex-import.js +97 -0
- package/dist/lib/tools/codex-import.js.map +1 -0
- package/dist/lib/tools/codex-keychain.d.ts +36 -0
- package/dist/lib/tools/codex-keychain.d.ts.map +1 -0
- package/dist/lib/tools/codex-keychain.js +289 -0
- package/dist/lib/tools/codex-keychain.js.map +1 -0
- package/dist/lib/tools/codex-label.d.ts +8 -0
- package/dist/lib/tools/codex-label.d.ts.map +1 -0
- package/dist/lib/tools/codex-label.js +143 -0
- package/dist/lib/tools/codex-label.js.map +1 -0
- package/dist/lib/tools/codex-limits.d.ts +8 -0
- package/dist/lib/tools/codex-limits.d.ts.map +1 -0
- package/dist/lib/tools/codex-limits.js +497 -0
- package/dist/lib/tools/codex-limits.js.map +1 -0
- package/dist/lib/tools/codex-list.d.ts +8 -0
- package/dist/lib/tools/codex-list.d.ts.map +1 -0
- package/dist/lib/tools/codex-list.js +260 -0
- package/dist/lib/tools/codex-list.js.map +1 -0
- package/dist/lib/tools/codex-metrics.d.ts +8 -0
- package/dist/lib/tools/codex-metrics.d.ts.map +1 -0
- package/dist/lib/tools/codex-metrics.js +180 -0
- package/dist/lib/tools/codex-metrics.js.map +1 -0
- package/dist/lib/tools/codex-next.d.ts +8 -0
- package/dist/lib/tools/codex-next.d.ts.map +1 -0
- package/dist/lib/tools/codex-next.js +54 -0
- package/dist/lib/tools/codex-next.js.map +1 -0
- package/dist/lib/tools/codex-note.d.ts +8 -0
- package/dist/lib/tools/codex-note.d.ts.map +1 -0
- package/dist/lib/tools/codex-note.js +79 -0
- package/dist/lib/tools/codex-note.js.map +1 -0
- package/dist/lib/tools/codex-refresh.d.ts +8 -0
- package/dist/lib/tools/codex-refresh.d.ts.map +1 -0
- package/dist/lib/tools/codex-refresh.js +78 -0
- package/dist/lib/tools/codex-refresh.js.map +1 -0
- package/dist/lib/tools/codex-remove.d.ts +8 -0
- package/dist/lib/tools/codex-remove.d.ts.map +1 -0
- package/dist/lib/tools/codex-remove.js +184 -0
- package/dist/lib/tools/codex-remove.js.map +1 -0
- package/dist/lib/tools/codex-setup.d.ts +8 -0
- package/dist/lib/tools/codex-setup.d.ts.map +1 -0
- package/dist/lib/tools/codex-setup.js +26 -0
- package/dist/lib/tools/codex-setup.js.map +1 -0
- package/dist/lib/tools/codex-status.d.ts +8 -0
- package/dist/lib/tools/codex-status.d.ts.map +1 -0
- package/dist/lib/tools/codex-status.js +263 -0
- package/dist/lib/tools/codex-status.js.map +1 -0
- package/dist/lib/tools/codex-switch.d.ts +8 -0
- package/dist/lib/tools/codex-switch.d.ts.map +1 -0
- package/dist/lib/tools/codex-switch.js +122 -0
- package/dist/lib/tools/codex-switch.js.map +1 -0
- package/dist/lib/tools/codex-tag.d.ts +8 -0
- package/dist/lib/tools/codex-tag.d.ts.map +1 -0
- package/dist/lib/tools/codex-tag.js +101 -0
- package/dist/lib/tools/codex-tag.js.map +1 -0
- package/dist/lib/tools/index.d.ts +143 -0
- package/dist/lib/tools/index.d.ts.map +1 -0
- package/dist/lib/tools/index.js +67 -0
- package/dist/lib/tools/index.js.map +1 -0
- package/dist/lib/ui/format.d.ts.map +1 -1
- package/dist/lib/ui/format.js +5 -0
- package/dist/lib/ui/format.js.map +1 -1
- package/dist/lib/ui/runtime.d.ts +10 -0
- package/dist/lib/ui/runtime.d.ts.map +1 -1
- package/dist/lib/ui/runtime.js +16 -11
- package/dist/lib/ui/runtime.js.map +1 -1
- package/dist/lib/ui/select.d.ts.map +1 -1
- package/dist/lib/ui/select.js +12 -3
- package/dist/lib/ui/select.js.map +1 -1
- package/dist/lib/ui/theme.d.ts +19 -0
- package/dist/lib/ui/theme.d.ts.map +1 -1
- package/dist/lib/ui/theme.js +27 -0
- package/dist/lib/ui/theme.js.map +1 -1
- package/package.json +24 -16
- package/scripts/copy-oauth-success.js +16 -6
- package/scripts/install-oc-codex-multi-auth-core.js +462 -381
- package/scripts/install-oc-codex-multi-auth.js +15 -15
- package/scripts/test-all-models.sh +1 -1
- package/dist/lib/audit.d.ts +0 -45
- package/dist/lib/audit.d.ts.map +0 -1
- package/dist/lib/audit.js +0 -154
- package/dist/lib/audit.js.map +0 -1
- package/dist/lib/auth-rate-limit.d.ts +0 -20
- package/dist/lib/auth-rate-limit.d.ts.map +0 -1
- package/dist/lib/auth-rate-limit.js +0 -91
- package/dist/lib/auth-rate-limit.js.map +0 -1
- package/dist/lib/runtime-contracts.d.ts +0 -16
- package/dist/lib/runtime-contracts.d.ts.map +0 -1
- package/dist/lib/runtime-contracts.js +0 -24
- package/dist/lib/runtime-contracts.js.map +0 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codex-keychain` tool — inspect and manage the opt-in OS-keychain backend.
|
|
3
|
+
*
|
|
4
|
+
* Phase 4 F1. Companion to `lib/storage/keychain.ts`. The tool exposes three
|
|
5
|
+
* subcommands chosen for operator-level control over the credential surface:
|
|
6
|
+
*
|
|
7
|
+
* - `status`: report which backend is active and whether the OS keychain
|
|
8
|
+
* is reachable. Never mutates state; safe to run under any config.
|
|
9
|
+
* - `migrate`: explicitly move the current on-disk JSON accounts file into
|
|
10
|
+
* the OS keychain, rename the JSON as
|
|
11
|
+
* `<path>.migrated-to-keychain.<ts>` for rollback, and leave the
|
|
12
|
+
* authoritative copy in the keychain. Idempotent: running again when
|
|
13
|
+
* the keychain already holds a fresher copy is a no-op.
|
|
14
|
+
* - `rollback`: restore the most recent `.migrated-to-keychain.<ts>`
|
|
15
|
+
* backup next to the accounts file and delete the keychain entry so
|
|
16
|
+
* subsequent loads read from disk again. The inverse of `migrate`.
|
|
17
|
+
*
|
|
18
|
+
* Runs under the same storage lock as `saveAccounts`/`loadAccounts` so the
|
|
19
|
+
* mutation cannot interleave with an in-flight rotation save.
|
|
20
|
+
*
|
|
21
|
+
* Security notes:
|
|
22
|
+
* - No secret value ever reaches the tool output. Success messages show
|
|
23
|
+
* account counts and file paths, never token material.
|
|
24
|
+
* - Failures fall back to JSON at the storage layer — this tool never
|
|
25
|
+
* hides that from the operator.
|
|
26
|
+
*/
|
|
27
|
+
import { promises as fs } from "node:fs";
|
|
28
|
+
import { basename, dirname, join } from "node:path";
|
|
29
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
30
|
+
import { clearAccounts, loadAccounts, saveAccounts, } from "../storage.js";
|
|
31
|
+
import { deleteFromKeychain, isKeychainOptInEnabled, keychainIsAvailable, readFromKeychain, } from "../storage/keychain.js";
|
|
32
|
+
import { getCurrentProjectStorageKey, getStoragePath } from "../storage/state.js";
|
|
33
|
+
import { normalizeAccountStorage } from "../storage/normalize.js";
|
|
34
|
+
import { formatUiHeader, formatUiItem, formatUiKeyValue, } from "../ui/format.js";
|
|
35
|
+
function normalizeSubcommand(raw) {
|
|
36
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
37
|
+
if (v === "migrate" || v === "rollback")
|
|
38
|
+
return v;
|
|
39
|
+
return "status";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* List `<path>.migrated-to-keychain.<ts>` siblings of the current storage
|
|
43
|
+
* path, sorted most-recent first by `fs.stat().mtimeMs` (F1 post-merge
|
|
44
|
+
* MEDIUM finding). The previous implementation sorted the filenames
|
|
45
|
+
* lexicographically, which happens to produce the correct order when all
|
|
46
|
+
* filenames share the fixed-width ISO-8601 suffix
|
|
47
|
+
* (`YYYY-MM-DDTHH-MM-SS-mmmZ`) emitted by `migrateOnDiskJsonToKeychainBackup`
|
|
48
|
+
* in `lib/storage/load-save.ts`. Any format drift (locale epoch, test
|
|
49
|
+
* fixture with non-ISO suffix, future migration-suffix change) silently
|
|
50
|
+
* picks the alphabetically-last entry instead of the most-recent. Sorting
|
|
51
|
+
* by `mtimeMs` is format-independent and matches "most recent backup"
|
|
52
|
+
* exactly. The filename tiebreaker (rare: identical mtime) preserves the
|
|
53
|
+
* previous descending-lex behaviour so the function stays deterministic.
|
|
54
|
+
*
|
|
55
|
+
* Exported as `_findMigrationBackupsForTests` below so the sort order can
|
|
56
|
+
* be asserted without stubbing the tool closure.
|
|
57
|
+
*/
|
|
58
|
+
async function findMigrationBackups(storagePath) {
|
|
59
|
+
const dir = dirname(storagePath);
|
|
60
|
+
const base = basename(storagePath);
|
|
61
|
+
const prefix = `${base}.migrated-to-keychain.`;
|
|
62
|
+
let entries;
|
|
63
|
+
try {
|
|
64
|
+
entries = await fs.readdir(dir);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const matches = entries.filter((name) => name.startsWith(prefix));
|
|
70
|
+
const withMtime = await Promise.all(matches.map(async (name) => {
|
|
71
|
+
const full = join(dir, name);
|
|
72
|
+
let mtimeMs = Number.NEGATIVE_INFINITY;
|
|
73
|
+
try {
|
|
74
|
+
const st = await fs.stat(full);
|
|
75
|
+
mtimeMs = st.mtimeMs;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Stat failure: keep -Infinity so the entry sorts last.
|
|
79
|
+
// This protects against a backup that disappeared between
|
|
80
|
+
// readdir and stat (race) without crashing the tool.
|
|
81
|
+
}
|
|
82
|
+
return { full, name, mtimeMs };
|
|
83
|
+
}));
|
|
84
|
+
withMtime.sort((a, b) => {
|
|
85
|
+
if (b.mtimeMs !== a.mtimeMs)
|
|
86
|
+
return b.mtimeMs - a.mtimeMs;
|
|
87
|
+
return a.name < b.name ? 1 : a.name > b.name ? -1 : 0;
|
|
88
|
+
});
|
|
89
|
+
return withMtime.map((entry) => entry.full);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Test-only export for `findMigrationBackups`. Kept separate from the
|
|
93
|
+
* tool factory so the sort semantics can be asserted directly against a
|
|
94
|
+
* temp directory in `test/tools-codex-keychain.test.ts`.
|
|
95
|
+
*/
|
|
96
|
+
export async function _findMigrationBackupsForTests(storagePath) {
|
|
97
|
+
return findMigrationBackups(storagePath);
|
|
98
|
+
}
|
|
99
|
+
export function createCodexKeychainTool(ctx) {
|
|
100
|
+
// ctx.resolveUiRuntime is the only helper we need: it threads the v2
|
|
101
|
+
// TUI / color-profile state from plugin config + CODEX_TUI_* env into
|
|
102
|
+
// every format helper call, so output is consistent with the rest of
|
|
103
|
+
// the codex-* tools without leaking the UI-runtime plumbing in here.
|
|
104
|
+
const { resolveUiRuntime } = ctx;
|
|
105
|
+
return tool({
|
|
106
|
+
description: "Inspect and manage the opt-in OS-keychain credential backend. Subcommands: status (default), migrate, rollback. Rollback requires confirm=true when a current accounts JSON file exists alongside the backup (safety gate).",
|
|
107
|
+
args: {
|
|
108
|
+
command: tool.schema
|
|
109
|
+
.string()
|
|
110
|
+
.optional()
|
|
111
|
+
.describe('Subcommand: "status" (default), "migrate", or "rollback".'),
|
|
112
|
+
confirm: tool.schema
|
|
113
|
+
.boolean()
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("rollback only: pass true to archive any current accounts JSON as `.pre-rollback.<ts>` before restoring the backup. Without confirm=true, rollback refuses if a current file exists."),
|
|
116
|
+
},
|
|
117
|
+
async execute({ command, confirm, }) {
|
|
118
|
+
const ui = resolveUiRuntime();
|
|
119
|
+
const sub = normalizeSubcommand(command);
|
|
120
|
+
const optIn = isKeychainOptInEnabled();
|
|
121
|
+
const projectKey = getCurrentProjectStorageKey();
|
|
122
|
+
const storagePath = (() => {
|
|
123
|
+
try {
|
|
124
|
+
return getStoragePath();
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return "<unresolved>";
|
|
128
|
+
}
|
|
129
|
+
})();
|
|
130
|
+
if (sub === "status") {
|
|
131
|
+
// When opt-in is off, skip the probe entirely (F1 post-merge
|
|
132
|
+
// LOW finding). Probing under an unset `CODEX_KEYCHAIN`
|
|
133
|
+
// violates the "unset -> no keychain code path" invariant
|
|
134
|
+
// and can trigger a first-run macOS "allow/always allow"
|
|
135
|
+
// prompt for users who run `codex-keychain status` without
|
|
136
|
+
// opting in. `keychainIsAvailable` already short-circuits
|
|
137
|
+
// on the opt-in check; we surface that explicitly here so
|
|
138
|
+
// the status line reads "not checked; CODEX_KEYCHAIN unset"
|
|
139
|
+
// instead of the misleading "keychain unavailable".
|
|
140
|
+
const available = optIn ? await keychainIsAvailable() : false;
|
|
141
|
+
const keychainHasEntry = optIn
|
|
142
|
+
? (await readFromKeychain(projectKey)) !== null
|
|
143
|
+
: false;
|
|
144
|
+
const activeBackend = !optIn
|
|
145
|
+
? "JSON (keychain disabled; CODEX_KEYCHAIN unset)"
|
|
146
|
+
: available && keychainHasEntry
|
|
147
|
+
? "keychain"
|
|
148
|
+
: available
|
|
149
|
+
? "keychain (empty, JSON fallback)"
|
|
150
|
+
: "JSON (keychain unavailable)";
|
|
151
|
+
const lines = [];
|
|
152
|
+
lines.push(...formatUiHeader(ui, "Codex keychain status"));
|
|
153
|
+
lines.push("");
|
|
154
|
+
lines.push(formatUiKeyValue(ui, "Active backend", activeBackend));
|
|
155
|
+
lines.push(formatUiKeyValue(ui, "CODEX_KEYCHAIN", optIn ? "1 (enabled)" : "unset/disabled"));
|
|
156
|
+
lines.push(formatUiKeyValue(ui, "Keychain reachable", optIn ? (available ? "yes" : "no") : "not checked (opt-in off)"));
|
|
157
|
+
lines.push(formatUiKeyValue(ui, "Project scope", projectKey ?? "global"));
|
|
158
|
+
lines.push(formatUiKeyValue(ui, "On-disk path", storagePath));
|
|
159
|
+
if (!optIn) {
|
|
160
|
+
lines.push("");
|
|
161
|
+
lines.push(formatUiItem(ui, "Set CODEX_KEYCHAIN=1 to enable the OS-keychain backend. Migration runs on the next save."));
|
|
162
|
+
}
|
|
163
|
+
return lines.join("\n");
|
|
164
|
+
}
|
|
165
|
+
if (sub === "migrate") {
|
|
166
|
+
if (!optIn) {
|
|
167
|
+
return "codex-keychain migrate: refusing to migrate because CODEX_KEYCHAIN is not set to 1. Enable the opt-in first, then re-run this command.";
|
|
168
|
+
}
|
|
169
|
+
const storage = await loadAccounts();
|
|
170
|
+
if (!storage) {
|
|
171
|
+
return "codex-keychain migrate: no accounts found to migrate. Nothing to do.";
|
|
172
|
+
}
|
|
173
|
+
// Re-saving under the opt-in path triggers the same keychain
|
|
174
|
+
// write + JSON-backup flow used by every rotation save, so we
|
|
175
|
+
// avoid duplicating the migration logic here.
|
|
176
|
+
await saveAccounts(storage);
|
|
177
|
+
return [
|
|
178
|
+
...formatUiHeader(ui, "Codex keychain migrate"),
|
|
179
|
+
"",
|
|
180
|
+
formatUiItem(ui, `Migrated ${storage.accounts.length} account(s) to the OS keychain.`),
|
|
181
|
+
formatUiKeyValue(ui, "Project scope", projectKey ?? "global"),
|
|
182
|
+
formatUiItem(ui, "On-disk JSON (if any) was renamed with a .migrated-to-keychain.<timestamp> suffix. Use `codex-keychain rollback` to restore it."),
|
|
183
|
+
].join("\n");
|
|
184
|
+
}
|
|
185
|
+
// rollback
|
|
186
|
+
const backups = await findMigrationBackups(storagePath);
|
|
187
|
+
const mostRecent = backups[0];
|
|
188
|
+
if (!mostRecent) {
|
|
189
|
+
return `codex-keychain rollback: no .migrated-to-keychain.<ts> backup found next to ${storagePath}. Nothing to restore.`;
|
|
190
|
+
}
|
|
191
|
+
// Verify the backup parses as a V3 storage blob before we trust
|
|
192
|
+
// it. A corrupt backup must not be promoted to the active file.
|
|
193
|
+
let accountCount = 0;
|
|
194
|
+
try {
|
|
195
|
+
const raw = await fs.readFile(mostRecent, "utf-8");
|
|
196
|
+
const parsed = JSON.parse(raw);
|
|
197
|
+
const normalized = normalizeAccountStorage(parsed, mostRecent);
|
|
198
|
+
if (!normalized) {
|
|
199
|
+
return `codex-keychain rollback: backup at ${mostRecent} did not parse as V3 account storage. Aborted.`;
|
|
200
|
+
}
|
|
201
|
+
accountCount = normalized.accounts.length;
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
return `codex-keychain rollback: failed to read backup at ${mostRecent}: ${err.message}`;
|
|
205
|
+
}
|
|
206
|
+
// Wipe the keychain entry + any current on-disk file, then rename
|
|
207
|
+
// the backup back to the canonical storage path so the next load
|
|
208
|
+
// reads from disk again. clearAccounts handles both sides.
|
|
209
|
+
await clearAccounts();
|
|
210
|
+
// Silent-clobber guard (F1 post-merge MEDIUM finding). On POSIX,
|
|
211
|
+
// `fs.rename(backup, storagePath)` silently overwrites an
|
|
212
|
+
// existing destination. If `clearAccounts` failed to unlink the
|
|
213
|
+
// current JSON (EACCES/EBUSY) or a race write landed a new file
|
|
214
|
+
// between clearAccounts and rename, the user's current accounts
|
|
215
|
+
// would be silently discarded with no way to recover them.
|
|
216
|
+
// Require explicit `confirm=true` before overwriting; without
|
|
217
|
+
// it, refuse and surface the offending path.
|
|
218
|
+
let currentExists = false;
|
|
219
|
+
try {
|
|
220
|
+
await fs.access(storagePath);
|
|
221
|
+
currentExists = true;
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
/* canonical path is clear; safe to rename */
|
|
225
|
+
}
|
|
226
|
+
let preRollbackArchive = null;
|
|
227
|
+
if (currentExists) {
|
|
228
|
+
if (!confirm) {
|
|
229
|
+
return [
|
|
230
|
+
`codex-keychain rollback: refusing to overwrite existing accounts file at ${storagePath}.`,
|
|
231
|
+
`Backup at ${mostRecent} was not restored.`,
|
|
232
|
+
"Pass confirm=true to archive the current file as .pre-rollback.<timestamp> and proceed, or move the current file aside and re-run.",
|
|
233
|
+
].join("\n");
|
|
234
|
+
}
|
|
235
|
+
const archiveSuffix = new Date()
|
|
236
|
+
.toISOString()
|
|
237
|
+
.replace(/[:.]/g, "-");
|
|
238
|
+
preRollbackArchive = `${storagePath}.pre-rollback.${archiveSuffix}`;
|
|
239
|
+
try {
|
|
240
|
+
await fs.rename(storagePath, preRollbackArchive);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
return `codex-keychain rollback: failed to archive current accounts file at ${storagePath} -> ${preRollbackArchive}: ${err.message}. Backup at ${mostRecent} was not restored.`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
await fs.rename(mostRecent, storagePath);
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
return `codex-keychain rollback: failed to rename ${mostRecent} -> ${storagePath}: ${err.message}`;
|
|
251
|
+
}
|
|
252
|
+
// Re-apply 0o600 after rollback rename (F1 post-merge LOW
|
|
253
|
+
// finding). Mirror the chmod applied on the backup-write path
|
|
254
|
+
// so a restored file can never end up group/world-readable even
|
|
255
|
+
// if the backup's mode drifted between migration and rollback.
|
|
256
|
+
// Windows ignores POSIX mode bits, so skip there.
|
|
257
|
+
if (process.platform !== "win32") {
|
|
258
|
+
try {
|
|
259
|
+
await fs.chmod(storagePath, 0o600);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
/* non-fatal: file is restored, mode drift is a hardening
|
|
263
|
+
* nicety. Swallow to avoid failing the rollback on a
|
|
264
|
+
* permission-sensitive mount. */
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Best-effort keychain delete in case opt-in is still on; the
|
|
268
|
+
// storage layer will honour that on subsequent saves.
|
|
269
|
+
try {
|
|
270
|
+
await deleteFromKeychain(projectKey);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
/* already deleted by clearAccounts */
|
|
274
|
+
}
|
|
275
|
+
const lines = [
|
|
276
|
+
...formatUiHeader(ui, "Codex keychain rollback"),
|
|
277
|
+
"",
|
|
278
|
+
formatUiItem(ui, `Restored ${accountCount} account(s) from backup ${mostRecent}.`),
|
|
279
|
+
formatUiKeyValue(ui, "Active file", storagePath),
|
|
280
|
+
];
|
|
281
|
+
if (preRollbackArchive) {
|
|
282
|
+
lines.push(formatUiKeyValue(ui, "Previous file archived at", preRollbackArchive));
|
|
283
|
+
}
|
|
284
|
+
lines.push(formatUiItem(ui, "To stop using the keychain backend, unset CODEX_KEYCHAIN (or set it to any value other than \"1\") before the next save."));
|
|
285
|
+
return lines.join("\n");
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=codex-keychain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-keychain.js","sourceRoot":"","sources":["../../../lib/tools/codex-keychain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codex-label` tool — set or clear per-account display label.
|
|
3
|
+
* Extracted from `index.ts` per RC-1 Phase 2.
|
|
4
|
+
*/
|
|
5
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
6
|
+
import type { ToolContext } from "./index.js";
|
|
7
|
+
export declare function createCodexLabelTool(ctx: ToolContext): ToolDefinition;
|
|
8
|
+
//# sourceMappingURL=codex-label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-label.d.ts","sourceRoot":"","sources":["../../../lib/tools/codex-label.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AASrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CA6LrE"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codex-label` tool — set or clear per-account display label.
|
|
3
|
+
* Extracted from `index.ts` per RC-1 Phase 2.
|
|
4
|
+
*/
|
|
5
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
6
|
+
import { loadAccounts, saveAccounts } from "../storage.js";
|
|
7
|
+
import { AccountManager } from "../accounts.js";
|
|
8
|
+
import { logWarn } from "../logger.js";
|
|
9
|
+
import { formatUiHeader, formatUiItem, formatUiKeyValue, } from "../ui/format.js";
|
|
10
|
+
export function createCodexLabelTool(ctx) {
|
|
11
|
+
const { resolveUiRuntime, promptAccountIndexSelection, supportsInteractiveMenus, formatCommandAccountLabel, getStatusMarker, cachedAccountManagerRef, accountManagerPromiseRef, } = ctx;
|
|
12
|
+
return tool({
|
|
13
|
+
description: "Set or clear a beginner-friendly display label for an account (interactive picker when index is omitted).",
|
|
14
|
+
args: {
|
|
15
|
+
index: tool.schema
|
|
16
|
+
.number()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Account number to update (1-based, e.g., 1 for first account)"),
|
|
19
|
+
label: tool.schema
|
|
20
|
+
.string()
|
|
21
|
+
.describe("Display label. Use an empty string to clear (e.g., Work, Personal, Team A)"),
|
|
22
|
+
},
|
|
23
|
+
async execute({ index, label }) {
|
|
24
|
+
const ui = resolveUiRuntime();
|
|
25
|
+
const storage = await loadAccounts();
|
|
26
|
+
if (!storage || storage.accounts.length === 0) {
|
|
27
|
+
if (ui.v2Enabled) {
|
|
28
|
+
return [
|
|
29
|
+
...formatUiHeader(ui, "Set account label"),
|
|
30
|
+
"",
|
|
31
|
+
formatUiItem(ui, "No accounts configured.", "warning"),
|
|
32
|
+
formatUiItem(ui, "Run: opencode auth login", "accent"),
|
|
33
|
+
].join("\n");
|
|
34
|
+
}
|
|
35
|
+
return "No Codex accounts configured. Run: opencode auth login";
|
|
36
|
+
}
|
|
37
|
+
let resolvedIndex = index;
|
|
38
|
+
if (resolvedIndex === undefined) {
|
|
39
|
+
const selectedIndex = await promptAccountIndexSelection(ui, storage, "Set account label");
|
|
40
|
+
if (selectedIndex === null) {
|
|
41
|
+
if (supportsInteractiveMenus()) {
|
|
42
|
+
if (ui.v2Enabled) {
|
|
43
|
+
return [
|
|
44
|
+
...formatUiHeader(ui, "Set account label"),
|
|
45
|
+
"",
|
|
46
|
+
formatUiItem(ui, "No account selected.", "warning"),
|
|
47
|
+
formatUiItem(ui, 'Run again and pick an account, or pass codex-label index=2 label="Work".', "muted"),
|
|
48
|
+
].join("\n");
|
|
49
|
+
}
|
|
50
|
+
return "No account selected.";
|
|
51
|
+
}
|
|
52
|
+
if (ui.v2Enabled) {
|
|
53
|
+
return [
|
|
54
|
+
...formatUiHeader(ui, "Set account label"),
|
|
55
|
+
"",
|
|
56
|
+
formatUiItem(ui, "Missing account number.", "warning"),
|
|
57
|
+
formatUiItem(ui, 'Use: codex-label index=2 label="Work"', "accent"),
|
|
58
|
+
].join("\n");
|
|
59
|
+
}
|
|
60
|
+
return 'Missing account number. Use: codex-label index=2 label="Work"';
|
|
61
|
+
}
|
|
62
|
+
resolvedIndex = selectedIndex + 1;
|
|
63
|
+
}
|
|
64
|
+
const targetIndex = Math.floor((resolvedIndex ?? 0) - 1);
|
|
65
|
+
if (!Number.isFinite(targetIndex) ||
|
|
66
|
+
targetIndex < 0 ||
|
|
67
|
+
targetIndex >= storage.accounts.length) {
|
|
68
|
+
if (ui.v2Enabled) {
|
|
69
|
+
return [
|
|
70
|
+
...formatUiHeader(ui, "Set account label"),
|
|
71
|
+
"",
|
|
72
|
+
formatUiItem(ui, `Invalid account number: ${resolvedIndex}`, "danger"),
|
|
73
|
+
formatUiKeyValue(ui, "Valid range", `1-${storage.accounts.length}`, "muted"),
|
|
74
|
+
].join("\n");
|
|
75
|
+
}
|
|
76
|
+
return `Invalid account number: ${resolvedIndex}\n\nValid range: 1-${storage.accounts.length}`;
|
|
77
|
+
}
|
|
78
|
+
const normalizedLabel = (label ?? "").trim().replace(/\s+/g, " ");
|
|
79
|
+
if (normalizedLabel.length > 60) {
|
|
80
|
+
if (ui.v2Enabled) {
|
|
81
|
+
return [
|
|
82
|
+
...formatUiHeader(ui, "Set account label"),
|
|
83
|
+
"",
|
|
84
|
+
formatUiItem(ui, "Label is too long (max 60 characters).", "danger"),
|
|
85
|
+
].join("\n");
|
|
86
|
+
}
|
|
87
|
+
return "Label is too long (max 60 characters).";
|
|
88
|
+
}
|
|
89
|
+
const account = storage.accounts[targetIndex];
|
|
90
|
+
if (!account) {
|
|
91
|
+
return `Account ${resolvedIndex} not found.`;
|
|
92
|
+
}
|
|
93
|
+
const previousLabel = account.accountLabel?.trim() ?? "";
|
|
94
|
+
if (normalizedLabel.length === 0) {
|
|
95
|
+
delete account.accountLabel;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
account.accountLabel = normalizedLabel;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await saveAccounts(storage);
|
|
102
|
+
}
|
|
103
|
+
catch (saveError) {
|
|
104
|
+
logWarn("Failed to save account label update", {
|
|
105
|
+
error: String(saveError),
|
|
106
|
+
});
|
|
107
|
+
if (ui.v2Enabled) {
|
|
108
|
+
return [
|
|
109
|
+
...formatUiHeader(ui, "Set account label"),
|
|
110
|
+
"",
|
|
111
|
+
formatUiItem(ui, "Label updated in memory but failed to persist.", "danger"),
|
|
112
|
+
].join("\n");
|
|
113
|
+
}
|
|
114
|
+
return "Label updated in memory but failed to persist. Changes may be lost on restart.";
|
|
115
|
+
}
|
|
116
|
+
if (cachedAccountManagerRef.current) {
|
|
117
|
+
const reloadedManager = await AccountManager.loadFromDisk();
|
|
118
|
+
cachedAccountManagerRef.current = reloadedManager;
|
|
119
|
+
accountManagerPromiseRef.current = Promise.resolve(reloadedManager);
|
|
120
|
+
}
|
|
121
|
+
const accountLabel = formatCommandAccountLabel(account, targetIndex);
|
|
122
|
+
if (ui.v2Enabled) {
|
|
123
|
+
const statusText = normalizedLabel.length === 0
|
|
124
|
+
? `Cleared label for ${accountLabel}`
|
|
125
|
+
: `Set label for ${accountLabel} to "${normalizedLabel}"`;
|
|
126
|
+
const previousText = previousLabel.length > 0
|
|
127
|
+
? formatUiKeyValue(ui, "Previous label", previousLabel, "muted")
|
|
128
|
+
: formatUiKeyValue(ui, "Previous label", "none", "muted");
|
|
129
|
+
return [
|
|
130
|
+
...formatUiHeader(ui, "Set account label"),
|
|
131
|
+
"",
|
|
132
|
+
formatUiItem(ui, `${getStatusMarker(ui, "ok")} ${statusText}`, "success"),
|
|
133
|
+
previousText,
|
|
134
|
+
].join("\n");
|
|
135
|
+
}
|
|
136
|
+
if (normalizedLabel.length === 0) {
|
|
137
|
+
return `Cleared label for ${accountLabel}`;
|
|
138
|
+
}
|
|
139
|
+
return `Set label for ${accountLabel} to "${normalizedLabel}"`;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=codex-label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-label.js","sourceRoot":"","sources":["../../../lib/tools/codex-label.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAuB,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACN,cAAc,EACd,YAAY,EACZ,gBAAgB,GAChB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,UAAU,oBAAoB,CAAC,GAAgB;IACpD,MAAM,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,GACxB,GAAG,GAAG,CAAC;IACR,OAAO,IAAI,CAAC;QACX,WAAW,EACV,2GAA2G;QAC5G,IAAI,EAAE;YACL,KAAK,EAAE,IAAI,CAAC,MAAM;iBAChB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACR,+DAA+D,CAC/D;YACF,KAAK,EAAE,IAAI,CAAC,MAAM;iBAChB,MAAM,EAAE;iBACR,QAAQ,CACR,4EAA4E,CAC5E;SACF;QACD,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAqC;YAChE,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,YAAY,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/C,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBAClB,OAAO;wBACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;wBAC1C,EAAE;wBACF,YAAY,CAAC,EAAE,EAAE,yBAAyB,EAAE,SAAS,CAAC;wBACtD,YAAY,CAAC,EAAE,EAAE,0BAA0B,EAAE,QAAQ,CAAC;qBACtD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,CAAC;gBACD,OAAO,wDAAwD,CAAC;YACjE,CAAC;YAED,IAAI,aAAa,GAAG,KAAK,CAAC;YAC1B,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBACjC,MAAM,aAAa,GAAG,MAAM,2BAA2B,CACtD,EAAE,EACF,OAAO,EACP,mBAAmB,CACnB,CAAC;gBACF,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;oBAC5B,IAAI,wBAAwB,EAAE,EAAE,CAAC;wBAChC,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;4BAClB,OAAO;gCACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;gCAC1C,EAAE;gCACF,YAAY,CAAC,EAAE,EAAE,sBAAsB,EAAE,SAAS,CAAC;gCACnD,YAAY,CACX,EAAE,EACF,0EAA0E,EAC1E,OAAO,CACP;6BACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACd,CAAC;wBACD,OAAO,sBAAsB,CAAC;oBAC/B,CAAC;oBACD,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;wBAClB,OAAO;4BACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;4BAC1C,EAAE;4BACF,YAAY,CAAC,EAAE,EAAE,yBAAyB,EAAE,SAAS,CAAC;4BACtD,YAAY,CACX,EAAE,EACF,uCAAuC,EACvC,QAAQ,CACR;yBACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACd,CAAC;oBACD,OAAO,+DAA+D,CAAC;gBACxE,CAAC;gBACD,aAAa,GAAG,aAAa,GAAG,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzD,IACC,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAC7B,WAAW,GAAG,CAAC;gBACf,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,EACrC,CAAC;gBACF,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBAClB,OAAO;wBACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;wBAC1C,EAAE;wBACF,YAAY,CACX,EAAE,EACF,2BAA2B,aAAa,EAAE,EAC1C,QAAQ,CACR;wBACD,gBAAgB,CACf,EAAE,EACF,aAAa,EACb,KAAK,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EAC9B,OAAO,CACP;qBACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,CAAC;gBACD,OAAO,2BAA2B,aAAa,sBAAsB,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAChG,CAAC;YAED,MAAM,eAAe,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAClE,IAAI,eAAe,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACjC,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBAClB,OAAO;wBACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;wBAC1C,EAAE;wBACF,YAAY,CACX,EAAE,EACF,wCAAwC,EACxC,QAAQ,CACR;qBACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,CAAC;gBACD,OAAO,wCAAwC,CAAC;YACjD,CAAC;YAED,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO,WAAW,aAAa,aAAa,CAAC;YAC9C,CAAC;YAED,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACzD,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,OAAO,CAAC,YAAY,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,YAAY,GAAG,eAAe,CAAC;YACxC,CAAC;YAED,IAAI,CAAC;gBACJ,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACpB,OAAO,CAAC,qCAAqC,EAAE;oBAC9C,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC;iBACxB,CAAC,CAAC;gBACH,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;oBAClB,OAAO;wBACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;wBAC1C,EAAE;wBACF,YAAY,CACX,EAAE,EACF,gDAAgD,EAChD,QAAQ,CACR;qBACD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,CAAC;gBACD,OAAO,gFAAgF,CAAC;YACzF,CAAC;YAED,IAAI,uBAAuB,CAAC,OAAO,EAAE,CAAC;gBACrC,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC,YAAY,EAAE,CAAC;gBAC5D,uBAAuB,CAAC,OAAO,GAAG,eAAe,CAAC;gBAClD,wBAAwB,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,YAAY,GAAG,yBAAyB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACrE,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;gBAClB,MAAM,UAAU,GACf,eAAe,CAAC,MAAM,KAAK,CAAC;oBAC3B,CAAC,CAAC,qBAAqB,YAAY,EAAE;oBACrC,CAAC,CAAC,iBAAiB,YAAY,QAAQ,eAAe,GAAG,CAAC;gBAC5D,MAAM,YAAY,GACjB,aAAa,CAAC,MAAM,GAAG,CAAC;oBACvB,CAAC,CAAC,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,EAAE,aAAa,EAAE,OAAO,CAAC;oBAChE,CAAC,CAAC,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC5D,OAAO;oBACN,GAAG,cAAc,CAAC,EAAE,EAAE,mBAAmB,CAAC;oBAC1C,EAAE;oBACF,YAAY,CACX,EAAE,EACF,GAAG,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,UAAU,EAAE,EAC5C,SAAS,CACT;oBACD,YAAY;iBACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,CAAC;YAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,qBAAqB,YAAY,EAAE,CAAC;YAC5C,CAAC;YACD,OAAO,iBAAiB,YAAY,QAAQ,eAAe,GAAG,CAAC;QAChE,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codex-limits` tool — show Codex usage limits per account.
|
|
3
|
+
* Extracted from `index.ts` per RC-1 Phase 2.
|
|
4
|
+
*/
|
|
5
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
6
|
+
import type { ToolContext } from "./index.js";
|
|
7
|
+
export declare function createCodexLimitsTool(ctx: ToolContext): ToolDefinition;
|
|
8
|
+
//# sourceMappingURL=codex-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-limits.d.ts","sourceRoot":"","sources":["../../../lib/tools/codex-limits.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAoBrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAwrBtE"}
|