UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

146 lines • 8.15 kB
/** * time/range — the library's one range, its two spellings, and one * conversion per boundary a range crosses. * * Pattern: one internal shape, converted at every edge by a named function — * never inline. Inside the library a range is HALF-OPEN `[from, to)`; * the places a range crosses do not share that edge (the time design, * `docs/design/time/README.md` § 3.3), so each crossing is a function * here and its inverse. * Role: L0 leaf (the time layer's one owner). Imports `instant.ts` and * `duration.ts`. Asked by `tools/declare.ts` · * `parsesUnderSpelling` (an `iso-range` argument is * {@link splitRange} under `'..'` and the strict profile). No other * file splits or joins a range. * Emits: N/A. * * ## The boundaries * * | Boundary | Its edge | Into it from `[from, to)` | Back | * |----------|----------|---------------------------|------| * | a result's `DeclaredPeriod.queried` / `held` | inclusive at both ends | not converted — the tool declares it | {@link fromInclusive} with the tool's step (`granularity`, else 1 ms) | * | a tool argument bound | declared on every `bounds`/`object` end (TQ18); only the sugar defaults inclusive | {@link boundInto} | {@link boundFrom} | * | a look-back argument | `[until − L, until]` | {@link lookbackRange} | {@link lookbackOf} | * | an ask answer / an ISO 8601 interval | `from/to`, half-open | identity: {@link spellRange} | identity: {@link parseRange} | * | an inclusive interval clause (SQL `BETWEEN`, a chart brush) | inclusive at both ends | {@link toInclusive} | {@link fromInclusive} | * * `coverage/period.ts` · `periodVerdict` stays inclusive and is NOT routed * through here: it compares the two inclusive spans a result declared. * * A derived bound keeps the offset its source was written in, spelled in the * strict profile; a bound that is not derived is kept as written. * * @example * ```ts * parseRange('2026-10-09T08:00:00-07:00/2026-10-09T08:41:00-07:00'); * // { from: '2026-10-09T08:00:00-07:00', to: '2026-10-09T08:41:00-07:00' } * toInclusive({ from: '2026-10-09T08:00:00-07:00', to: '2026-10-09T08:41:00-07:00' }, 60_000); * // { from: '2026-10-09T08:00:00-07:00', to: '2026-10-09T08:40:00-07:00' } — "through 08:40" * ``` */ import { type DurationText } from './duration.js'; import { type InstantProfile, type InstantText, type ParsedInstant } from './instant.js'; /** * The library's INTERNAL range: half-open `[from, to)`, `from` before `to`. * NOT the same reading as `DeclaredPeriod.queried`, whose bounds are * inclusive — every boundary converts (the module table). */ export interface TimeRange { readonly from: InstantText; readonly to: InstantText; } /** Two instants with inclusive ends, `from` not after `to` — a declared period's span, an SQL `BETWEEN`. */ export interface InclusiveSpan { readonly from: InstantText; readonly to: InstantText; } /** How two bounds are joined in one string: an ISO 8601 interval (`/`) or a tool's joined argument (`..`). */ export type RangeJoiner = '/' | '..'; /** Whether a tool's bound includes the instant it names. */ export type Edge = 'inclusive' | 'exclusive'; /** * The two bounds of a joined range string — exactly one `joiner`, each half an * instant under `profile` — or `undefined`. The ORDER is not checked: a format * check, for a declaration that only promises a spelling. */ export declare function splitRange(value: unknown, joiner: RangeJoiner, profile: InstantProfile): readonly [ParsedInstant, ParsedInstant] | undefined; /** * A joined string read as a {@link TimeRange} — strict instants, `from` * before `to` — or `undefined`. The bounds are kept as written. */ export declare function parseRange(value: unknown, joiner?: RangeJoiner): TimeRange | undefined; /** Whether `value` is a well-formed {@link TimeRange}: strict instants, `from` before `to`, no other key. */ export declare function isTimeRange(value: unknown): value is TimeRange; /** The range spelled as one string: `from<joiner>to`, bounds as written. Throws on a range that is not well formed. */ export declare function spellRange(range: TimeRange, joiner?: RangeJoiner): string; /** The step a tool's `granularity` names (under `units`), else 1 ms — the § 3.3 rule. */ export declare function stepMsOf(granularity: DurationText | undefined, units: string): number; /** * An inclusive span read back as half-open: `[from, to + step)`. The step is * the source's smallest step (a tool's `granularity`, else 1 ms). The span is * read in the LENIENT profile — a result declares it. */ export declare function fromInclusive(span: InclusiveSpan, stepMs?: number): TimeRange; /** * A half-open range written with inclusive ends: `[from, to − step]` — the * last instant inside the range at the reader's precision. Refused when the * range is narrower than one step (it holds no instant at that precision). */ export declare function toInclusive(range: TimeRange, stepMs?: number): InclusiveSpan; /** * A half-open range's end as a tool's `to` bound: `exclusive` → as is; * `inclusive` → the last instant inside at the argument's precision * (`to − step`). */ export declare function boundInto(to: InstantText, edge: Edge, stepMs: number): InstantText; /** The inverse of {@link boundInto}: a tool's `to` bound as a half-open range's end. */ export declare function boundFrom(to: InstantText, edge: Edge, stepMs: number): InstantText; /** * A look-back `duration` evaluated at `until` — `[until − L, until]`, both * ends inside — as a half-open range `[until − L, until + 1 ms)`. */ export declare function lookbackRange(until: InstantText, duration: DurationText, units: string): TimeRange; /** * The inverse of {@link lookbackRange}: the `until` and the smallest exact * look-back spelling a half-open range is, or `undefined` when its length is * no whole duration in `units`. */ export declare function lookbackOf(range: TimeRange, units: string): { readonly until: InstantText; readonly duration: DurationText; } | undefined; /** * How far a half-open range `[from, to)` REACHES, in milliseconds: from its * first instant to its last (`to − 1 ms − from`) — the length a tool's * `maxRange` is held against (an inclusive ceiling: a range is over it only * when its last instant lies further than `maxRange` after its first). The one * owner of that length, so a range is judged by the instants it holds, never by * how it was spelled: the look-back row `[until − L, until]` ({@link lookbackRange}, * half-open `[until − L, until + 1 ms)`) reaches `L`, exactly as the same instants * written as bounds do — a look-back exactly `maxRange` long is one the tool reads * at once, and one more step (`L + 1 min`) is not. * * @example * ```ts * reachMs(Date.parse('2026-10-08T15:40:00Z'), Date.parse('2026-10-09T15:40:00.001Z')); // 86_400_000 — 'last 24h' * reachMs(Date.parse('2026-10-08T00:00:00Z'), Date.parse('2026-10-09T00:00:00Z')); // 86_399_999 — one day * ``` */ export declare function reachMs(fromMs: number, toMs: number): number; /** Whether `outer` holds every instant of `inner` (half-open). */ export declare function covers(outer: TimeRange, inner: TimeRange): boolean; /** Whether two ranges hold the same instants (their spellings and offsets aside). */ export declare function sameRange(a: TimeRange, b: TimeRange): boolean; /** Whether `a` and `b` share at least one instant (half-open: touching ends do not overlap). */ export declare function overlaps(a: TimeRange, b: TimeRange): boolean; /** * The range widened to whole steps — `from` down, `to` up, never inward — * with `rounded` saying whether anything moved. Steps are counted from the * epoch in UTC: right for seconds, minutes and hours; a calendar day or week * in a zone is `zone.ts`'s question, not this one. */ export declare function roundOutward(range: TimeRange, stepMs: number): { readonly range: TimeRange; readonly rounded: boolean; }; //# sourceMappingURL=range.d.ts.map