fix: droid转发增加runtimeAddon调试插件

This commit is contained in:
shaw
2025-10-15 15:17:20 +08:00
parent 92712277db
commit d72897f835
3 changed files with 149 additions and 3 deletions

View File

@@ -7,8 +7,10 @@ const apiKeyService = require('./apiKeyService')
const redis = require('../models/redis')
const { updateRateLimitCounters } = require('../utils/rateLimitHelper')
const logger = require('../utils/logger')
const runtimeAddon = require('../utils/runtimeAddon')
const SYSTEM_PROMPT = 'You are Droid, an AI software engineering agent built by Factory.'
const RUNTIME_EVENT_FMT_PAYLOAD = 'fmtPayload'
/**
* Droid API 转发服务
@@ -246,11 +248,34 @@ class DroidRelayService {
// 处理请求体(注入 system prompt 等)
const streamRequested = !disableStreaming && this._isStreamRequested(normalizedRequestBody)
const processedBody = this._processRequestBody(normalizedRequestBody, normalizedEndpoint, {
let processedBody = this._processRequestBody(normalizedRequestBody, normalizedEndpoint, {
disableStreaming,
streamRequested
})
const extensionPayload = {
body: processedBody,
endpoint: normalizedEndpoint,
rawRequest: normalizedRequestBody,
originalRequest: requestBody
}
const extensionResult = runtimeAddon.emitSync(RUNTIME_EVENT_FMT_PAYLOAD, extensionPayload)
const resolvedPayload =
extensionResult && typeof extensionResult === 'object' ? extensionResult : extensionPayload
if (resolvedPayload && typeof resolvedPayload === 'object') {
if (resolvedPayload.abortResponse && typeof resolvedPayload.abortResponse === 'object') {
return resolvedPayload.abortResponse
}
if (resolvedPayload.body && typeof resolvedPayload.body === 'object') {
processedBody = resolvedPayload.body
} else if (resolvedPayload !== extensionPayload) {
processedBody = resolvedPayload
}
}
// 发送请求
const isStreaming = streamRequested

View File

@@ -171,7 +171,7 @@ class DroidScheduler {
if (filtered.length === 0) {
throw new Error(
`No available Droid accounts for endpoint ${normalizedEndpoint}${apiKeyData?.droidAccountId ? ' (respecting binding)' : ''}`
`No available accounts for endpoint ${normalizedEndpoint}${apiKeyData?.droidAccountId ? ' (respecting binding)' : ''}`
)
}
@@ -197,7 +197,7 @@ class DroidScheduler {
if (!selected) {
throw new Error(
`No schedulable Droid account available after sorting (${normalizedEndpoint})`
`No schedulable account available after sorting (${normalizedEndpoint})`
)
}

121
src/utils/runtimeAddon.js Normal file
View File

@@ -0,0 +1,121 @@
const fs = require('fs')
const path = require('path')
const logger = require('./logger')
const ADDON_DIRECTORIES = [
path.join(process.cwd(), '.local', 'ext'),
path.join(process.cwd(), '.local', 'extensions')
]
class RuntimeAddonBus {
constructor() {
this._handlers = new Map()
this._initialized = false
}
register(eventId, handler) {
if (!eventId || typeof handler !== 'function') {
return
}
if (!this._handlers.has(eventId)) {
this._handlers.set(eventId, [])
}
this._handlers.get(eventId).push(handler)
}
emitSync(eventId, payload) {
this._ensureInitialized()
if (!eventId) {
return payload
}
const handlers = this._handlers.get(eventId)
if (!handlers || handlers.length === 0) {
return payload
}
let current = payload
for (const handler of handlers) {
try {
const result = handler(current)
if (typeof result !== 'undefined') {
current = result
}
} catch (error) {
this._log('warn', `本地扩展处理 ${eventId} 失败: ${error.message}`, error)
}
}
return current
}
_ensureInitialized() {
if (this._initialized) {
return
}
this._initialized = true
const loadedPaths = new Set()
for (const dir of ADDON_DIRECTORIES) {
if (!dir || !fs.existsSync(dir)) {
continue
}
let entries = []
try {
entries = fs.readdirSync(dir, { withFileTypes: true })
} catch (error) {
this._log('warn', `读取本地扩展目录 ${dir} 失败: ${error.message}`, error)
continue
}
for (const entry of entries) {
if (!entry.isFile()) {
continue
}
if (!entry.name.endsWith('.js')) {
continue
}
const targetPath = path.join(dir, entry.name)
if (loadedPaths.has(targetPath)) {
continue
}
loadedPaths.add(targetPath)
try {
const registrar = require(targetPath)
if (typeof registrar === 'function') {
registrar(this)
}
} catch (error) {
this._log('warn', `加载本地扩展 ${entry.name} 失败: ${error.message}`, error)
}
}
}
}
_log(level, message, error) {
const targetLevel = typeof level === 'string' ? level : 'info'
const loggerMethod =
logger && typeof logger[targetLevel] === 'function' ? logger[targetLevel].bind(logger) : null
if (loggerMethod) {
loggerMethod(message, error)
} else if (targetLevel === 'error') {
console.error(message, error)
} else {
console.log(message, error)
}
}
}
module.exports = new RuntimeAddonBus()