import type { BackgroundJobLease } from '../../utils/background-job-board'; import type { BackgroundJobStore } from '../../utils/background-job-store'; import type { BackgroundJobSupervisor } from '../../utils/background-job-supervisor'; import type { BackgroundTaskConcurrencyTicket } from '../../utils/background-task-concurrency'; export interface EarlyTaskRegistration { taskID: string; generation: number; backgroundJobBoard: BackgroundJobStore; backgroundJobSupervisor?: BackgroundJobSupervisor; } export interface PendingTaskCall { callId: string; parentSessionId: string; agentType: string; label: string; /** Untruncated objective text the label was derived from; board comparison * uses this so long exact duplicates are not missed. */ fullObjective?: string; background: boolean; /** Deletion epoch observed when this native task call started. */ lifecycleEpoch: number; resumedTaskId?: string; relaunchLease?: BackgroundJobLease; /** Board generation that owns the relaunch lease. */ releaseLease?: (lease: BackgroundJobLease) => boolean; concurrencyTicket?: BackgroundTaskConcurrencyTicket; earlyRegisteredTaskID?: string; earlyRegistration?: EarlyTaskRegistration; earlyRegistrationRejected?: boolean; /** Consumed without verified call identity (no-ID drain fallback or a * window-shifted sole take): the label/objective may belong to a * sibling call and must not be painted onto the board record. */ identityUnresolved?: boolean; } export interface PendingCallTracker { add(call: PendingTaskCall): void; take(callId?: string, parentSessionId?: string, ownerBoard?: BackgroundJobStore, options?: { recordConsumed?: boolean; }): PendingTaskCall | undefined; /** Remove and return the pending call whose early registration claimed * `taskID` for this parent — an identity-verified take for hosts that * do not supply tool call IDs. When `ownerBoard` is given and the * early registration was adopted by a different board generation, the * pending is left for that generation (same fence as `take`). */ takeByTaskID(parentSessionId: string, taskID: string, ownerBoard?: BackgroundJobStore): PendingTaskCall | undefined; /** Guarded drain fallback for no-tool-call-ID hosts: when neither a * call ID nor an early-registration claim could identify the * pending, remove and return the OLDEST unmarked pending for the * parent — constrained to `agentType` when the child's agent is * known, and never a resumed pending pinned to a different * `identityTaskID` (that pending provably belongs to another call). * Pendings claimed by an early registration or fenced for another * board generation are left for their owners. Consumption is * recorded exactly like `take()`. The consumed call is marked * `identityUnresolved` and arms the parent's unresolved window, so * later no-callID sole-survivor takes for the same parent are * flagged too. Returns undefined when no eligible pending exists. */ takeUnresolvedFirstMatch(parentSessionId: string, selection?: { /** Task ID parsed from the consuming call's own output. */ identityTaskID?: string; /** Agent of the child session that produced that output. */ agentType?: string; /** Board-generation fence, same as take()/takeByTaskID(). */ ownerBoard?: BackgroundJobStore; }): PendingTaskCall | undefined; release(call: PendingTaskCall): void; peekByParent(parentSessionId: string): PendingTaskCall | undefined; peekByParentAndAgent(parentSessionId: string, agentHint?: string, title?: string): PendingTaskCall | undefined; /** True when a pending call for this parent (optionally of the given * agent type) was already consumed by its tool.execute.after. A * no-title session.created that arrives after such consumption may be * a stale child of the consumed call, so claims must be refused. */ hasConsumedCall(parentSessionId: string, agentType?: string): boolean; adoptEarlyRegistrations(backgroundJobBoard: BackgroundJobStore, backgroundJobSupervisor?: BackgroundJobSupervisor): void; clearSession(sessionId: string): void; clearAll(): void; pendingCallId(sessionID?: string, callID?: string): string; } export declare function createPendingCallTracker(options?: { releaseLease?: (lease: BackgroundJobLease) => boolean; }): PendingCallTracker;