@attest-ai/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,38 +1,18 @@
1
- import { InitializeResult, ProtocolLogger, ProtocolDiagnostic, Trace, Assertion, BatchBudget, BatchContext, EvaluateBatchResult, DriftReport, SimulatePersona, ConversationMessage, SimulateFaultConfig, Step, AssertionResult, Usage, Outcome } from './proto/index.cjs';
1
+ import { ProtocolLogger, ProtocolDiagnostic, Trace, Assertion, BatchBudget, BatchContext, EvaluateBatchResult, DriftReport, SimulatePersona, ConversationMessage, SimulateFaultConfig, InitializeResult, Usage, Step, AssertionResult, Outcome } from './proto/index.cjs';
2
2
  export { AgentId, AssertionId, AssertionSpec, BiasProbe, ConstraintSpec, ContentSpec, ERR_ASSERTION_ERROR, ERR_ENGINE_ERROR, ERR_INVALID_TRACE, ERR_PROVIDER_ERROR, ERR_SESSION_ERROR, ERR_TIMEOUT, EffectSpec, EmbeddingSpec, EngineTimeoutError, ErrorData, EvaluateBatchParams, Exchange, FailureClass, GenerateUserMessageParams, GenerateUserMessageResult, Handoff, InitializeParams, JudgeAgreement, JudgeMetadata, LlmJudgeSpec, OTLPConversionError, OUTCOME_FAIL, OUTCOME_PASS, OUTCOME_SKIP, PluginSpec, ProtocolDesyncError, ProtocolDiagnosticBuffer, ProtocolDiagnosticKind, ProtocolError, QueryDriftParams, QueryDriftResult, REASON_BUDGET_EXHAUSTED, REASON_JUDGE_ABSTAINED, REASON_MISSING_EVIDENCE, REASON_PROVIDER_NOT_CONFIGURED, REASON_PROVIDER_UNAVAILABLE, REASON_REPLAY_MISS, REASON_SHORT_CIRCUITED, REASON_SIMULATION, RPCError, RPCRequest, RPCResponse, STATUS_HARD_FAIL, STATUS_NOT_EVALUATED, STATUS_PASS, STATUS_SOFT_FAIL, STEP_AGENT_CALL, STEP_LLM_CALL, STEP_RETRIEVAL, STEP_TOOL_CALL, SchemaSpec, ShutdownResult, StepError, SubmitPluginResultParams, TYPE_CONSTRAINT, TYPE_CONTENT, TYPE_EFFECT, TYPE_EMBEDDING, TYPE_LLM_JUDGE, TYPE_PLUGIN, TYPE_SCHEMA, TYPE_TRACE, TYPE_TRACE_TREE, TraceId, TraceMetadata, TraceSpec, TraceTreeSpec, Turn, agentId, assertionId, decodeResponse, encodeRequest, extractId, extractResult, layerForType, previewLine, traceId } from './proto/index.cjs';
3
3
  import { ChildProcess } from 'node:child_process';
4
4
  import { Interface } from 'node:readline';
5
5
  import { AsyncLocalStorage } from 'node:async_hooks';
6
6
  import { EventEmitter } from 'node:events';
7
7
 
8
- declare const VERSION = "1.0.0";
9
- declare const ENGINE_VERSION = "1.0.0";
8
+ declare const VERSION = "1.0.1";
9
+ declare const ENGINE_VERSION = "1.0.1";
10
10
 
11
- declare class EngineManager {
12
- private enginePath;
13
- private readonly logLevel;
14
- private process;
15
- private reader;
16
- private initialized;
17
- private requestId;
18
- private initResult;
19
- constructor(options?: {
20
- enginePath?: string;
21
- logLevel?: string;
22
- });
23
- start(): Promise<InitializeResult>;
24
- /** Send initialize and check the engine's version and capabilities. */
25
- private initialize;
26
- stop(): Promise<void>;
27
- sendRequest(method: string, params: Record<string, unknown>): Promise<unknown>;
28
- private sendRequestInternal;
29
- get isRunning(): boolean;
30
- /** Expose process for AttestClient reader loop access */
31
- get childProcess(): ChildProcess | null;
32
- /** Expose readline interface for AttestClient reader loop */
33
- get readlineInterface(): Interface | null;
11
+ /** Budget a timed-out request may have consumed; null means the whole remaining budget. */
12
+ interface BudgetReservation {
13
+ readonly judgeCalls: number | null;
14
+ readonly usd: number | null;
34
15
  }
35
-
36
16
  interface AttestClientOptions {
37
17
  /** Logger override. When omitted, warnings only emit if ATTEST_DEBUG_PROTOCOL=1. */
38
18
  logger?: ProtocolLogger;
@@ -62,6 +42,7 @@ declare class AttestClient {
62
42
  private writeChain;
63
43
  private readerActive;
64
44
  private lineHandler;
45
+ private attachedReader;
65
46
  private readonly logger;
66
47
  private readonly diagnosticBuffer;
67
48
  private readonly diagnosticListeners;
@@ -73,19 +54,40 @@ declare class AttestClient {
73
54
  onProtocolDiagnostic(listener: (diagnostic: ProtocolDiagnostic) => void): () => void;
74
55
  /** Snapshot of the diagnostic ring buffer (most recent last). */
75
56
  protocolDiagnostics(): readonly ProtocolDiagnostic[];
57
+ /**
58
+ * Attach the id-routed reader to the engine's stdout. Idempotent; `sendRequest` starts it
59
+ * on first use, so calling it is optional.
60
+ */
76
61
  startReader(): void;
77
62
  stopReader(): void;
78
63
  private recordDiagnostic;
79
64
  private maybeTriggerDesync;
80
65
  private handleLine;
81
66
  private handleDecodeFailure;
67
+ /** Reject every request still waiting for a response. */
68
+ rejectPending(err: Error): void;
82
69
  private failAll;
70
+ /**
71
+ * Send one request and resolve with the result of the response that carries its id.
72
+ *
73
+ * After a timeout the engine is restarted (its late response can no longer be matched),
74
+ * every other pending request is rejected, and the new engine gets the remaining session
75
+ * budget.
76
+ */
83
77
  sendRequest(method: string, params: Record<string, unknown>, timeoutMs?: number): Promise<unknown>;
78
+ /** `sendRequest` without the restart-on-timeout step, for the engine's own handshake. */
79
+ sendWithoutRestart(method: string, params: Record<string, unknown>, timeoutMs: number): Promise<unknown>;
80
+ private send;
81
+ /** A failed pipe write names the engine's stderr tail; the original error stays as `cause` and `code`. */
82
+ private describeWriteError;
83
+ private recoverFromTimeout;
84
84
  evaluateBatch(trace: Trace, assertions: readonly Assertion[], options?: {
85
85
  timeout?: number;
86
86
  budget?: BatchBudget;
87
87
  context?: BatchContext;
88
88
  }): Promise<EvaluateBatchResult>;
89
+ /** Reject a response whose assertion ids differ from the ids that were sent. */
90
+ private requireSentAssertionIds;
89
91
  submitPluginResult(traceId: string, pluginName: string, assertionId: string, status: string, score: number, explanation: string, options?: {
90
92
  timeout?: number;
91
93
  }): Promise<boolean>;
@@ -103,6 +105,70 @@ declare class AttestClient {
103
105
  */
104
106
  declare function requireSimulationCapability(init: InitializeResult | null | undefined): void;
105
107
 
108
+ declare class EngineManager {
109
+ private enginePath;
110
+ private readonly logLevel;
111
+ private readonly initializeTimeoutMs;
112
+ private process;
113
+ private reader;
114
+ private initialized;
115
+ private initResult;
116
+ private routedClient;
117
+ /** The running engine's stderr tail; each launch owns a fresh one so a killed engine cannot write into it. */
118
+ private stderr;
119
+ private restarting;
120
+ private configuredBudget;
121
+ private usedJudgeCalls;
122
+ private usedUsd;
123
+ private heldJudgeCalls;
124
+ private heldUsd;
125
+ /** Spend the SDK cannot observe may have happened; a restart then leaves no budget. */
126
+ private unknownSpend;
127
+ constructor(options?: {
128
+ enginePath?: string;
129
+ logLevel?: string;
130
+ initializeTimeoutMs?: number;
131
+ });
132
+ /**
133
+ * Start the engine and complete the `initialize` handshake. Rejects when the engine exits,
134
+ * closes its pipes or fails to answer within the initialize timeout; the error carries the
135
+ * tail of the engine's stderr.
136
+ */
137
+ start(): Promise<InitializeResult>;
138
+ /** Spawn the engine and run `initialize` on it; the engine is stopped when that fails. */
139
+ private launch;
140
+ /** Send initialize and check the engine's version and capabilities. */
141
+ private initialize;
142
+ stop(): Promise<void>;
143
+ /** Close the pipes, reject pending requests and stop the engine process (SIGKILL when `force`). */
144
+ private terminate;
145
+ /**
146
+ * Replace the engine after a request timed out: its late response can no longer be told
147
+ * apart from a new one. The new engine gets the remaining session budget: the configured
148
+ * limit minus the usage already returned, minus what the abandoned requests may still have
149
+ * reserved. A restart that leaves no budget makes later model calls
150
+ * `not_evaluated(budget_exhausted)`.
151
+ */
152
+ restartAfterTimeout(abandoned: readonly BudgetReservation[]): Promise<void>;
153
+ /** An engine reply the SDK cannot account for (no usage, an RPC error, a dropped reply) may have spent budget. */
154
+ markUnknownSpend(): void;
155
+ private restart;
156
+ /** Count the usage an evaluate_batch result reported against the session budget. */
157
+ recordUsage(usage: Usage): void;
158
+ /** Resolves once an engine restart in progress has finished. */
159
+ whenReady(): Promise<void>;
160
+ /** Tail of the engine's stderr: the reason an engine died. */
161
+ get stderrTail(): string;
162
+ /** The client that routes this engine's responses by id; replaced when the engine restarts. */
163
+ get client(): AttestClient | undefined;
164
+ sendRequest(method: string, params: Record<string, unknown>): Promise<unknown>;
165
+ get isRunning(): boolean;
166
+ /** Expose process for AttestClient reader loop access */
167
+ get childProcess(): ChildProcess | null;
168
+ /** Expose readline interface for AttestClient reader loop */
169
+ get readlineInterface(): Interface | null;
170
+ }
171
+
106
172
  declare class TraceBuilder {
107
173
  private traceId;
108
174
  private agentId;
package/dist/esm/cli.js CHANGED
@@ -8,8 +8,8 @@ import * as path4 from "path";
8
8
  import { fileURLToPath as fileURLToPath2 } from "url";
9
9
 
10
10
  // src/version.ts
11
- var VERSION = "1.0.0";
12
- var ENGINE_VERSION = "1.0.0";
11
+ var VERSION = "1.0.1";
12
+ var ENGINE_VERSION = "1.0.1";
13
13
 
14
14
  // src/engine-manager.ts
15
15
  import { spawn, spawnSync } from "child_process";