UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

179 lines (178 loc) • 7.53 kB
/** * Async delegation (N2) — spawn a background worker, collect it later, in any * order — types. * * Delegation today is a synchronous tool call: the supervising agent blocks * until the worker is done, so four investigations take four times as long as * one and the supervisor cannot do anything useful while it waits. These types * describe the background form — `spawn` hands back a `DelegateHandle` * immediately, `collect` returns whichever worker finished FIRST regardless of * which was started first, and each outcome carries a bounded summary plus a * {@link BankedArtifactRef} to the worker's full report, which is banked to a * file rather than pushed into the conversation. * * Naming: `agentNetwork.ts` already owns `DelegationRule` / `DelegationCondition` * and `isolatedAgent.ts` owns `AgentDelegationTurnState`, so everything here * carries the `Delegate` prefix (Critical Rule 9). */ import type { BankedArtifactRef } from "./artifact.js"; import type { AgentRunStatus } from "./isolatedAgent.js"; /** What a supervisor hands down when it spawns a background worker. */ export type DelegateSpawnOptions = { /** The task, in the supervisor's own words. Required and non-empty. */ task: string; /** What the worker may look at — files, directories, systems. */ scope?: string; /** Brief slice of context handed down (never the whole rulebook). */ context?: string; /** Model override for this worker. */ model?: string; /** Provider override for this worker. */ provider?: string; /** Read-only tool allowlist for the worker (tool names). */ tools?: string[]; /** * Caller's session. Collection is scoped to it, and it is the key the task * checklist's `delegatesPending` / `delegatesReady` counters are read by. * Defaults to the session the host's tool context declares. */ sessionId?: string; /** Caller's delegation depth; the worker runs one level deeper. */ depth?: number; /** Short human label used in logs and in the banked report's name. */ label?: string; /** Parent cancellation — an aborted parent cancels this worker. */ abortSignal?: AbortSignal; /** Max agentic steps for the worker's research pass. */ maxSteps?: number; /** Wall-clock budget for the worker's research pass (ms). */ budgetMs?: number; }; /** * Returned the moment a worker is spawned — before it has run anything. * `queued` is true when the process-wide delegation pool was full and the * worker is waiting for a slot. */ export type DelegateHandle = { workerId: string; spawnedAt: number; queued: boolean; }; /** * A settled worker, claimed exactly once. * * `summary` is bounded; `report` points at the COMPLETE report on disk. The * two are not alternatives — the summary is what the conversation carries, the * report is what the evidence lives in. */ export type DelegateOutcome = { workerId: string; /** Human label the spawn was given (defaults to the worker id). */ label: string; /** Reused from the isolated-agent runner — no parallel taxonomy. */ status: AgentRunStatus; /** True for `completed` and `partial`: the worker produced usable evidence. */ ok: boolean; /** Bounded narrative for the conversation. Never the whole report. */ summary: string; /** The FULL report, always banked to a file. */ report: BankedArtifactRef; durationMs: number; toolCallsUsed: number; /** Mechanical waste signatures the runner tripped, if any. */ wasteSignals?: string[]; /** `continueAgent()` handle when the worker was cut short mid-investigation. */ handle?: string; /** Why the worker failed, when it did. */ error?: string; }; /** `any` returns the first worker to finish; `all` waits for every one. */ export type DelegateCollectMode = "any" | "all"; /** * What to collect. `waitMs` of 0 polls (return what is ready right now); * omitting it uses the runtime default. */ export type DelegateCollectRequest = { mode: DelegateCollectMode; waitMs?: number; sessionId?: string; } | { workerId: string; waitMs?: number; sessionId?: string; }; /** * Outcomes claimed by one collect call, in COMPLETION order — the order * workers finished in, which has nothing to do with the order they were * spawned in. */ export type DelegateCollectResult = { /** Claimed exactly once: these outcomes are gone from the registry. */ completed: DelegateOutcome[]; /** Still running or waiting for a pool slot. */ pending: number; /** Finished but not yet claimed. */ ready: number; /** * True when the wait expired before this call claimed what it asked for: * for a named worker, that worker's outcome; for `any`, any outcome while * work was still pending; for `all`, pending work remained when the wait * ran out. A collect that claimed something reports `false` even if other * work is still outstanding — `pending`/`ready` carry that. */ timedOut: boolean; }; /** Lifecycle of one background job. `claimed` jobs are dropped immediately. */ export type DelegateJobPhase = "queued" | "running" | "ready" | "claimed"; /** * Provider/model a model-invoked `delegate_task` spawn falls back to. The spawn * schema deliberately exposes no `provider` — a model cannot name a provider it * cannot see — so without a default the worker instance falls back to provider * auto-selection, which on a host with stray credentials puts a worker on a * provider nobody configured — observed live as workers walking several * unconfigured providers before reaching the configured one. The model's own * `model` argument still wins over `model` here. */ export type DelegateSpawnDefaults = { provider?: string; model?: string; }; /** Per-host delegation policy, resolved from registration options. */ export type DelegateRuntimeSettings = { /** Caller depth at which `delegate_task` refuses rather than spawning. */ maxDepth: number; /** How long a spawned worker waits for a pool slot before giving up (ms). */ poolQueueTimeoutMs: number; /** Default `waitMs` for a collect that does not name one (ms). */ defaultCollectWaitMs: number; /** Defaults merged under every model-invoked `delegate_task` spawn. */ spawnDefaults?: DelegateSpawnDefaults; }; /** Options for `NeuroLink.registerDelegationTools()`. */ export type DelegateRegistrationOptions = { /** * Caller depth at which further delegation is refused. Default 1: a * background worker does not spawn background workers, because nothing * would ever collect them. */ maxDepth?: number; /** * Raise the process-wide delegation pool to at least this many concurrent * workers. The pool is shared with `registerAgentTool` and only ever rises. */ maxConcurrent?: number; /** Queue wait before a spawned worker gives up on a pool slot (ms). */ poolQueueTimeoutMs?: number; /** Provider/model for model-invoked spawns — see {@link DelegateSpawnDefaults}. */ spawnDefaults?: DelegateSpawnDefaults; }; /** What `delegate_task` returns: the handle plus the outstanding counters. */ export type DelegateSpawnToolResult = DelegateHandle & { pending: number; ready: number; }; /** Refusal shape shared with the agent tool registrar: recovery text included. */ export type DelegateRefusal = { isError: true; error: string; };