opencode-nim-rotator 0.0.2 → 0.0.4
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/README.md +17 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -10
- package/dist/index.js.map +1 -1
- package/dist/storage.d.ts +21 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +272 -16
- package/dist/storage.js.map +1 -1
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +8 -14
- package/dist/themes.js.map +1 -1
- package/dist/tui/actions.d.ts +2 -0
- package/dist/tui/actions.d.ts.map +1 -1
- package/dist/tui/actions.js +48 -2
- package/dist/tui/actions.js.map +1 -1
- package/dist/tui/app.d.ts.map +1 -1
- package/dist/tui/app.js +21 -2
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/screens.d.ts +3 -0
- package/dist/tui/screens.d.ts.map +1 -1
- package/dist/tui/screens.js +121 -3
- package/dist/tui/screens.js.map +1 -1
- package/dist/tui/state.d.ts +3 -0
- package/dist/tui/state.d.ts.map +1 -1
- package/dist/tui/state.js +2 -0
- package/dist/tui/state.js.map +1 -1
- package/dist/tui/types.d.ts +1 -1
- package/dist/tui/types.d.ts.map +1 -1
- package/dist/tui/ui.js +1 -1
- package/dist/tui/ui.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +1 -1
- package/scripts/uninstall.js +39 -5
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ An [OpenCode](https://opencode.ai) plugin for managing and rotating multiple NVI
|
|
|
4
4
|
|
|
5
5
|
## How It Works
|
|
6
6
|
|
|
7
|
-
The plugin
|
|
7
|
+
The plugin hooks into OpenCode's `chat.headers` pipeline to inject a rotated API key into the `Authorization` header on every outgoing NVIDIA NIM API request. It also hooks `shell.env` so NVIDIA API keys are rotated for shell commands too.
|
|
8
8
|
|
|
9
|
-
**Key rotation happens per-request**: each LLM call uses the next key in the rotation. If a key returns 401
|
|
9
|
+
**Key rotation happens per-request**: each LLM call uses the next key in the rotation. If a key returns 401, 403, or 429, it automatically increments the failure count and retries with the next key.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -48,10 +48,12 @@ The TUI lets you:
|
|
|
48
48
|
- **Toggle** keys on/off
|
|
49
49
|
- **Reset** failure counts
|
|
50
50
|
- **Switch** rotation strategy (round-robin or least-failures)
|
|
51
|
+
- **Export** keys to a JSON file
|
|
52
|
+
- **Import** keys from a JSON file
|
|
51
53
|
|
|
52
54
|
### 3. Restart OpenCode
|
|
53
55
|
|
|
54
|
-
After adding keys, restart opencode. The plugin's `
|
|
56
|
+
After adding keys, restart opencode. The plugin's `chat.headers` hook will rotate keys on every NVIDIA API request.
|
|
55
57
|
|
|
56
58
|
## Configuration
|
|
57
59
|
|
|
@@ -61,6 +63,7 @@ After adding keys, restart opencode. The plugin's `auth` loader will fire on sta
|
|
|
61
63
|
| -------------------------- | ----------------------------------- | ------------------------------------------ |
|
|
62
64
|
| `NIM_ROTATOR_STORE_PATH` | Path to key store JSON file | `~/.config/opencode/nim-rotator-keys.json` |
|
|
63
65
|
| `NIM_ROTATOR_MAX_FAILURES` | Max failures before disabling a key | `5` |
|
|
66
|
+
| `NVIDIA_API_KEY` | Fallback API key (auto-seeded) | — |
|
|
64
67
|
|
|
65
68
|
### opencode.json Options
|
|
66
69
|
|
|
@@ -85,11 +88,11 @@ After adding keys, restart opencode. The plugin's `auth` loader will fire on sta
|
|
|
85
88
|
|
|
86
89
|
## How Key Rotation Works
|
|
87
90
|
|
|
88
|
-
1. On startup, the
|
|
89
|
-
2. Every NVIDIA API call goes through
|
|
90
|
-
3. The
|
|
91
|
+
1. On startup, the plugin loads the key store
|
|
92
|
+
2. Every NVIDIA API call goes through the `chat.headers` hook
|
|
93
|
+
3. The hook selects the next key based on the rotation strategy
|
|
91
94
|
4. The `Authorization: Bearer <key>` header is replaced with the rotated key
|
|
92
|
-
5. If the request returns 401
|
|
95
|
+
5. If the request returns 401, 403, or 429, the failure count is incremented and the next key is tried
|
|
93
96
|
6. Keys that exceed `NIM_ROTATOR_MAX_FAILURES` are automatically skipped
|
|
94
97
|
7. Successful requests reset the key's failure count to 0
|
|
95
98
|
|
|
@@ -163,11 +166,13 @@ Set the store `theme` field to `""` or remove it to revert to syncing with `open
|
|
|
163
166
|
|
|
164
167
|
The TUI is built with [OpenTUI](https://opentui.com) and provides a menu-driven interface:
|
|
165
168
|
|
|
166
|
-
- Main menu with Add,
|
|
167
|
-
- Key selector showing name, masked key, failure count, last used
|
|
168
|
-
- Key actions
|
|
169
|
-
- Add key flow: enter name, then enter key
|
|
170
|
-
- Theme selector with sync-to-opencode option
|
|
169
|
+
- **Main menu** with Manage, Add, Reset Failures, Export, Import, Strategy, Theme, and Quit options
|
|
170
|
+
- **Key selector** showing name, masked key, failure count, last used
|
|
171
|
+
- **Key actions**: toggle, rename, delete
|
|
172
|
+
- **Add key** flow: enter name, then enter key (must start with `nvapi-`)
|
|
173
|
+
- **Theme selector** with live preview and sync-to-opencode option
|
|
174
|
+
- **Export keys** to JSON file
|
|
175
|
+
- **Import keys** from JSON file with validation and deduplication
|
|
171
176
|
|
|
172
177
|
## Development
|
|
173
178
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAsB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAsB,MAAM,qBAAqB,CAAC;AA2CtE,eAAO,MAAM,mBAAmB,EAAE,MA8FjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,17 +3,27 @@ const PROVIDER_ID = "nvidia";
|
|
|
3
3
|
const NIM_BASE_URL = "https://integrate.api.nvidia.com";
|
|
4
4
|
const VALID_STRATEGIES = ["round-robin", "least-failures"];
|
|
5
5
|
function isValidStrategy(val) {
|
|
6
|
-
return
|
|
6
|
+
return val === "round-robin" || val === "least-failures";
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function isRecoverableError(obj) {
|
|
9
9
|
if (typeof obj === "object" && obj !== null) {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
10
|
+
const rec = obj;
|
|
11
|
+
const name = rec.name;
|
|
12
|
+
if (name === "ProviderAuthError")
|
|
13
13
|
return true;
|
|
14
|
+
if (name === "APIError") {
|
|
15
|
+
const data = rec.data;
|
|
16
|
+
const statusCode = data?.statusCode;
|
|
17
|
+
if (statusCode === 401 || statusCode === 403 || statusCode === 429)
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
14
20
|
}
|
|
15
21
|
const msg = String(obj).toLowerCase();
|
|
16
|
-
return (
|
|
22
|
+
return (/\b401\b/.test(msg) ||
|
|
23
|
+
/\b403\b/.test(msg) ||
|
|
24
|
+
/\b429\b/.test(msg) ||
|
|
25
|
+
msg.includes("unauthorized") ||
|
|
26
|
+
msg.includes("rate limit"));
|
|
17
27
|
}
|
|
18
28
|
export const NvidiaNimKeyRotator = async (input, options) => {
|
|
19
29
|
const config = {
|
|
@@ -89,10 +99,15 @@ export const NvidiaNimKeyRotator = async (input, options) => {
|
|
|
89
99
|
}
|
|
90
100
|
},
|
|
91
101
|
event: async ({ event }) => {
|
|
92
|
-
if (event.type === "session.error"
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
if (event.type === "session.error") {
|
|
103
|
+
const evt = event;
|
|
104
|
+
const props = evt.properties;
|
|
105
|
+
const error = evt.error ?? props?.error;
|
|
106
|
+
if (isRecoverableError(error)) {
|
|
107
|
+
if (store.lastUsedKeyId) {
|
|
108
|
+
recordFailure(store, store.lastUsedKeyId);
|
|
109
|
+
saveStore(store, config);
|
|
110
|
+
}
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
},
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EACT,SAAS,EACT,MAAM,EACN,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,MAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,MAAM,YAAY,GAAG,kCAAkC,CAAC;AACxD,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,gBAAgB,CAAU,CAAC;AAEpE,SAAS,eAAe,CACtB,GAAY;IAEZ,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { ApiKeyEntry, KeyStore, KeyStoreConfig } from "./types.js";
|
|
1
|
+
import type { ApiKeyEntry, ExportedKey, ExportPayload, KeyStore, KeyStoreConfig } from "./types.js";
|
|
2
2
|
export declare const DEFAULT_MAX_FAILURES = 5;
|
|
3
3
|
export declare function resolveStorePath(config?: KeyStoreConfig): string;
|
|
4
|
+
export declare function checkFilePermissions(filePath: string): string | null;
|
|
5
|
+
export declare function validateExportPath(filePath: string): string | null;
|
|
4
6
|
export declare function loadStore(config?: KeyStoreConfig): KeyStore;
|
|
5
7
|
export declare function saveStore(store: KeyStore, config?: KeyStoreConfig): void;
|
|
6
8
|
export declare function addKey(store: KeyStore, name: string, key: string): void;
|
|
@@ -15,4 +17,22 @@ export declare function getNextKey(store: KeyStore, config?: KeyStoreConfig): {
|
|
|
15
17
|
} | null;
|
|
16
18
|
export declare function recordFailure(store: KeyStore, keyId: string): void;
|
|
17
19
|
export declare function resetFailures(store: KeyStore, keyId?: string): void;
|
|
20
|
+
export declare function exportKeys(store: KeyStore): ExportPayload;
|
|
21
|
+
export declare function writeExportFile(payload: ExportPayload, filePath: string): void;
|
|
22
|
+
export declare function readAndValidateImportFile(filePath: string): {
|
|
23
|
+
raw: string;
|
|
24
|
+
} | {
|
|
25
|
+
error: string;
|
|
26
|
+
};
|
|
27
|
+
export interface ImportResult {
|
|
28
|
+
added: number;
|
|
29
|
+
skipped: number;
|
|
30
|
+
errors: string[];
|
|
31
|
+
pendingKeys: ExportedKey[];
|
|
32
|
+
}
|
|
33
|
+
export declare function validateImportPayload(raw: string): ImportResult;
|
|
34
|
+
export declare function applyImport(store: KeyStore, pendingKeys: ExportedKey[]): {
|
|
35
|
+
added: number;
|
|
36
|
+
skipped: number;
|
|
37
|
+
};
|
|
18
38
|
//# sourceMappingURL=storage.d.ts.map
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACb,QAAQ,EACR,cAAc,EACf,MAAM,YAAY,CAAC;AAQpB,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAkBtC,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAMhE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyBpE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAelE;AA2BD,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,QAAQ,CAmD3D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAmBxE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAUvE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAO3D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAG5E;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,QAAQ,EACf,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI,CAGN;AAED,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAK9D;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,QAAQ,EACf,MAAM,CAAC,EAAE,cAAc,GACtB,WAAW,EAAE,CAGf;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,QAAQ,EACf,MAAM,CAAC,EAAE,cAAc,GACtB;IAAE,GAAG,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAkC5C;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGlE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAOnE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,CAMzD;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,GACf,IAAI,CAmBN;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAerC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAuF/D;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,WAAW,EAAE,GACzB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAsBpC"}
|
package/dist/storage.js
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
-
import { join, dirname } from "path";
|
|
1
|
+
import { closeSync, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from "fs";
|
|
2
|
+
import { join, dirname, basename, resolve } from "path";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
const DEFAULT_STORE_PATH = join(homedir(), ".config", "opencode", "nim-rotator-keys.json");
|
|
5
5
|
export const DEFAULT_MAX_FAILURES = 5;
|
|
6
|
+
const MAX_IMPORT_SIZE = 1024 * 1024;
|
|
7
|
+
const MAX_IMPORT_KEYS = 100;
|
|
8
|
+
const MAX_KEY_LENGTH = 256;
|
|
9
|
+
const MAX_NAME_LENGTH = 128;
|
|
10
|
+
const SYSTEM_PATH_PREFIXES = ["/etc/", "/proc/", "/sys/", "/dev/"];
|
|
6
11
|
function getDefaultStore() {
|
|
7
12
|
return {
|
|
8
13
|
keys: [],
|
|
9
14
|
currentIndex: 0,
|
|
10
15
|
rotationStrategy: "round-robin",
|
|
11
16
|
updatedAt: Date.now(),
|
|
17
|
+
lastUsedKeyId: undefined,
|
|
12
18
|
};
|
|
13
19
|
}
|
|
14
20
|
export function resolveStorePath(config) {
|
|
@@ -16,24 +22,118 @@ export function resolveStorePath(config) {
|
|
|
16
22
|
process.env.NIM_ROTATOR_STORE_PATH ??
|
|
17
23
|
DEFAULT_STORE_PATH);
|
|
18
24
|
}
|
|
25
|
+
export function checkFilePermissions(filePath) {
|
|
26
|
+
try {
|
|
27
|
+
if (!existsSync(filePath))
|
|
28
|
+
return "File does not exist";
|
|
29
|
+
const resolvedPath = realpathSync(filePath);
|
|
30
|
+
const lstat = lstatSync(filePath);
|
|
31
|
+
if (lstat.isSymbolicLink()) {
|
|
32
|
+
return "File is a symbolic link. Refusing to follow symlinks.";
|
|
33
|
+
}
|
|
34
|
+
const stat = statSync(resolvedPath);
|
|
35
|
+
const mode = stat.mode;
|
|
36
|
+
const othersPerm = mode & 0o007;
|
|
37
|
+
if (othersPerm !== 0) {
|
|
38
|
+
return "File is world-accessible. Refusing to read from insecure file.";
|
|
39
|
+
}
|
|
40
|
+
const groupPerm = mode & 0o070;
|
|
41
|
+
if ((groupPerm & 0o040) !== 0) {
|
|
42
|
+
return "File is group-readable. Refusing to read from insecure file.";
|
|
43
|
+
}
|
|
44
|
+
if ((groupPerm & 0o020) !== 0) {
|
|
45
|
+
return "File is group-writable. Refusing to read from insecure file.";
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return "Cannot verify file permissions";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function validateExportPath(filePath) {
|
|
54
|
+
let resolved;
|
|
55
|
+
const dir = dirname(filePath);
|
|
56
|
+
try {
|
|
57
|
+
const dirRes = realpathSync(dir);
|
|
58
|
+
resolved = join(dirRes, basename(filePath));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
resolved = resolve(filePath);
|
|
62
|
+
}
|
|
63
|
+
for (const prefix of SYSTEM_PATH_PREFIXES) {
|
|
64
|
+
if (resolved.startsWith(prefix)) {
|
|
65
|
+
return "Cannot write to system directories";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function readSecureFile(filePath) {
|
|
71
|
+
let fd;
|
|
72
|
+
try {
|
|
73
|
+
fd = openSync(filePath, "r");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const stat = fstatSync(fd);
|
|
80
|
+
const mode = stat.mode;
|
|
81
|
+
const othersPerm = mode & 0o007;
|
|
82
|
+
if (othersPerm !== 0)
|
|
83
|
+
return null;
|
|
84
|
+
const groupPerm = mode & 0o070;
|
|
85
|
+
if ((groupPerm & 0o040) !== 0)
|
|
86
|
+
return null;
|
|
87
|
+
if ((groupPerm & 0o020) !== 0)
|
|
88
|
+
return null;
|
|
89
|
+
const buf = Buffer.alloc(stat.size);
|
|
90
|
+
const bytesRead = readSync(fd, buf, 0, stat.size, 0);
|
|
91
|
+
return buf.toString("utf-8", 0, bytesRead);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
closeSync(fd);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
19
100
|
export function loadStore(config) {
|
|
20
101
|
const storePath = resolveStorePath(config);
|
|
21
102
|
try {
|
|
22
103
|
if (existsSync(storePath)) {
|
|
23
|
-
const
|
|
104
|
+
const resolvedPath = realpathSync(storePath);
|
|
105
|
+
const lstat = lstatSync(storePath);
|
|
106
|
+
if (lstat.isSymbolicLink()) {
|
|
107
|
+
console.error("[nim-rotator] SECURITY: Key store is a symlink. Refusing to load.");
|
|
108
|
+
return getDefaultStore();
|
|
109
|
+
}
|
|
110
|
+
const permError = checkFilePermissions(storePath);
|
|
111
|
+
if (permError) {
|
|
112
|
+
console.error(`[nim-rotator] SECURITY: ${permError}`);
|
|
113
|
+
console.error(`[nim-rotator] Fix permissions: chmod 600 "${storePath}"`);
|
|
114
|
+
return getDefaultStore();
|
|
115
|
+
}
|
|
116
|
+
const raw = readFileSync(resolvedPath, "utf-8");
|
|
24
117
|
const data = JSON.parse(raw);
|
|
25
|
-
if (!data
|
|
26
|
-
console.warn(
|
|
118
|
+
if (!data || typeof data !== "object" || !Array.isArray(data.keys)) {
|
|
119
|
+
console.warn("[nim-rotator] Store has invalid format, using defaults");
|
|
27
120
|
return getDefaultStore();
|
|
28
121
|
}
|
|
29
122
|
return {
|
|
30
|
-
|
|
31
|
-
|
|
123
|
+
keys: Array.isArray(data.keys) ? data.keys : [],
|
|
124
|
+
currentIndex: typeof data.currentIndex === "number" ? data.currentIndex : 0,
|
|
125
|
+
rotationStrategy: data.rotationStrategy === "least-failures"
|
|
126
|
+
? "least-failures"
|
|
127
|
+
: "round-robin",
|
|
128
|
+
updatedAt: typeof data.updatedAt === "number" ? data.updatedAt : Date.now(),
|
|
129
|
+
lastUsedKeyId: typeof data.lastUsedKeyId === "string"
|
|
130
|
+
? data.lastUsedKeyId
|
|
131
|
+
: undefined,
|
|
32
132
|
};
|
|
33
133
|
}
|
|
34
134
|
}
|
|
35
|
-
catch
|
|
36
|
-
console.error(
|
|
135
|
+
catch {
|
|
136
|
+
console.error("[nim-rotator] Failed to load key store. Check file permissions and format.");
|
|
37
137
|
console.warn("[nim-rotator] Starting with a fresh store. Your existing keys are preserved on disk.");
|
|
38
138
|
}
|
|
39
139
|
return getDefaultStore();
|
|
@@ -42,12 +142,23 @@ export function saveStore(store, config) {
|
|
|
42
142
|
const storePath = resolveStorePath(config);
|
|
43
143
|
const dir = dirname(storePath);
|
|
44
144
|
if (!existsSync(dir)) {
|
|
45
|
-
mkdirSync(dir, { recursive: true });
|
|
145
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
46
146
|
}
|
|
47
147
|
store.updatedAt = Date.now();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
148
|
+
const tmpPath = storePath + ".tmp." + process.pid;
|
|
149
|
+
try {
|
|
150
|
+
writeFileSync(tmpPath, JSON.stringify(store, null, 2) + "\n", {
|
|
151
|
+
mode: 0o600,
|
|
152
|
+
});
|
|
153
|
+
renameSync(tmpPath, storePath);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
try {
|
|
157
|
+
unlinkSync(tmpPath);
|
|
158
|
+
}
|
|
159
|
+
catch { }
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
51
162
|
}
|
|
52
163
|
export function addKey(store, name, key) {
|
|
53
164
|
const entry = {
|
|
@@ -93,7 +204,12 @@ export function getNextKey(store, config) {
|
|
|
93
204
|
return null;
|
|
94
205
|
const strategy = config?.rotationStrategy ?? store.rotationStrategy ?? "round-robin";
|
|
95
206
|
if (strategy === "least-failures") {
|
|
96
|
-
const sorted = [...active].sort((a, b) =>
|
|
207
|
+
const sorted = [...active].sort((a, b) => {
|
|
208
|
+
if (a.failureCount !== b.failureCount) {
|
|
209
|
+
return a.failureCount - b.failureCount;
|
|
210
|
+
}
|
|
211
|
+
return (a.lastUsedAt ?? 0) - (b.lastUsedAt ?? 0);
|
|
212
|
+
});
|
|
97
213
|
const best = sorted[0];
|
|
98
214
|
const idx = store.keys.indexOf(best);
|
|
99
215
|
store.currentIndex = idx;
|
|
@@ -102,10 +218,15 @@ export function getNextKey(store, config) {
|
|
|
102
218
|
return { key: best, index: idx };
|
|
103
219
|
}
|
|
104
220
|
// round-robin
|
|
105
|
-
|
|
221
|
+
const idx = store.currentIndex % active.length;
|
|
106
222
|
const selected = active[idx];
|
|
107
223
|
const realIdx = store.keys.indexOf(selected);
|
|
108
|
-
store.currentIndex
|
|
224
|
+
if (store.currentIndex >= active.length) {
|
|
225
|
+
store.currentIndex = 0;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
store.currentIndex = (idx + 1) % active.length;
|
|
229
|
+
}
|
|
109
230
|
store.lastUsedKeyId = selected.id;
|
|
110
231
|
selected.lastUsedAt = Date.now();
|
|
111
232
|
return { key: selected, index: realIdx };
|
|
@@ -126,4 +247,139 @@ export function resetFailures(store, keyId) {
|
|
|
126
247
|
k.failureCount = 0;
|
|
127
248
|
}
|
|
128
249
|
}
|
|
250
|
+
export function exportKeys(store) {
|
|
251
|
+
return {
|
|
252
|
+
version: 1,
|
|
253
|
+
exportedAt: Date.now(),
|
|
254
|
+
keys: store.keys.map((k) => ({ name: k.name, key: k.key })),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
export function writeExportFile(payload, filePath) {
|
|
258
|
+
const pathError = validateExportPath(filePath);
|
|
259
|
+
if (pathError)
|
|
260
|
+
throw new Error(pathError);
|
|
261
|
+
const dir = dirname(filePath);
|
|
262
|
+
if (!existsSync(dir)) {
|
|
263
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
264
|
+
}
|
|
265
|
+
const tmpPath = filePath + ".tmp." + process.pid;
|
|
266
|
+
try {
|
|
267
|
+
writeFileSync(tmpPath, JSON.stringify(payload, null, 2) + "\n", {
|
|
268
|
+
mode: 0o600,
|
|
269
|
+
});
|
|
270
|
+
renameSync(tmpPath, filePath);
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
try {
|
|
274
|
+
unlinkSync(tmpPath);
|
|
275
|
+
}
|
|
276
|
+
catch { }
|
|
277
|
+
throw err;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
export function readAndValidateImportFile(filePath) {
|
|
281
|
+
const resolved = resolve(filePath);
|
|
282
|
+
for (const prefix of SYSTEM_PATH_PREFIXES) {
|
|
283
|
+
if (resolved.startsWith(prefix)) {
|
|
284
|
+
return { error: "Cannot read from system directories" };
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
let raw;
|
|
288
|
+
try {
|
|
289
|
+
raw = readFileSync(resolved, "utf-8");
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return { error: "Cannot read file" };
|
|
293
|
+
}
|
|
294
|
+
return { raw };
|
|
295
|
+
}
|
|
296
|
+
export function validateImportPayload(raw) {
|
|
297
|
+
const result = {
|
|
298
|
+
added: 0,
|
|
299
|
+
skipped: 0,
|
|
300
|
+
errors: [],
|
|
301
|
+
pendingKeys: [],
|
|
302
|
+
};
|
|
303
|
+
if (raw.length > MAX_IMPORT_SIZE) {
|
|
304
|
+
result.errors.push(`Import file too large (max ${MAX_IMPORT_SIZE / 1024}KB)`);
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
let data;
|
|
308
|
+
try {
|
|
309
|
+
data = JSON.parse(raw);
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
result.errors.push("Invalid JSON format");
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
if (typeof data !== "object" || data === null) {
|
|
316
|
+
result.errors.push("Expected a JSON object");
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
const rec = data;
|
|
320
|
+
if (rec.version !== 1) {
|
|
321
|
+
result.errors.push("Unsupported export version");
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
if (!Array.isArray(rec.keys)) {
|
|
325
|
+
result.errors.push("Missing or invalid 'keys' array");
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
for (const entry of rec.keys) {
|
|
329
|
+
if (result.pendingKeys.length >= MAX_IMPORT_KEYS) {
|
|
330
|
+
result.errors.push(`Too many keys in import file (max ${MAX_IMPORT_KEYS})`);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
if (typeof entry !== "object" ||
|
|
334
|
+
entry === null ||
|
|
335
|
+
typeof entry.name !== "string" ||
|
|
336
|
+
typeof entry.key !== "string") {
|
|
337
|
+
result.errors.push("Invalid key entry: must have 'name' and 'key' strings");
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const name = entry.name.trim();
|
|
341
|
+
const key = entry.key.trim();
|
|
342
|
+
if (!name) {
|
|
343
|
+
result.errors.push("Key entry has empty name");
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (name.length > MAX_NAME_LENGTH) {
|
|
347
|
+
result.errors.push("Key name exceeds maximum length");
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (!key) {
|
|
351
|
+
result.errors.push(`Key "${name}" has empty key value`);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (key.length > MAX_KEY_LENGTH) {
|
|
355
|
+
result.errors.push(`Key "${name}" exceeds maximum length`);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (!key.startsWith("nvapi-")) {
|
|
359
|
+
result.errors.push(`Key "${name}" does not start with 'nvapi-'`);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
result.pendingKeys.push({ name, key });
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
export function applyImport(store, pendingKeys) {
|
|
367
|
+
let added = 0;
|
|
368
|
+
let skipped = 0;
|
|
369
|
+
for (const { name, key } of pendingKeys) {
|
|
370
|
+
const existingByName = store.keys.find((k) => k.name === name);
|
|
371
|
+
if (existingByName) {
|
|
372
|
+
skipped++;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
const existingByKey = store.keys.find((k) => k.key === key);
|
|
376
|
+
if (existingByKey) {
|
|
377
|
+
skipped++;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
addKey(store, name, key);
|
|
381
|
+
added++;
|
|
382
|
+
}
|
|
383
|
+
return { added, skipped };
|
|
384
|
+
}
|
|
129
385
|
//# sourceMappingURL=storage.js.map
|
package/dist/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|
package/dist/themes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"AA6EA,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAWnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,CAOjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAWzE;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE;IACN,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;CAClC,EACD,MAAM,EAAE,iBAAiB,GACxB,IAAI,CASN;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AA+PD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAEjD;AAED,wBAAgB,UAAU,IAAI,YAAY,EAAE,CAE3C;AAED,wBAAgB,4BAA4B,IAAI,MAAM,GAAG,IAAI,CAG5D;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAM/C;
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"AA6EA,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAWnE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,CAOjE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAWzE;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE;IACN,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,CAAC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wBAAwB,EAAE,MAAM,CAAC;CAClC,EACD,MAAM,EAAE,iBAAiB,GACxB,IAAI,CASN;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AA+PD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAEjD;AAED,wBAAgB,UAAU,IAAI,YAAY,EAAE,CAE3C;AAED,wBAAgB,4BAA4B,IAAI,MAAM,GAAG,IAAI,CAG5D;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAM/C;AAID,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAQhD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAavD;AAID,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE5D;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,cAAc,IAAI,YAAY,CAS7C"}
|
package/dist/themes.js
CHANGED
|
@@ -369,12 +369,12 @@ export function getResolvedTheme() {
|
|
|
369
369
|
}
|
|
370
370
|
return themes["opencode"];
|
|
371
371
|
}
|
|
372
|
+
const THEME_OVERRIDE_PATH = join(CONFIG_DIR, "nim-rotator-theme.json");
|
|
372
373
|
export function getThemeOverride() {
|
|
373
374
|
try {
|
|
374
|
-
|
|
375
|
-
if (!existsSync(storePath))
|
|
375
|
+
if (!existsSync(THEME_OVERRIDE_PATH))
|
|
376
376
|
return null;
|
|
377
|
-
const raw = readFileSync(
|
|
377
|
+
const raw = readFileSync(THEME_OVERRIDE_PATH, "utf-8");
|
|
378
378
|
const data = JSON.parse(raw);
|
|
379
379
|
return data.theme ?? null;
|
|
380
380
|
}
|
|
@@ -383,23 +383,17 @@ export function getThemeOverride() {
|
|
|
383
383
|
}
|
|
384
384
|
export function saveThemeOverride(themeId) {
|
|
385
385
|
try {
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
if (existsSync(storePath)) {
|
|
389
|
-
const raw = readFileSync(storePath, "utf-8");
|
|
390
|
-
data = JSON.parse(raw);
|
|
391
|
-
}
|
|
392
|
-
data.theme = themeId;
|
|
393
|
-
const dir = dirname(storePath);
|
|
386
|
+
const data = { theme: themeId };
|
|
387
|
+
const dir = dirname(THEME_OVERRIDE_PATH);
|
|
394
388
|
if (!existsSync(dir)) {
|
|
395
|
-
mkdirSync(dir, { recursive: true });
|
|
389
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
396
390
|
}
|
|
397
|
-
writeFileSync(
|
|
391
|
+
writeFileSync(THEME_OVERRIDE_PATH, JSON.stringify(data, null, 2) + "\n", {
|
|
398
392
|
mode: 0o600,
|
|
399
393
|
});
|
|
400
394
|
}
|
|
401
395
|
catch (err) {
|
|
402
|
-
console.warn("[nim-rotator] Could not save theme preference
|
|
396
|
+
console.warn("[nim-rotator] Could not save theme preference");
|
|
403
397
|
}
|
|
404
398
|
}
|
|
405
399
|
let previewThemeOverride = null;
|