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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,eAAe,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;IACzD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;IACzD,mBAAmB,CAAC,EAAE,gBAAgB,CAAC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3D;AAMD,wBAAgB,aAAa,CAAC,EAAE,EAAE,gBAAgB,GAAG,gBAAgB,CAoCpE"}
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,43 @@
|
|
|
3
3
|
* Extracted from storage.ts to reduce module size.
|
|
4
4
|
*/
|
|
5
5
|
import { MODEL_FAMILIES } from "../prompts/codex.js";
|
|
6
|
+
/**
|
|
7
|
+
* StorageError code emitted when a `version: 2` account file is loaded.
|
|
8
|
+
*
|
|
9
|
+
* V2 is an intermediate account schema produced by legacy 4.x plugin builds
|
|
10
|
+
* that never shipped with a documented shape nor a forward-migrator to V3.
|
|
11
|
+
* The safe behaviour is to refuse to load V2 explicitly so the user's
|
|
12
|
+
* credentials are not silently discarded; callers surface this code to the
|
|
13
|
+
* user alongside a recovery hint.
|
|
14
|
+
*/
|
|
15
|
+
export const UNKNOWN_V2_FORMAT_CODE = "UNKNOWN_V2_FORMAT";
|
|
16
|
+
/**
|
|
17
|
+
* Diagnostic message shown when the loader refuses a V2 storage file.
|
|
18
|
+
* Pulled into a helper so storage.ts, import paths, and tests produce
|
|
19
|
+
* identical copy without drifting.
|
|
20
|
+
*/
|
|
21
|
+
export function buildV2RejectionMessage() {
|
|
22
|
+
return ("Unsupported account storage schema version 2; this plugin only ships " +
|
|
23
|
+
"migrations for v1 and v3. V2 files were produced by an intermediate " +
|
|
24
|
+
"4.x build that never documented its shape, so migrating blindly would " +
|
|
25
|
+
"risk silent account corruption.");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Recovery hint shown alongside the V2 rejection message.
|
|
29
|
+
* @param path - Absolute path of the offending storage file, or a placeholder
|
|
30
|
+
* when the caller cannot determine the source (e.g. in-memory normalization).
|
|
31
|
+
*/
|
|
32
|
+
export function buildV2RecoveryHint(path) {
|
|
33
|
+
const resolvedPath = path || "<unknown>";
|
|
34
|
+
return (`The storage file at ${resolvedPath} uses account schema v2, which ` +
|
|
35
|
+
"this plugin cannot migrate automatically. To recover: " +
|
|
36
|
+
"(1) back up the file outside the .opencode directory, " +
|
|
37
|
+
"(2) remove or rename the original so the plugin can start fresh, " +
|
|
38
|
+
"(3) run `opencode auth login` to create a v3 account pool, then " +
|
|
39
|
+
"(4) if you need the old credentials, open each account manually or " +
|
|
40
|
+
"re-run login per account. If you believe this file was produced by " +
|
|
41
|
+
"the current plugin, please open an issue so V2 can be documented.");
|
|
42
|
+
}
|
|
6
43
|
function nowMs() {
|
|
7
44
|
return Date.now();
|
|
8
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../lib/storage/migrations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AAKvE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAgB1D;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACtC,OAAO,CACN,uEAAuE;QACvE,sEAAsE;QACtE,wEAAwE;QACxE,iCAAiC,CACjC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC/C,MAAM,YAAY,GAAG,IAAI,IAAI,WAAW,CAAC;IACzC,OAAO,CACN,uBAAuB,YAAY,iCAAiC;QACpE,wDAAwD;QACxD,wDAAwD;QACxD,mEAAmE;QACnE,kEAAkE;QAClE,qEAAqE;QACrE,qEAAqE;QACrE,mEAAmE,CACnE,CAAC;AACH,CAAC;AA+DD,SAAS,KAAK;IACb,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAoB;IACjD,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;IACpB,OAAO;QACN,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACrC,MAAM,mBAAmB,GAAqB,EAAE,CAAC;YACjD,IAAI,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ,IAAI,OAAO,CAAC,kBAAkB,GAAG,GAAG,EAAE,CAAC;gBACxF,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;oBACrC,mBAAmB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;gBAC1D,CAAC;YACF,CAAC;YACD,OAAO;gBACN,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS;gBAClG,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,cAAc,EAAE,OAAO,CAAC,cAAc;aACtC,CAAC;QACH,CAAC,CAAC;QACF,WAAW,EAAE,EAAE,CAAC,WAAW;QAC3B,mBAAmB,EAAE,MAAM,CAAC,WAAW,CACtC,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAChB;KACzC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema normalization, forward-compat guard, and V2 detection for account
|
|
3
|
+
* storage files.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `lib/storage.ts` in RC-2. This module does not touch disk: it
|
|
6
|
+
* takes already-parsed JSON and returns a canonical `AccountStorageV3` (or
|
|
7
|
+
* throws a typed `StorageError` for schemas we can't safely read).
|
|
8
|
+
*/
|
|
9
|
+
import { type AccountStorageV3 } from "./migrations.js";
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes and validates account storage data, migrating from v1 to v3 if needed.
|
|
12
|
+
* Handles deduplication, index clamping, and per-family active index mapping.
|
|
13
|
+
* @param data - Raw storage data (unknown format)
|
|
14
|
+
* @param sourcePath - Optional origin path used for error diagnostics
|
|
15
|
+
* @returns Normalized AccountStorageV3 or null if invalid
|
|
16
|
+
* @throws StorageError (code `UNSUPPORTED_SCHEMA_VERSION`) when `data.version`
|
|
17
|
+
* is a finite number greater than the newest format this plugin understands.
|
|
18
|
+
* Throwing prevents a downgraded plugin from silently discarding future
|
|
19
|
+
* schemas that still contain valid credentials.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizeAccountStorage(data: unknown, sourcePath?: string): AccountStorageV3 | null;
|
|
22
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../lib/storage/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,EAOL,KAAK,gBAAgB,EACtB,MAAM,iBAAiB,CAAC;AAMzB;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,EACb,UAAU,CAAC,EAAE,MAAM,GAClB,gBAAgB,GAAG,IAAI,CAwHzB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema normalization, forward-compat guard, and V2 detection for account
|
|
3
|
+
* storage files.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `lib/storage.ts` in RC-2. This module does not touch disk: it
|
|
6
|
+
* takes already-parsed JSON and returns a canonical `AccountStorageV3` (or
|
|
7
|
+
* throws a typed `StorageError` for schemas we can't safely read).
|
|
8
|
+
*/
|
|
9
|
+
import { createLogger } from "../logger.js";
|
|
10
|
+
import { MODEL_FAMILIES } from "../prompts/codex.js";
|
|
11
|
+
import { AccountStorageV2DetectionSchema } from "../schemas.js";
|
|
12
|
+
import { StorageError } from "./errors.js";
|
|
13
|
+
import { clampIndex, deduplicateAccountsForStorage, extractActiveKeys, findAccountIndexByIdentityKeys, isRecord, } from "./identity.js";
|
|
14
|
+
import { buildV2RecoveryHint, buildV2RejectionMessage, migrateV1ToV3, UNKNOWN_V2_FORMAT_CODE, } from "./migrations.js";
|
|
15
|
+
const log = createLogger("storage");
|
|
16
|
+
/**
|
|
17
|
+
* Normalizes and validates account storage data, migrating from v1 to v3 if needed.
|
|
18
|
+
* Handles deduplication, index clamping, and per-family active index mapping.
|
|
19
|
+
* @param data - Raw storage data (unknown format)
|
|
20
|
+
* @param sourcePath - Optional origin path used for error diagnostics
|
|
21
|
+
* @returns Normalized AccountStorageV3 or null if invalid
|
|
22
|
+
* @throws StorageError (code `UNSUPPORTED_SCHEMA_VERSION`) when `data.version`
|
|
23
|
+
* is a finite number greater than the newest format this plugin understands.
|
|
24
|
+
* Throwing prevents a downgraded plugin from silently discarding future
|
|
25
|
+
* schemas that still contain valid credentials.
|
|
26
|
+
*/
|
|
27
|
+
export function normalizeAccountStorage(data, sourcePath) {
|
|
28
|
+
if (!isRecord(data)) {
|
|
29
|
+
log.warn("Invalid storage format, ignoring");
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const rawVersion = data.version;
|
|
33
|
+
// Forward-compat guard: a finite version above the newest supported schema
|
|
34
|
+
// signals a file written by a newer plugin build. Returning null here would
|
|
35
|
+
// make the caller treat the data as corrupt and overwrite it with an empty
|
|
36
|
+
// or downgraded payload, permanently destroying the user's accounts.
|
|
37
|
+
if (typeof rawVersion === "number" && Number.isFinite(rawVersion) && rawVersion > 3) {
|
|
38
|
+
const resolvedPath = sourcePath ?? "<unknown>";
|
|
39
|
+
const hint = `The storage file at ${resolvedPath} was written by a newer version ` +
|
|
40
|
+
`of this plugin (schema v${rawVersion}). Upgrade the plugin to a build ` +
|
|
41
|
+
`that understands schema v${rawVersion}, or back up and remove the ` +
|
|
42
|
+
`file to start fresh.`;
|
|
43
|
+
throw new StorageError(`Unsupported account storage schema version ${rawVersion}; this plugin supports up to version 3.`, "UNSUPPORTED_SCHEMA_VERSION", resolvedPath, hint);
|
|
44
|
+
}
|
|
45
|
+
// V2 files were produced by an intermediate 4.x build whose shape was never
|
|
46
|
+
// documented and for which no forward-migrator shipped. Silently treating
|
|
47
|
+
// them as "unknown version" (the previous behaviour) meant users with a V2
|
|
48
|
+
// file had their credentials discarded without any signal. Detect V2
|
|
49
|
+
// explicitly and throw a typed StorageError so the caller can surface the
|
|
50
|
+
// recovery hint to the user. Audit top-20 #8; see
|
|
51
|
+
// `lib/storage/migrations.ts:buildV2RejectionMessage` for copy.
|
|
52
|
+
if (AccountStorageV2DetectionSchema.safeParse(data).success) {
|
|
53
|
+
throw new StorageError(buildV2RejectionMessage(), UNKNOWN_V2_FORMAT_CODE, "", buildV2RecoveryHint(""));
|
|
54
|
+
}
|
|
55
|
+
if (data.version !== 1 && data.version !== 3) {
|
|
56
|
+
log.warn("Unknown storage version, ignoring", {
|
|
57
|
+
version: rawVersion,
|
|
58
|
+
});
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const rawAccounts = data.accounts;
|
|
62
|
+
if (!Array.isArray(rawAccounts)) {
|
|
63
|
+
log.warn("Invalid storage format, ignoring");
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const activeIndexValue = typeof data.activeIndex === "number" && Number.isFinite(data.activeIndex)
|
|
67
|
+
? data.activeIndex
|
|
68
|
+
: 0;
|
|
69
|
+
const rawActiveIndex = clampIndex(activeIndexValue, rawAccounts.length);
|
|
70
|
+
const activeKeys = extractActiveKeys(rawAccounts, rawActiveIndex);
|
|
71
|
+
const fromVersion = data.version;
|
|
72
|
+
const baseStorage = fromVersion === 1
|
|
73
|
+
? migrateV1ToV3(data)
|
|
74
|
+
: data;
|
|
75
|
+
const validAccounts = rawAccounts.filter((account) => isRecord(account) && typeof account.refreshToken === "string" && !!account.refreshToken.trim());
|
|
76
|
+
const deduplicatedAccounts = deduplicateAccountsForStorage(validAccounts);
|
|
77
|
+
const activeIndex = (() => {
|
|
78
|
+
if (deduplicatedAccounts.length === 0)
|
|
79
|
+
return 0;
|
|
80
|
+
if (activeKeys.length > 0) {
|
|
81
|
+
const mappedIndex = findAccountIndexByIdentityKeys(deduplicatedAccounts, activeKeys);
|
|
82
|
+
if (mappedIndex >= 0)
|
|
83
|
+
return mappedIndex;
|
|
84
|
+
}
|
|
85
|
+
return clampIndex(rawActiveIndex, deduplicatedAccounts.length);
|
|
86
|
+
})();
|
|
87
|
+
const activeIndexByFamily = {};
|
|
88
|
+
const rawFamilyIndices = isRecord(baseStorage.activeIndexByFamily)
|
|
89
|
+
? baseStorage.activeIndexByFamily
|
|
90
|
+
: {};
|
|
91
|
+
for (const family of MODEL_FAMILIES) {
|
|
92
|
+
const rawIndexValue = rawFamilyIndices[family];
|
|
93
|
+
const rawIndex = typeof rawIndexValue === "number" && Number.isFinite(rawIndexValue)
|
|
94
|
+
? rawIndexValue
|
|
95
|
+
: rawActiveIndex;
|
|
96
|
+
const clampedRawIndex = clampIndex(rawIndex, rawAccounts.length);
|
|
97
|
+
const familyKeys = extractActiveKeys(rawAccounts, clampedRawIndex);
|
|
98
|
+
let mappedIndex = clampIndex(rawIndex, deduplicatedAccounts.length);
|
|
99
|
+
if (familyKeys.length > 0 && deduplicatedAccounts.length > 0) {
|
|
100
|
+
const idx = findAccountIndexByIdentityKeys(deduplicatedAccounts, familyKeys);
|
|
101
|
+
if (idx >= 0) {
|
|
102
|
+
mappedIndex = idx;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
activeIndexByFamily[family] = mappedIndex;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
version: 3,
|
|
109
|
+
accounts: deduplicatedAccounts,
|
|
110
|
+
activeIndex,
|
|
111
|
+
activeIndexByFamily,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../lib/storage/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../lib/storage/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../lib/storage/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAgBD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAQhE;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB/D;AAcD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyBpD"}
|
|
@@ -6,6 +6,7 @@ import { existsSync } from "node:fs";
|
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
8
8
|
import { homedir, tmpdir } from "node:os";
|
|
9
|
+
import { StorageError } from "../errors.js";
|
|
9
10
|
const PROJECT_MARKERS = [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".opencode"];
|
|
10
11
|
const PROJECTS_DIR = "projects";
|
|
11
12
|
const PROJECT_KEY_HASH_LENGTH = 12;
|
|
@@ -85,7 +86,7 @@ export function resolvePath(filePath) {
|
|
|
85
86
|
if (!isWithinDirectory(home, resolved) &&
|
|
86
87
|
!isWithinDirectory(cwd, resolved) &&
|
|
87
88
|
!isWithinDirectory(tmp, resolved)) {
|
|
88
|
-
throw new
|
|
89
|
+
throw new StorageError(`Access denied: path must be within home directory, project directory, or temp directory`, "PATH_ACCESS_DENIED", resolved, "The requested path is outside the allowed roots (home, project, temp). Pick a path inside one of those directories.");
|
|
89
90
|
}
|
|
90
91
|
return resolved;
|
|
91
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../lib/storage/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../lib/storage/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-scoped storage state and the single shared mutex that serializes
|
|
3
|
+
* every read-modify-write against the accounts files.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `lib/storage.ts` in RC-2 so the identity helpers, normalize,
|
|
6
|
+
* load/save, flagged, and export-import modules can all share the same
|
|
7
|
+
* resolved path and the same lock without creating circular imports.
|
|
8
|
+
*
|
|
9
|
+
* Invariants this module preserves:
|
|
10
|
+
* - `currentStoragePath` is either `null` (use global fallback) or an
|
|
11
|
+
* absolute path to a project-scoped accounts file.
|
|
12
|
+
* - `currentProjectRoot` is only non-null when `currentStoragePath` is
|
|
13
|
+
* project-scoped; `setStoragePathDirect` deliberately clears it so
|
|
14
|
+
* ad-hoc overrides (tests, one-off CLI paths) never look like a real
|
|
15
|
+
* project.
|
|
16
|
+
* - `withStorageLock` chains every critical section through a single
|
|
17
|
+
* promise so nothing can interleave between a load and its paired save.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Serializes storage I/O to keep account file reads/writes lock-step and avoid
|
|
21
|
+
* cross-request races during migration/seeding flows.
|
|
22
|
+
*/
|
|
23
|
+
export declare function withStorageLock<T>(fn: () => Promise<T>): Promise<T>;
|
|
24
|
+
export declare function setStoragePath(projectPath: string | null): void;
|
|
25
|
+
export declare function setStoragePathDirect(path: string | null): void;
|
|
26
|
+
/**
|
|
27
|
+
* Returns the file path for the account storage JSON file.
|
|
28
|
+
* @returns Absolute path to the accounts.json file
|
|
29
|
+
*/
|
|
30
|
+
export declare function getStoragePath(): string;
|
|
31
|
+
export declare function getCurrentStoragePath(): string | null;
|
|
32
|
+
export declare function getCurrentLegacyProjectStoragePath(): string | null;
|
|
33
|
+
export declare function getCurrentProjectRoot(): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the project storage key (e.g. `my-project-abc123def456`) that the
|
|
36
|
+
* active project storage path is rooted under, or `null` when no per-project
|
|
37
|
+
* root is active (global storage is in use). Used by the opt-in keychain
|
|
38
|
+
* backend as the account identifier so each project's credentials live
|
|
39
|
+
* under a distinct (service, account) pair in the OS keychain.
|
|
40
|
+
*
|
|
41
|
+
* When `setStoragePathDirect` overrode the path to something outside the
|
|
42
|
+
* standard per-project layout (tests, custom CLI override), we fall back to
|
|
43
|
+
* `null` because there is no meaningful project identity to key off.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getCurrentProjectStorageKey(): string | null;
|
|
46
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../lib/storage/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOnE;AAMD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAkB/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAI9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAMD,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,kCAAkC,IAAI,MAAM,GAAG,IAAI,CAElE;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,IAAI,CAG3D"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-scoped storage state and the single shared mutex that serializes
|
|
3
|
+
* every read-modify-write against the accounts files.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `lib/storage.ts` in RC-2 so the identity helpers, normalize,
|
|
6
|
+
* load/save, flagged, and export-import modules can all share the same
|
|
7
|
+
* resolved path and the same lock without creating circular imports.
|
|
8
|
+
*
|
|
9
|
+
* Invariants this module preserves:
|
|
10
|
+
* - `currentStoragePath` is either `null` (use global fallback) or an
|
|
11
|
+
* absolute path to a project-scoped accounts file.
|
|
12
|
+
* - `currentProjectRoot` is only non-null when `currentStoragePath` is
|
|
13
|
+
* project-scoped; `setStoragePathDirect` deliberately clears it so
|
|
14
|
+
* ad-hoc overrides (tests, one-off CLI paths) never look like a real
|
|
15
|
+
* project.
|
|
16
|
+
* - `withStorageLock` chains every critical section through a single
|
|
17
|
+
* promise so nothing can interleave between a load and its paired save.
|
|
18
|
+
*/
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { ACCOUNTS_FILE_NAME, LEGACY_ACCOUNTS_FILE_NAME } from "../constants.js";
|
|
21
|
+
import { findProjectRoot, getConfigDir, getProjectConfigDir, getProjectGlobalConfigDir, getProjectStorageKey, } from "./paths.js";
|
|
22
|
+
let storageMutex = Promise.resolve();
|
|
23
|
+
/**
|
|
24
|
+
* Serializes storage I/O to keep account file reads/writes lock-step and avoid
|
|
25
|
+
* cross-request races during migration/seeding flows.
|
|
26
|
+
*/
|
|
27
|
+
export function withStorageLock(fn) {
|
|
28
|
+
const previousMutex = storageMutex;
|
|
29
|
+
let releaseLock;
|
|
30
|
+
storageMutex = new Promise((resolve) => {
|
|
31
|
+
releaseLock = resolve;
|
|
32
|
+
});
|
|
33
|
+
return previousMutex.then(fn).finally(() => releaseLock());
|
|
34
|
+
}
|
|
35
|
+
let currentStoragePath = null;
|
|
36
|
+
let currentLegacyProjectStoragePath = null;
|
|
37
|
+
let currentProjectRoot = null;
|
|
38
|
+
export function setStoragePath(projectPath) {
|
|
39
|
+
if (!projectPath) {
|
|
40
|
+
currentStoragePath = null;
|
|
41
|
+
currentLegacyProjectStoragePath = null;
|
|
42
|
+
currentProjectRoot = null;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const projectRoot = findProjectRoot(projectPath);
|
|
46
|
+
if (projectRoot) {
|
|
47
|
+
currentProjectRoot = projectRoot;
|
|
48
|
+
currentStoragePath = join(getProjectGlobalConfigDir(projectRoot), ACCOUNTS_FILE_NAME);
|
|
49
|
+
currentLegacyProjectStoragePath = join(getProjectConfigDir(projectRoot), LEGACY_ACCOUNTS_FILE_NAME);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
currentStoragePath = null;
|
|
53
|
+
currentLegacyProjectStoragePath = null;
|
|
54
|
+
currentProjectRoot = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function setStoragePathDirect(path) {
|
|
58
|
+
currentStoragePath = path;
|
|
59
|
+
currentLegacyProjectStoragePath = null;
|
|
60
|
+
currentProjectRoot = null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns the file path for the account storage JSON file.
|
|
64
|
+
* @returns Absolute path to the accounts.json file
|
|
65
|
+
*/
|
|
66
|
+
export function getStoragePath() {
|
|
67
|
+
if (currentStoragePath) {
|
|
68
|
+
return currentStoragePath;
|
|
69
|
+
}
|
|
70
|
+
return join(getConfigDir(), ACCOUNTS_FILE_NAME);
|
|
71
|
+
}
|
|
72
|
+
// Internal accessors used by sibling storage modules. Not re-exported from the
|
|
73
|
+
// top-level barrel: callers outside `lib/storage/` should use the public
|
|
74
|
+
// `setStoragePath` / `getStoragePath` APIs.
|
|
75
|
+
export function getCurrentStoragePath() {
|
|
76
|
+
return currentStoragePath;
|
|
77
|
+
}
|
|
78
|
+
export function getCurrentLegacyProjectStoragePath() {
|
|
79
|
+
return currentLegacyProjectStoragePath;
|
|
80
|
+
}
|
|
81
|
+
export function getCurrentProjectRoot() {
|
|
82
|
+
return currentProjectRoot;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns the project storage key (e.g. `my-project-abc123def456`) that the
|
|
86
|
+
* active project storage path is rooted under, or `null` when no per-project
|
|
87
|
+
* root is active (global storage is in use). Used by the opt-in keychain
|
|
88
|
+
* backend as the account identifier so each project's credentials live
|
|
89
|
+
* under a distinct (service, account) pair in the OS keychain.
|
|
90
|
+
*
|
|
91
|
+
* When `setStoragePathDirect` overrode the path to something outside the
|
|
92
|
+
* standard per-project layout (tests, custom CLI override), we fall back to
|
|
93
|
+
* `null` because there is no meaningful project identity to key off.
|
|
94
|
+
*/
|
|
95
|
+
export function getCurrentProjectStorageKey() {
|
|
96
|
+
if (!currentProjectRoot)
|
|
97
|
+
return null;
|
|
98
|
+
return getProjectStorageKey(currentProjectRoot);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../lib/storage/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EACL,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,IAAI,YAAY,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAI,EAAoB;IACrD,MAAM,aAAa,GAAG,YAAY,CAAC;IACnC,IAAI,WAAuB,CAAC;IAC5B,YAAY,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC3C,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC,CAAC,CAAC;IACH,OAAO,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAC7C,IAAI,+BAA+B,GAAkB,IAAI,CAAC;AAC1D,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C,MAAM,UAAU,cAAc,CAAC,WAA0B;IACvD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,kBAAkB,GAAG,IAAI,CAAC;QAC1B,+BAA+B,GAAG,IAAI,CAAC;QACvC,kBAAkB,GAAG,IAAI,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,WAAW,EAAE,CAAC;QAChB,kBAAkB,GAAG,WAAW,CAAC;QACjC,kBAAkB,GAAG,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACtF,+BAA+B,GAAG,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACtG,CAAC;SAAM,CAAC;QACN,kBAAkB,GAAG,IAAI,CAAC;QAC1B,+BAA+B,GAAG,IAAI,CAAC;QACvC,kBAAkB,GAAG,IAAI,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAmB;IACtD,kBAAkB,GAAG,IAAI,CAAC;IAC1B,+BAA+B,GAAG,IAAI,CAAC;IACvC,kBAAkB,GAAG,IAAI,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,+EAA+E;AAC/E,yEAAyE;AACzE,4CAA4C;AAE5C,MAAM,UAAU,qBAAqB;IACnC,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,kCAAkC;IAChD,OAAO,+BAA+B,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B;IACzC,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-worktree collision detection for per-project account storage.
|
|
3
|
+
*
|
|
4
|
+
* Problem: when multiple OpenCode sessions (tabs, IDE windows, detached
|
|
5
|
+
* worktrees, or CI runs) point at the same per-project accounts file, their
|
|
6
|
+
* writes can interleave and lose rotation updates, health-score changes, or
|
|
7
|
+
* rate-limit state. The in-process `withStorageLock` mutex solves intra-process
|
|
8
|
+
* races but cannot see another Node process mutating the same file.
|
|
9
|
+
*
|
|
10
|
+
* Strategy: sidecar lock file at `<storage>.lock`. Every `loadAccounts` /
|
|
11
|
+
* `saveAccounts` call verifies ownership:
|
|
12
|
+
*
|
|
13
|
+
* - No lock on disk -> write our own, proceed.
|
|
14
|
+
* - Lock owned by us (same pid + hostname) -> refresh `lastActive`, proceed.
|
|
15
|
+
* - Foreign lock with dead owner (same host, pid gone) -> take over.
|
|
16
|
+
* - Foreign lock stale (`lastActive` older than STALE_THRESHOLD_MS) -> take
|
|
17
|
+
* over. Required because a prior process that SIGKILL'd never released
|
|
18
|
+
* its lock, so "dead pid" detection alone leaks locks on long-lived hosts.
|
|
19
|
+
* - Foreign lock live -> surface a WARNING to the logger identifying both
|
|
20
|
+
* worktrees and proceed anyway. The locking contract here is advisory
|
|
21
|
+
* (Phase 4 F2 audit recommendation): blocking would strand the user when
|
|
22
|
+
* two legitimate sessions share a project, so we prefer visibility over
|
|
23
|
+
* enforcement.
|
|
24
|
+
*
|
|
25
|
+
* Cross-host note: we cannot probe a PID on a different machine, so a lock
|
|
26
|
+
* written from another hostname is always treated as live until its
|
|
27
|
+
* `lastActive` timestamp ages past STALE_THRESHOLD_MS. This is conservative
|
|
28
|
+
* but matches the audit requirement to "not block" — the worst case is a
|
|
29
|
+
* warning the user can dismiss.
|
|
30
|
+
*
|
|
31
|
+
* See `docs/audits/08-feature-recommendations.md` and
|
|
32
|
+
* `docs/audits/13-phased-roadmap.md#phase-4-f2` for background.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Time after which a lock whose owner never refreshed it is considered
|
|
36
|
+
* abandoned, regardless of PID liveness. One hour matches the roadmap spec
|
|
37
|
+
* and is long enough to avoid stealing a lock from a session that is merely
|
|
38
|
+
* idle between saves.
|
|
39
|
+
*/
|
|
40
|
+
export declare const STALE_THRESHOLD_MS: number;
|
|
41
|
+
/**
|
|
42
|
+
* Persisted lock-file payload. Written as pretty-printed JSON so a human
|
|
43
|
+
* inspecting the file can immediately tell which worktree holds the lock.
|
|
44
|
+
*/
|
|
45
|
+
export interface WorktreeLockInfo {
|
|
46
|
+
pid: number;
|
|
47
|
+
hostname: string;
|
|
48
|
+
cwd: string;
|
|
49
|
+
startedAt: string;
|
|
50
|
+
lastActive: string;
|
|
51
|
+
}
|
|
52
|
+
export interface AcquireLockResult {
|
|
53
|
+
/** True when we now own the lock on disk. */
|
|
54
|
+
acquired: boolean;
|
|
55
|
+
/** Populated only when a foreign live lock was detected. */
|
|
56
|
+
foreign?: WorktreeLockInfo;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Checks ownership of the worktree lock and acquires it when possible.
|
|
60
|
+
*
|
|
61
|
+
* Contract:
|
|
62
|
+
* - Never throws on lock I/O errors *other than* propagating read/write
|
|
63
|
+
* failures the caller needs to know about (disk full, EACCES).
|
|
64
|
+
* - Always returns a discriminated result: either `acquired: true` (we
|
|
65
|
+
* now own or refreshed the lock) or `acquired: false` with `foreign`
|
|
66
|
+
* populated (another live worktree owns it; caller should warn).
|
|
67
|
+
* - Never blocks. This is advisory locking by design.
|
|
68
|
+
*/
|
|
69
|
+
export declare function acquireOrDetectLock(storagePath: string): Promise<AcquireLockResult>;
|
|
70
|
+
export declare function releaseLock(storagePath: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Test-only reset hook. Vitest reuses a single Node process across files,
|
|
73
|
+
* so `ownedLockPaths` state would leak between suites and confuse the
|
|
74
|
+
* "no lock on disk" acquire branch. Not re-exported from the barrel.
|
|
75
|
+
*/
|
|
76
|
+
export declare function __resetWorktreeLockForTests(): void;
|
|
77
|
+
/** Test-only: inspect owned paths without exposing the internal Set. */
|
|
78
|
+
export declare function __getOwnedLockPathsForTests(): readonly string[];
|
|
79
|
+
//# sourceMappingURL=worktree-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-lock.d.ts","sourceRoot":"","sources":["../../../lib/storage/worktree-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AASH;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC3B;AAqID;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACxC,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAkD5B;AAyBD,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD;AAED,wEAAwE;AACxE,wBAAgB,2BAA2B,IAAI,SAAS,MAAM,EAAE,CAE/D"}
|