refactor(subagent): share provider dispose window
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
|||||||
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
||||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||||
import {
|
import {
|
||||||
|
doubledGraceWindow,
|
||||||
settleRunResult,
|
settleRunResult,
|
||||||
subprocessRunHandle,
|
subprocessRunHandle,
|
||||||
type SubagentResult,
|
type SubagentResult,
|
||||||
@@ -38,47 +39,6 @@ import {
|
|||||||
/** Default POSIX grace between subprocess termination tiers. */
|
/** Default POSIX grace between subprocess termination tiers. */
|
||||||
export const DEFAULT_DISPOSE_GRACE_MS = 3_000
|
export const DEFAULT_DISPOSE_GRACE_MS = 3_000
|
||||||
|
|
||||||
/** Largest delay Node schedules without collapsing it to one millisecond. */
|
|
||||||
const MAX_TIMER_DELAY_MS = 2_147_483_647n
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bound final exit observation at twice a positive finite grace without
|
|
||||||
* narrowing the public config to Node's single-timer integer range.
|
|
||||||
*/
|
|
||||||
function doubledGraceWindow(graceMs: number): {
|
|
||||||
readonly signal: AbortSignal
|
|
||||||
readonly cancel: () => void
|
|
||||||
} {
|
|
||||||
const whole = Math.floor(graceMs)
|
|
||||||
let remaining = BigInt(whole) * 2n
|
|
||||||
+ BigInt(Math.ceil((graceMs - whole) * 2))
|
|
||||||
const controller = new AbortController()
|
|
||||||
let timer: ReturnType<typeof setTimeout> | undefined
|
|
||||||
const arm = (): void => {
|
|
||||||
const chunk = remaining > MAX_TIMER_DELAY_MS
|
|
||||||
? MAX_TIMER_DELAY_MS
|
|
||||||
: remaining
|
|
||||||
remaining -= chunk
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
timer = undefined
|
|
||||||
if (remaining === 0n) {
|
|
||||||
controller.abort()
|
|
||||||
} else {
|
|
||||||
arm()
|
|
||||||
}
|
|
||||||
}, Number(chunk))
|
|
||||||
}
|
|
||||||
arm()
|
|
||||||
return {
|
|
||||||
signal: controller.signal,
|
|
||||||
cancel: () => {
|
|
||||||
if (timer === undefined) return
|
|
||||||
clearTimeout(timer)
|
|
||||||
timer = undefined
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryFactory = (params: {
|
type QueryFactory = (params: {
|
||||||
prompt: string
|
prompt: string
|
||||||
options: Options
|
options: Options
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { randomUUID } from 'node:crypto'
|
|||||||
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
||||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||||
import {
|
import {
|
||||||
|
doubledGraceWindow,
|
||||||
settleRunResult,
|
settleRunResult,
|
||||||
subprocessRunHandle,
|
subprocessRunHandle,
|
||||||
type SubagentResult,
|
type SubagentResult,
|
||||||
@@ -24,47 +25,6 @@ import { CodexAppServerWire } from './wire.ts'
|
|||||||
/** Default POSIX grace between subprocess termination tiers. */
|
/** Default POSIX grace between subprocess termination tiers. */
|
||||||
export const DEFAULT_DISPOSE_GRACE_MS = 3_000
|
export const DEFAULT_DISPOSE_GRACE_MS = 3_000
|
||||||
|
|
||||||
/** Largest delay Node schedules without collapsing it to one millisecond. */
|
|
||||||
const MAX_TIMER_DELAY_MS = 2_147_483_647n
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bound final exit observation at twice a positive finite grace without
|
|
||||||
* narrowing the public config to Node's single-timer integer range.
|
|
||||||
*/
|
|
||||||
function doubledGraceWindow(graceMs: number): {
|
|
||||||
readonly signal: AbortSignal
|
|
||||||
readonly cancel: () => void
|
|
||||||
} {
|
|
||||||
const whole = Math.floor(graceMs)
|
|
||||||
let remaining = BigInt(whole) * 2n
|
|
||||||
+ BigInt(Math.ceil((graceMs - whole) * 2))
|
|
||||||
const controller = new AbortController()
|
|
||||||
let timer: ReturnType<typeof setTimeout> | undefined
|
|
||||||
const arm = (): void => {
|
|
||||||
const chunk = remaining > MAX_TIMER_DELAY_MS
|
|
||||||
? MAX_TIMER_DELAY_MS
|
|
||||||
: remaining
|
|
||||||
remaining -= chunk
|
|
||||||
timer = setTimeout(() => {
|
|
||||||
timer = undefined
|
|
||||||
if (remaining === 0n) {
|
|
||||||
controller.abort()
|
|
||||||
} else {
|
|
||||||
arm()
|
|
||||||
}
|
|
||||||
}, Number(chunk))
|
|
||||||
}
|
|
||||||
arm()
|
|
||||||
return {
|
|
||||||
signal: controller.signal,
|
|
||||||
cancel: () => {
|
|
||||||
if (timer === undefined) return
|
|
||||||
clearTimeout(timer)
|
|
||||||
timer = undefined
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Fully resolved inputs for one Codex app-server run. */
|
/** Fully resolved inputs for one Codex app-server run. */
|
||||||
export interface CodexRunSpec {
|
export interface CodexRunSpec {
|
||||||
/** Parent Session workspace, also supplied to `thread/start`. */
|
/** Parent Session workspace, also supplied to `thread/start`. */
|
||||||
|
|||||||
@@ -42,6 +42,49 @@ export function assertPositiveFinite(prefix: string, name: string, value: number
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Largest delay Node schedules without collapsing it to one millisecond. */
|
||||||
|
const MAX_TIMER_DELAY_MS = 2_147_483_647n
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bound final exit observation at twice a positive finite grace without
|
||||||
|
* narrowing public provider config to Node's single-timer integer range.
|
||||||
|
* @param graceMs - the already validated positive finite termination grace.
|
||||||
|
* @returns a cancellable abort signal for the doubled observation window.
|
||||||
|
*/
|
||||||
|
export function doubledGraceWindow(graceMs: number): {
|
||||||
|
readonly signal: AbortSignal
|
||||||
|
readonly cancel: () => void
|
||||||
|
} {
|
||||||
|
const whole = Math.floor(graceMs)
|
||||||
|
let remaining = BigInt(whole) * 2n
|
||||||
|
+ BigInt(Math.ceil((graceMs - whole) * 2))
|
||||||
|
const controller = new AbortController()
|
||||||
|
let timer: ReturnType<typeof setTimeout> | undefined
|
||||||
|
const arm = (): void => {
|
||||||
|
const chunk = remaining > MAX_TIMER_DELAY_MS
|
||||||
|
? MAX_TIMER_DELAY_MS
|
||||||
|
: remaining
|
||||||
|
remaining -= chunk
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
timer = undefined
|
||||||
|
if (remaining === 0n) {
|
||||||
|
controller.abort()
|
||||||
|
} else {
|
||||||
|
arm()
|
||||||
|
}
|
||||||
|
}, Number(chunk))
|
||||||
|
}
|
||||||
|
arm()
|
||||||
|
return {
|
||||||
|
signal: controller.signal,
|
||||||
|
cancel: () => {
|
||||||
|
if (timer === undefined) return
|
||||||
|
clearTimeout(timer)
|
||||||
|
timer = undefined
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether `path` names an existing directory the harness can ENTER. The
|
* Whether `path` names an existing directory the harness can ENTER. The
|
||||||
* search-permission probe matters: `statSync().isDirectory()` is true for a
|
* search-permission probe matters: `statSync().isDirectory()` is true for a
|
||||||
|
|||||||
Reference in New Issue
Block a user