vskill 0.5.103 → 0.5.105
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 +147 -4
- package/agents.json +1 -1
- package/dist/agents/agents-registry.d.ts +13 -3
- package/dist/agents/agents-registry.js +100 -57
- package/dist/agents/agents-registry.js.map +1 -1
- package/dist/api/client.d.ts +21 -0
- package/dist/api/client.js +39 -5
- package/dist/api/client.js.map +1 -1
- package/dist/commands/diff.d.ts +6 -0
- package/dist/commands/diff.js +104 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/eval/serve.js +29 -83
- package/dist/commands/eval/serve.js.map +1 -1
- package/dist/commands/keys.d.ts +14 -0
- package/dist/commands/keys.js +166 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/masked-stdin.d.ts +14 -0
- package/dist/commands/masked-stdin.js +79 -0
- package/dist/commands/masked-stdin.js.map +1 -0
- package/dist/commands/skill.d.ts +6 -0
- package/dist/commands/skill.js +366 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/update.js +15 -4
- package/dist/commands/update.js.map +1 -1
- package/dist/core/skill-emitter.d.ts +37 -0
- package/dist/core/skill-emitter.js +333 -0
- package/dist/core/skill-emitter.js.map +1 -0
- package/dist/core/skill-generator.d.ts +27 -0
- package/dist/core/skill-generator.js +100 -0
- package/dist/core/skill-generator.js.map +1 -0
- package/dist/eval/anthropic-catalog.d.ts +49 -0
- package/dist/eval/anthropic-catalog.js +238 -0
- package/dist/eval/anthropic-catalog.js.map +1 -0
- package/dist/eval/llm.d.ts +1 -1
- package/dist/eval/llm.js +68 -10
- package/dist/eval/llm.js.map +1 -1
- package/dist/eval/mcp-detector.js +24 -3
- package/dist/eval/mcp-detector.js.map +1 -1
- package/dist/eval/model-resolver.d.ts +39 -0
- package/dist/eval/model-resolver.js +94 -0
- package/dist/eval/model-resolver.js.map +1 -0
- package/dist/eval/pricing.js +42 -16
- package/dist/eval/pricing.js.map +1 -1
- package/dist/eval/skill-scanner.d.ts +0 -5
- package/dist/eval/skill-scanner.js +0 -12
- package/dist/eval/skill-scanner.js.map +1 -1
- package/dist/eval-server/api-routes.d.ts +1 -0
- package/dist/eval-server/api-routes.js +191 -63
- package/dist/eval-server/api-routes.js.map +1 -1
- package/dist/eval-server/authoring-routes.js +21 -1
- package/dist/eval-server/authoring-routes.js.map +1 -1
- package/dist/eval-server/boot-preflight.js +8 -10
- package/dist/eval-server/boot-preflight.js.map +1 -1
- package/dist/eval-server/darwin-migrator.d.ts +57 -0
- package/dist/eval-server/darwin-migrator.js +169 -0
- package/dist/eval-server/darwin-migrator.js.map +1 -0
- package/dist/eval-server/eval-server.d.ts +1 -0
- package/dist/eval-server/eval-server.js +10 -0
- package/dist/eval-server/eval-server.js.map +1 -1
- package/dist/eval-server/providers.d.ts +7 -12
- package/dist/eval-server/providers.js +13 -15
- package/dist/eval-server/providers.js.map +1 -1
- package/dist/eval-server/settings-store.d.ts +17 -19
- package/dist/eval-server/settings-store.js +192 -189
- package/dist/eval-server/settings-store.js.map +1 -1
- package/dist/eval-server/skill-create-routes.d.ts +62 -0
- package/dist/eval-server/skill-create-routes.js +97 -132
- package/dist/eval-server/skill-create-routes.js.map +1 -1
- package/dist/eval-ui/assets/{CommandPalette-6cLEufX0.js → CommandPalette-DAWyTgXL.js} +1 -1
- package/dist/eval-ui/assets/CreateSkillPage-D5xmvnzV.js +12 -0
- package/dist/eval-ui/assets/UpdateDropdown-6bfwsX0-.js +1 -0
- package/dist/eval-ui/assets/index-C_-YXE6O.js +102 -0
- package/dist/eval-ui/index.html +1 -1
- package/dist/first-run-onboarding.d.ts +19 -0
- package/dist/first-run-onboarding.js +104 -0
- package/dist/first-run-onboarding.js.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/installer/canonical.d.ts +2 -0
- package/dist/installer/canonical.js +33 -3
- package/dist/installer/canonical.js.map +1 -1
- package/dist/studio/lib/ops-log.js +1 -4
- package/dist/studio/lib/ops-log.js.map +1 -1
- package/dist/studio/lib/scope-transfer.d.ts +0 -10
- package/dist/studio/lib/scope-transfer.js +13 -116
- package/dist/studio/lib/scope-transfer.js.map +1 -1
- package/dist/studio/routes/ops.js +3 -26
- package/dist/studio/routes/ops.js.map +1 -1
- package/dist/studio/routes/promote.js +15 -9
- package/dist/studio/routes/promote.js.map +1 -1
- package/dist/studio/routes/test-install.js +11 -4
- package/dist/studio/routes/test-install.js.map +1 -1
- package/dist/utils/agent-filter.js +5 -4
- package/dist/utils/agent-filter.js.map +1 -1
- package/dist/utils/resolve-binary.d.ts +22 -0
- package/dist/utils/resolve-binary.js +44 -1
- package/dist/utils/resolve-binary.js.map +1 -1
- package/package.json +3 -1
- package/scripts/preuninstall.cjs +2 -9
- package/dist/eval-ui/assets/CreateSkillPage-kn7xDaAP.js +0 -12
- package/dist/eval-ui/assets/UpdateDropdown-9qR5NxTi.js +0 -1
- package/dist/eval-ui/assets/index-4LdVR3Lo.js +0 -102
|
@@ -1,254 +1,265 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// settings-store.ts — File-backed
|
|
2
|
+
// settings-store.ts — File-backed credential store for vSkill Studio.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// `mergeStoredKeysIntoEnv(...)` so provider SDKs that read env vars
|
|
8
|
-
// directly (e.g. createAnthropicClient) see them without any wiring changes.
|
|
4
|
+
// Single on-disk file at `<configDir>/keys.env` (default configDir:
|
|
5
|
+
// `~/.vskill`, overridable via VSKILL_CONFIG_DIR). KEY=VALUE dotenv format.
|
|
6
|
+
// Atomic write via temp-file + rename; POSIX writes explicit 0600.
|
|
9
7
|
//
|
|
10
8
|
// Contract:
|
|
11
|
-
// -
|
|
12
|
-
// Only `redactKey()` output (`****<last-4>`)
|
|
13
|
-
// -
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
9
|
+
// - Raw keys NEVER appear in any log, error message, toast, or stdout.
|
|
10
|
+
// Only `redactKey()` output (`****<last-4>`) may be emitted.
|
|
11
|
+
// - `readKey()` consults `process.env` FIRST, then the raw-key `memoryMap`.
|
|
12
|
+
// After `mergeStoredKeysIntoEnv()` the `memoryMap` is cleared; subsequent
|
|
13
|
+
// reads hit process.env directly, minimizing plaintext dwell time.
|
|
14
|
+
// - `listKeys()` returns { stored, updatedAt } metadata only. A parallel
|
|
15
|
+
// `metadataMap` holds `{ updatedAt }` and SURVIVES merge, so listKeys()
|
|
16
|
+
// stays truthful across a boot cycle without keeping key bytes around.
|
|
17
|
+
// - `removeKey()` is idempotent; clears memoryMap, metadataMap, and the
|
|
18
|
+
// process.env entry (post-merge, env is where the live key lives).
|
|
19
|
+
// - Malformed lines in keys.env never crash parse — they are skipped with
|
|
20
|
+
// exactly ONE aggregated warning.
|
|
21
|
+
//
|
|
22
|
+
// Tests inject `{logger, fs, configDir}` via `resetSettingsStore(opts)`.
|
|
18
23
|
// ---------------------------------------------------------------------------
|
|
19
24
|
import * as nodeFs from "node:fs";
|
|
20
25
|
import * as os from "node:os";
|
|
21
26
|
import * as path from "node:path";
|
|
22
|
-
import { PROVIDERS } from "./providers.js";
|
|
27
|
+
import { PROVIDERS, } from "./providers.js";
|
|
23
28
|
// ---------------------------------------------------------------------------
|
|
24
|
-
//
|
|
29
|
+
// Module-level state. Tests reset via `resetSettingsStore()`.
|
|
25
30
|
// ---------------------------------------------------------------------------
|
|
26
|
-
export function redactKey(key) {
|
|
27
|
-
if (!key || key.length <= 4)
|
|
28
|
-
return "****";
|
|
29
|
-
return "****" + key.slice(-4);
|
|
30
|
-
}
|
|
31
31
|
const defaultLogger = {
|
|
32
32
|
warn: (m) => console.warn(m),
|
|
33
33
|
error: (m) => console.error(m),
|
|
34
|
-
info: (m) => console.info(m),
|
|
35
34
|
};
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
const memoryMap = new Map();
|
|
52
|
-
let loadedForPath = null;
|
|
35
|
+
// Wrappers read through the nodeFs namespace at CALL time so test files that
|
|
36
|
+
// mock `node:fs` without exporting every member (e.g. comparison-sse-events
|
|
37
|
+
// which only mocks existsSync/readFileSync/writeFileSync) don't fail at
|
|
38
|
+
// module-load time. Direct property access happens only inside the call.
|
|
39
|
+
const defaultFs = {
|
|
40
|
+
writeFileSync: (...args) => nodeFs.writeFileSync(...args),
|
|
41
|
+
renameSync: (...args) => nodeFs.renameSync(...args),
|
|
42
|
+
chmodSync: (...args) => nodeFs.chmodSync(...args),
|
|
43
|
+
readFileSync: ((...args) => nodeFs.readFileSync(...args)),
|
|
44
|
+
existsSync: (...args) => nodeFs.existsSync(...args),
|
|
45
|
+
unlinkSync: (...args) => nodeFs.unlinkSync(...args),
|
|
46
|
+
mkdirSync: ((...args) => nodeFs.mkdirSync(...args)),
|
|
47
|
+
statSync: ((...args) => nodeFs.statSync(...args)),
|
|
48
|
+
};
|
|
53
49
|
let logger = defaultLogger;
|
|
54
|
-
let
|
|
50
|
+
let fsImpl = defaultFs;
|
|
51
|
+
let configDirOverride = null;
|
|
52
|
+
const memoryMap = new Map();
|
|
53
|
+
// metadataMap retains `{ updatedAt }` after mergeStoredKeysIntoEnv() clears
|
|
54
|
+
// the raw-key memoryMap. Keeps listKeys() truthful across a boot cycle without
|
|
55
|
+
// extending plaintext dwell time.
|
|
56
|
+
const metadataMap = new Map();
|
|
57
|
+
let loaded = false;
|
|
55
58
|
// ---------------------------------------------------------------------------
|
|
56
59
|
// Path resolution
|
|
57
60
|
// ---------------------------------------------------------------------------
|
|
58
61
|
function resolveConfigDir() {
|
|
59
|
-
|
|
62
|
+
if (configDirOverride)
|
|
63
|
+
return configDirOverride;
|
|
64
|
+
const fromEnv = process.env.VSKILL_CONFIG_DIR;
|
|
65
|
+
if (fromEnv && fromEnv.length > 0)
|
|
66
|
+
return fromEnv;
|
|
67
|
+
return path.join(os.homedir(), ".vskill");
|
|
60
68
|
}
|
|
61
69
|
export function getKeysFilePath() {
|
|
62
70
|
return path.join(resolveConfigDir(), "keys.env");
|
|
63
71
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Redaction
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
export function redactKey(key) {
|
|
76
|
+
if (!key || key.length <= 4)
|
|
77
|
+
return "****";
|
|
78
|
+
return "****" + key.slice(-4);
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Parser — lenient, single aggregated warning
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
function parseFile(contents) {
|
|
69
84
|
const entries = new Map();
|
|
70
85
|
let malformedCount = 0;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
// Strip BOM.
|
|
87
|
+
const stripped = contents.replace(/^\uFEFF/, "");
|
|
88
|
+
const lines = stripped.split(/\r?\n/);
|
|
89
|
+
const envToId = new Map(PROVIDERS.map((p) => [p.envVarName, p.id]));
|
|
90
|
+
for (const rawLine of lines) {
|
|
91
|
+
const line = rawLine.trim();
|
|
92
|
+
if (line.length === 0)
|
|
75
93
|
continue;
|
|
76
|
-
|
|
77
|
-
if (eqIdx <= 0) {
|
|
78
|
-
malformedCount++;
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const key = line.slice(0, eqIdx).trim();
|
|
82
|
-
const value = line.slice(eqIdx + 1).trim();
|
|
83
|
-
if (key.length === 0 || value.length === 0) {
|
|
84
|
-
malformedCount++;
|
|
94
|
+
if (line.startsWith("#"))
|
|
85
95
|
continue;
|
|
96
|
+
try {
|
|
97
|
+
const eq = line.indexOf("=");
|
|
98
|
+
if (eq <= 0) {
|
|
99
|
+
malformedCount++;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const name = line.slice(0, eq).trim();
|
|
103
|
+
const value = line.slice(eq + 1).trim();
|
|
104
|
+
if (name.length === 0 || value.length === 0) {
|
|
105
|
+
malformedCount++;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const pid = envToId.get(name);
|
|
109
|
+
if (!pid) {
|
|
110
|
+
// Unknown env var name — skip silently (not "malformed", just
|
|
111
|
+
// unrelated). Do NOT count toward malformedCount.
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
entries.set(pid, { key: value, updatedAt: new Date().toISOString() });
|
|
86
115
|
}
|
|
87
|
-
|
|
88
|
-
const providerId = ENV_VAR_TO_PROVIDER.get(key);
|
|
89
|
-
if (!providerId) {
|
|
116
|
+
catch {
|
|
90
117
|
malformedCount++;
|
|
91
|
-
continue;
|
|
92
118
|
}
|
|
93
|
-
entries.set(providerId, { key: value, updatedAt: fileMtime });
|
|
94
119
|
}
|
|
95
120
|
return { entries, malformedCount };
|
|
96
121
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
|
-
function loadFromDisk() {
|
|
101
|
-
const filePath = getKeysFilePath();
|
|
102
|
-
if (loadedForPath === filePath)
|
|
122
|
+
function loadIfNeeded() {
|
|
123
|
+
if (loaded)
|
|
103
124
|
return;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (!
|
|
125
|
+
loaded = true;
|
|
126
|
+
const filePath = getKeysFilePath();
|
|
127
|
+
if (!fsImpl.existsSync(filePath))
|
|
107
128
|
return;
|
|
108
|
-
let content;
|
|
109
|
-
let mtime;
|
|
110
129
|
try {
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
130
|
+
const contents = fsImpl.readFileSync(filePath, "utf8");
|
|
131
|
+
const { entries, malformedCount } = parseFile(contents);
|
|
132
|
+
for (const [pid, entry] of entries)
|
|
133
|
+
memoryMap.set(pid, entry);
|
|
134
|
+
if (malformedCount > 0) {
|
|
135
|
+
logger.warn(`[settings-store] ${malformedCount} malformed line(s) in ${filePath} were skipped`);
|
|
136
|
+
}
|
|
114
137
|
}
|
|
115
138
|
catch (err) {
|
|
116
|
-
logger.warn(`[settings-store]
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const parsed = parseKeysEnv(content, mtime);
|
|
120
|
-
for (const [id, entry] of parsed.entries) {
|
|
121
|
-
memoryMap.set(id, entry);
|
|
122
|
-
}
|
|
123
|
-
if (parsed.malformedCount > 0) {
|
|
124
|
-
logger.warn(`[settings-store] ${parsed.malformedCount} malformed line(s) in ${filePath} were skipped`);
|
|
139
|
+
logger.warn(`[settings-store] failed to read ${filePath}: ${err.message}`);
|
|
125
140
|
}
|
|
126
141
|
}
|
|
127
142
|
// ---------------------------------------------------------------------------
|
|
128
|
-
//
|
|
143
|
+
// Serialization
|
|
129
144
|
// ---------------------------------------------------------------------------
|
|
130
|
-
function
|
|
131
|
-
const filePath = getKeysFilePath();
|
|
132
|
-
const dir = path.dirname(filePath);
|
|
133
|
-
// Ensure the config directory exists.
|
|
134
|
-
try {
|
|
135
|
-
if (!fsApi.existsSync(dir)) {
|
|
136
|
-
fsApi.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
catch (err) {
|
|
140
|
-
logger.error(`[settings-store] could not create config dir: ${err.message}`);
|
|
141
|
-
throw err;
|
|
142
|
-
}
|
|
143
|
-
// Build the file body in PROVIDERS order for stable output.
|
|
145
|
+
function serialize(entries) {
|
|
144
146
|
const lines = [
|
|
145
147
|
"# vskill credentials — do not commit. Managed by `vskill keys` or Skill Studio Settings.",
|
|
146
148
|
];
|
|
147
149
|
for (const p of PROVIDERS) {
|
|
148
|
-
const entry =
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
lines.push(`${p.envVarName}=${entry.key}`);
|
|
150
|
+
const entry = entries.get(p.id);
|
|
151
|
+
if (entry)
|
|
152
|
+
lines.push(`${p.envVarName}=${entry.key}`);
|
|
152
153
|
}
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
return lines.join("\n") + "\n";
|
|
155
|
+
}
|
|
156
|
+
function atomicWrite(contents) {
|
|
157
|
+
const filePath = getKeysFilePath();
|
|
158
|
+
const dir = path.dirname(filePath);
|
|
159
|
+
fsImpl.mkdirSync(dir, { recursive: true });
|
|
160
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
155
161
|
try {
|
|
156
|
-
|
|
162
|
+
fsImpl.writeFileSync(tmpPath, contents, "utf8");
|
|
157
163
|
if (process.platform !== "win32") {
|
|
158
164
|
try {
|
|
159
|
-
|
|
165
|
+
fsImpl.chmodSync(tmpPath, 0o600);
|
|
160
166
|
}
|
|
161
167
|
catch {
|
|
162
|
-
|
|
168
|
+
/* non-fatal; rename will still proceed */
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
|
-
|
|
171
|
+
fsImpl.renameSync(tmpPath, filePath);
|
|
166
172
|
}
|
|
167
173
|
catch (err) {
|
|
168
|
-
//
|
|
174
|
+
// Clean up tmp if present.
|
|
169
175
|
try {
|
|
170
|
-
if (
|
|
171
|
-
|
|
176
|
+
if (fsImpl.existsSync(tmpPath))
|
|
177
|
+
fsImpl.unlinkSync(tmpPath);
|
|
172
178
|
}
|
|
173
179
|
catch {
|
|
174
|
-
/*
|
|
180
|
+
/* swallow */
|
|
175
181
|
}
|
|
176
|
-
|
|
177
|
-
const sanitized = new Error(`[settings-store] atomic write to ${filePath} failed: ${err.message}`);
|
|
178
|
-
logger.error(sanitized.message);
|
|
179
|
-
throw sanitized;
|
|
182
|
+
throw err;
|
|
180
183
|
}
|
|
181
184
|
}
|
|
182
185
|
// ---------------------------------------------------------------------------
|
|
183
186
|
// Public API — save / read / remove / list
|
|
184
187
|
// ---------------------------------------------------------------------------
|
|
185
|
-
function assertProvider(provider) {
|
|
186
|
-
if (!PROVIDERS.some((p) => p.id === provider)) {
|
|
187
|
-
throw new Error(`unknown provider: ${String(provider)}`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
188
|
export async function saveKey(provider, key) {
|
|
191
189
|
if (!key || typeof key !== "string" || key.trim().length === 0) {
|
|
192
190
|
throw new Error("key must be non-empty string");
|
|
193
191
|
}
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
loadIfNeeded();
|
|
193
|
+
// Build the full entry set: current memory snapshot + new entry.
|
|
196
194
|
const updatedAt = new Date().toISOString();
|
|
197
|
-
|
|
195
|
+
const next = new Map(memoryMap);
|
|
196
|
+
next.set(provider, { key, updatedAt });
|
|
198
197
|
try {
|
|
199
|
-
|
|
198
|
+
atomicWrite(serialize(next));
|
|
200
199
|
}
|
|
201
200
|
catch (err) {
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
throw err;
|
|
201
|
+
// NEVER include the raw key in the error message.
|
|
202
|
+
const redacted = redactKey(key);
|
|
203
|
+
logger.error(`[settings-store] saveKey(${provider}, ${redacted}) failed: ${err.message}`);
|
|
204
|
+
throw new Error(`saveKey(${provider}, ${redacted}) failed: ${err.message}`);
|
|
207
205
|
}
|
|
206
|
+
memoryMap.set(provider, { key, updatedAt });
|
|
207
|
+
metadataMap.set(provider, { updatedAt });
|
|
208
208
|
return { updatedAt };
|
|
209
209
|
}
|
|
210
|
-
export
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
210
|
+
export function readKey(provider) {
|
|
211
|
+
loadIfNeeded();
|
|
212
|
+
const descriptor = PROVIDERS.find((p) => p.id === provider);
|
|
213
|
+
if (descriptor) {
|
|
214
|
+
const fromEnv = process.env[descriptor.envVarName];
|
|
215
|
+
if (fromEnv && fromEnv.length > 0)
|
|
216
|
+
return fromEnv;
|
|
217
|
+
}
|
|
218
218
|
return memoryMap.get(provider)?.key ?? null;
|
|
219
219
|
}
|
|
220
220
|
export function readKeySync(provider) {
|
|
221
|
-
|
|
222
|
-
loadFromDisk();
|
|
223
|
-
const p = PROVIDERS.find((x) => x.id === provider);
|
|
224
|
-
const envVal = process.env[p.envVarName];
|
|
225
|
-
if (envVal && envVal.length > 0)
|
|
226
|
-
return envVal;
|
|
227
|
-
return memoryMap.get(provider)?.key ?? null;
|
|
221
|
+
return readKey(provider);
|
|
228
222
|
}
|
|
229
223
|
export function hasKeySync(provider) {
|
|
230
|
-
|
|
231
|
-
loadFromDisk();
|
|
232
|
-
const p = PROVIDERS.find((x) => x.id === provider);
|
|
233
|
-
if (process.env[p.envVarName])
|
|
234
|
-
return true;
|
|
235
|
-
return memoryMap.has(provider);
|
|
224
|
+
return readKey(provider) !== null;
|
|
236
225
|
}
|
|
237
226
|
export async function removeKey(provider) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
227
|
+
loadIfNeeded();
|
|
228
|
+
// Idempotent: short-circuit only if neither map has the provider AND the
|
|
229
|
+
// on-disk file won't have it either. Post-merge, memoryMap is empty but
|
|
230
|
+
// metadataMap is the source of truth for "was it stored?".
|
|
231
|
+
if (!memoryMap.has(provider) && !metadataMap.has(provider))
|
|
241
232
|
return;
|
|
233
|
+
const next = new Map(memoryMap);
|
|
234
|
+
next.delete(provider);
|
|
235
|
+
try {
|
|
236
|
+
atomicWrite(serialize(next));
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
logger.error(`[settings-store] removeKey(${provider}) failed: ${err.message}`);
|
|
240
|
+
throw err;
|
|
241
|
+
}
|
|
242
242
|
memoryMap.delete(provider);
|
|
243
|
-
|
|
243
|
+
metadataMap.delete(provider);
|
|
244
|
+
// Clear the process.env copy too — post-merge, this is where the live key
|
|
245
|
+
// lives. Without this, a "remove" followed by a readKey() would still
|
|
246
|
+
// resolve the removed provider from process.env.
|
|
247
|
+
const descriptor = PROVIDERS.find((p) => p.id === provider);
|
|
248
|
+
if (descriptor)
|
|
249
|
+
delete process.env[descriptor.envVarName];
|
|
244
250
|
}
|
|
245
251
|
export function listKeys() {
|
|
246
|
-
|
|
247
|
-
const read = (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
loadIfNeeded();
|
|
253
|
+
const read = (p) => {
|
|
254
|
+
// memoryMap wins if present (freshest), else fall back to retained
|
|
255
|
+
// metadata from a prior mergeStoredKeysIntoEnv() call.
|
|
256
|
+
const live = memoryMap.get(p);
|
|
257
|
+
if (live)
|
|
258
|
+
return { stored: true, updatedAt: live.updatedAt };
|
|
259
|
+
const meta = metadataMap.get(p);
|
|
260
|
+
if (meta)
|
|
261
|
+
return { stored: true, updatedAt: meta.updatedAt };
|
|
262
|
+
return { stored: false, updatedAt: null };
|
|
252
263
|
};
|
|
253
264
|
return {
|
|
254
265
|
anthropic: read("anthropic"),
|
|
@@ -257,39 +268,31 @@ export function listKeys() {
|
|
|
257
268
|
};
|
|
258
269
|
}
|
|
259
270
|
// ---------------------------------------------------------------------------
|
|
260
|
-
//
|
|
261
|
-
// Real env vars WIN; only missing env vars are populated. After merge the
|
|
262
|
-
// in-memory map is cleared to shrink the plaintext dwell window.
|
|
271
|
+
// Boot-time env merge
|
|
263
272
|
// ---------------------------------------------------------------------------
|
|
264
273
|
export function mergeStoredKeysIntoEnv() {
|
|
265
|
-
|
|
274
|
+
loadIfNeeded();
|
|
266
275
|
for (const p of PROVIDERS) {
|
|
267
|
-
const
|
|
268
|
-
if (!
|
|
269
|
-
continue;
|
|
270
|
-
const current = process.env[p.envVarName];
|
|
271
|
-
if (current && current.length > 0) {
|
|
272
|
-
// Real env var wins — do not overwrite.
|
|
276
|
+
const entry = memoryMap.get(p.id);
|
|
277
|
+
if (!entry)
|
|
273
278
|
continue;
|
|
279
|
+
// Nullish coalescing: real env vars always win.
|
|
280
|
+
if (process.env[p.envVarName] === undefined) {
|
|
281
|
+
process.env[p.envVarName] = entry.key;
|
|
274
282
|
}
|
|
275
|
-
|
|
283
|
+
// Retain metadata so listKeys() can report `stored: true` post-merge
|
|
284
|
+
// without keeping the raw key plaintext around.
|
|
285
|
+
metadataMap.set(p.id, { updatedAt: entry.updatedAt });
|
|
276
286
|
}
|
|
277
|
-
// Shrink plaintext dwell
|
|
287
|
+
// Shrink plaintext dwell time.
|
|
278
288
|
memoryMap.clear();
|
|
279
|
-
// Keep loadedForPath so subsequent listKeys()/readKey() re-read from disk
|
|
280
|
-
// on demand rather than returning a stale empty map.
|
|
281
|
-
loadedForPath = null;
|
|
282
289
|
}
|
|
283
|
-
|
|
284
|
-
// Test hooks
|
|
285
|
-
// ---------------------------------------------------------------------------
|
|
286
|
-
export function resetSettingsStore(opts) {
|
|
290
|
+
export function resetSettingsStore(opts = {}) {
|
|
287
291
|
memoryMap.clear();
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return memoryMap.size;
|
|
292
|
+
metadataMap.clear();
|
|
293
|
+
loaded = false;
|
|
294
|
+
logger = opts.logger ?? defaultLogger;
|
|
295
|
+
fsImpl = opts.fs ?? defaultFs;
|
|
296
|
+
configDirOverride = opts.configDir ?? null;
|
|
294
297
|
}
|
|
295
298
|
//# sourceMappingURL=settings-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-store.js","sourceRoot":"","sources":["../../src/eval-server/settings-store.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,
|
|
1
|
+
{"version":3,"file":"settings-store.js","sourceRoot":"","sources":["../../src/eval-server/settings-store.ts"],"names":[],"mappings":"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"}
|