Merge pull request #2173 from Lynricsy/feat/sync-poll-timeout-config
feat(delegate-task): ⚙️ make sync subagent timeout configurable via syncPollTimeoutMs
This commit is contained in:
commit
fdd806e729
@ -3685,6 +3685,10 @@
|
|||||||
"messageStalenessTimeoutMs": {
|
"messageStalenessTimeoutMs": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"minimum": 60000
|
"minimum": 60000
|
||||||
|
},
|
||||||
|
"syncPollTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 60000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
51
src/config/schema/background-task.test.ts
Normal file
51
src/config/schema/background-task.test.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { ZodError } from "zod/v4"
|
||||||
|
import { BackgroundTaskConfigSchema } from "./background-task"
|
||||||
|
|
||||||
|
describe("BackgroundTaskConfigSchema", () => {
|
||||||
|
describe("syncPollTimeoutMs", () => {
|
||||||
|
describe("#given valid syncPollTimeoutMs (120000)", () => {
|
||||||
|
test("#when parsed #then returns correct value", () => {
|
||||||
|
const result = BackgroundTaskConfigSchema.parse({ syncPollTimeoutMs: 120000 })
|
||||||
|
|
||||||
|
expect(result.syncPollTimeoutMs).toBe(120000)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given syncPollTimeoutMs below minimum (59999)", () => {
|
||||||
|
test("#when parsed #then throws ZodError", () => {
|
||||||
|
let thrownError: unknown
|
||||||
|
|
||||||
|
try {
|
||||||
|
BackgroundTaskConfigSchema.parse({ syncPollTimeoutMs: 59999 })
|
||||||
|
} catch (error) {
|
||||||
|
thrownError = error
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(thrownError).toBeInstanceOf(ZodError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given syncPollTimeoutMs not provided", () => {
|
||||||
|
test("#when parsed #then field is undefined", () => {
|
||||||
|
const result = BackgroundTaskConfigSchema.parse({})
|
||||||
|
|
||||||
|
expect(result.syncPollTimeoutMs).toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#given syncPollTimeoutMs is non-number ("abc")', () => {
|
||||||
|
test("#when parsed #then throws ZodError", () => {
|
||||||
|
let thrownError: unknown
|
||||||
|
|
||||||
|
try {
|
||||||
|
BackgroundTaskConfigSchema.parse({ syncPollTimeoutMs: "abc" })
|
||||||
|
} catch (error) {
|
||||||
|
thrownError = error
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(thrownError).toBeInstanceOf(ZodError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -8,6 +8,7 @@ export const BackgroundTaskConfigSchema = z.object({
|
|||||||
staleTimeoutMs: z.number().min(60000).optional(),
|
staleTimeoutMs: z.number().min(60000).optional(),
|
||||||
/** Timeout for tasks that never received any progress update, falling back to startedAt (default: 600000 = 10 minutes, minimum: 60000 = 1 minute) */
|
/** Timeout for tasks that never received any progress update, falling back to startedAt (default: 600000 = 10 minutes, minimum: 60000 = 1 minute) */
|
||||||
messageStalenessTimeoutMs: z.number().min(60000).optional(),
|
messageStalenessTimeoutMs: z.number().min(60000).optional(),
|
||||||
|
syncPollTimeoutMs: z.number().min(60000).optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>
|
export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>
|
||||||
|
|||||||
@ -67,6 +67,7 @@ export function createToolRegistry(args: {
|
|||||||
disabledSkills: skillContext.disabledSkills,
|
disabledSkills: skillContext.disabledSkills,
|
||||||
availableCategories,
|
availableCategories,
|
||||||
availableSkills: skillContext.availableSkills,
|
availableSkills: skillContext.availableSkills,
|
||||||
|
syncPollTimeoutMs: pluginConfig.background_task?.syncPollTimeoutMs,
|
||||||
onSyncSessionCreated: async (event) => {
|
onSyncSessionCreated: async (event) => {
|
||||||
log("[index] onSyncSessionCreated callback", {
|
log("[index] onSyncSessionCreated callback", {
|
||||||
sessionID: event.sessionID,
|
sessionID: event.sessionID,
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export interface ExecutorContext {
|
|||||||
browserProvider?: BrowserAutomationProvider
|
browserProvider?: BrowserAutomationProvider
|
||||||
agentOverrides?: AgentOverrides
|
agentOverrides?: AgentOverrides
|
||||||
onSyncSessionCreated?: (event: { sessionID: string; parentID: string; title: string }) => Promise<void>
|
onSyncSessionCreated?: (event: { sessionID: string; parentID: string; title: string }) => Promise<void>
|
||||||
|
syncPollTimeoutMs?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ParentContext {
|
export interface ParentContext {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export async function executeSyncContinuation(
|
|||||||
executorCtx: ExecutorContext,
|
executorCtx: ExecutorContext,
|
||||||
deps: SyncContinuationDeps = syncContinuationDeps
|
deps: SyncContinuationDeps = syncContinuationDeps
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const { client } = executorCtx
|
const { client, syncPollTimeoutMs } = executorCtx
|
||||||
const toastManager = getTaskToastManager()
|
const toastManager = getTaskToastManager()
|
||||||
const taskId = `resume_sync_${args.session_id!.slice(0, 8)}`
|
const taskId = `resume_sync_${args.session_id!.slice(0, 8)}`
|
||||||
const startTime = new Date()
|
const startTime = new Date()
|
||||||
@ -112,7 +112,7 @@ export async function executeSyncContinuation(
|
|||||||
toastManager,
|
toastManager,
|
||||||
taskId,
|
taskId,
|
||||||
anchorMessageCount,
|
anchorMessageCount,
|
||||||
})
|
}, syncPollTimeoutMs)
|
||||||
if (pollError) {
|
if (pollError) {
|
||||||
return pollError
|
return pollError
|
||||||
}
|
}
|
||||||
|
|||||||
176
src/tools/delegate-task/sync-poll-timeout.test.ts
Normal file
176
src/tools/delegate-task/sync-poll-timeout.test.ts
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
declare const require: (name: string) => any
|
||||||
|
const { describe, test, expect, beforeEach, afterEach } = require("bun:test")
|
||||||
|
import { __setTimingConfig, __resetTimingConfig, DEFAULT_SYNC_POLL_TIMEOUT_MS } from "./timing"
|
||||||
|
|
||||||
|
function createMockCtx(aborted = false) {
|
||||||
|
const controller = new AbortController()
|
||||||
|
if (aborted) controller.abort()
|
||||||
|
return {
|
||||||
|
sessionID: "parent-session",
|
||||||
|
messageID: "parent-message",
|
||||||
|
agent: "test-agent",
|
||||||
|
abort: controller.signal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNeverCompleteClient(sessionID: string) {
|
||||||
|
return {
|
||||||
|
session: {
|
||||||
|
messages: async () => ({
|
||||||
|
data: [{ info: { id: "msg_001", role: "user", time: { created: 1000 } } }],
|
||||||
|
}),
|
||||||
|
status: async () => ({ data: { [sessionID]: { type: "idle" } } }),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function withMockedDateNow(stepMs: number, run: () => Promise<void>) {
|
||||||
|
const originalDateNow = Date.now
|
||||||
|
let now = 0
|
||||||
|
|
||||||
|
Date.now = () => {
|
||||||
|
const current = now
|
||||||
|
now += stepMs
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await run()
|
||||||
|
} finally {
|
||||||
|
Date.now = originalDateNow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("syncPollTimeoutMs threading", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__setTimingConfig({
|
||||||
|
POLL_INTERVAL_MS: 10,
|
||||||
|
MIN_STABILITY_TIME_MS: 0,
|
||||||
|
STABILITY_POLLS_REQUIRED: 1,
|
||||||
|
MAX_POLL_TIME_MS: 5000,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
__resetTimingConfig()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given pollSyncSession timeoutMs input", () => {
|
||||||
|
describe("#when custom timeout is provided", () => {
|
||||||
|
test("#then custom timeout value is used", async () => {
|
||||||
|
const { pollSyncSession } = require("./sync-session-poller")
|
||||||
|
const mockClient = createNeverCompleteClient("ses_custom")
|
||||||
|
|
||||||
|
await withMockedDateNow(60_000, async () => {
|
||||||
|
const result = await pollSyncSession(createMockCtx(), mockClient, {
|
||||||
|
sessionID: "ses_custom",
|
||||||
|
agentToUse: "test-agent",
|
||||||
|
toastManager: null,
|
||||||
|
taskId: undefined,
|
||||||
|
}, 120_000)
|
||||||
|
|
||||||
|
expect(result).toBe("Poll timeout reached after 120000ms for session ses_custom")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#when timeoutMs is omitted", () => {
|
||||||
|
test("#then default timeout constant is used", async () => {
|
||||||
|
const { pollSyncSession } = require("./sync-session-poller")
|
||||||
|
const mockClient = createNeverCompleteClient("ses_default")
|
||||||
|
|
||||||
|
expect(DEFAULT_SYNC_POLL_TIMEOUT_MS).toBe(600_000)
|
||||||
|
|
||||||
|
await withMockedDateNow(300_000, async () => {
|
||||||
|
const result = await pollSyncSession(createMockCtx(), mockClient, {
|
||||||
|
sessionID: "ses_default",
|
||||||
|
agentToUse: "test-agent",
|
||||||
|
toastManager: null,
|
||||||
|
taskId: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(result).toBe(`Poll timeout reached after ${DEFAULT_SYNC_POLL_TIMEOUT_MS}ms for session ses_default`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#when timeoutMs is lower than minimum guard", () => {
|
||||||
|
test("#then minimum 50ms timeout is enforced", async () => {
|
||||||
|
const { pollSyncSession } = require("./sync-session-poller")
|
||||||
|
const mockClient = createNeverCompleteClient("ses_guard")
|
||||||
|
|
||||||
|
await withMockedDateNow(25, async () => {
|
||||||
|
const result = await pollSyncSession(createMockCtx(), mockClient, {
|
||||||
|
sessionID: "ses_guard",
|
||||||
|
agentToUse: "test-agent",
|
||||||
|
toastManager: null,
|
||||||
|
taskId: undefined,
|
||||||
|
}, 10)
|
||||||
|
|
||||||
|
expect(result).toBe("Poll timeout reached after 50ms for session ses_guard")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("#given unstable-agent-task path", () => {
|
||||||
|
describe("#when syncPollTimeoutMs is set in executor context", () => {
|
||||||
|
test("#then unstable path uses configured timeout budget", async () => {
|
||||||
|
const { executeUnstableAgentTask } = require("./unstable-agent-task")
|
||||||
|
|
||||||
|
let statusCallCount = 0
|
||||||
|
const mockClient = {
|
||||||
|
session: {
|
||||||
|
status: async () => {
|
||||||
|
statusCallCount++
|
||||||
|
return { data: { ses_unstable: { type: "idle" } } }
|
||||||
|
},
|
||||||
|
messages: async () => ({
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
info: { id: "msg_001", role: "assistant", time: { created: 2000 } },
|
||||||
|
parts: [{ type: "text", text: "unstable path done" }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockManager = {
|
||||||
|
launch: async () => ({ id: "task_001", sessionID: "ses_unstable", status: "running" }),
|
||||||
|
getTask: () => ({ id: "task_001", sessionID: "ses_unstable", status: "running" }),
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await executeUnstableAgentTask(
|
||||||
|
{
|
||||||
|
description: "unstable timeout threading",
|
||||||
|
prompt: "run",
|
||||||
|
category: "unspecified-low",
|
||||||
|
run_in_background: false,
|
||||||
|
load_skills: [],
|
||||||
|
command: undefined,
|
||||||
|
},
|
||||||
|
createMockCtx(),
|
||||||
|
{
|
||||||
|
manager: mockManager,
|
||||||
|
client: mockClient,
|
||||||
|
syncPollTimeoutMs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sessionID: "parent-session",
|
||||||
|
messageID: "parent-message",
|
||||||
|
model: "gpt-test",
|
||||||
|
agent: "test-agent",
|
||||||
|
},
|
||||||
|
"test-agent",
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
"gpt-test"
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(statusCallCount).toBe(0)
|
||||||
|
expect(result).toContain("SUPERVISED TASK COMPLETED SUCCESSFULLY")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -273,7 +273,7 @@ describe("pollSyncSession", () => {
|
|||||||
agentToUse: "test-agent",
|
agentToUse: "test-agent",
|
||||||
toastManager: null,
|
toastManager: null,
|
||||||
taskId: undefined,
|
taskId: undefined,
|
||||||
})
|
}, 0)
|
||||||
|
|
||||||
//#then - timeout returns error string
|
//#then - timeout returns error string
|
||||||
expect(result).toBe("Poll timeout reached after 50ms for session ses_timeout")
|
expect(result).toBe("Poll timeout reached after 50ms for session ses_timeout")
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { ToolContextWithMetadata, OpencodeClient } from "./types"
|
import type { ToolContextWithMetadata, OpencodeClient } from "./types"
|
||||||
import type { SessionMessage } from "./executor-types"
|
import type { SessionMessage } from "./executor-types"
|
||||||
import { getTimingConfig } from "./timing"
|
import { DEFAULT_SYNC_POLL_TIMEOUT_MS, getTimingConfig } from "./timing"
|
||||||
import { log } from "../../shared/logger"
|
import { log } from "../../shared/logger"
|
||||||
import { normalizeSDKResponse } from "../../shared"
|
import { normalizeSDKResponse } from "../../shared"
|
||||||
|
|
||||||
@ -32,10 +32,11 @@ export async function pollSyncSession(
|
|||||||
toastManager: { removeTask: (id: string) => void } | null | undefined
|
toastManager: { removeTask: (id: string) => void } | null | undefined
|
||||||
taskId: string | undefined
|
taskId: string | undefined
|
||||||
anchorMessageCount?: number
|
anchorMessageCount?: number
|
||||||
}
|
},
|
||||||
|
timeoutMs?: number
|
||||||
): Promise<string | null> {
|
): Promise<string | null> {
|
||||||
const syncTiming = getTimingConfig()
|
const syncTiming = getTimingConfig()
|
||||||
const maxPollTimeMs = Math.max(syncTiming.MAX_POLL_TIME_MS, 50)
|
const maxPollTimeMs = Math.max(timeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS, 50)
|
||||||
const pollStart = Date.now()
|
const pollStart = Date.now()
|
||||||
let pollCount = 0
|
let pollCount = 0
|
||||||
let timedOut = false
|
let timedOut = false
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export async function executeSyncTask(
|
|||||||
fallbackChain?: import("../../shared/model-requirements").FallbackEntry[],
|
fallbackChain?: import("../../shared/model-requirements").FallbackEntry[],
|
||||||
deps: SyncTaskDeps = syncTaskDeps
|
deps: SyncTaskDeps = syncTaskDeps
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const { client, directory, onSyncSessionCreated } = executorCtx
|
const { client, directory, onSyncSessionCreated, syncPollTimeoutMs } = executorCtx
|
||||||
const toastManager = getTaskToastManager()
|
const toastManager = getTaskToastManager()
|
||||||
let taskId: string | undefined
|
let taskId: string | undefined
|
||||||
let syncSessionID: string | undefined
|
let syncSessionID: string | undefined
|
||||||
@ -117,7 +117,7 @@ export async function executeSyncTask(
|
|||||||
agentToUse,
|
agentToUse,
|
||||||
toastManager,
|
toastManager,
|
||||||
taskId,
|
taskId,
|
||||||
})
|
}, syncPollTimeoutMs)
|
||||||
if (pollError) {
|
if (pollError) {
|
||||||
return pollError
|
return pollError
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ let WAIT_FOR_SESSION_TIMEOUT_MS = 30000
|
|||||||
let MAX_POLL_TIME_MS = 10 * 60 * 1000
|
let MAX_POLL_TIME_MS = 10 * 60 * 1000
|
||||||
let SESSION_CONTINUATION_STABILITY_MS = 5000
|
let SESSION_CONTINUATION_STABILITY_MS = 5000
|
||||||
|
|
||||||
|
export const DEFAULT_SYNC_POLL_TIMEOUT_MS = 600_000
|
||||||
|
|
||||||
export function getTimingConfig() {
|
export function getTimingConfig() {
|
||||||
return {
|
return {
|
||||||
POLL_INTERVAL_MS,
|
POLL_INTERVAL_MS,
|
||||||
|
|||||||
@ -1357,12 +1357,8 @@ describe("sisyphus-task", () => {
|
|||||||
return { data: {} }
|
return { data: {} }
|
||||||
})
|
})
|
||||||
|
|
||||||
const mockClient = {
|
const baseTime = Date.now()
|
||||||
session: {
|
const initialMessages = [
|
||||||
prompt: promptMock,
|
|
||||||
promptAsync: promptMock,
|
|
||||||
messages: async () => ({
|
|
||||||
data: [
|
|
||||||
{
|
{
|
||||||
info: {
|
info: {
|
||||||
id: "msg_001",
|
id: "msg_001",
|
||||||
@ -1370,16 +1366,49 @@ describe("sisyphus-task", () => {
|
|||||||
agent: "sisyphus-junior",
|
agent: "sisyphus-junior",
|
||||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||||
variant: "max",
|
variant: "max",
|
||||||
time: { created: Date.now() },
|
time: { created: baseTime },
|
||||||
},
|
},
|
||||||
parts: [{ type: "text", text: "previous message" }],
|
parts: [{ type: "text", text: "previous message" }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
info: { id: "msg_002", role: "assistant", time: { created: Date.now() + 1 }, finish: "end_turn" },
|
info: { id: "msg_002", role: "assistant", time: { created: baseTime + 1 }, finish: "end_turn" },
|
||||||
parts: [{ type: "text", text: "Completed." }],
|
parts: [{ type: "text", text: "Completed." }],
|
||||||
},
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const messagesCallCounts: Record<string, number> = {}
|
||||||
|
|
||||||
|
const mockClient = {
|
||||||
|
session: {
|
||||||
|
prompt: promptMock,
|
||||||
|
promptAsync: promptMock,
|
||||||
|
messages: async (input: any) => {
|
||||||
|
const sessionID = input?.path?.id
|
||||||
|
if (typeof sessionID !== "string") {
|
||||||
|
return { data: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
const callCount = (messagesCallCounts[sessionID] ?? 0) + 1
|
||||||
|
messagesCallCounts[sessionID] = callCount
|
||||||
|
|
||||||
|
if (sessionID !== "ses_var_test") {
|
||||||
|
return { data: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callCount === 1) {
|
||||||
|
return { data: initialMessages }
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: [
|
||||||
|
...initialMessages,
|
||||||
|
{
|
||||||
|
info: { id: "msg_003", role: "assistant", time: { created: baseTime + 2 }, finish: "end_turn" },
|
||||||
|
parts: [{ type: "text", text: "Continued." }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}
|
||||||
|
},
|
||||||
status: async () => ({ data: { "ses_var_test": { type: "idle" } } }),
|
status: async () => ({ data: { "ses_var_test": { type: "idle" } } }),
|
||||||
},
|
},
|
||||||
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
|
||||||
|
|||||||
@ -68,6 +68,7 @@ export interface DelegateTaskToolOptions {
|
|||||||
availableSkills?: AvailableSkill[]
|
availableSkills?: AvailableSkill[]
|
||||||
agentOverrides?: AgentOverrides
|
agentOverrides?: AgentOverrides
|
||||||
onSyncSessionCreated?: (event: SyncSessionCreatedEvent) => Promise<void>
|
onSyncSessionCreated?: (event: SyncSessionCreatedEvent) => Promise<void>
|
||||||
|
syncPollTimeoutMs?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BuildSystemContentInput {
|
export interface BuildSystemContentInput {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
import type { DelegateTaskArgs, ToolContextWithMetadata } from "./types"
|
||||||
import type { ExecutorContext, ParentContext, SessionMessage } from "./executor-types"
|
import type { ExecutorContext, ParentContext, SessionMessage } from "./executor-types"
|
||||||
import { getTimingConfig } from "./timing"
|
import { DEFAULT_SYNC_POLL_TIMEOUT_MS, getTimingConfig } from "./timing"
|
||||||
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
import { storeToolMetadata } from "../../features/tool-metadata-store"
|
||||||
import { formatDuration } from "./time-formatter"
|
import { formatDuration } from "./time-formatter"
|
||||||
import { formatDetailedError } from "./error-formatting"
|
import { formatDetailedError } from "./error-formatting"
|
||||||
@ -17,7 +17,7 @@ export async function executeUnstableAgentTask(
|
|||||||
systemContent: string | undefined,
|
systemContent: string | undefined,
|
||||||
actualModel: string | undefined
|
actualModel: string | undefined
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const { manager, client } = executorCtx
|
const { manager, client, syncPollTimeoutMs } = executorCtx
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const task = await manager.launch({
|
const task = await manager.launch({
|
||||||
@ -80,7 +80,7 @@ export async function executeUnstableAgentTask(
|
|||||||
let stablePolls = 0
|
let stablePolls = 0
|
||||||
let terminalStatus: { status: string; error?: string } | undefined
|
let terminalStatus: { status: string; error?: string } | undefined
|
||||||
|
|
||||||
while (Date.now() - pollStart < timingCfg.MAX_POLL_TIME_MS) {
|
while (Date.now() - pollStart < (syncPollTimeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS)) {
|
||||||
if (ctx.abort?.aborted) {
|
if (ctx.abort?.aborted) {
|
||||||
return `Task aborted (was running in background mode).\n\nSession ID: ${sessionID}`
|
return `Task aborted (was running in background mode).\n\nSession ID: ${sessionID}`
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user