Until Types
Type definitions for termination predicates, verdicts, snapshots, and combinators in Noetic.
Until
A termination predicate function. Called after each loop iteration to decide whether to stop.
type Until = (snapshot: Snapshot) => Verdict | Promise<Verdict>;Snapshot
The state visible to an Until predicate at the end of each iteration.
interface Snapshot {
stepCount: number;
tokens: {
input: number;
output: number;
total: number;
};
elapsed: number;
cost: number;
lastOutput: unknown;
lastText: string;
history: unknown[];
depth: number;
lastStepMeta?: StepMeta | null;
}| Field | Type | Description |
|---|---|---|
stepCount | number | Number of iterations completed |
tokens.input | number | Total input tokens consumed |
tokens.output | number | Total output tokens generated |
tokens.total | number | Total tokens (input + output) |
elapsed | number | Elapsed time in milliseconds |
cost | number | Accumulated cost in USD |
lastOutput | unknown | Raw output from the last iteration |
lastText | string | Text output from the last iteration |
history | unknown[] | All previous outputs |
depth | number | Execution nesting depth |
lastStepMeta | StepMeta | null | Metadata from the last step (optional) |
Verdict
The return value from an Until predicate.
interface Verdict {
stop: boolean;
reason?: string;
feedback?: string;
}| Field | Type | Required | Description |
|---|---|---|---|
stop | boolean | yes | Whether to stop the loop |
reason | string | no | Human-readable reason for stopping |
feedback | string | no | Feedback to pass to prepareNext for the next iteration |
Built-in Predicates
The until object provides factory functions for common predicates:
until.maxSteps(n)
Stops after n iterations.
until.maxSteps(n: number): Untiluntil.maxCost(usd)
Stops when accumulated cost reaches the USD limit.
until.maxCost(usd: number): Untiluntil.maxDuration(ms)
Stops when elapsed time reaches the millisecond limit.
until.maxDuration(ms: number): Untiluntil.noToolCalls()
Stops when the LLM responds without making any tool calls. Skips the first iteration (step count < 1).
until.noToolCalls(): Untiluntil.verified(fn)
Stops when the verify function returns { pass: true }. Feedback from failed verification is available in the verdict.
until.verified(fn: VerifyFn): Untiluntil.converged(opts)
Stops when the output text is identical to the previous iteration's output.
until.converged(opts: ConvergeOpts): Untiluntil.outputContains(marker)
Stops when the output text contains the given marker string.
until.outputContains(marker: string): Untiluntil.custom(fn)
Wraps any Until function (identity passthrough for documentation purposes).
until.custom(fn: Until): UntilVerifyFn
The verification function used by until.verified():
type VerifyFn = (output: unknown) => Promise<{
pass: boolean;
feedback?: string;
}>;| Field | Type | Description |
|---|---|---|
pass | boolean | Whether verification succeeded |
feedback | string | Feedback for the next iteration (optional) |
ConvergeOpts
interface ConvergeOpts {
threshold?: number;
embed?: EmbedFn;
cache?: StorageAdapter;
}| Field | Type | Default | Description |
|---|---|---|---|
threshold | number | 1 | Similarity threshold. At 1 (default), uses exact string equality. When embed is provided and threshold < 1, uses cosine similarity. |
embed | EmbedFn | — | Embedding function. When provided with threshold < 1, enables semantic convergence detection. |
cache | StorageAdapter | — | Persist the previous output vector across ephemeral invocations (e.g., Cloudflare Workers). |
Combinators
any(...predicates)
Returns an Until that stops when any predicate returns { stop: true }.
function any(...predicates: Until[]): Untilall(...predicates)
Returns an Until that stops when all predicates return { stop: true }. Reasons from all predicates are joined with '; '.
function all(...predicates: Until[]): UntilExample: Combining Predicates
import { until, any, all } from '@noetic/core';
// Stop on any condition
const stopEarly = any(
until.maxSteps(10),
until.maxCost(1.00),
until.noToolCalls(),
);
// Stop only when all conditions are met
const strictStop = all(
until.verified(myVerifyFn),
until.maxSteps(3),
);