feat: improve Droid provider implementation and configuration

- Add --skip-permissions-unsafe flag to droid exec commands for non-interactive execution
- Improve error handling to accept output from both stdout and stderr
- Map droid protocol to claude in getProtocolPrefix for proper request conversion
- Add DROID_AUTH_FILE and DROID_COMMAND to config.json.example
- Add droid-factory-oauth provider pool example to provider_pools.json.example

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
bee4come 2025-10-15 13:26:58 +08:00
parent 3111119f93
commit 66b6363ad4
5 changed files with 32 additions and 8 deletions

View file

@ -13,6 +13,8 @@
"KIRO_OAUTH_CREDS_BASE64": null, "KIRO_OAUTH_CREDS_BASE64": null,
"KIRO_OAUTH_CREDS_FILE_PATH": null, "KIRO_OAUTH_CREDS_FILE_PATH": null,
"QWEN_OAUTH_CREDS_FILE_PATH": null, "QWEN_OAUTH_CREDS_FILE_PATH": null,
"DROID_AUTH_FILE": null,
"DROID_COMMAND": "droid",
"SYSTEM_PROMPT_FILE_PATH": "input_system_prompt.txt", "SYSTEM_PROMPT_FILE_PATH": "input_system_prompt.txt",
"SYSTEM_PROMPT_MODE": "overwrite", "SYSTEM_PROMPT_MODE": "overwrite",
"PROMPT_LOG_BASE_NAME": "prompt_log", "PROMPT_LOG_BASE_NAME": "prompt_log",

2
package-lock.json generated
View file

@ -1,5 +1,5 @@
{ {
"name": "AIClient2API", "name": "AIClient-2-API",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {

View file

@ -104,5 +104,18 @@
"errorCount": 0, "errorCount": 0,
"lastErrorTime": null "lastErrorTime": null
} }
],
"droid-factory-oauth": [
{
"DROID_AUTH_FILE": "~/.factory/auth.json",
"DROID_COMMAND": "droid",
"uuid": "9d8e7f6a-5c4b-3a2d-1e0f-9a8b7c6d5e4f",
"checkModelName": null,
"isHealthy": true,
"lastUsed": null,
"usageCount": 0,
"errorCount": 0,
"lastErrorTime": null
}
] ]
} }

View file

@ -37,10 +37,17 @@ export const MODEL_PROVIDER = {
*/ */
export function getProtocolPrefix(provider) { export function getProtocolPrefix(provider) {
const hyphenIndex = provider.indexOf('-'); const hyphenIndex = provider.indexOf('-');
let prefix = provider;
if (hyphenIndex !== -1) { if (hyphenIndex !== -1) {
return provider.substring(0, hyphenIndex); prefix = provider.substring(0, hyphenIndex);
} }
return provider; // Return original if no hyphen is found
// Map droid protocol to claude (since droid uses Claude API)
if (prefix === 'droid') {
return 'claude';
}
return prefix;
} }
export const ENDPOINT_TYPE = { export const ENDPOINT_TYPE = {

View file

@ -53,10 +53,12 @@ export class DroidApiService {
}); });
droid.on('close', (code) => { droid.on('close', (code) => {
if (code !== 0) { // Droid CLI may output to stderr even on success
reject(new Error(`Droid command failed: ${stderr || stdout}`)); const output = stdout || stderr;
if (code !== 0 && !output) {
reject(new Error(`Droid command failed with code ${code}: ${stderr || stdout}`));
} else { } else {
resolve(stdout); resolve(output);
} }
}); });
@ -97,7 +99,7 @@ export class DroidApiService {
try { try {
const prompt = this.messagesToPrompt(requestBody.messages); const prompt = this.messagesToPrompt(requestBody.messages);
const output = await this.executeDroidCommand(['exec', prompt]); const output = await this.executeDroidCommand(['exec', '--skip-permissions-unsafe', prompt]);
return { return {
id: `msg_${Date.now()}`, id: `msg_${Date.now()}`,
@ -149,7 +151,7 @@ export class DroidApiService {
content_block: { type: 'text', text: '' } content_block: { type: 'text', text: '' }
}; };
const droid = spawn(this.droidCommand, ['exec', prompt]); const droid = spawn(this.droidCommand, ['exec', '--skip-permissions-unsafe', prompt]);
let buffer = ''; let buffer = '';
for await (const chunk of droid.stdout) { for await (const chunk of droid.stdout) {