mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 08:03:46 +00:00
fix: use sandbox-agent CLI for credential extraction in tests and add delay for permission approval
This commit is contained in:
parent
bfd2a80bf1
commit
0faa608822
3 changed files with 90 additions and 18 deletions
|
|
@ -1559,6 +1559,34 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"StderrOutput": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"truncated"
|
||||
],
|
||||
"properties": {
|
||||
"head": {
|
||||
"type": "string",
|
||||
"description": "First N lines of stderr (if truncated) or full stderr (if not truncated)",
|
||||
"nullable": true
|
||||
},
|
||||
"tail": {
|
||||
"type": "string",
|
||||
"description": "Last N lines of stderr (only present if truncated)",
|
||||
"nullable": true
|
||||
},
|
||||
"total_lines": {
|
||||
"type": "integer",
|
||||
"description": "Total number of lines in stderr",
|
||||
"nullable": true,
|
||||
"minimum": 0
|
||||
},
|
||||
"truncated": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the output was truncated"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TerminatedBy": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
|
|||
|
|
@ -46,28 +46,58 @@ const log = {
|
|||
section: (msg: string) => console.log(`\n\x1b[1m=== ${msg} ===\x1b[0m`),
|
||||
};
|
||||
|
||||
// Credentials extraction (mirrors agent-credentials logic)
|
||||
function getAnthropicApiKey(): string | undefined {
|
||||
if (process.env.ANTHROPIC_API_KEY) return process.env.ANTHROPIC_API_KEY;
|
||||
const home = homedir();
|
||||
for (const path of [join(home, ".claude.json"), join(home, ".claude.json.api")]) {
|
||||
try {
|
||||
const data = JSON.parse(readFileSync(path, "utf-8"));
|
||||
const key = data.primaryApiKey || data.apiKey || data.anthropicApiKey;
|
||||
if (key?.startsWith("sk-ant-")) return key;
|
||||
} catch {}
|
||||
// Credentials extraction using sandbox-agent CLI
|
||||
function extractCredentials(): { anthropicApiKey?: string; openaiApiKey?: string } {
|
||||
// First check environment variables
|
||||
const envCreds = {
|
||||
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
|
||||
openaiApiKey: process.env.OPENAI_API_KEY,
|
||||
};
|
||||
|
||||
// If both are set in env, use them
|
||||
if (envCreds.anthropicApiKey && envCreds.openaiApiKey) {
|
||||
return envCreds;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
// Try to extract using sandbox-agent CLI
|
||||
try {
|
||||
const binaryPath = join(ROOT_DIR, "target/release/sandbox-agent");
|
||||
const debugBinaryPath = join(ROOT_DIR, "target/debug/sandbox-agent");
|
||||
const binary = existsSync(binaryPath) ? binaryPath : existsSync(debugBinaryPath) ? debugBinaryPath : null;
|
||||
|
||||
if (binary) {
|
||||
const output = execSync(`${binary} credentials extract-env --export`, {
|
||||
encoding: "utf-8",
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
// Parse export statements: export KEY="value"
|
||||
for (const line of output.split("\n")) {
|
||||
const match = line.match(/^export (\w+)="(.*)"/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
if (key === "ANTHROPIC_API_KEY" && !envCreds.anthropicApiKey) {
|
||||
envCreds.anthropicApiKey = value;
|
||||
} else if (key === "OPENAI_API_KEY" && !envCreds.openaiApiKey) {
|
||||
envCreds.openaiApiKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug(`Extracted credentials via sandbox-agent CLI`);
|
||||
}
|
||||
} catch (err) {
|
||||
log.debug(`Failed to extract credentials via CLI: ${err}`);
|
||||
}
|
||||
|
||||
return envCreds;
|
||||
}
|
||||
|
||||
function getAnthropicApiKey(): string | undefined {
|
||||
return extractCredentials().anthropicApiKey;
|
||||
}
|
||||
|
||||
function getOpenAiApiKey(): string | undefined {
|
||||
if (process.env.OPENAI_API_KEY) return process.env.OPENAI_API_KEY;
|
||||
const home = homedir();
|
||||
try {
|
||||
const data = JSON.parse(readFileSync(join(home, ".codex", "codex.json"), "utf-8"));
|
||||
if (data.apiKey) return data.apiKey;
|
||||
} catch {}
|
||||
return undefined;
|
||||
return extractCredentials().openaiApiKey;
|
||||
}
|
||||
|
||||
// Build sandbox-agent
|
||||
|
|
@ -520,6 +550,10 @@ async function testAgentActions(baseUrl: string, agent: string, sandbox: Sandbox
|
|||
const fileMessage = `Create a file at ${testFile} with exactly this content (no quotes, no extra text): ${expectedContent}`;
|
||||
await sendMessage(baseUrl, sessionId, fileMessage);
|
||||
|
||||
// Wait for agent to complete action after permission approval
|
||||
log.info("Waiting for agent to complete action...");
|
||||
await new Promise((r) => setTimeout(r, 5000));
|
||||
|
||||
// Verify file was created
|
||||
log.info("Verifying file was created...");
|
||||
const fileCheck = await sandbox.exec(`cat ${testFile} 2>&1`);
|
||||
|
|
|
|||
|
|
@ -286,6 +286,16 @@ export interface components {
|
|||
SessionStartedData: {
|
||||
metadata?: unknown;
|
||||
};
|
||||
StderrOutput: {
|
||||
/** @description First N lines of stderr (if truncated) or full stderr (if not truncated) */
|
||||
head?: string | null;
|
||||
/** @description Last N lines of stderr (only present if truncated) */
|
||||
tail?: string | null;
|
||||
/** @description Total number of lines in stderr */
|
||||
total_lines?: number | null;
|
||||
/** @description Whether the output was truncated */
|
||||
truncated: boolean;
|
||||
};
|
||||
/** @enum {string} */
|
||||
TerminatedBy: "agent" | "daemon";
|
||||
TurnStreamQuery: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue