fix: write auth profiles to multi-agent path during onboarding

- Onboarding now writes auth profiles under ~/.clawdbot/agents/main/agent so the gateway sees credentials on first start.
- Hardened onboarding test to ignore legacy env vars.

Thanks @minghinmatthewlam!
This commit is contained in:
minghinmatthewlam
2026-01-06 15:53:18 -05:00
committed by GitHub
parent c7ffa28980
commit 2dd6b3aeb2
4 changed files with 29 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
- Groups: `whatsapp.groups`, `telegram.groups`, and `imessage.groups` now act as allowlists when set. Add `"*"` to keep allow-all behavior. - Groups: `whatsapp.groups`, `telegram.groups`, and `imessage.groups` now act as allowlists when set. Add `"*"` to keep allow-all behavior.
### Fixes ### Fixes
- Onboarding: write auth profiles to the multi-agent path (`~/.clawdbot/agents/main/agent/`) so the gateway finds credentials on first startup. Thanks @minghinmatthewlam for PR #327.
- Docs: add missing `ui:install` setup step in the README. Thanks @hugobarauna for PR #300. - Docs: add missing `ui:install` setup step in the README. Thanks @hugobarauna for PR #300.
- Build: import tool-display JSON as a module instead of runtime file reads. Thanks @mukhtharcm for PR #312. - Build: import tool-display JSON as a module instead of runtime file reads. Thanks @mukhtharcm for PR #312.
- Browser: fix `browser snapshot`/`browser act` timeouts under Bun by patching Playwrights CDP WebSocket selection. Thanks @azade-c for PR #307. - Browser: fix `browser snapshot`/`browser act` timeouts under Bun by patching Playwrights CDP WebSocket selection. Thanks @azade-c for PR #307.

View File

@@ -53,3 +53,12 @@ export function resolveAgentDir(cfg: ClawdbotConfig, agentId: string) {
const root = resolveStateDir(process.env, os.homedir); const root = resolveStateDir(process.env, os.homedir);
return path.join(root, "agents", id, "agent"); return path.join(root, "agents", id, "agent");
} }
/**
* Resolve the agent directory for the default agent without requiring config.
* Used by onboarding when writing auth profiles before config is fully set up.
*/
export function resolveDefaultAgentDir(): string {
const root = resolveStateDir(process.env, os.homedir);
return path.join(root, "agents", DEFAULT_AGENT_ID, "agent");
}

View File

@@ -36,9 +36,10 @@ describe("writeOAuthCredentials", () => {
delete process.env.CLAWDBOT_OAUTH_DIR; delete process.env.CLAWDBOT_OAUTH_DIR;
}); });
it("writes auth-profiles.json under CLAWDBOT_STATE_DIR/agent", async () => { it("writes auth-profiles.json under CLAWDBOT_STATE_DIR/agents/main/agent", async () => {
tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-oauth-")); tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-oauth-"));
process.env.CLAWDBOT_STATE_DIR = tempStateDir; process.env.CLAWDBOT_STATE_DIR = tempStateDir;
// Even if legacy env vars are set, onboarding should write to the multi-agent path.
process.env.CLAWDBOT_AGENT_DIR = path.join(tempStateDir, "agent"); process.env.CLAWDBOT_AGENT_DIR = path.join(tempStateDir, "agent");
process.env.PI_CODING_AGENT_DIR = process.env.CLAWDBOT_AGENT_DIR; process.env.PI_CODING_AGENT_DIR = process.env.CLAWDBOT_AGENT_DIR;
@@ -50,8 +51,11 @@ describe("writeOAuthCredentials", () => {
await writeOAuthCredentials("anthropic", creds); await writeOAuthCredentials("anthropic", creds);
// Now writes to the multi-agent path: agents/main/agent
const authProfilePath = path.join( const authProfilePath = path.join(
tempStateDir, tempStateDir,
"agents",
"main",
"agent", "agent",
"auth-profiles.json", "auth-profiles.json",
); );
@@ -64,5 +68,12 @@ describe("writeOAuthCredentials", () => {
access: "access-token", access: "access-token",
type: "oauth", type: "oauth",
}); });
await expect(
fs.readFile(
path.join(tempStateDir, "agent", "auth-profiles.json"),
"utf8",
),
).rejects.toThrow();
}); });
}); });

View File

@@ -1,4 +1,5 @@
import type { OAuthCredentials, OAuthProvider } from "@mariozechner/pi-ai"; import type { OAuthCredentials, OAuthProvider } from "@mariozechner/pi-ai";
import { resolveDefaultAgentDir } from "../agents/agent-scope.js";
import { upsertAuthProfile } from "../agents/auth-profiles.js"; import { upsertAuthProfile } from "../agents/auth-profiles.js";
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
@@ -6,6 +7,8 @@ export async function writeOAuthCredentials(
provider: OAuthProvider, provider: OAuthProvider,
creds: OAuthCredentials, creds: OAuthCredentials,
): Promise<void> { ): Promise<void> {
// Write to the multi-agent path so gateway finds credentials on startup
const agentDir = resolveDefaultAgentDir();
upsertAuthProfile({ upsertAuthProfile({
profileId: `${provider}:${creds.email ?? "default"}`, profileId: `${provider}:${creds.email ?? "default"}`,
credential: { credential: {
@@ -13,10 +16,13 @@ export async function writeOAuthCredentials(
provider, provider,
...creds, ...creds,
}, },
agentDir,
}); });
} }
export async function setAnthropicApiKey(key: string) { export async function setAnthropicApiKey(key: string) {
// Write to the multi-agent path so gateway finds credentials on startup
const agentDir = resolveDefaultAgentDir();
upsertAuthProfile({ upsertAuthProfile({
profileId: "anthropic:default", profileId: "anthropic:default",
credential: { credential: {
@@ -24,6 +30,7 @@ export async function setAnthropicApiKey(key: string) {
provider: "anthropic", provider: "anthropic",
key, key,
}, },
agentDir,
}); });
} }