2026-04-28 15:29:49 +09:00
import type { BackgroundTaskAttempt , BackgroundTaskStatus } from "./types"
2026-02-08 16:20:52 +09:00
2026-03-27 15:48:07 +09:00
export type BackgroundTaskNotificationStatus = "COMPLETED" | "CANCELLED" | "INTERRUPTED" | "ERROR"
2026-02-08 16:20:52 +09:00
2026-04-03 17:43:33 +09:00
export interface BackgroundTaskNotificationTask {
id : string
description : string
status : BackgroundTaskStatus
error? : string
2026-04-28 15:29:49 +09:00
attempts? : BackgroundTaskAttempt [ ]
}
function formatAttemptModel ( attempt : BackgroundTaskAttempt ) : string {
2026-05-02 03:01:03 +09:00
if ( attempt . providerId && attempt . modelId ) {
return ` ${ attempt . providerId } / ${ attempt . modelId } `
2026-04-28 15:29:49 +09:00
}
2026-05-02 03:01:03 +09:00
if ( attempt . modelId ) {
return attempt . modelId
2026-04-28 15:29:49 +09:00
}
2026-05-02 03:01:03 +09:00
if ( attempt . providerId ) {
return attempt . providerId
2026-04-28 15:29:49 +09:00
}
return "unknown-model"
}
function formatAttemptTimeline ( task : BackgroundTaskNotificationTask ) : string {
if ( ! task . attempts || task . attempts . length <= 1 ) {
return ""
}
const lines = task . attempts
. map ( ( attempt ) = > {
const attemptLines = [
2026-05-02 03:01:03 +09:00
` - Attempt ${ attempt . attemptNumber } — ${ attempt . status . toUpperCase ( ) } — ${ formatAttemptModel ( attempt ) } — ${ attempt . sessionId ? ? "unknown" } ` ,
2026-04-28 15:29:49 +09:00
]
if ( attempt . status !== "completed" && attempt . error ) {
attemptLines . push ( ` Error: ${ attempt . error } ` )
}
return attemptLines . join ( "\n" )
} )
. join ( "\n" )
return ` Background task attempts: \ n ${ lines } `
}
function formatTaskSummaryLine ( task : BackgroundTaskNotificationTask ) : string {
const baseLine = ` - \` ${ task . id } \` : ${ task . description || task . id } `
const statusSuffix = task . status === "completed"
? ""
: ` [ ${ task . status . toUpperCase ( ) } ] ${ task . error ? ` - ${ task . error } ` : "" } `
const timeline = formatAttemptTimeline ( task )
return ` ${ baseLine } ${ statusSuffix } ${ timeline ? ` \ n ${ timeline } ` : "" } `
2026-04-03 17:43:33 +09:00
}
2026-02-08 16:20:52 +09:00
export function buildBackgroundTaskNotificationText ( input : {
2026-04-03 17:43:33 +09:00
task : BackgroundTaskNotificationTask
2026-02-08 16:20:52 +09:00
duration : string
statusText : BackgroundTaskNotificationStatus
allComplete : boolean
remainingCount : number
2026-04-03 17:43:33 +09:00
completedTasks : BackgroundTaskNotificationTask [ ]
2026-02-08 16:20:52 +09:00
} ) : string {
const { task , duration , statusText , allComplete , remainingCount , completedTasks } = input
2026-04-05 15:46:24 +09:00
const safeDescription = ( t : BackgroundTaskNotificationTask ) : string = > t . description || t . id
2026-02-08 16:20:52 +09:00
const errorInfo = task . error ? ` \ n**Error:** ${ task . error } ` : ""
if ( allComplete ) {
2026-03-27 15:48:07 +09:00
const succeededTasks = completedTasks . filter ( ( t ) = > t . status === "completed" )
const failedTasks = completedTasks . filter ( ( t ) = > t . status !== "completed" )
const succeededText = succeededTasks . length > 0
2026-04-28 15:29:49 +09:00
? succeededTasks . map ( ( t ) = > formatTaskSummaryLine ( t ) ) . join ( "\n" )
2026-03-27 15:48:07 +09:00
: ""
const failedText = failedTasks . length > 0
2026-04-28 15:29:49 +09:00
? failedTasks . map ( ( t ) = > formatTaskSummaryLine ( t ) ) . join ( "\n" )
2026-03-27 15:48:07 +09:00
: ""
const hasFailures = failedTasks . length > 0
const header = hasFailures
? ` [ALL BACKGROUND TASKS FINISHED - ${ failedTasks . length } FAILED] `
: "[ALL BACKGROUND TASKS COMPLETE]"
let body = ""
if ( succeededText ) {
body += ` **Completed:** \ n ${ succeededText } \ n `
}
if ( failedText ) {
body += ` \ n**Failed:** \ n ${ failedText } \ n `
}
if ( ! body ) {
2026-04-28 15:29:49 +09:00
body = ` ${ formatTaskSummaryLine ( task ) } \ n `
2026-03-27 15:48:07 +09:00
}
2026-02-08 16:20:52 +09:00
return ` <system-reminder>
2026-03-27 15:48:07 +09:00
${ header }
2026-02-08 16:20:52 +09:00
2026-03-27 15:48:07 +09:00
${ body . trim ( ) }
2026-02-08 16:20:52 +09:00
2026-03-27 15:48:07 +09:00
Use \` background_output(task_id="<id>") \` to retrieve each result. ${ hasFailures ? ` \ n \ n**ACTION REQUIRED:** ${ failedTasks . length } task(s) failed. Check errors above and decide whether to retry or proceed. ` : "" }
2026-02-08 16:20:52 +09:00
</system-reminder> `
}
2026-03-27 15:48:07 +09:00
const isFailure = statusText !== "COMPLETED"
2026-02-08 16:20:52 +09:00
return ` <system-reminder>
[BACKGROUND TASK ${ statusText } ]
**ID:** \` ${ task . id } \`
2026-04-05 15:46:24 +09:00
**Description:** ${ safeDescription ( task ) }
2026-02-08 16:20:52 +09:00
**Duration:** ${ duration } ${ errorInfo }
** ${ remainingCount } task ${ remainingCount === 1 ? "" : "s" } still in progress.** You WILL be notified when ALL complete.
2026-03-27 15:48:07 +09:00
${ isFailure ? "**ACTION REQUIRED:** This task failed. Check the error and decide whether to retry, cancel remaining tasks, or continue." : "Do NOT poll - continue productive work." }
2026-02-08 16:20:52 +09:00
Use \` background_output(task_id=" ${ task . id } ") \` to retrieve this result when ready.
</system-reminder> `
}