agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
112 lines • 5.2 kB
TypeScript
/**
* classify/types — the PORT for a calibrated classifier.
*
* Pattern: port + adapters (the `LLMProvider` precedent). A classifier is
* not a model that generates text: handed a STATE and a set of
* typed QUESTIONS it scores the declared candidates from one
* reading and answers each question with a distribution, a
* confidence, or a probability — the "scored choice" of
* docs/design/2026-09-scored-choice.md, opened 2026-09-17.
* Role: zero-import leaf. `src/injection-engine/classifierScorer.ts`
* (a pure-core file behind `agentfootprint/skill-graph`) types its
* port against this file, so nothing here may import anything.
*
* LAWS.
* - A score is data only when the provider produced it. Nothing in this
* folder infers a probability, defaults a choice or renormalises a
* distribution — `probabilities` is the wire's own object, whatever it sums
* to (the real probe summed to 1.0; a provider that rounds may not).
* - Cost is data: every result carries `latencyMs` measured around the
* call, and `usage` when the provider reported it, so a bench or a lens
* reads the cost of a judgment off the record instead of estimating it.
* - A failure is a `ClassifierError` with the provider's status when there
* was one — never a guessed answer.
*/
/** Pick ONE of the declared options; `criteria` describes each option by id. */
export interface ClassifyChoiceQuestion {
readonly type: 'choice';
readonly instructions: string;
/** `{ optionId: what that option means }` — the candidates, declared before the call. */
readonly criteria: Readonly<Record<string, string>>;
}
/** A yes/no proposition, answered as a probability of `true` ("noul"). */
export interface ClassifyNoulQuestion {
readonly type: 'noul';
readonly instructions: string;
/** Optional wording for each pole. */
readonly criteria?: {
readonly true: string;
readonly false: string;
};
}
/** A position on an ordered scale; `criteria` names the rungs low to high. */
export interface ClassifyScoreQuestion {
readonly type: 'score';
readonly instructions: string;
readonly criteria: readonly string[];
}
export type ClassifyQuestion = ClassifyChoiceQuestion | ClassifyNoulQuestion | ClassifyScoreQuestion;
/** One call: the state to read, and the questions to answer about it. */
export interface ClassifyRequest {
/** A string, an object or an array — serialised as given; never model text the library wrote. */
readonly state: unknown;
readonly questions: Readonly<Record<string, ClassifyQuestion>>;
}
/** The answer to a `choice` question: the pick and the WHOLE distribution behind it. */
export interface ClassifyChoiceAnswer {
readonly type: 'choice';
readonly choice: string;
readonly confidence: number;
/** Per option id, as the provider gave it — never renormalised. */
readonly probabilities: Readonly<Record<string, number>>;
}
/** The answer to a `noul` question: the probability the proposition holds. */
export interface ClassifyNoulAnswer {
readonly type: 'noul';
readonly noul: number;
}
/** The answer to a `score` question: the rung, its confidence and the distribution over rungs. */
export interface ClassifyScoreAnswer {
readonly type: 'score';
readonly score: number;
readonly confidence: number;
readonly probabilities: Readonly<Record<string, number>>;
/** The provider's own legend for the rungs, when it sends one. */
readonly legend?: Readonly<Record<string, string>>;
}
export type ClassifyAnswer = ClassifyChoiceAnswer | ClassifyNoulAnswer | ClassifyScoreAnswer;
/** What one call answered, and what it cost. */
export interface ClassifyResult {
/** The provider's model string for THIS answer (`jev-1.13.0`), not the alias requested. */
readonly model: string;
readonly answers: Readonly<Record<string, ClassifyAnswer>>;
/** Present when the provider reported it. */
readonly usage?: {
readonly inputTokens: number;
readonly outputTokens: number;
};
/** Wall-clock milliseconds around the call, measured by the adapter. */
readonly latencyMs: number;
}
/** A calibrated classifier — one method, honoured by every adapter and the mock. */
export interface Classifier {
/** Short, stable name (`'typesafe'`, `'mock'`) — what a record row names as the judge. */
readonly name: string;
classify(request: ClassifyRequest, signal?: AbortSignal): Promise<ClassifyResult>;
}
/**
* A classifier call that produced no answer. `status` is the provider's HTTP
* status when there was one; `retryable` says whether the adapter judged it
* a transient (rate limit, overload) — an adapter has already retried those
* up to its `maxRetries` before this reaches a caller. The message carries
* the provider's error text, never a key.
*/
export declare class ClassifierError extends Error {
readonly status?: number;
readonly retryable: boolean;
constructor(message: string, options?: {
status?: number;
retryable?: boolean;
});
}
//# sourceMappingURL=types.d.ts.map