2026-03-18 14:21:27 +01:00
import type { DelegateTaskArgs , OpencodeClient , DelegatedModelConfig } from "./types"
2026-03-28 09:34:58 -07:00
import type { SisyphusAgentConfig } from "../../config/schema"
2026-04-10 15:53:14 +09:00
import { isPlanFamily } from "./constants"
2026-03-06 22:56:51 +09:00
import { buildTaskPrompt } from "./prompt-builder"
2026-02-17 01:29:17 +09:00
import {
promptSyncWithModelSuggestionRetry ,
promptWithModelSuggestionRetry ,
} from "../../shared/model-suggestion-retry"
2026-05-12 18:14:17 +09:00
import { routePromptRetry , routePromptSyncRetry } from "../../shared/session-route"
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-04-15 10:46:41 +09:00
import { stripInvisibleAgentCharacters } from "../../shared/agent-display-names"
2026-03-25 09:28:59 +01:00
import { applySessionPromptParams } from "../../shared/session-prompt-params-helpers"
2026-02-14 14:30:22 +09:00
import { setSessionTools } from "../../shared/session-tools-store"
2026-02-21 16:24:18 +09:00
import { createInternalAgentTextPart } from "../../shared/internal-initiator-marker"
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 ,
}
2026-04-04 15:40:37 +09:00
function buildPromptGenerationParams ( model : DelegatedModelConfig | undefined ) : Record < string , unknown > {
if ( ! model ) {
return { }
}
const promptOptions : Record < string , unknown > = {
. . . ( model . reasoningEffort ? { reasoningEffort : model.reasoningEffort } : { } ) ,
. . . ( model . thinking ? { thinking : model.thinking } : { } ) ,
}
return {
. . . ( model . temperature !== undefined ? { temperature : model.temperature } : { } ) ,
. . . ( model . top_p !== undefined ? { topP : model.top_p } : { } ) ,
2026-04-08 17:14:17 +09:00
. . . ( model . maxTokens !== undefined ? { maxOutputTokens : model.maxTokens } : { } ) ,
2026-04-04 15:40:37 +09:00
. . . ( Object . keys ( promptOptions ) . length > 0 ? { options : promptOptions } : { } ) ,
}
}
2026-02-17 01:29:17 +09:00
function isOracleAgent ( agentToUse : string ) : boolean {
2026-04-15 10:46:41 +09:00
return stripInvisibleAgentCharacters ( agentToUse ) . toLowerCase ( ) === "oracle"
2026-02-17 01:29:17 +09:00
}
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
2026-03-18 14:21:27 +01:00
categoryModel : DelegatedModelConfig | undefined
2026-05-12 18:14:17 +09:00
directory : string
2026-02-08 13:57:26 +09:00
toastManager : { removeTask : ( id : string ) = > void } | null | undefined
taskId : string | undefined
2026-03-28 09:34:58 -07:00
sisyphusAgentConfig? : SisyphusAgentConfig
2026-02-17 01:29:17 +09:00
} ,
deps : SendSyncPromptDeps = sendSyncPromptDeps
2026-02-08 13:57:26 +09:00
) : Promise < string | null > {
2026-04-10 15:53:14 +09:00
const allowTask = isPlanFamily ( input . agentToUse )
2026-03-28 09:34:58 -07:00
const tddEnabled = input . sisyphusAgentConfig ? . tdd
2026-05-15 19:13:48 +09:00
const effectivePrompt = buildTaskPrompt ( input . args . prompt , input . agentToUse , tddEnabled )
2026-02-17 01:29:17 +09:00
const tools = {
task : allowTask ,
call_omo_agent : true ,
question : false ,
. . . getAgentToolRestrictions ( input . agentToUse ) ,
}
setSessionTools ( input . sessionID , tools )
2026-03-25 09:28:59 +01:00
applySessionPromptParams ( input . sessionID , input . categoryModel )
2026-03-18 14:21:27 +01:00
2026-02-17 01:29:17 +09:00
const promptArgs = {
path : { id : input.sessionID } ,
body : {
2026-04-15 10:46:41 +09:00
agent : stripInvisibleAgentCharacters ( input . agentToUse ) ,
2026-02-17 01:29:17 +09:00
system : input.systemContent ,
tools ,
2026-03-06 22:56:51 +09:00
parts : [ createInternalAgentTextPart ( effectivePrompt ) ] ,
2026-02-17 01:29:17 +09:00
. . . ( input . categoryModel
2026-03-18 14:21:27 +01:00
? {
model : {
providerID : input.categoryModel.providerID ,
modelID : input.categoryModel.modelID ,
} ,
}
2026-02-17 01:29:17 +09:00
: { } ) ,
. . . ( input . categoryModel ? . variant ? { variant : input.categoryModel.variant } : { } ) ,
2026-04-04 15:40:37 +09:00
. . . buildPromptGenerationParams ( input . categoryModel ) ,
2026-02-17 01:29:17 +09:00
} ,
}
2026-02-08 13:57:26 +09:00
try {
2026-05-12 18:14:17 +09:00
const routedPromptArgs = routePromptRetry ( promptArgs , input . directory )
await deps . promptWithModelSuggestionRetry ( client , routedPromptArgs )
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 {
2026-05-12 18:14:17 +09:00
await deps . promptSyncWithModelSuggestionRetry ( client , routePromptSyncRetry ( promptArgs , input . directory ) )
2026-02-17 01:29:17 +09:00
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
}