2026-02-08 13:57:26 +09:00
import type { DelegateTaskArgs , OpencodeClient } from "./types"
2026-02-08 17:34:47 +09:00
import { isPlanFamily } from "./constants"
2026-02-17 01:29:17 +09:00
import {
promptSyncWithModelSuggestionRetry ,
promptWithModelSuggestionRetry ,
} from "../../shared/model-suggestion-retry"
2026-02-08 13:57:26 +09:00
import { formatDetailedError } from "./error-formatting"
2026-02-10 19:09:22 +09:00
import { getAgentToolRestrictions } from "../../shared/agent-tool-restrictions"
2026-02-14 14:30:22 +09:00
import { setSessionTools } from "../../shared/session-tools-store"
2026-02-08 13:57:26 +09:00
2026-02-17 01:29:17 +09:00
type SendSyncPromptDeps = {
promptWithModelSuggestionRetry : typeof promptWithModelSuggestionRetry
promptSyncWithModelSuggestionRetry : typeof promptSyncWithModelSuggestionRetry
}
const sendSyncPromptDeps : SendSyncPromptDeps = {
promptWithModelSuggestionRetry ,
promptSyncWithModelSuggestionRetry ,
}
function isOracleAgent ( agentToUse : string ) : boolean {
return agentToUse . toLowerCase ( ) === "oracle"
}
function isUnexpectedEofError ( error : unknown ) : boolean {
const message = error instanceof Error ? error.message : String ( error )
const lowered = message . toLowerCase ( )
return lowered . includes ( "unexpected eof" ) || lowered . includes ( "json parse error" )
}
2026-02-08 13:57:26 +09:00
export async function sendSyncPrompt (
client : OpencodeClient ,
input : {
sessionID : string
agentToUse : string
args : DelegateTaskArgs
systemContent : string | undefined
categoryModel : { providerID : string ; modelID : string ; variant? : string } | undefined
toastManager : { removeTask : ( id : string ) = > void } | null | undefined
taskId : string | undefined
2026-02-17 01:29:17 +09:00
} ,
deps : SendSyncPromptDeps = sendSyncPromptDeps
2026-02-08 13:57:26 +09:00
) : Promise < string | null > {
2026-02-17 01:29:17 +09:00
const allowTask = isPlanFamily ( input . agentToUse )
const tools = {
task : allowTask ,
call_omo_agent : true ,
question : false ,
. . . getAgentToolRestrictions ( input . agentToUse ) ,
}
setSessionTools ( input . sessionID , tools )
const promptArgs = {
path : { id : input.sessionID } ,
body : {
agent : input.agentToUse ,
system : input.systemContent ,
tools ,
parts : [ { type : "text" , text : input.args.prompt } ] ,
. . . ( input . categoryModel
? { model : { providerID : input.categoryModel.providerID , modelID : input.categoryModel.modelID } }
: { } ) ,
. . . ( input . categoryModel ? . variant ? { variant : input.categoryModel.variant } : { } ) ,
} ,
}
2026-02-08 13:57:26 +09:00
try {
2026-02-17 01:29:17 +09:00
await deps . promptWithModelSuggestionRetry ( client , promptArgs )
2026-02-08 13:57:26 +09:00
} catch ( promptError ) {
2026-02-17 01:29:17 +09:00
if ( isOracleAgent ( input . agentToUse ) && isUnexpectedEofError ( promptError ) ) {
try {
await deps . promptSyncWithModelSuggestionRetry ( client , promptArgs )
return null
} catch ( oracleRetryError ) {
promptError = oracleRetryError
}
}
2026-02-08 13:57:26 +09:00
if ( input . toastManager && input . taskId !== undefined ) {
input . toastManager . removeTask ( input . taskId )
}
const errorMessage = promptError instanceof Error ? promptError.message : String ( promptError )
if ( errorMessage . includes ( "agent.name" ) || errorMessage . includes ( "undefined" ) ) {
return formatDetailedError ( new Error ( ` Agent " ${ input . agentToUse } " not found. Make sure the agent is registered in your opencode.json or provided by a plugin. ` ) , {
operation : "Send prompt to agent" ,
args : input.args ,
sessionID : input.sessionID ,
agent : input.agentToUse ,
category : input.args.category ,
} )
}
return formatDetailedError ( promptError , {
operation : "Send prompt" ,
args : input.args ,
sessionID : input.sessionID ,
agent : input.agentToUse ,
category : input.args.category ,
} )
}
return null
}