fix: pipeline — case-insensitive agent join, remove stale model routing, single-task dispatch, 300s timeout
- JOIN agents uses lower() for case-insensitive name matching - Removed hardcoded 9router/cc/ model IDs — agents use their own OC config - Dispatch LIMIT 3 → 1 to prevent concurrent gateway saturation - Gateway timeout 120s → 300s (engineer agent has 130k token context) - Direct API classifyDirectModel simplified — all routing via OC gateway
This commit is contained in:
parent
4931e008b2
commit
b2ae69e3b8
|
|
@ -49,31 +49,8 @@ function classifyTaskModel(task: DispatchableTask): string | null {
|
|||
const text = `${task.title} ${task.description ?? ''}`.toLowerCase()
|
||||
const priority = task.priority?.toLowerCase() ?? ''
|
||||
|
||||
// Complex signals → Opus
|
||||
const complexSignals = [
|
||||
'debug', 'diagnos', 'architect', 'design system', 'security audit',
|
||||
'root cause', 'investigate', 'incident', 'failure', 'broken', 'not working',
|
||||
'refactor', 'migration', 'performance optim', 'why is',
|
||||
]
|
||||
if (priority === 'critical' || complexSignals.some(s => text.includes(s))) {
|
||||
return '9router/cc/claude-opus-4-6'
|
||||
}
|
||||
|
||||
// Routine signals → Haiku
|
||||
const routineSignals = [
|
||||
'status check', 'health check', 'ping', 'list ', 'fetch ', 'format',
|
||||
'rename', 'move file', 'read file', 'update readme', 'bump version',
|
||||
'send message', 'post to', 'notify', 'summarize', 'translate',
|
||||
'quick ', 'simple ', 'routine ', 'minor ',
|
||||
]
|
||||
if (priority === 'low' && routineSignals.some(s => text.includes(s))) {
|
||||
return '9router/cc/claude-haiku-4-5-20251001'
|
||||
}
|
||||
if (routineSignals.some(s => text.includes(s)) && priority !== 'high' && priority !== 'critical') {
|
||||
return '9router/cc/claude-haiku-4-5-20251001'
|
||||
}
|
||||
|
||||
// Default: let the agent's own configured model handle it (no override)
|
||||
// Let the agent's own configured model handle it — no dispatch-side model override.
|
||||
// The OC gateway agents already have their models set in openclaw.json.
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
@ -213,34 +190,12 @@ function classifyDirectModel(task: DispatchableTask): string {
|
|||
try {
|
||||
const cfg = JSON.parse(task.agent_config)
|
||||
if (typeof cfg.dispatchModel === 'string' && cfg.dispatchModel) {
|
||||
// Return model ID as-is — full provider/model paths are valid
|
||||
return cfg.dispatchModel
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
const text = `${task.title} ${task.description ?? ''}`.toLowerCase()
|
||||
const priority = task.priority?.toLowerCase() ?? ''
|
||||
|
||||
// Complex → Opus
|
||||
const complexSignals = [
|
||||
'debug', 'diagnos', 'architect', 'design system', 'security audit',
|
||||
'root cause', 'investigate', 'incident', 'refactor', 'migration',
|
||||
]
|
||||
if (priority === 'critical' || complexSignals.some(s => text.includes(s))) {
|
||||
return 'claude-opus-4-6'
|
||||
}
|
||||
|
||||
// Routine → Haiku
|
||||
const routineSignals = [
|
||||
'status check', 'health check', 'format', 'rename', 'summarize',
|
||||
'translate', 'quick ', 'simple ', 'routine ', 'minor ',
|
||||
]
|
||||
if (routineSignals.some(s => text.includes(s)) && priority !== 'high' && priority !== 'critical') {
|
||||
return 'claude-haiku-4-5-20251001'
|
||||
}
|
||||
|
||||
// Default → Sonnet
|
||||
// Default → Sonnet (agents configure their own models via OC gateway)
|
||||
return 'claude-sonnet-4-6'
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +396,7 @@ export async function runAegisReviews(): Promise<{ ok: boolean; message: string
|
|||
p.ticket_prefix, t.project_ticket_no, a.config as agent_config
|
||||
FROM tasks t
|
||||
LEFT JOIN projects p ON p.id = t.project_id AND p.workspace_id = t.workspace_id
|
||||
LEFT JOIN agents a ON a.name = t.assigned_to AND a.workspace_id = t.workspace_id
|
||||
LEFT JOIN agents a ON lower(a.name) = lower(t.assigned_to) AND a.workspace_id = t.workspace_id
|
||||
WHERE t.status = 'review'
|
||||
ORDER BY t.updated_at ASC
|
||||
LIMIT 3
|
||||
|
|
@ -489,8 +444,8 @@ export async function runAegisReviews(): Promise<{ ok: boolean; message: string
|
|||
deliver: false,
|
||||
}
|
||||
const finalResult = await runOpenClaw(
|
||||
['gateway', 'call', 'agent', '--expect-final', '--timeout', '120000', '--params', JSON.stringify(invokeParams), '--json'],
|
||||
{ timeoutMs: 125_000 }
|
||||
['gateway', 'call', 'agent', '--expect-final', '--timeout', '300000', '--params', JSON.stringify(invokeParams), '--json'],
|
||||
{ timeoutMs: 305_000 }
|
||||
)
|
||||
const finalPayload = parseGatewayJson(finalResult.stdout)
|
||||
?? parseGatewayJson(String((finalResult as any)?.stderr || ''))
|
||||
|
|
@ -732,7 +687,7 @@ export async function requeueStaleTasks(): Promise<{ ok: boolean; message: strin
|
|||
SELECT t.id, t.title, t.assigned_to, t.dispatch_attempts, t.workspace_id,
|
||||
a.status as agent_status, a.last_seen as agent_last_seen
|
||||
FROM tasks t
|
||||
LEFT JOIN agents a ON a.name = t.assigned_to AND a.workspace_id = t.workspace_id
|
||||
LEFT JOIN agents a ON lower(a.name) = lower(t.assigned_to) AND a.workspace_id = t.workspace_id
|
||||
WHERE t.status = 'in_progress'
|
||||
AND t.updated_at < ?
|
||||
`).all(staleThreshold) as Array<{
|
||||
|
|
@ -808,14 +763,14 @@ export async function dispatchAssignedTasks(): Promise<{ ok: boolean; message: s
|
|||
SELECT t.*, a.name as agent_name, a.id as agent_id, a.config as agent_config,
|
||||
p.ticket_prefix, t.project_ticket_no
|
||||
FROM tasks t
|
||||
JOIN agents a ON a.name = t.assigned_to AND a.workspace_id = t.workspace_id
|
||||
JOIN agents a ON lower(a.name) = lower(t.assigned_to) AND a.workspace_id = t.workspace_id
|
||||
LEFT JOIN projects p ON p.id = t.project_id AND p.workspace_id = t.workspace_id
|
||||
WHERE t.status = 'assigned'
|
||||
AND t.assigned_to IS NOT NULL
|
||||
ORDER BY
|
||||
CASE t.priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END ASC,
|
||||
t.created_at ASC
|
||||
LIMIT 3
|
||||
LIMIT 1
|
||||
`).all() as (DispatchableTask & { tags?: string })[]
|
||||
|
||||
if (tasks.length === 0) {
|
||||
|
|
@ -921,8 +876,8 @@ export async function dispatchAssignedTasks(): Promise<{ ok: boolean; message: s
|
|||
// response payload (result.payloads[0].text). The two-step agent → agent.wait
|
||||
// pattern only returns lifecycle metadata and never includes the agent's text.
|
||||
const finalResult = await runOpenClaw(
|
||||
['gateway', 'call', 'agent', '--expect-final', '--timeout', '120000', '--params', JSON.stringify(invokeParams), '--json'],
|
||||
{ timeoutMs: 125_000 }
|
||||
['gateway', 'call', 'agent', '--expect-final', '--timeout', '300000', '--params', JSON.stringify(invokeParams), '--json'],
|
||||
{ timeoutMs: 305_000 }
|
||||
)
|
||||
const finalPayload = parseGatewayJson(finalResult.stdout)
|
||||
?? parseGatewayJson(String((finalResult as any)?.stderr || ''))
|
||||
|
|
|
|||
Loading…
Reference in New Issue