mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 20:43:36 +00:00
feat(electron): enhance feature execution with async prompt handling and authentication checks
- Updated the FeatureExecutor to wrap content blocks in an async generator for multimodal prompt compatibility. - Added authentication checks in the ClaudeProvider to ensure proper API key or token availability, including loading from local CLI config. - Improved error handling for missing authentication, providing clear console messages for user guidance. This update enhances the robustness of feature execution and ensures proper authentication management for the Claude SDK.
This commit is contained in:
@@ -323,8 +323,18 @@ class FeatureExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// Use content blocks instead of plain text
|
||||
prompt = contentBlocks;
|
||||
// Wrap content blocks in async generator for SDK (required format for multimodal prompts)
|
||||
prompt = (async function* () {
|
||||
yield {
|
||||
type: "user",
|
||||
session_id: "",
|
||||
message: {
|
||||
role: "user",
|
||||
content: contentBlocks,
|
||||
},
|
||||
parent_tool_use_id: null,
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
// Planning: Analyze the codebase and create implementation plan
|
||||
@@ -356,6 +366,15 @@ class FeatureExecutor {
|
||||
let currentQuery;
|
||||
isCodex = this.isCodexModel(feature);
|
||||
|
||||
// Ensure provider auth is available (especially for Claude SDK)
|
||||
const provider = this.getProvider(feature);
|
||||
if (provider?.ensureAuthEnv && !provider.ensureAuthEnv()) {
|
||||
const authMsg =
|
||||
"Missing Anthropic auth. Set ANTHROPIC_API_KEY or run `claude login` so ~/.claude/config.json contains oauth_token.";
|
||||
console.error(`[FeatureExecutor] ${authMsg}`);
|
||||
throw new Error(authMsg);
|
||||
}
|
||||
|
||||
// Validate that model string matches the provider
|
||||
if (isCodex) {
|
||||
// Ensure model string is actually a Codex model, not a Claude model
|
||||
@@ -367,7 +386,6 @@ class FeatureExecutor {
|
||||
|
||||
// Use Codex provider for OpenAI models
|
||||
console.log(`[FeatureExecutor] Using Codex provider for model: ${modelString}`);
|
||||
const provider = this.getProvider(feature);
|
||||
currentQuery = provider.executeQuery({
|
||||
prompt,
|
||||
model: modelString,
|
||||
@@ -712,8 +730,18 @@ class FeatureExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// Use content blocks instead of plain text
|
||||
prompt = contentBlocks;
|
||||
// Wrap content blocks in async generator for SDK (required format for multimodal prompts)
|
||||
prompt = (async function* () {
|
||||
yield {
|
||||
type: "user",
|
||||
session_id: "",
|
||||
message: {
|
||||
role: "user",
|
||||
content: contentBlocks,
|
||||
},
|
||||
parent_tool_use_id: null,
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
// Use appropriate provider based on model type
|
||||
|
||||
@@ -94,6 +94,45 @@ class ClaudeProvider extends ModelProvider {
|
||||
this.sdk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load a Claude OAuth token from the local CLI config (~/.claude/config.json).
|
||||
* Returns the token string or null if not found.
|
||||
*/
|
||||
loadTokenFromCliConfig() {
|
||||
try {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const configPath = path.join(require('os').homedir(), '.claude', 'config.json');
|
||||
if (!fs.existsSync(configPath)) {
|
||||
return null;
|
||||
}
|
||||
const raw = fs.readFileSync(configPath, 'utf-8');
|
||||
const parsed = JSON.parse(raw);
|
||||
// CLI config stores token as oauth_token (newer) or token (older)
|
||||
return parsed.oauth_token || parsed.token || null;
|
||||
} catch (err) {
|
||||
console.warn('[ClaudeProvider] Failed to read CLI config token:', err?.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ensureAuthEnv() {
|
||||
// If API key or token already present, keep as-is.
|
||||
if (process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
||||
console.log('[ClaudeProvider] Auth already present in environment');
|
||||
return true;
|
||||
}
|
||||
// Try to hydrate from CLI login config
|
||||
const token = this.loadTokenFromCliConfig();
|
||||
if (token) {
|
||||
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
||||
console.log('[ClaudeProvider] Loaded CLAUDE_CODE_OAUTH_TOKEN from ~/.claude/config.json');
|
||||
return true;
|
||||
}
|
||||
console.error('[ClaudeProvider] No Anthropic auth found (env empty, ~/.claude/config.json missing token)');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily load the Claude SDK
|
||||
*/
|
||||
@@ -105,6 +144,14 @@ class ClaudeProvider extends ModelProvider {
|
||||
}
|
||||
|
||||
async *executeQuery(options) {
|
||||
// Ensure we have auth; fall back to CLI login token if available.
|
||||
if (!this.ensureAuthEnv()) {
|
||||
const msg = 'Missing Anthropic auth. Set ANTHROPIC_API_KEY or run `claude login` (CLI) so ~/.claude/config.json contains oauth_token.';
|
||||
console.error(`[ClaudeProvider] ${msg}`);
|
||||
yield { type: 'error', error: msg };
|
||||
return;
|
||||
}
|
||||
|
||||
const { query } = this.loadSdk();
|
||||
|
||||
const sdkOptions = {
|
||||
@@ -168,9 +215,11 @@ class ClaudeProvider extends ModelProvider {
|
||||
validateConfig() {
|
||||
const errors = [];
|
||||
|
||||
// Check for OAuth token or API key
|
||||
// Ensure auth is available (try to auto-load from CLI config)
|
||||
this.ensureAuthEnv();
|
||||
|
||||
if (!process.env.CLAUDE_CODE_OAUTH_TOKEN && !process.env.ANTHROPIC_API_KEY) {
|
||||
errors.push('No Claude authentication found. Set CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY.');
|
||||
errors.push('No Claude authentication found. Set CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY, or run `claude login` to populate ~/.claude/config.json.');
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user