@datename/fastcode-termux 0.1.6 → 0.1.8-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -0
- package/README.md +67 -16
- package/dist/agent/approval-json.d.ts +43 -0
- package/dist/agent/approval-json.js +69 -0
- package/dist/agent/approval-native.d.ts +3 -0
- package/dist/agent/approval-native.js +165 -0
- package/dist/agent/approval-store.d.ts +16 -0
- package/dist/agent/approval-store.js +21 -0
- package/dist/agent/approval.d.ts +83 -0
- package/dist/agent/approval.js +42 -0
- package/dist/agent/compaction.d.ts +41 -0
- package/dist/agent/compaction.js +270 -0
- package/dist/agent/context.d.ts +29 -0
- package/dist/agent/context.js +62 -0
- package/dist/agent/guards.d.ts +24 -16
- package/dist/agent/guards.js +1167 -18
- package/dist/agent/ignore.d.ts +11 -0
- package/dist/agent/ignore.js +129 -0
- package/dist/agent/policy/defaults.d.ts +16 -0
- package/dist/agent/policy/defaults.js +17 -0
- package/dist/agent/policy/egress.d.ts +32 -0
- package/dist/agent/policy/egress.js +280 -0
- package/dist/agent/process-tree.d.ts +22 -0
- package/dist/agent/process-tree.js +102 -0
- package/dist/agent/protocol-mode.d.ts +6 -0
- package/dist/agent/protocol-mode.js +51 -0
- package/dist/agent/protocol.d.ts +20 -1
- package/dist/agent/protocol.js +169 -39
- package/dist/agent/registry.d.ts +19 -0
- package/dist/agent/registry.js +247 -0
- package/dist/agent/runner.d.ts +127 -0
- package/dist/agent/runner.js +391 -0
- package/dist/agent/shell-ast.d.ts +11 -0
- package/dist/agent/shell-ast.js +204 -0
- package/dist/agent/shell-session.d.ts +51 -0
- package/dist/agent/shell-session.js +611 -0
- package/dist/agent/stream.d.ts +29 -0
- package/dist/agent/stream.js +103 -0
- package/dist/agent/tool-schemas.d.ts +2 -0
- package/dist/agent/tool-schemas.js +82 -0
- package/dist/agent/tools/append_file.d.ts +2 -0
- package/dist/agent/tools/append_file.js +28 -0
- package/dist/agent/tools/apply_patch.d.ts +10 -0
- package/dist/agent/tools/apply_patch.js +92 -0
- package/dist/agent/tools/copy_file.d.ts +2 -0
- package/dist/agent/tools/copy_file.js +53 -0
- package/dist/agent/tools/delete_file.d.ts +2 -0
- package/dist/agent/tools/delete_file.js +43 -0
- package/dist/agent/tools/grep.d.ts +2 -0
- package/dist/agent/tools/grep.js +54 -0
- package/dist/agent/tools/index.d.ts +2 -0
- package/dist/agent/tools/index.js +32 -0
- package/dist/agent/tools/list_files.d.ts +2 -0
- package/dist/agent/tools/list_files.js +17 -0
- package/dist/agent/tools/make_dir.d.ts +2 -0
- package/dist/agent/tools/make_dir.js +26 -0
- package/dist/agent/tools/move_path.d.ts +9 -0
- package/dist/agent/tools/move_path.js +73 -0
- package/dist/agent/tools/paths.d.ts +7 -0
- package/dist/agent/tools/paths.js +84 -0
- package/dist/agent/tools/pwd.d.ts +2 -0
- package/dist/agent/tools/pwd.js +10 -0
- package/dist/agent/tools/read_file.d.ts +2 -0
- package/dist/agent/tools/read_file.js +81 -0
- package/dist/agent/tools/read_many.d.ts +2 -0
- package/dist/agent/tools/read_many.js +43 -0
- package/dist/agent/tools/readers.d.ts +58 -0
- package/dist/agent/tools/readers.js +426 -0
- package/dist/agent/tools/replace_in_file.d.ts +2 -0
- package/dist/agent/tools/replace_in_file.js +63 -0
- package/dist/agent/tools/shell.d.ts +2 -0
- package/dist/agent/tools/shell.js +48 -0
- package/dist/agent/tools/stat_path.d.ts +2 -0
- package/dist/agent/tools/stat_path.js +31 -0
- package/dist/agent/tools/types.d.ts +65 -0
- package/dist/agent/tools/types.js +1 -0
- package/dist/agent/tools/validate.d.ts +19 -0
- package/dist/agent/tools/validate.js +92 -0
- package/dist/agent/tools/write_file.d.ts +2 -0
- package/dist/agent/tools/write_file.js +28 -0
- package/dist/agent/tools.d.ts +3 -1
- package/dist/agent/tools.js +2 -377
- package/dist/app.d.ts +2 -1
- package/dist/app.js +846 -173
- package/dist/cli-main.js +363 -0
- package/dist/cli.js +444 -333
- package/dist/commands/about.js +1 -1
- package/dist/commands/attach.d.ts +9 -0
- package/dist/commands/attach.js +15 -0
- package/dist/commands/bg.d.ts +7 -0
- package/dist/commands/bg.js +9 -0
- package/dist/commands/cancel.d.ts +10 -0
- package/dist/commands/cancel.js +10 -0
- package/dist/commands/clear.d.ts +1 -0
- package/dist/commands/clear.js +1 -1
- package/dist/commands/compact.d.ts +22 -0
- package/dist/commands/compact.js +34 -0
- package/dist/commands/context.d.ts +7 -0
- package/dist/commands/context.js +25 -0
- package/dist/commands/edit.d.ts +10 -0
- package/dist/commands/edit.js +36 -0
- package/dist/commands/effort.d.ts +25 -0
- package/dist/commands/effort.js +48 -0
- package/dist/commands/expand.d.ts +10 -0
- package/dist/commands/expand.js +8 -0
- package/dist/commands/index.js +24 -0
- package/dist/commands/jobs.d.ts +7 -0
- package/dist/commands/jobs.js +17 -0
- package/dist/commands/kill.d.ts +7 -0
- package/dist/commands/kill.js +13 -0
- package/dist/commands/login.d.ts +6 -4
- package/dist/commands/login.js +24 -22
- package/dist/commands/logout.js +8 -16
- package/dist/commands/model.d.ts +1 -0
- package/dist/commands/model.js +10 -22
- package/dist/commands/provider.d.ts +1 -2
- package/dist/commands/provider.js +4 -11
- package/dist/commands/skills.js +34 -4
- package/dist/commands/steer.d.ts +11 -0
- package/dist/commands/steer.js +13 -0
- package/dist/commands/threads.d.ts +9 -0
- package/dist/commands/threads.js +26 -0
- package/dist/commands/whoami.js +6 -5
- package/dist/config/store.d.ts +53 -12
- package/dist/config/store.js +163 -73
- package/dist/config/trust.d.ts +30 -8
- package/dist/config/trust.js +139 -14
- package/dist/headless.d.ts +7 -0
- package/dist/headless.js +213 -0
- package/dist/index.js +19 -3
- package/dist/lib/debug.d.ts +2 -0
- package/dist/lib/debug.js +22 -0
- package/dist/lib/diagnostics.d.ts +48 -4
- package/dist/lib/diagnostics.js +90 -8
- package/dist/lib/highlight-subset.d.ts +21 -0
- package/dist/lib/highlight-subset.js +88 -0
- package/dist/lib/http.d.ts +11 -1
- package/dist/lib/http.js +62 -4
- package/dist/lib/lifecycle.d.ts +5 -0
- package/dist/lib/lifecycle.js +62 -0
- package/dist/lib/markdown.js +22 -4
- package/dist/lib/model-meta.d.ts +19 -0
- package/dist/lib/model-meta.js +113 -0
- package/dist/lib/native-tools.d.ts +12 -0
- package/dist/lib/native-tools.js +21 -0
- package/dist/lib/net.d.ts +33 -0
- package/dist/lib/net.js +168 -0
- package/dist/patch/apply.d.ts +15 -0
- package/dist/patch/apply.js +172 -0
- package/dist/patch/parse.d.ts +29 -0
- package/dist/patch/parse.js +112 -0
- package/dist/patch/plan.d.ts +49 -0
- package/dist/patch/plan.js +273 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.js +12 -0
- package/dist/providers/custom.d.ts +9 -0
- package/dist/providers/deepseek.d.ts +10 -0
- package/dist/providers/deepseek.js +3 -2
- package/dist/providers/google.d.ts +9 -0
- package/dist/providers/groq.d.ts +10 -0
- package/dist/providers/groq.js +2 -1
- package/dist/providers/index.d.ts +10 -201
- package/dist/providers/index.js +30 -0
- package/dist/providers/mistral.d.ts +10 -0
- package/dist/providers/mistral.js +2 -1
- package/dist/providers/moonshot.d.ts +10 -0
- package/dist/providers/moonshot.js +2 -1
- package/dist/providers/ollama.d.ts +9 -0
- package/dist/providers/openai.d.ts +10 -0
- package/dist/providers/openai.js +2 -1
- package/dist/providers/openaiCompatible.d.ts +33 -2
- package/dist/providers/openaiCompatible.js +78 -16
- package/dist/providers/openrouter.d.ts +10 -0
- package/dist/providers/openrouter.js +2 -1
- package/dist/providers/qwen.d.ts +10 -0
- package/dist/providers/qwen.js +2 -1
- package/dist/providers/spec.d.ts +12 -0
- package/dist/providers/spec.js +29 -0
- package/dist/providers/xai.d.ts +10 -0
- package/dist/providers/xai.js +2 -1
- package/dist/providers/zhipu.d.ts +10 -0
- package/dist/providers/zhipu.js +2 -1
- package/dist/session/log.d.ts +49 -14
- package/dist/session/log.js +236 -11
- package/dist/session/projection.d.ts +76 -0
- package/dist/session/projection.js +526 -0
- package/dist/skills/manager.d.ts +15 -0
- package/dist/skills/manager.js +135 -18
- package/dist/types.d.ts +75 -1
- package/dist/ui/Message.d.ts +1 -7
- package/dist/ui/Message.js +13 -2
- package/dist/ui/Picker.d.ts +8 -0
- package/dist/ui/Picker.js +24 -0
- package/dist/ui/Prompt.d.ts +1 -2
- package/dist/ui/Prompt.js +2 -2
- package/dist/ui/Spinner.js +11 -5
- package/dist/ui/StatusBar.d.ts +2 -1
- package/dist/ui/StatusBar.js +6 -5
- package/package.json +3 -2
- package/src/agent/approval-json.ts +103 -0
- package/src/agent/approval-native.ts +168 -0
- package/src/agent/approval-store.ts +38 -0
- package/src/agent/approval.ts +94 -0
- package/src/agent/compaction.ts +321 -0
- package/src/agent/context.ts +97 -0
- package/src/agent/guards.ts +1239 -19
- package/src/agent/ignore.ts +147 -0
- package/src/agent/policy/defaults.ts +34 -0
- package/src/agent/policy/egress.ts +335 -0
- package/src/agent/process-tree.ts +114 -0
- package/src/agent/protocol-mode.ts +59 -0
- package/src/agent/protocol.ts +191 -40
- package/src/agent/registry.ts +270 -0
- package/src/agent/runner.ts +486 -0
- package/src/agent/shell-ast.ts +227 -0
- package/src/agent/shell-session.ts +673 -0
- package/src/agent/stream.ts +143 -0
- package/src/agent/tool-schemas.ts +86 -0
- package/src/agent/tools/append_file.ts +30 -0
- package/src/agent/tools/apply_patch.ts +95 -0
- package/src/agent/tools/copy_file.ts +56 -0
- package/src/agent/tools/delete_file.ts +45 -0
- package/src/agent/tools/grep.ts +57 -0
- package/src/agent/tools/index.ts +34 -0
- package/src/agent/tools/list_files.ts +19 -0
- package/src/agent/tools/make_dir.ts +28 -0
- package/src/agent/tools/move_path.ts +83 -0
- package/src/agent/tools/paths.ts +92 -0
- package/src/agent/tools/pwd.ts +12 -0
- package/src/agent/tools/read_file.ts +84 -0
- package/src/agent/tools/read_many.ts +45 -0
- package/src/agent/tools/readers.ts +491 -0
- package/src/agent/tools/replace_in_file.ts +66 -0
- package/src/agent/tools/shell.ts +53 -0
- package/src/agent/tools/stat_path.ts +33 -0
- package/src/agent/tools/types.ts +84 -0
- package/src/agent/tools/validate.ts +104 -0
- package/src/agent/tools/write_file.ts +30 -0
- package/src/agent/tools.ts +3 -377
- package/src/app.ts +853 -170
- package/src/{cli.ts → cli-main.ts} +64 -9
- package/src/commands/about.ts +1 -1
- package/src/commands/attach.ts +16 -0
- package/src/commands/bg.ts +9 -0
- package/src/commands/cancel.ts +10 -0
- package/src/commands/clear.ts +1 -1
- package/src/commands/compact.ts +35 -0
- package/src/commands/context.ts +26 -0
- package/src/commands/edit.ts +37 -0
- package/src/commands/effort.ts +49 -0
- package/src/commands/expand.ts +8 -0
- package/src/commands/index.ts +24 -0
- package/src/commands/jobs.ts +18 -0
- package/src/commands/kill.ts +14 -0
- package/src/commands/login.ts +24 -22
- package/src/commands/logout.ts +8 -16
- package/src/commands/model.ts +10 -22
- package/src/commands/provider.ts +4 -11
- package/src/commands/skills.ts +34 -4
- package/src/commands/steer.ts +13 -0
- package/src/commands/threads.ts +28 -0
- package/src/commands/whoami.ts +6 -5
- package/src/config/store.ts +168 -77
- package/src/config/trust.ts +181 -22
- package/src/headless.ts +225 -0
- package/src/index.ts +19 -3
- package/src/lib/debug.ts +24 -0
- package/src/lib/diagnostics.ts +90 -8
- package/src/lib/highlight-subset.ts +93 -0
- package/src/lib/http.ts +66 -4
- package/src/lib/lifecycle.ts +69 -0
- package/src/lib/markdown.ts +22 -4
- package/src/lib/model-meta.ts +138 -0
- package/src/lib/native-tools.ts +32 -0
- package/src/lib/net.ts +204 -0
- package/src/patch/apply.ts +194 -0
- package/src/patch/parse.ts +131 -0
- package/src/patch/plan.ts +317 -0
- package/src/providers/anthropic.ts +13 -1
- package/src/providers/deepseek.ts +3 -2
- package/src/providers/groq.ts +2 -1
- package/src/providers/index.ts +32 -1
- package/src/providers/mistral.ts +2 -1
- package/src/providers/moonshot.ts +2 -1
- package/src/providers/openai.ts +2 -1
- package/src/providers/openaiCompatible.ts +104 -19
- package/src/providers/openrouter.ts +2 -1
- package/src/providers/qwen.ts +2 -1
- package/src/providers/spec.ts +42 -0
- package/src/providers/xai.ts +2 -1
- package/src/providers/zhipu.ts +2 -1
- package/src/session/log.ts +311 -29
- package/src/session/projection.ts +621 -0
- package/src/skills/manager.ts +140 -18
- package/src/types/highlight-shims.d.ts +14 -0
- package/src/types.ts +79 -2
- package/src/ui/Message.ts +13 -2
- package/src/ui/Picker.ts +24 -0
- package/src/ui/Prompt.ts +2 -2
- package/src/ui/Spinner.ts +11 -5
- package/src/ui/StatusBar.ts +6 -5
- package/tsconfig.json +1 -0
- /package/dist/{cli.d.ts → cli-main.d.ts} +0 -0
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getProvider } from "../providers/index.js";
|
|
2
2
|
export const providerCommand = {
|
|
3
3
|
name: "provider",
|
|
4
4
|
description: "List or switch the active LLM provider. Usage: /provider [id]",
|
|
5
|
-
run({ args, actions
|
|
5
|
+
run({ args, actions }) {
|
|
6
6
|
if (args.length === 0) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const marker = p.id === state.providerId ? "● " : " ";
|
|
10
|
-
const auth = p.authEnv.length === 0 ? "(no key needed)" : `[${p.authEnv.join(", ")}]`;
|
|
11
|
-
lines.push(`${marker}${p.id.padEnd(12)} ${p.label} ${auth}`);
|
|
12
|
-
}
|
|
13
|
-
lines.push("");
|
|
14
|
-
lines.push("Switch with `/provider <id>` (e.g. `/provider openrouter`).");
|
|
15
|
-
return { message: lines.join("\n") };
|
|
7
|
+
actions.startLogin({ flow: "provider" });
|
|
8
|
+
return { message: "Configure a provider: choose a provider and model, then enter its API key." };
|
|
16
9
|
}
|
|
17
10
|
const target = args[0];
|
|
18
11
|
const next = getProvider(target);
|
package/dist/commands/skills.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { installSkill, uninstallSkill, listInstalledSkills, searchRegistry, getSkill, } from "../skills/manager.js";
|
|
1
|
+
import { installSkill, uninstallSkill, listInstalledSkills, searchRegistry, getSkill, rebaselineSkills, resolveRegistry, } from "../skills/manager.js";
|
|
2
2
|
export const skillsCommand = {
|
|
3
3
|
name: "skills",
|
|
4
4
|
description: "Manage Agent Skills (download from skills.sh and toggle).",
|
|
@@ -17,15 +17,20 @@ export const skillsCommand = {
|
|
|
17
17
|
const enabled = state.enabledSkills.includes(s.name) ? "● " : " ";
|
|
18
18
|
lines.push(`${enabled}${s.name} — ${truncate(s.description, 80)}`);
|
|
19
19
|
lines.push(` source: ${s.source}`);
|
|
20
|
+
if (s.integrity !== "ok")
|
|
21
|
+
lines.push(` integrity: ${s.integrity === "drift" ? "DRIFT (disabled; run /skills verify " + s.name + " --confirm)" : "unverified (run /skills verify " + s.name + " --confirm)"}`);
|
|
20
22
|
}
|
|
21
23
|
lines.push("");
|
|
22
24
|
lines.push("Toggle with `/skills enable <name>` or `/skills disable <name>`.");
|
|
23
25
|
return { message: lines.join("\n") };
|
|
24
26
|
}
|
|
25
27
|
if (sub === "search") {
|
|
28
|
+
const registry = resolveRegistry(process.env["FASTCODE_SKILLS_REGISTRY"], state.skillsRegistry);
|
|
29
|
+
if (!registry)
|
|
30
|
+
return { message: "No skills registry configured. Set one with `/skills registry <url>` or FASTCODE_SKILLS_REGISTRY." };
|
|
26
31
|
if (rest.length === 0)
|
|
27
32
|
return { message: "Usage: /skills search <query>" };
|
|
28
|
-
const hits = await searchRegistry(rest.join(" "),
|
|
33
|
+
const hits = await searchRegistry(rest.join(" "), registry);
|
|
29
34
|
if (hits.length === 0) {
|
|
30
35
|
return { message: `No skills found for "${rest.join(" ")}".` };
|
|
31
36
|
}
|
|
@@ -66,6 +71,10 @@ export const skillsCommand = {
|
|
|
66
71
|
const skill = getSkill(rest[0]);
|
|
67
72
|
if (!skill)
|
|
68
73
|
return { message: `Skill "${rest[0]}" is not installed.` };
|
|
74
|
+
if (skill.integrity !== "ok") {
|
|
75
|
+
const reason = skill.integrity === "drift" ? "content drift detected" : "no integrity baseline";
|
|
76
|
+
return { message: `Skill "${skill.name}" is disabled (${reason}). Run /skills verify ${skill.name} --confirm to re-baseline.` };
|
|
77
|
+
}
|
|
69
78
|
actions.enableSkill(skill.name);
|
|
70
79
|
return { message: `Enabled skill "${skill.name}".` };
|
|
71
80
|
}
|
|
@@ -84,9 +93,30 @@ export const skillsCommand = {
|
|
|
84
93
|
const head = `# ${skill.name}\n_${skill.description}_\n\nSource: ${skill.source}\n\n---\n\n`;
|
|
85
94
|
return { message: head + skill.body };
|
|
86
95
|
}
|
|
96
|
+
if (sub === "verify") {
|
|
97
|
+
const confirm = rest.includes("--confirm") || rest.includes("--yes");
|
|
98
|
+
const all = rest.includes("--all");
|
|
99
|
+
const names = rest.filter((entry) => !entry.startsWith("-"));
|
|
100
|
+
if (!all && names.length === 0)
|
|
101
|
+
return { message: "Usage: /skills verify <name> --confirm (or /skills verify --all --confirm)" };
|
|
102
|
+
if (!confirm) {
|
|
103
|
+
return { message: `Re-baselining ${all ? "all skills" : names.join(", ")} trusts the current files as the new baseline. ` +
|
|
104
|
+
"Re-run the same command with --confirm to proceed." };
|
|
105
|
+
}
|
|
106
|
+
const results = rebaselineSkills(all ? undefined : names);
|
|
107
|
+
if (results.length === 0)
|
|
108
|
+
return { message: "No matching installed skills to verify." };
|
|
109
|
+
const lines = ["Skill integrity re-baselined:"];
|
|
110
|
+
for (const result of results)
|
|
111
|
+
lines.push(result.ok ? ` • ${result.name}: locked` : ` • ${result.name}: FAILED — ${result.warning ?? "unknown error"}`);
|
|
112
|
+
return { message: lines.join("\n") };
|
|
113
|
+
}
|
|
87
114
|
if (sub === "registry") {
|
|
88
115
|
if (rest.length === 0) {
|
|
89
|
-
|
|
116
|
+
const registry = resolveRegistry(process.env["FASTCODE_SKILLS_REGISTRY"], state.skillsRegistry);
|
|
117
|
+
return { message: registry
|
|
118
|
+
? `Skills registry: ${registry}`
|
|
119
|
+
: "No skills registry configured. Set one with `/skills registry <url>` or FASTCODE_SKILLS_REGISTRY." };
|
|
90
120
|
}
|
|
91
121
|
// Mutate via AppActions so the in-memory React state stays in sync —
|
|
92
122
|
// direct saveConfig() would be silently overwritten by the next state
|
|
@@ -95,7 +125,7 @@ export const skillsCommand = {
|
|
|
95
125
|
return { message: `Skills registry set to ${rest[0]}.` };
|
|
96
126
|
}
|
|
97
127
|
return {
|
|
98
|
-
message: "Unknown subcommand. Try: list, search, install, uninstall, enable, disable, info, registry.",
|
|
128
|
+
message: "Unknown subcommand. Try: list, search, install, uninstall, enable, disable, info, verify, registry.",
|
|
99
129
|
};
|
|
100
130
|
},
|
|
101
131
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const steerCommand = {
|
|
2
|
+
name: "steer",
|
|
3
|
+
description: "Add guidance to the next request of an active run (/steer <text>)",
|
|
4
|
+
run({ args, state, actions }) {
|
|
5
|
+
const text = args.join(" ").trim();
|
|
6
|
+
if (!text)
|
|
7
|
+
return { message: "Usage: /steer <guidance>" };
|
|
8
|
+
if (!state.busy)
|
|
9
|
+
return { message: "No active run. Just send the guidance as the next message." };
|
|
10
|
+
actions.steer(text);
|
|
11
|
+
return { message: "Steering queued for the next request." };
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DEFAULT_SHELL_POOL_SIZE, MAX_SHELL_POOL_SIZE, shellPoolSize } from "../agent/shell-session.js";
|
|
2
|
+
export const threadsCommand = {
|
|
3
|
+
name: "threads",
|
|
4
|
+
aliases: ["pool"],
|
|
5
|
+
description: `Show or set resident shell concurrency (default ${DEFAULT_SHELL_POOL_SIZE}, max ${MAX_SHELL_POOL_SIZE}). Usage: /threads [1-${MAX_SHELL_POOL_SIZE}]`,
|
|
6
|
+
run({ args, actions }) {
|
|
7
|
+
const before = shellPoolSize();
|
|
8
|
+
if (args.length === 0) {
|
|
9
|
+
return {
|
|
10
|
+
message: `Shell concurrency: ${before} resident slot(s) (default ${DEFAULT_SHELL_POOL_SIZE}, max ${MAX_SHELL_POOL_SIZE}). ` +
|
|
11
|
+
`Usage: /threads <1-${MAX_SHELL_POOL_SIZE}>.`,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const requested = Number(args[0]);
|
|
15
|
+
if (!Number.isFinite(requested)) {
|
|
16
|
+
return { message: `Invalid thread count "${args[0]}". Use /threads <1-${MAX_SHELL_POOL_SIZE}>.` };
|
|
17
|
+
}
|
|
18
|
+
actions.setShellPoolSize(requested);
|
|
19
|
+
const applied = shellPoolSize();
|
|
20
|
+
const clamped = applied !== Math.floor(requested) ? " (clamped)" : "";
|
|
21
|
+
return {
|
|
22
|
+
message: `Shell concurrency: ${before} → ${applied}${clamped} (default ${DEFAULT_SHELL_POOL_SIZE}, max ${MAX_SHELL_POOL_SIZE}). ` +
|
|
23
|
+
"Running jobs keep their slots.",
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
};
|
package/dist/commands/whoami.js
CHANGED
|
@@ -10,19 +10,20 @@ export const whoamiCommand = {
|
|
|
10
10
|
lines.push(" " + describeLookup(current, resolveApiKey(current.id, state.model, current.authEnv)));
|
|
11
11
|
const credentials = listCredentials();
|
|
12
12
|
lines.push("");
|
|
13
|
-
lines.push(`Stored keys (${credentials.length}):`);
|
|
13
|
+
lines.push(`Stored keys (${credentials.length}, provider-wide):`);
|
|
14
14
|
if (credentials.length === 0)
|
|
15
15
|
lines.push(" (none) — add one with /login");
|
|
16
16
|
for (const c of credentials) {
|
|
17
|
-
const marker = c.provider === state.providerId
|
|
18
|
-
|
|
17
|
+
const marker = c.provider === state.providerId ? "● " : " ";
|
|
18
|
+
const origin = c.model ? ` (originally saved for ${c.model})` : "";
|
|
19
|
+
lines.push(`${marker}${c.provider} ${maskKey(c.key)}${origin}`);
|
|
19
20
|
}
|
|
20
21
|
const legacy = listLegacy();
|
|
21
22
|
if (legacy.length > 0) {
|
|
22
23
|
lines.push("");
|
|
23
|
-
lines.push("
|
|
24
|
+
lines.push("Legacy keys (could not be migrated — re-save with /login):");
|
|
24
25
|
for (const l of legacy)
|
|
25
|
-
lines.push(` ${l.provider} ${maskKey(l.key)}
|
|
26
|
+
lines.push(` ${l.provider} ${maskKey(l.key)}`);
|
|
26
27
|
}
|
|
27
28
|
const envLines = [];
|
|
28
29
|
for (const p of PROVIDERS) {
|
package/dist/config/store.d.ts
CHANGED
|
@@ -8,20 +8,55 @@ export declare const DEFAULT_CONFIG: {
|
|
|
8
8
|
enabledPlugins: any[];
|
|
9
9
|
skillsRegistry: string;
|
|
10
10
|
lifetimeCostUsd: number;
|
|
11
|
+
/**
|
|
12
|
+
* Extra directories the file tools may read and write outside the project
|
|
13
|
+
* root. Relative entries are resolved against the project root; `~/` is
|
|
14
|
+
* expanded against the user's home directory.
|
|
15
|
+
*/
|
|
16
|
+
sharedDirs: any[];
|
|
17
|
+
/** Maximum agent tool turns before the loop asks the user to continue. */
|
|
18
|
+
maxAgentTurns: number;
|
|
19
|
+
/** Abort a stream that receives no data for this long (ms). */
|
|
20
|
+
requestIdleTimeoutMs: number;
|
|
21
|
+
/** Approximate character budget before history compaction kicks in. */
|
|
22
|
+
contextBudgetChars: number;
|
|
23
|
+
/** Thinking depth: auto = send nothing, provider default. */
|
|
24
|
+
reasoningEffort: string;
|
|
25
|
+
/** Resident shell concurrency: safe default 2, max 6. `/threads` changes it. */
|
|
26
|
+
shellPoolSize: number;
|
|
27
|
+
/** Cached per-provider/model capabilities (native vs pseudo tool calling). */
|
|
28
|
+
capabilities: {
|
|
29
|
+
toolCalling: {};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Application-layer egress policy. Default is audit-only; set
|
|
33
|
+
* enabled:true + mode:"block" to enforce. See docs/CONFIGURATION.md.
|
|
34
|
+
*/
|
|
35
|
+
egress: {
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
mode: import("../agent/policy/defaults.js").EgressMode;
|
|
38
|
+
denyPaths: string[];
|
|
39
|
+
denyGlobs: string[];
|
|
40
|
+
denyContentMarkers: string[];
|
|
41
|
+
maxScanBytes: number;
|
|
42
|
+
scanToolOutput: boolean;
|
|
43
|
+
};
|
|
11
44
|
};
|
|
12
45
|
export interface StoredCredential {
|
|
13
46
|
provider: string;
|
|
14
|
-
|
|
47
|
+
/** Model the key was originally saved for (display only; keys are provider-wide). */
|
|
48
|
+
model?: string;
|
|
15
49
|
key: string;
|
|
16
50
|
addedAt: string;
|
|
17
51
|
}
|
|
18
52
|
export interface AuthStore {
|
|
19
53
|
version: number;
|
|
20
|
-
/**
|
|
54
|
+
/** Provider-scoped credentials, keyed by provider id. */
|
|
21
55
|
keys: Record<string, StoredCredential>;
|
|
22
|
-
/** Old provider-only keys
|
|
56
|
+
/** Old provider-only keys that could not be migrated (kept for diagnostics). */
|
|
23
57
|
legacy: Record<string, string>;
|
|
24
58
|
}
|
|
59
|
+
export declare const AUTH_VERSION = 3;
|
|
25
60
|
export type KeyLookup = {
|
|
26
61
|
status: "ok";
|
|
27
62
|
key: string;
|
|
@@ -34,33 +69,39 @@ export type KeyLookup = {
|
|
|
34
69
|
} | {
|
|
35
70
|
status: "missing";
|
|
36
71
|
};
|
|
72
|
+
/** Drop the cached config so the next loadConfig() re-stats and re-reads. */
|
|
73
|
+
export declare function invalidateConfigCache(): void;
|
|
74
|
+
export declare function configCacheStatus(): {
|
|
75
|
+
cached: boolean;
|
|
76
|
+
fingerprint?: string;
|
|
77
|
+
};
|
|
37
78
|
export declare function loadConfig(): any;
|
|
38
79
|
export declare function saveConfig(cfg: any): void;
|
|
39
|
-
/** Composite
|
|
80
|
+
/** Composite id used by the legacy v2 format; kept for API compatibility. */
|
|
40
81
|
export declare function scopeId(providerId: any, model: any): string;
|
|
41
82
|
export declare function loadAuth(): AuthStore;
|
|
42
83
|
export declare function saveAuth(store: AuthStore): void;
|
|
43
|
-
export declare function getCredential(providerId: any,
|
|
84
|
+
export declare function getCredential(providerId: any, _model?: any): StoredCredential | undefined;
|
|
44
85
|
export declare function listCredentials(): StoredCredential[];
|
|
45
86
|
export declare function listLegacy(): Array<{
|
|
46
87
|
provider: string;
|
|
47
88
|
key: string;
|
|
48
89
|
}>;
|
|
49
90
|
export declare function getLegacy(providerId: any): string | undefined;
|
|
50
|
-
/** Save/replace the
|
|
91
|
+
/** Save/replace the provider-wide credential (drops any legacy key). */
|
|
51
92
|
export declare function setCredential(providerId: any, model: any, key: any): StoredCredential;
|
|
52
|
-
export declare function removeCredential(providerId: any,
|
|
53
|
-
/** Remove
|
|
93
|
+
export declare function removeCredential(providerId: any, _model?: any): boolean;
|
|
94
|
+
/** Remove the provider-wide credential plus any legacy leftovers. */
|
|
54
95
|
export declare function removeCredentialsForProvider(providerId: any): number;
|
|
55
96
|
/** Turn a key into a safe terminal echo: `sk-****abcd`. */
|
|
56
97
|
export declare function maskKey(key: any): string;
|
|
57
98
|
/**
|
|
58
|
-
* Resolve the key to use for a
|
|
59
|
-
* 1. the
|
|
99
|
+
* Resolve the key to use for a provider:
|
|
100
|
+
* 1. the provider-wide credential in auth.json,
|
|
60
101
|
* 2. the provider's environment variable (provider-scoped, any model), and
|
|
61
|
-
* 3.
|
|
102
|
+
* 3. a legacy provider-only key that somehow escaped migration.
|
|
62
103
|
*/
|
|
63
|
-
export declare function resolveApiKey(providerId: any,
|
|
104
|
+
export declare function resolveApiKey(providerId: any, _model: any, envVars: any): KeyLookup;
|
|
64
105
|
/** Best-effort key for a provider regardless of model (used to list models). */
|
|
65
106
|
export declare function resolveProviderKey(providerId: any, envVars: any): {
|
|
66
107
|
key?: string;
|
package/dist/config/store.js
CHANGED
|
@@ -5,17 +5,16 @@
|
|
|
5
5
|
* edit it from `nano ~/.fastcode/config.json` if needed. Atomic writes prevent
|
|
6
6
|
* partial files on Ctrl+C.
|
|
7
7
|
*
|
|
8
|
-
* API keys are
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* "legacy": it is shown back to the user but never used silently, because a
|
|
13
|
-
* provider-only key does not tell us which model it was meant for.
|
|
8
|
+
* API keys are scoped to a provider, not to a model. auth.json stores one
|
|
9
|
+
* credential per provider id, so switching between models of the same provider
|
|
10
|
+
* reuses the same key. The old "provider::model" (v2) and provider-only (v1)
|
|
11
|
+
* formats are read and migrated to the provider-scoped v3 layout on first load.
|
|
14
12
|
*/
|
|
15
|
-
import { readFileSync, writeFileSync, existsSync, renameSync } from "node:fs";
|
|
13
|
+
import { readFileSync, writeFileSync, existsSync, renameSync, copyFileSync, statSync } from "node:fs";
|
|
16
14
|
import { join, dirname } from "node:path";
|
|
17
15
|
import { getPaths, lockdown, ensureDir } from "./paths.js";
|
|
18
16
|
import { DEFAULT_THEME } from "./themes.js";
|
|
17
|
+
import { DEFAULT_EGRESS_CONFIG } from "../agent/policy/defaults.js";
|
|
19
18
|
export const DEFAULT_CONFIG = {
|
|
20
19
|
providerId: "anthropic",
|
|
21
20
|
model: "claude-sonnet-5.5",
|
|
@@ -27,77 +26,172 @@ export const DEFAULT_CONFIG = {
|
|
|
27
26
|
"or unified diffs the user can apply.",
|
|
28
27
|
enabledSkills: [],
|
|
29
28
|
enabledPlugins: [],
|
|
30
|
-
skillsRegistry: "
|
|
29
|
+
skillsRegistry: "",
|
|
31
30
|
lifetimeCostUsd: 0,
|
|
31
|
+
/**
|
|
32
|
+
* Extra directories the file tools may read and write outside the project
|
|
33
|
+
* root. Relative entries are resolved against the project root; `~/` is
|
|
34
|
+
* expanded against the user's home directory.
|
|
35
|
+
*/
|
|
36
|
+
sharedDirs: [],
|
|
37
|
+
/** Maximum agent tool turns before the loop asks the user to continue. */
|
|
38
|
+
maxAgentTurns: 24,
|
|
39
|
+
/** Abort a stream that receives no data for this long (ms). */
|
|
40
|
+
requestIdleTimeoutMs: 60_000,
|
|
41
|
+
/** Approximate character budget before history compaction kicks in. */
|
|
42
|
+
contextBudgetChars: 400_000,
|
|
43
|
+
/** Thinking depth: auto = send nothing, provider default. */
|
|
44
|
+
reasoningEffort: "auto",
|
|
45
|
+
/** Resident shell concurrency: safe default 2, max 6. `/threads` changes it. */
|
|
46
|
+
shellPoolSize: 2,
|
|
47
|
+
/** Cached per-provider/model capabilities (native vs pseudo tool calling). */
|
|
48
|
+
capabilities: {
|
|
49
|
+
toolCalling: {},
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* Application-layer egress policy. Default is audit-only; set
|
|
53
|
+
* enabled:true + mode:"block" to enforce. See docs/CONFIGURATION.md.
|
|
54
|
+
*/
|
|
55
|
+
egress: { ...DEFAULT_EGRESS_CONFIG },
|
|
32
56
|
};
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return { ...DEFAULT_CONFIG };
|
|
57
|
+
export const AUTH_VERSION = 3;
|
|
58
|
+
let configCache;
|
|
59
|
+
function configFingerprint(file) {
|
|
37
60
|
try {
|
|
38
|
-
const
|
|
39
|
-
|
|
61
|
+
const info = statSync(file);
|
|
62
|
+
// mtime + size are required; ctime adds resilience on filesystems with
|
|
63
|
+
// coarse mtime resolution. stat() is much cheaper than a full read on
|
|
64
|
+
// Termux shared storage.
|
|
65
|
+
return `${info.mtimeMs}:${info.size}:${info.ctimeMs}`;
|
|
40
66
|
}
|
|
41
67
|
catch {
|
|
42
|
-
return
|
|
68
|
+
return "missing";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Drop the cached config so the next loadConfig() re-stats and re-reads. */
|
|
72
|
+
export function invalidateConfigCache() {
|
|
73
|
+
configCache = undefined;
|
|
74
|
+
}
|
|
75
|
+
export function configCacheStatus() {
|
|
76
|
+
return configCache ? { cached: true, fingerprint: configCache.fingerprint } : { cached: false };
|
|
77
|
+
}
|
|
78
|
+
export function loadConfig() {
|
|
79
|
+
const { config } = getPaths();
|
|
80
|
+
const fingerprint = configFingerprint(config);
|
|
81
|
+
if (configCache && configCache.path === config && configCache.fingerprint === fingerprint)
|
|
82
|
+
return { ...configCache.value };
|
|
83
|
+
let value;
|
|
84
|
+
if (!existsSync(config)) {
|
|
85
|
+
value = { ...DEFAULT_CONFIG };
|
|
43
86
|
}
|
|
87
|
+
else {
|
|
88
|
+
try {
|
|
89
|
+
const raw = JSON.parse(readFileSync(config, "utf8"));
|
|
90
|
+
value = { ...DEFAULT_CONFIG, ...raw };
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
value = { ...DEFAULT_CONFIG };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
configCache = { path: config, fingerprint, value };
|
|
97
|
+
return { ...value };
|
|
44
98
|
}
|
|
45
99
|
export function saveConfig(cfg) {
|
|
46
100
|
const { config } = getPaths();
|
|
47
101
|
atomicWrite(config, JSON.stringify(cfg, null, 2));
|
|
102
|
+
invalidateConfigCache();
|
|
48
103
|
}
|
|
49
|
-
/** Composite
|
|
104
|
+
/** Composite id used by the legacy v2 format; kept for API compatibility. */
|
|
50
105
|
export function scopeId(providerId, model) {
|
|
51
106
|
return `${providerId}::${model}`;
|
|
52
107
|
}
|
|
108
|
+
/** Pick the most recently saved credential when several legacy scopes map to one provider. */
|
|
109
|
+
function keepNewest(keys, credential) {
|
|
110
|
+
const existing = keys[credential.provider];
|
|
111
|
+
if (!existing) {
|
|
112
|
+
keys[credential.provider] = credential;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const previous = Date.parse(existing.addedAt || "") || 0;
|
|
116
|
+
const next = Date.parse(credential.addedAt || "") || 0;
|
|
117
|
+
if (next > previous)
|
|
118
|
+
keys[credential.provider] = credential;
|
|
119
|
+
}
|
|
120
|
+
let migrationChecked = false;
|
|
53
121
|
export function loadAuth() {
|
|
54
122
|
const { auth } = getPaths();
|
|
55
|
-
const empty = { version:
|
|
123
|
+
const empty = { version: AUTH_VERSION, keys: {}, legacy: {} };
|
|
56
124
|
if (!existsSync(auth))
|
|
57
125
|
return empty;
|
|
126
|
+
let raw;
|
|
58
127
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
128
|
+
raw = JSON.parse(readFileSync(auth, "utf8"));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return empty;
|
|
132
|
+
}
|
|
133
|
+
if (!raw || typeof raw !== "object")
|
|
134
|
+
return empty;
|
|
135
|
+
const keys = {};
|
|
136
|
+
const legacy = {};
|
|
137
|
+
let migrated = false;
|
|
138
|
+
const source = raw.keys && typeof raw.keys === "object" ? raw.keys : {};
|
|
139
|
+
for (const [id, value] of Object.entries(source)) {
|
|
140
|
+
if (value && typeof value === "object" && typeof value.key === "string" && value.key.trim()) {
|
|
141
|
+
const [idProvider, idModel] = id.split("::");
|
|
142
|
+
const provider = typeof value.provider === "string" && value.provider ? value.provider : idProvider || id;
|
|
143
|
+
const model = typeof value.model === "string" ? value.model : idModel || "";
|
|
144
|
+
if (id.includes("::") || raw.version !== AUTH_VERSION)
|
|
145
|
+
migrated = true;
|
|
146
|
+
keepNewest(keys, {
|
|
147
|
+
provider,
|
|
148
|
+
model,
|
|
149
|
+
key: value.key,
|
|
150
|
+
addedAt: typeof value.addedAt === "string" ? value.addedAt : "",
|
|
151
|
+
});
|
|
78
152
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
153
|
+
else if (typeof value === "string" && value.trim()) {
|
|
154
|
+
// v1: keys were plain provider -> key strings.
|
|
155
|
+
keepNewest(keys, { provider: id, key: value, addedAt: "" });
|
|
156
|
+
migrated = true;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (raw.legacy && typeof raw.legacy === "object") {
|
|
160
|
+
for (const [provider, value] of Object.entries(raw.legacy)) {
|
|
161
|
+
if (typeof value === "string" && value.trim()) {
|
|
162
|
+
// Provider-only keys are exactly what v3 wants: migrate instead
|
|
163
|
+
// of leaving them unusable.
|
|
164
|
+
keepNewest(keys, { provider, key: value, addedAt: "" });
|
|
165
|
+
migrated = true;
|
|
83
166
|
}
|
|
84
167
|
}
|
|
85
|
-
return { version: 2, keys, legacy };
|
|
86
168
|
}
|
|
87
|
-
|
|
88
|
-
|
|
169
|
+
if (migrated && !migrationChecked) {
|
|
170
|
+
try {
|
|
171
|
+
// Keep the pre-migration file so a user with several old model
|
|
172
|
+
// keys can recover a credential we had to collapse.
|
|
173
|
+
const backup = auth + ".v2.bak";
|
|
174
|
+
if (!existsSync(backup))
|
|
175
|
+
copyFileSync(auth, backup);
|
|
176
|
+
writeAuth({ version: AUTH_VERSION, keys, legacy });
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Read-only home (or locked file): keep the migrated view in memory.
|
|
180
|
+
}
|
|
89
181
|
}
|
|
182
|
+
migrationChecked = true;
|
|
183
|
+
return { version: AUTH_VERSION, keys, legacy };
|
|
90
184
|
}
|
|
91
|
-
|
|
185
|
+
function writeAuth(store) {
|
|
92
186
|
const { auth } = getPaths();
|
|
93
|
-
|
|
94
|
-
if (Object.keys(store.legacy).length > 0)
|
|
95
|
-
payload.legacy = store.legacy;
|
|
96
|
-
atomicWrite(auth, JSON.stringify(payload, null, 2));
|
|
187
|
+
atomicWrite(auth, JSON.stringify({ version: AUTH_VERSION, keys: store.keys }, null, 2));
|
|
97
188
|
lockdown(auth);
|
|
98
189
|
}
|
|
99
|
-
export function
|
|
100
|
-
|
|
190
|
+
export function saveAuth(store) {
|
|
191
|
+
writeAuth(store);
|
|
192
|
+
}
|
|
193
|
+
export function getCredential(providerId, _model) {
|
|
194
|
+
return loadAuth().keys[providerId];
|
|
101
195
|
}
|
|
102
196
|
export function listCredentials() {
|
|
103
197
|
return Object.values(loadAuth().keys);
|
|
@@ -108,7 +202,7 @@ export function listLegacy() {
|
|
|
108
202
|
export function getLegacy(providerId) {
|
|
109
203
|
return loadAuth().legacy[providerId];
|
|
110
204
|
}
|
|
111
|
-
/** Save/replace the
|
|
205
|
+
/** Save/replace the provider-wide credential (drops any legacy key). */
|
|
112
206
|
export function setCredential(providerId, model, key) {
|
|
113
207
|
const store = loadAuth();
|
|
114
208
|
const credential = {
|
|
@@ -117,29 +211,26 @@ export function setCredential(providerId, model, key) {
|
|
|
117
211
|
key: key.trim(),
|
|
118
212
|
addedAt: new Date().toISOString(),
|
|
119
213
|
};
|
|
120
|
-
store.keys[
|
|
214
|
+
store.keys[providerId] = credential;
|
|
121
215
|
delete store.legacy[providerId];
|
|
122
216
|
saveAuth(store);
|
|
123
217
|
return credential;
|
|
124
218
|
}
|
|
125
|
-
export function removeCredential(providerId,
|
|
219
|
+
export function removeCredential(providerId, _model) {
|
|
126
220
|
const store = loadAuth();
|
|
127
|
-
|
|
128
|
-
if (!store.keys[id])
|
|
221
|
+
if (!store.keys[providerId])
|
|
129
222
|
return false;
|
|
130
|
-
delete store.keys[
|
|
223
|
+
delete store.keys[providerId];
|
|
131
224
|
saveAuth(store);
|
|
132
225
|
return true;
|
|
133
226
|
}
|
|
134
|
-
/** Remove
|
|
227
|
+
/** Remove the provider-wide credential plus any legacy leftovers. */
|
|
135
228
|
export function removeCredentialsForProvider(providerId) {
|
|
136
229
|
const store = loadAuth();
|
|
137
230
|
let removed = 0;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
removed += 1;
|
|
142
|
-
}
|
|
231
|
+
if (store.keys[providerId]) {
|
|
232
|
+
delete store.keys[providerId];
|
|
233
|
+
removed += 1;
|
|
143
234
|
}
|
|
144
235
|
if (store.legacy[providerId]) {
|
|
145
236
|
delete store.legacy[providerId];
|
|
@@ -159,16 +250,16 @@ export function maskKey(key) {
|
|
|
159
250
|
return value.slice(0, 3) + "****" + value.slice(-4);
|
|
160
251
|
}
|
|
161
252
|
/**
|
|
162
|
-
* Resolve the key to use for a
|
|
163
|
-
* 1. the
|
|
253
|
+
* Resolve the key to use for a provider:
|
|
254
|
+
* 1. the provider-wide credential in auth.json,
|
|
164
255
|
* 2. the provider's environment variable (provider-scoped, any model), and
|
|
165
|
-
* 3.
|
|
256
|
+
* 3. a legacy provider-only key that somehow escaped migration.
|
|
166
257
|
*/
|
|
167
|
-
export function resolveApiKey(providerId,
|
|
258
|
+
export function resolveApiKey(providerId, _model, envVars) {
|
|
168
259
|
const store = loadAuth();
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
return { status: "ok", key:
|
|
260
|
+
const credential = store.keys[providerId];
|
|
261
|
+
if (credential && credential.key)
|
|
262
|
+
return { status: "ok", key: credential.key, source: "file" };
|
|
172
263
|
for (const envVar of envVars ?? []) {
|
|
173
264
|
const value = process.env[envVar];
|
|
174
265
|
if (value && value.trim())
|
|
@@ -181,10 +272,9 @@ export function resolveApiKey(providerId, model, envVars) {
|
|
|
181
272
|
/** Best-effort key for a provider regardless of model (used to list models). */
|
|
182
273
|
export function resolveProviderKey(providerId, envVars) {
|
|
183
274
|
const store = loadAuth();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
275
|
+
const credential = store.keys[providerId];
|
|
276
|
+
if (credential && credential.key)
|
|
277
|
+
return { key: credential.key, source: "file" };
|
|
188
278
|
for (const envVar of envVars ?? []) {
|
|
189
279
|
const value = process.env[envVar];
|
|
190
280
|
if (value && value.trim())
|