Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions apps/server/src/lib/agents-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ export function validateProviderConfig(input: Record<string, unknown>): Provider
* 1. `~/.agents/config.json` (or `AGENTS_CONFIG_PATH`)
* 2. `process.env` (which already includes `.env` loaded by the server bootstrap)
*
* The disk file may contain only a provider selection; missing fields are
* backfilled from the running process environment so users don't have to
* manually copy values from `.env` into the settings dialog.
* The disk file may contain only a provider selection; missing fields for every
* provider are backfilled from the running process environment so users can
* switch providers in the settings dialog without manually copying `.env`.
*/
export async function readProviderConfig(): Promise<Partial<ProviderConfig>> {
const path = providerConfigPath();
Expand All @@ -92,10 +92,13 @@ export async function readProviderConfig(): Promise<Partial<ProviderConfig>> {

const provider: ProviderConfigProvider = diskConfig.AGENTS_PROVIDER ?? resolveActiveProvider();
const merged: Partial<ProviderConfig> = { AGENTS_PROVIDER: provider };
for (const field of AGENTS_PROVIDER_FIELDS[provider]) {
const diskValue = diskConfig[field.key]?.trim();
const envValue = process.env[field.key]?.trim();
merged[field.key] = diskValue || envValue;
for (const candidateProvider of AGENTS_CONFIG_PROVIDERS) {
for (const field of AGENTS_PROVIDER_FIELDS[candidateProvider]) {
const diskValue = diskConfig[field.key]?.trim();
const envValue = process.env[field.key]?.trim();
const value = diskValue || envValue;
if (value) merged[field.key] = value;
}
}
return merged;
}
Expand Down
25 changes: 25 additions & 0 deletions apps/server/tests/agents-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,23 @@ describe("agents-config", () => {
const prevProvider = process.env.AGENTS_PROVIDER;
const prevKey = process.env.DASHSCOPE_API_KEY;
const prevWs = process.env.BAILIAN_WORKSPACE_ID;
const prevQoderPat = process.env.QODER_PAT;
const prevArkKey = process.env.ARK_API_KEY;
const prevAnthropicKey = process.env.ANTHROPIC_API_KEY;
process.env.AGENTS_CONFIG_PATH = path;
delete process.env.AGENTS_PROVIDER;
process.env.DASHSCOPE_API_KEY = "from-env-key";
process.env.BAILIAN_WORKSPACE_ID = "from-env-ws";
process.env.QODER_PAT = "from-env-qoder";
delete process.env.ARK_API_KEY;
delete process.env.ANTHROPIC_API_KEY;
try {
const config = await readProviderConfig();
expect(config).toEqual({
AGENTS_PROVIDER: "bailian",
DASHSCOPE_API_KEY: "from-env-key",
BAILIAN_WORKSPACE_ID: "from-env-ws",
QODER_PAT: "from-env-qoder",
});
} finally {
if (prevConfigPath === undefined) delete process.env.AGENTS_CONFIG_PATH;
Expand All @@ -74,6 +81,12 @@ describe("agents-config", () => {
else process.env.DASHSCOPE_API_KEY = prevKey;
if (prevWs === undefined) delete process.env.BAILIAN_WORKSPACE_ID;
else process.env.BAILIAN_WORKSPACE_ID = prevWs;
if (prevQoderPat === undefined) delete process.env.QODER_PAT;
else process.env.QODER_PAT = prevQoderPat;
if (prevArkKey === undefined) delete process.env.ARK_API_KEY;
else process.env.ARK_API_KEY = prevArkKey;
if (prevAnthropicKey === undefined) delete process.env.ANTHROPIC_API_KEY;
else process.env.ANTHROPIC_API_KEY = prevAnthropicKey;
await rm(dir, { recursive: true, force: true });
}
});
Expand All @@ -84,9 +97,15 @@ describe("agents-config", () => {
const prevConfigPath = process.env.AGENTS_CONFIG_PATH;
const prevKey = process.env.DASHSCOPE_API_KEY;
const prevWs = process.env.BAILIAN_WORKSPACE_ID;
const prevQoderPat = process.env.QODER_PAT;
const prevArkKey = process.env.ARK_API_KEY;
const prevAnthropicKey = process.env.ANTHROPIC_API_KEY;
process.env.AGENTS_CONFIG_PATH = path;
process.env.DASHSCOPE_API_KEY = "env-key";
process.env.BAILIAN_WORKSPACE_ID = "env-ws";
delete process.env.QODER_PAT;
delete process.env.ARK_API_KEY;
delete process.env.ANTHROPIC_API_KEY;
try {
await writeFile(
path,
Expand All @@ -113,6 +132,12 @@ describe("agents-config", () => {
else process.env.DASHSCOPE_API_KEY = prevKey;
if (prevWs === undefined) delete process.env.BAILIAN_WORKSPACE_ID;
else process.env.BAILIAN_WORKSPACE_ID = prevWs;
if (prevQoderPat === undefined) delete process.env.QODER_PAT;
else process.env.QODER_PAT = prevQoderPat;
if (prevArkKey === undefined) delete process.env.ARK_API_KEY;
else process.env.ARK_API_KEY = prevArkKey;
if (prevAnthropicKey === undefined) delete process.env.ANTHROPIC_API_KEY;
else process.env.ANTHROPIC_API_KEY = prevAnthropicKey;
await rm(dir, { recursive: true, force: true });
}
});
Expand Down
2 changes: 1 addition & 1 deletion apps/webui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export default function Home() {
if (bottomBarVisibleRef.current) {
bottomBarRef.current?.expand();
} else {
setTimeout(() => composerHandleRef.current?.focus(), 80);
setTimeout(() => composerHandleRef.current?.focusStart(), 80);
}
},
[roleCards],
Expand Down
Loading
Loading