{"version":3,"file":"index.mjs","names":[],"sources":["../src/adapter.ts","../src/queue.ts"],"sourcesContent":["import type { CreateJobRequest, JobInfo } from '@workerdeck/protocol'\n\nexport type JobRecord = {\n  info: JobInfo\n  request: CreateJobRequest\n}\n\nexport interface QueueAdapter {\n  add(job: JobRecord): Promise<void>\n  claimNext(): Promise<JobRecord | null>\n  get(id: string): Promise<JobRecord | null>\n  list(): Promise<JobRecord[]>\n  update(id: string, patch: Partial<JobInfo>): Promise<JobRecord | null>\n  prune(olderThanMs: number): Promise<number>\n  addDailyTokens(dayKey: string, tokens: number): Promise<number>\n  dailyTokens(dayKey: string): Promise<number>\n  nextRunAt?(): Promise<number | undefined>\n  onWork?(listener: () => void): () => void\n}\n\nexport function earliestRunAt(jobs: Iterable<JobRecord>, now: number): number | undefined {\n  let earliest: number | undefined\n  for (const { info } of jobs) {\n    if (info.status === 'queued' && info.nextRunAt !== undefined && info.nextRunAt > now) {\n      earliest = earliest === undefined ? info.nextRunAt : Math.min(earliest, info.nextRunAt)\n    }\n  }\n  return earliest\n}\n\nexport class InMemoryQueueAdapter implements QueueAdapter {\n  #jobs = new Map<string, JobRecord>()\n  #dailyTokens = new Map<string, number>()\n\n  add(job: JobRecord): Promise<void> {\n    this.#jobs.set(job.info.id, job)\n    return Promise.resolve()\n  }\n\n  claimNext(): Promise<JobRecord | null> {\n    const now = Date.now()\n    for (const job of this.#jobs.values()) {\n      if (job.info.status === 'queued' && (job.info.nextRunAt === undefined || job.info.nextRunAt <= now)) {\n        job.info = { ...job.info, status: 'running' }\n        return Promise.resolve(job)\n      }\n    }\n    return Promise.resolve(null)\n  }\n\n  get(id: string): Promise<JobRecord | null> {\n    return Promise.resolve(this.#jobs.get(id) ?? null)\n  }\n\n  list(): Promise<JobRecord[]> {\n    return Promise.resolve([...this.#jobs.values()])\n  }\n\n  update(id: string, patch: Partial<JobInfo>): Promise<JobRecord | null> {\n    const job = this.#jobs.get(id)\n    if (!job) {\n      return Promise.resolve(null)\n    }\n    job.info = { ...job.info, ...patch }\n    return Promise.resolve(job)\n  }\n\n  prune(olderThanMs: number): Promise<number> {\n    const cutoff = Date.now() - olderThanMs\n    let removed = 0\n    for (const [id, job] of this.#jobs) {\n      const { status, finishedAt } = job.info\n      const terminal = status === 'succeeded' || status === 'failed' || status === 'canceled'\n      if (terminal && (finishedAt ?? 0) <= cutoff) {\n        this.#jobs.delete(id)\n        removed++\n      }\n    }\n    return Promise.resolve(removed)\n  }\n\n  addDailyTokens(dayKey: string, tokens: number): Promise<number> {\n    const next = (this.#dailyTokens.get(dayKey) ?? 0) + tokens\n    this.#dailyTokens.set(dayKey, next)\n    return Promise.resolve(next)\n  }\n\n  dailyTokens(dayKey: string): Promise<number> {\n    return Promise.resolve(this.#dailyTokens.get(dayKey) ?? 0)\n  }\n\n  nextRunAt(): Promise<number | undefined> {\n    return Promise.resolve(earliestRunAt(this.#jobs.values(), Date.now()))\n  }\n}\n","import { randomUUID } from 'node:crypto'\nimport type { Runner, SessionRunnerConfig } from '@workerdeck/core'\nimport {\n  pickCreateSessionRequest,\n  type ApiMessage,\n  type CreateJobRequest,\n  type CreateSessionRequest,\n  type JobEvent,\n  type JobInfo,\n  type JobProgress,\n  type JobUsage,\n  type QueueStats,\n  type SessionEvent,\n} from '@workerdeck/protocol'\nimport { earliestRunAt, InMemoryQueueAdapter, type JobRecord, type QueueAdapter } from './adapter.ts'\n\nexport type JobQueueOptions = {\n  createRunner: (config: SessionRunnerConfig) => Runner | Promise<Runner>\n  adapter?: QueueAdapter\n  maxConcurrency?: number\n  sessionTokenLimit?: number\n  dailyTokenLimit?: number\n  maxJobDurationMs?: number\n  maxParkedDurationMs?: number\n  killGraceMs?: number\n  retention?: { maxAgeMs: number; sweepIntervalMs?: number }\n  buildRunnerConfig?: (req: CreateSessionRequest) => SessionRunnerConfig\n  discardSession?: (sessionId: string) => void | Promise<void>\n  fetchImpl?: typeof fetch\n  webhookAttempts?: number\n  webhookRetryDelayMs?: number\n  onEvent?: (event: JobEvent) => void\n  onError?: (error: unknown, context: JobQueueErrorContext) => void\n}\n\nexport type JobQueueErrorPhase = 'pump' | 'start' | 'event' | 'finalize' | 'park' | 'resume'\n\nexport type JobQueueErrorContext = { jobId?: string; phase: JobQueueErrorPhase }\n\ntype StartingJob = { canceled: boolean }\n\ntype RunningJob = {\n  record: JobRecord\n  runner: Runner\n  unsubscribe: () => void\n  lastSeq: number\n  estimatedTokens: number\n  killReason?: string\n  canceled: boolean\n  finalized: boolean\n  deliveries: Promise<void>\n  durationTimer?: ReturnType<typeof setTimeout>\n  forceTimer?: ReturnType<typeof setTimeout>\n  runningMs: number\n  legStartedAt: number\n  parkedAt?: number\n  parkedExecutionId?: string\n  parkTimer?: ReturnType<typeof setTimeout>\n  parkedMs: number\n}\n\nconst MAX_TIMER_MS = 2 ** 31 - 1\n\nconst PUMP_RETRY_MS = 5_000\n\nfunction nextUtcMidnight(epochMs: number): number {\n  const now = new Date(epochMs)\n  return Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1)\n}\n\nfunction reportToConsole(error: unknown, context: JobQueueErrorContext): void {\n  const job = context.jobId ? ` (job ${context.jobId})` : ''\n  console.warn(`[workerdeck] queue ${context.phase} failed${job}: ${error instanceof Error ? error.message : String(error)}`)\n}\n\nfunction dayKey(epochMs: number): string {\n  return new Date(epochMs).toISOString().slice(0, 10)\n}\n\n// An attempt that reported no priced figure at all stays unknown rather than banking a zero:\n// only the claude engine reports a cost of its own, and `$0.00` is a claim.\nfunction addOptionalCost(prior: number | undefined, attempt: number | undefined): number | undefined {\n  if (prior === undefined && attempt === undefined) {\n    return undefined\n  }\n  return (prior ?? 0) + (attempt ?? 0)\n}\n\nfunction sumUsage(usage: unknown): number {\n  if (typeof usage !== 'object' || usage === null) {\n    return 0\n  }\n  const u = usage as Record<string, unknown>\n  return (\n    (typeof u.input_tokens === 'number' ? u.input_tokens : 0) +\n    (typeof u.output_tokens === 'number' ? u.output_tokens : 0) +\n    (typeof u.cache_creation_input_tokens === 'number' ? u.cache_creation_input_tokens : 0) +\n    (typeof u.cache_read_input_tokens === 'number' ? u.cache_read_input_tokens : 0)\n  )\n}\n\nfunction textPreview(message: ApiMessage, max = 140): JobProgress | null {\n  const blocks = typeof message.content === 'string' ? [{ type: 'text', text: message.content }] : message.content\n  for (const block of blocks) {\n    if (block.type === 'tool_use') {\n      return { kind: 'tool_use', preview: (block as { name?: string }).name }\n    }\n    if (block.type === 'text') {\n      const text = (block as { text?: string }).text ?? ''\n      if (text.trim()) {\n        return {\n          kind: 'assistant_text',\n          preview: text.length > max ? text.slice(0, max - 1) + '…' : text,\n        }\n      }\n    }\n  }\n  return null\n}\n\nexport class JobQueue {\n  #options: JobQueueOptions\n  #adapter: QueueAdapter\n  #running = new Map<string, RunningJob>()\n  #parked = new Map<string, RunningJob>()\n  #starting = new Map<string, StartingJob>()\n  #pumping = false\n  #pumpRequested = false\n  #paused = false\n  #closed = false\n  #wakeTimer: ReturnType<typeof setTimeout> | undefined\n  #wakeAt = Number.POSITIVE_INFINITY\n  #offWork: (() => void) | undefined\n  #sweepTimer: ReturnType<typeof setInterval> | undefined\n  #retryTimers = new Set<ReturnType<typeof setTimeout>>()\n\n  constructor(options: JobQueueOptions) {\n    this.#options = options\n    this.#adapter = options.adapter ?? new InMemoryQueueAdapter()\n    this.#offWork = this.#adapter.onWork?.(() => this.#pump())\n    const retention = options.retention\n    if (retention) {\n      const interval = retention.sweepIntervalMs ?? Math.min(retention.maxAgeMs, 60_000)\n      this.#sweepTimer = setInterval(() => this.#sweep(), interval)\n      this.#sweepTimer.unref?.()\n    }\n  }\n\n  async submit(request: CreateJobRequest): Promise<JobInfo> {\n    if (this.#closed) {\n      throw new Error('queue is closed')\n    }\n    if (!request.session?.prompt?.trim()) {\n      throw new Error('session.prompt is required')\n    }\n    if (request.session.resume || request.session.forkSession) {\n      throw new Error('resume/forkSession are not supported for queued jobs')\n    }\n    const attempts = request.attempts ?? 1\n    if (!Number.isInteger(attempts) || attempts < 1) {\n      throw new Error('attempts must be a positive integer')\n    }\n    if (request.retryDelayMs !== undefined && !(request.retryDelayMs >= 0)) {\n      throw new Error('retryDelayMs must be >= 0')\n    }\n    const info: JobInfo = {\n      id: randomUUID(),\n      status: 'queued',\n      cwd: request.session.cwd ?? '',\n      profile: request.session.profile,\n      prompt: request.session.prompt,\n      createdAt: Date.now(),\n      attempt: 1,\n      maxAttempts: attempts,\n      usage: { tokens: 0, totalCostUsd: 0, numTurns: 0 },\n      meta: request.meta,\n      scope: request.session.scope,\n    }\n    const record: JobRecord = { info, request }\n    await this.#adapter.add(record)\n    this.#emit(record, { type: 'job_submitted', job: info, ts: Date.now() }, undefined, {\n      skipWebhook: true,\n    })\n    this.#pump()\n    return info\n  }\n\n  async get(id: string): Promise<JobInfo | null> {\n    return (await this.#adapter.get(id))?.info ?? null\n  }\n\n  async list(): Promise<JobInfo[]> {\n    return (await this.#adapter.list()).map((j) => j.info)\n  }\n\n  canParkSession(sessionId: string): boolean {\n    const job = this.#bySession(this.#running, sessionId)\n    return !job || (!job.finalized && !job.killReason)\n  }\n\n  onSessionParking(sessionId: string, executionId: string): boolean {\n    const job = this.#bySession(this.#running, sessionId)\n    if (!job) {\n      return true\n    }\n    if (job.finalized || job.killReason) {\n      return false\n    }\n    const now = Date.now()\n    job.unsubscribe()\n    job.runningMs += now - job.legStartedAt\n    clearTimeout(job.durationTimer)\n    job.durationTimer = undefined\n    job.parkedAt = now\n    job.parkedExecutionId = executionId\n    this.#running.delete(job.record.info.id)\n    this.#parked.set(job.record.info.id, job)\n    this.#armLimit(job, 'parkTimer', this.#options.maxParkedDurationMs, job.parkedMs, 'max parked duration')\n    const patch: Partial<JobInfo> = { status: 'parked', parkedAt: job.parkedAt, parkedExecutionId: executionId }\n    this.#spawn('park', job.record.info.id, async () => {\n      await this.#recordTransition(job, patch, (info) => ({ type: 'job_parked', job: info, executionId, ts: Date.now() }))\n      this.#pump()\n    })\n    return true\n  }\n\n  onSessionResumed(sessionId: string, runner: Runner): void {\n    const job = this.#bySession(this.#parked, sessionId)\n    if (!job || job.finalized) {\n      return\n    }\n    const now = Date.now()\n    const executionId = job.parkedExecutionId ?? ''\n    clearTimeout(job.parkTimer)\n    job.parkTimer = undefined\n    job.parkedMs += now - (job.parkedAt ?? now)\n    job.parkedAt = undefined\n    job.parkedExecutionId = undefined\n    job.legStartedAt = now\n    job.runner = runner\n    this.#parked.delete(job.record.info.id)\n    this.#running.set(job.record.info.id, job)\n    this.#armLimit(job, 'durationTimer', this.#effectiveDurationLimit(job.record.request), job.runningMs, 'max duration')\n    job.unsubscribe = this.#subscribe(job, job.lastSeq)\n    const patch: Partial<JobInfo> = { status: 'running', parkedAt: undefined, parkedExecutionId: undefined }\n    this.#spawn('resume', job.record.info.id, () =>\n      this.#recordTransition(job, patch, (info) => ({ type: 'job_resumed', job: info, executionId, ts: Date.now() })),\n    )\n  }\n\n  async #recordTransition(job: RunningJob, patch: Partial<JobInfo>, event: (info: JobInfo) => JobEvent): Promise<void> {\n    const updated = await this.#adapter.update(job.record.info.id, patch)\n    if (updated) {\n      job.record = updated\n    }\n    this.#emit(job.record, event(job.record.info), job)\n  }\n\n  #armLimit(job: RunningJob, key: 'durationTimer' | 'parkTimer', limit: number | undefined, spentMs: number, label: string): void {\n    if (limit === undefined) {\n      return\n    }\n    const timer = setTimeout(() => this.#kill(job, `job exceeded ${label} (${limit}ms)`), Math.max(0, limit - spentMs))\n    timer.unref?.()\n    job[key] = timer\n  }\n\n  #bySession(jobs: Map<string, RunningJob>, sessionId: string): RunningJob | undefined {\n    for (const job of jobs.values()) {\n      if (job.record.info.sessionId === sessionId) {\n        return job\n      }\n    }\n    return undefined\n  }\n\n  async cancel(id: string): Promise<JobInfo | null> {\n    const record = await this.#adapter.get(id)\n    if (!record) {\n      return null\n    }\n    const running = this.#running.get(id) ?? this.#parked.get(id)\n    if (running) {\n      running.canceled = true\n      running.killReason = 'canceled'\n      await this.#finalize(running, this.#abortPatch(running, 'canceled'))\n      return running.record.info\n    }\n    const starting = this.#starting.get(id)\n    if (starting) {\n      if (starting.canceled) {\n        return record.info\n      }\n      starting.canceled = true\n      return this.#markCanceled(id)\n    }\n    if (record.info.status !== 'queued') {\n      return record.info\n    }\n    return this.#markCanceled(id)\n  }\n\n  async #markCanceled(id: string): Promise<JobInfo | null> {\n    const updated = await this.#adapter.update(id, {\n      status: 'canceled',\n      finishedAt: Date.now(),\n      error: 'canceled',\n    })\n    if (updated) {\n      this.#emit(updated, { type: 'job_completed', job: updated.info, ts: Date.now() })\n    }\n    return updated?.info ?? null\n  }\n\n  pause(): void {\n    this.#paused = true\n  }\n\n  resume(): void {\n    if (!this.#paused) {\n      return\n    }\n    this.#paused = false\n    this.#pump()\n  }\n\n  get paused(): boolean {\n    return this.#paused\n  }\n\n  async stats(): Promise<QueueStats> {\n    const jobs = await this.#adapter.list()\n    const dailyTokensUsed = await this.#adapter.dailyTokens(dayKey(Date.now()))\n    const dailyTokenLimit = this.#options.dailyTokenLimit\n    return {\n      maxConcurrency: this.#options.maxConcurrency ?? 1,\n      running: this.#running.size + this.#starting.size,\n      parked: this.#parked.size,\n      queued: jobs.filter((j) => j.info.status === 'queued').length,\n      sessionTokenLimit: this.#options.sessionTokenLimit,\n      dailyTokenLimit,\n      dailyTokensUsed,\n      paused: this.#paused || (dailyTokenLimit !== undefined && dailyTokensUsed >= dailyTokenLimit),\n    }\n  }\n\n  close(): void {\n    this.#closed = true\n    this.#offWork?.()\n    clearInterval(this.#sweepTimer)\n    clearTimeout(this.#wakeTimer)\n    this.#wakeTimer = undefined\n    for (const timer of this.#retryTimers) {\n      clearTimeout(timer)\n    }\n    this.#retryTimers.clear()\n  }\n\n  #sweep(): void {\n    const retention = this.#options.retention\n    if (!retention) {\n      return\n    }\n    this.#adapter.prune(retention.maxAgeMs).catch(() => {})\n  }\n\n  #pump(): void {\n    if (this.#closed || this.#paused) {\n      return\n    }\n    if (this.#pumping) {\n      this.#pumpRequested = true\n      return\n    }\n    this.#pumping = true\n    this.#spawn('pump', undefined, () => this.#drainRequests())\n  }\n\n  async #drainRequests(): Promise<void> {\n    try {\n      do {\n        this.#pumpRequested = false\n        await this.#fill()\n      } while (this.#pumpRequested && !this.#closed && !this.#paused)\n    } catch (error) {\n      this.#wake(Date.now() + PUMP_RETRY_MS)\n      throw error\n    } finally {\n      this.#pumping = false\n    }\n  }\n\n  async #fill(): Promise<void> {\n    const maxConcurrency = this.#options.maxConcurrency ?? 1\n    while (this.#running.size + this.#starting.size < maxConcurrency && !this.#closed && !this.#paused) {\n      const limit = this.#options.dailyTokenLimit\n      if (limit !== undefined && (await this.#adapter.dailyTokens(dayKey(Date.now()))) >= limit) {\n        this.#wake(nextUtcMidnight(Date.now()))\n        return\n      }\n      const record = await this.#adapter.claimNext()\n      if (!record) {\n        const next = await this.#nextRunAt()\n        if (next !== undefined) {\n          this.#wake(next)\n        }\n        return\n      }\n      if (this.#closed || this.#paused) {\n        await this.#adapter.update(record.info.id, { status: 'queued' })\n        return\n      }\n      const id = record.info.id\n      this.#starting.set(id, { canceled: false })\n      this.#spawn('start', id, () => this.#start(record))\n    }\n  }\n\n  async #nextRunAt(): Promise<number | undefined> {\n    if (this.#adapter.nextRunAt) {\n      return this.#adapter.nextRunAt()\n    }\n    return earliestRunAt(await this.#adapter.list(), Date.now())\n  }\n\n  #wake(at: number): void {\n    if (this.#closed || (this.#wakeTimer !== undefined && this.#wakeAt <= at)) {\n      return\n    }\n    clearTimeout(this.#wakeTimer)\n    this.#wakeAt = at\n    this.#wakeTimer = setTimeout(\n      () => {\n        this.#wakeTimer = undefined\n        this.#wakeAt = Number.POSITIVE_INFINITY\n        this.#pump()\n      },\n      Math.min(MAX_TIMER_MS, Math.max(0, at - Date.now())),\n    )\n    this.#wakeTimer.unref?.()\n  }\n\n  async #start(record: JobRecord): Promise<void> {\n    const id = record.info.id\n    const starting = this.#starting.get(id) ?? { canceled: false }\n    const build = this.#options.buildRunnerConfig ?? ((req: CreateSessionRequest) => req)\n    let runner: Runner\n    try {\n      // Projected again here, not only at the HTTP door: a durable adapter can hold a record written before the door did.\n      const request: CreateSessionRequest = {\n        ...pickCreateSessionRequest(record.request.session),\n        meta: { ...record.request.session.meta, jobId: id },\n      }\n      runner = await this.#options.createRunner(build(request))\n    } catch (error) {\n      this.#starting.delete(id)\n      this.#pump()\n      if (starting.canceled) {\n        return\n      }\n      const failed = await this.#adapter.update(id, {\n        status: 'failed',\n        finishedAt: Date.now(),\n        error: error instanceof Error ? error.message : String(error),\n      })\n      if (failed) {\n        this.#emit(failed, { type: 'job_completed', job: failed.info, ts: Date.now() })\n      }\n      return\n    }\n    this.#starting.delete(id)\n    if (starting.canceled) {\n      runner.close('server')\n      this.#pump()\n      return\n    }\n    const job: RunningJob = {\n      record,\n      runner,\n      unsubscribe: () => {},\n      lastSeq: 0,\n      estimatedTokens: 0,\n      canceled: false,\n      finalized: false,\n      deliveries: Promise.resolve(),\n      runningMs: 0,\n      legStartedAt: Date.now(),\n      parkedMs: 0,\n    }\n    this.#running.set(id, job)\n    const updated = await this.#adapter.update(id, { startedAt: Date.now(), sessionId: runner.id }).catch((error: unknown) => {\n      this.#report(error, { jobId: id, phase: 'start' })\n      return null\n    })\n    if (updated) {\n      job.record = updated\n    }\n    this.#emit(job.record, { type: 'job_started', job: job.record.info, ts: Date.now() })\n    this.#armLimit(job, 'durationTimer', this.#effectiveDurationLimit(record.request), 0, 'max duration')\n    job.unsubscribe = this.#subscribe(job)\n  }\n\n  #subscribe(job: RunningJob, afterSeq?: number): () => void {\n    return job.runner.subscribe((event) => this.#spawn('event', job.record.info.id, () => this.#handleEvent(job, event)), afterSeq)\n  }\n\n  #spawn(phase: JobQueueErrorPhase, jobId: string | undefined, run: () => Promise<void>): void {\n    try {\n      run().catch((error: unknown) => this.#report(error, { jobId, phase }))\n    } catch (error) {\n      this.#report(error, { jobId, phase })\n    }\n  }\n\n  #report(error: unknown, context: JobQueueErrorContext): void {\n    try {\n      ;(this.#options.onError ?? reportToConsole)(error, context)\n    } catch {}\n  }\n\n  // How a run that never produced a `turn_result` is written down. There is no authoritative\n  // usage for such a run, so it reports the tokens counted from the message stream, no cost\n  // and no turns. `turn_result` is the one path that does NOT come through here - it has real\n  // numbers - which is exactly the distinction five inline copies of this used to hide.\n  #abortPatch(job: RunningJob, error: string): Partial<JobInfo> {\n    return {\n      usage: { tokens: job.estimatedTokens, totalCostUsd: 0, numTurns: 0 },\n      status: job.canceled ? 'canceled' : 'failed',\n      error,\n    }\n  }\n\n  #kill(job: RunningJob, reason: string): void {\n    if (job.finalized || job.killReason) {\n      return\n    }\n    job.killReason = reason\n    const id = job.record.info.id\n    if (job.parkedAt !== undefined) {\n      this.#spawn('finalize', id, () => this.#finalize(job, this.#abortPatch(job, reason)))\n      return\n    }\n    void job.runner.interrupt().catch(() => {})\n    job.forceTimer = setTimeout(() => {\n      this.#spawn('finalize', id, () => this.#finalize(job, this.#abortPatch(job, reason)))\n    }, this.#options.killGraceMs ?? 5000)\n    job.forceTimer.unref?.()\n  }\n\n  async #handleEvent(job: RunningJob, event: SessionEvent): Promise<void> {\n    if (job.finalized) {\n      return\n    }\n    job.lastSeq = Math.max(job.lastSeq, event.seq)\n    switch (event.type) {\n      case 'system_init': {\n        await this.#adapter.update(job.record.info.id, { sdkSessionId: event.sdkSessionId })\n        return\n      }\n      case 'assistant_message': {\n        if (event.replay) {\n          return\n        }\n        job.estimatedTokens += sumUsage(event.message.usage)\n        const limit = this.#effectiveTokenLimit(job.record.request)\n        if (limit !== undefined && job.estimatedTokens > limit) {\n          this.#kill(job, `session token limit exceeded (${job.estimatedTokens} > ${limit})`)\n        }\n        const progress = textPreview(event.message)\n        if (progress) {\n          this.#progress(job, progress)\n        }\n        return\n      }\n      case 'permission_requested': {\n        if (event.byPolicy) {\n          return\n        }\n        this.#progress(job, {\n          kind: 'permission_requested',\n          preview: event.request.title ?? event.request.toolName,\n          request: event.request,\n        })\n        return\n      }\n      case 'permission_resolved': {\n        this.#progress(job, { kind: 'permission_resolved', preview: event.behavior })\n        return\n      }\n      case 'turn_result': {\n        const tokens = sumUsage(event.usage) || job.estimatedTokens\n        await this.#finalize(job, {\n          usage: {\n            tokens,\n            totalCostUsd: event.totalCostUsd,\n            numTurns: event.numTurns,\n            costUsd: event.costUsd,\n          },\n          result: {\n            subtype: event.subtype,\n            isError: event.isError,\n            result: event.result,\n            errors: event.errors,\n            durationMs: event.durationMs,\n          },\n          status: job.killReason ? (job.canceled ? 'canceled' : 'failed') : event.isError ? 'failed' : 'succeeded',\n          error: job.killReason ?? (event.isError ? event.errors?.join('; ') || event.subtype : undefined),\n        })\n        return\n      }\n      case 'session_error': {\n        await this.#finalize(job, this.#abortPatch(job, job.killReason ?? event.message))\n        return\n      }\n      case 'session_closed': {\n        await this.#finalize(job, this.#abortPatch(job, job.killReason ?? 'session closed before completing'))\n        return\n      }\n      default: {\n        return\n      }\n    }\n  }\n\n  #effectiveTokenLimit(request: CreateJobRequest): number | undefined {\n    return tightest(request.maxTokens, this.#options.sessionTokenLimit)\n  }\n\n  #effectiveDurationLimit(request: CreateJobRequest): number | undefined {\n    return tightest(request.maxDurationMs, this.#options.maxJobDurationMs)\n  }\n\n  async #finalize(job: RunningJob, patch: Partial<JobInfo>): Promise<void> {\n    if (job.finalized) {\n      return\n    }\n    try {\n      await this.#settle(job, patch)\n    } finally {\n      this.#pump()\n    }\n  }\n\n  async #settle(job: RunningJob, patch: Partial<JobInfo>): Promise<void> {\n    job.finalized = true\n    job.unsubscribe()\n    clearTimeout(job.durationTimer)\n    clearTimeout(job.forceTimer)\n    clearTimeout(job.parkTimer)\n    this.#running.delete(job.record.info.id)\n    const wasParked = this.#parked.delete(job.record.info.id)\n    job.runner.close('server')\n    if (wasParked && job.record.info.sessionId) {\n      try {\n        void Promise.resolve(this.#options.discardSession?.(job.record.info.sessionId)).catch(() => {})\n      } catch {}\n    }\n    const attemptUsage = patch.usage ?? { tokens: 0, totalCostUsd: 0, numTurns: 0 }\n    if (attemptUsage.tokens > 0) {\n      await this.#adapter.addDailyTokens(dayKey(Date.now()), attemptUsage.tokens)\n    }\n    const prior = job.record.info.usage\n    const usage: JobUsage = {\n      tokens: prior.tokens + attemptUsage.tokens,\n      totalCostUsd: prior.totalCostUsd + attemptUsage.totalCostUsd,\n      numTurns: prior.numTurns + attemptUsage.numTurns,\n      costUsd: addOptionalCost(prior.costUsd, attemptUsage.costUsd),\n    }\n    const attempt = job.record.info.attempt ?? 1\n    const maxAttempts = job.record.request.attempts ?? 1\n    if (patch.status === 'failed' && attempt < maxAttempts && !this.#closed) {\n      const baseDelay = job.record.request.retryDelayMs ?? 5000\n      const delay = baseDelay * 2 ** (attempt - 1)\n      const updated = await this.#adapter.update(job.record.info.id, {\n        status: 'queued',\n        attempt: attempt + 1,\n        nextRunAt: Date.now() + delay,\n        error: patch.error,\n        usage,\n        sessionId: undefined,\n        sdkSessionId: undefined,\n        startedAt: undefined,\n        result: undefined,\n      })\n      if (updated) {\n        job.record = updated\n        this.#emit(updated, { type: 'job_retrying', job: updated.info, ts: Date.now() }, job)\n        const timer = setTimeout(() => {\n          this.#retryTimers.delete(timer)\n          this.#pump()\n        }, delay)\n        timer.unref?.()\n        this.#retryTimers.add(timer)\n      }\n      return\n    }\n    const updated = await this.#adapter.update(job.record.info.id, {\n      ...patch,\n      usage,\n      nextRunAt: undefined,\n      finishedAt: Date.now(),\n    })\n    if (updated) {\n      job.record = updated\n      this.#emit(job.record, { type: 'job_completed', job: updated.info, ts: Date.now() }, job)\n    }\n    this.#sweep()\n  }\n\n  #progress(job: RunningJob, progress: JobProgress): void {\n    const event: JobEvent = { type: 'job_progress', job: job.record.info, progress, ts: Date.now() }\n    if (job.record.request.webhook?.progress === 'completion') {\n      try {\n        this.#options.onEvent?.(event)\n      } catch {}\n      return\n    }\n    this.#emit(job.record, event, job)\n  }\n\n  #emit(record: JobRecord, event: JobEvent, chainOwner?: RunningJob, { skipWebhook = false }: { skipWebhook?: boolean } = {}): void {\n    try {\n      this.#options.onEvent?.(event)\n    } catch {}\n    const webhook = record.request.webhook\n    if (!webhook || skipWebhook) {\n      return\n    }\n    const running = chainOwner ?? this.#running.get(record.info.id)\n    const deliver = () => this.#deliver(webhook.url, webhook.headers, event)\n    if (running) {\n      running.deliveries = running.deliveries.then(deliver)\n    } else {\n      void deliver()\n    }\n  }\n\n  async #deliver(url: string, headers: Record<string, string> | undefined, event: JobEvent): Promise<void> {\n    const fetchImpl = this.#options.fetchImpl ?? fetch\n    const attempts = this.#options.webhookAttempts ?? 3\n    const baseDelay = this.#options.webhookRetryDelayMs ?? 500\n    for (let attempt = 0; attempt < attempts; attempt++) {\n      try {\n        const res = await fetchImpl(url, {\n          method: 'POST',\n          headers: { 'content-type': 'application/json', ...headers },\n          body: JSON.stringify(event),\n        })\n        if (res.ok) {\n          return\n        }\n      } catch {}\n      if (attempt < attempts - 1) {\n        await new Promise((resolve) => setTimeout(resolve, baseDelay * 2 ** attempt))\n      }\n    }\n  }\n}\n\nfunction tightest(...limits: (number | undefined)[]): number | undefined {\n  const set = limits.filter((n): n is number => typeof n === 'number')\n  return set.length > 0 ? Math.min(...set) : undefined\n}\n"],"mappings":"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"}