@attest-ai/core 1.0.0-rc.3 → 1.0.0-rc.4
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.
- package/dist/cjs/index.cjs +4 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +5 -4
- package/dist/cjs/proto/index.cjs.map +1 -1
- package/dist/cjs/proto/index.d.cts +14 -1
- package/dist/esm/cli.d.ts +3 -1
- package/dist/esm/cli.js +230 -31
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/index.d.ts +5 -4
- package/dist/esm/index.js +4 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/proto/index.d.ts +14 -1
- package/dist/esm/proto/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.d.cts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { InitializeResult, ProtocolLogger, ProtocolDiagnostic, Trace, Assertion, BatchBudget, EvaluateBatchResult, DriftReport, SimulatePersona, ConversationMessage, SimulateFaultConfig, Step, AssertionResult, Usage, Outcome } from './proto/index.cjs';
|
|
1
|
+
import { InitializeResult, ProtocolLogger, ProtocolDiagnostic, Trace, Assertion, BatchBudget, BatchContext, EvaluateBatchResult, DriftReport, SimulatePersona, ConversationMessage, SimulateFaultConfig, Step, AssertionResult, Usage, 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-rc.
|
|
9
|
-
declare const ENGINE_VERSION = "1.0.0-rc.
|
|
8
|
+
declare const VERSION = "1.0.0-rc.4";
|
|
9
|
+
declare const ENGINE_VERSION = "1.0.0-rc.4";
|
|
10
10
|
|
|
11
11
|
declare class EngineManager {
|
|
12
12
|
private enginePath;
|
|
@@ -84,6 +84,7 @@ declare class AttestClient {
|
|
|
84
84
|
evaluateBatch(trace: Trace, assertions: readonly Assertion[], options?: {
|
|
85
85
|
timeout?: number;
|
|
86
86
|
budget?: BatchBudget;
|
|
87
|
+
context?: BatchContext;
|
|
87
88
|
}): Promise<EvaluateBatchResult>;
|
|
88
89
|
submitPluginResult(traceId: string, pluginName: string, assertionId: string, status: string, score: number, explanation: string, options?: {
|
|
89
90
|
timeout?: number;
|
|
@@ -1662,5 +1663,5 @@ interface TraceAdapter {
|
|
|
1662
1663
|
traceFromResponse(response: unknown, options?: Record<string, unknown>): Trace;
|
|
1663
1664
|
}
|
|
1664
1665
|
|
|
1665
|
-
export { ADVERSARIAL_USER, Agent, AgentResult, AlertDispatcher, AnthropicAdapter, Assertion, AssertionResult, AttestClient, BatchBudget, CONFUSED_USER, COOPERATIVE_USER, CaptureError, ContinuousEvalRunner, ConversationMessage, DriftReport, ENGINE_VERSION, EgressBlockedError, EngineManager, EvaluateBatchResult, ExpectChain, FRIENDLY_USER, GeminiAdapter, InitializeResult, LangChainAdapter, ManualAdapter, OTelAdapter, OllamaAdapter, OpenAIAdapter, Outcome, PluginRegistry, ProtocolDiagnostic, ProtocolLogger, ReplayError, ReplayMissError, ReplayNotEvaluatedError, Sampler, SimulateFaultConfig, SimulatePersona, Step, TIER_1, TIER_2, TIER_3, Trace, TraceBuilder, TraceTree, Usage, VERSION, WorldChecks, WorldError, activeBuilder, addUsage, agent, attestExpect, computeAgreement, config, delegate, dslCall, egressBlockRequested, emitVitest, executePluginAssertion, firstMiss, formatUsage, getSampleRate, installEgressGuard, isProviderHost, isSimulationMode, liveLine, loadFixture, loadLabelsCSV, loadLabelsJSONL, parseUsage, promptHash, record, renderAssertionFailure, renderDiagnostics, renderSummary, renderVitest, requireSimulationCapability, resetConfig, resolveMode, simulationEnvEnabled, startReplay, startWorld, sumUsage, testPathFor, tier, uninstallEgressGuard, usageSummaryLine, zeroUsage };
|
|
1666
|
+
export { ADVERSARIAL_USER, Agent, AgentResult, AlertDispatcher, AnthropicAdapter, Assertion, AssertionResult, AttestClient, BatchBudget, BatchContext, CONFUSED_USER, COOPERATIVE_USER, CaptureError, ContinuousEvalRunner, ConversationMessage, DriftReport, ENGINE_VERSION, EgressBlockedError, EngineManager, EvaluateBatchResult, ExpectChain, FRIENDLY_USER, GeminiAdapter, InitializeResult, LangChainAdapter, ManualAdapter, OTelAdapter, OllamaAdapter, OpenAIAdapter, Outcome, PluginRegistry, ProtocolDiagnostic, ProtocolLogger, ReplayError, ReplayMissError, ReplayNotEvaluatedError, Sampler, SimulateFaultConfig, SimulatePersona, Step, TIER_1, TIER_2, TIER_3, Trace, TraceBuilder, TraceTree, Usage, VERSION, WorldChecks, WorldError, activeBuilder, addUsage, agent, attestExpect, computeAgreement, config, delegate, dslCall, egressBlockRequested, emitVitest, executePluginAssertion, firstMiss, formatUsage, getSampleRate, installEgressGuard, isProviderHost, isSimulationMode, liveLine, loadFixture, loadLabelsCSV, loadLabelsJSONL, parseUsage, promptHash, record, renderAssertionFailure, renderDiagnostics, renderSummary, renderVitest, requireSimulationCapability, resetConfig, resolveMode, simulationEnvEnabled, startReplay, startWorld, sumUsage, testPathFor, tier, uninstallEgressGuard, usageSummaryLine, zeroUsage };
|
|
1666
1667
|
export type { AgreementResult, AlertPayload, AttestClientOptions, AttestPlugin, Capture, Contract, ContractResult, Fixture, LabelPair, LabeledRecord, PluginResult, RecordOptions, RecordResult, RenderOptions, ReplayMode, ReplayModeSetting, ReplayOptions, ReplayRecord, ReplaySession, ReplaySummary, TraceAdapter, WorldOptions, WorldSession, WorldSnapshot };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/proto/index.ts","../../../src/proto/constants.ts","../../../src/proto/types.ts","../../../src/proto/errors.ts","../../../src/proto/diagnostics.ts","../../../src/proto/codec.ts"],"sourcesContent":["export * from \"./constants.js\";\nexport * from \"./types.js\";\nexport * from \"./errors.js\";\nexport {\n ProtocolDiagnosticBuffer,\n previewLine,\n} from \"./diagnostics.js\";\nexport type {\n ProtocolDiagnostic,\n ProtocolDiagnosticKind,\n ProtocolLogger,\n} from \"./diagnostics.js\";\nexport { encodeRequest, decodeResponse, extractResult, extractId } from \"./codec.js\";\n","// Step type constants\nexport const STEP_LLM_CALL = \"llm_call\" as const;\nexport const STEP_TOOL_CALL = \"tool_call\" as const;\nexport const STEP_RETRIEVAL = \"retrieval\" as const;\nexport const STEP_AGENT_CALL = \"agent_call\" as const;\n\n// Status constants\nexport const STATUS_PASS = \"pass\" as const;\nexport const STATUS_SOFT_FAIL = \"soft_fail\" as const;\nexport const STATUS_HARD_FAIL = \"hard_fail\" as const;\nexport const STATUS_NOT_EVALUATED = \"not_evaluated\" as const;\n\n// Reasons carried by a not_evaluated result (AssertionResult.reason)\nexport const REASON_PROVIDER_UNAVAILABLE = \"provider_unavailable\" as const;\nexport const REASON_PROVIDER_NOT_CONFIGURED = \"provider_not_configured\" as const;\nexport const REASON_SIMULATION = \"simulation\" as const;\nexport const REASON_MISSING_EVIDENCE = \"missing_evidence\" as const;\nexport const REASON_SHORT_CIRCUITED = \"short_circuited\" as const;\nexport const REASON_BUDGET_EXHAUSTED = \"budget_exhausted\" as const;\nexport const REASON_JUDGE_ABSTAINED = \"judge_abstained\" as const;\nexport const REASON_REPLAY_MISS = \"replay_miss\" as const;\n\n// Test outcomes derived from a batch of assertion results (AgentResult.outcome)\nexport const OUTCOME_PASS = \"pass\" as const;\nexport const OUTCOME_FAIL = \"fail\" as const;\nexport const OUTCOME_SKIP = \"skip\" as const;\nexport type Outcome = typeof OUTCOME_PASS | typeof OUTCOME_FAIL | typeof OUTCOME_SKIP;\n\n// Assertion type constants\nexport const TYPE_SCHEMA = \"schema\" as const;\nexport const TYPE_CONSTRAINT = \"constraint\" as const;\nexport const TYPE_TRACE = \"trace\" as const;\nexport const TYPE_EFFECT = \"effect\" as const;\nexport const TYPE_CONTENT = \"content\" as const;\nexport const TYPE_EMBEDDING = \"embedding\" as const;\nexport const TYPE_LLM_JUDGE = \"llm_judge\" as const;\nexport const TYPE_TRACE_TREE = \"trace_tree\" as const;\nexport const TYPE_PLUGIN = \"plugin\" as const;\n\n// Error code constants\nexport const ERR_INVALID_TRACE = 1001 as const;\nexport const ERR_ASSERTION_ERROR = 1002 as const;\nexport const ERR_PROVIDER_ERROR = 2001 as const;\nexport const ERR_ENGINE_ERROR = 3001 as const;\nexport const ERR_TIMEOUT = 3002 as const;\nexport const ERR_SESSION_ERROR = 3003 as const;\n","// ---------------------------------------------------------------------------\n// Branded ID types (T6)\n// ---------------------------------------------------------------------------\n\ndeclare const __brand: unique symbol;\ntype Brand<T, B extends string> = T & { readonly [__brand]: B };\n\nexport type TraceId = Brand<string, \"TraceId\">;\nexport type AssertionId = Brand<string, \"AssertionId\">;\nexport type AgentId = Brand<string, \"AgentId\">;\n\nexport function traceId(id: string): TraceId {\n return id as TraceId;\n}\n\nexport function assertionId(id: string): AssertionId {\n return id as AssertionId;\n}\n\nexport function agentId(id: string): AgentId {\n return id as AgentId;\n}\n\n// ---------------------------------------------------------------------------\n// Assertion spec discriminated unions (T5)\n// ---------------------------------------------------------------------------\n\nexport interface SchemaSpec {\n readonly type: \"schema\";\n readonly target: string;\n readonly schema: Record<string, unknown>;\n}\n\nexport interface ConstraintSpec {\n readonly type: \"constraint\";\n readonly field: string;\n readonly operator: string;\n readonly value?: number;\n readonly min?: number;\n readonly max?: number;\n readonly soft: boolean;\n}\n\nexport interface TraceSpec {\n readonly type: \"trace\";\n readonly check: string;\n readonly tools?: string[];\n readonly tool?: string;\n readonly max_repetitions?: number;\n readonly soft: boolean;\n}\n\nexport interface EffectSpec {\n readonly type: \"effect\";\n readonly check: \"count\" | \"unique\" | \"idempotent\";\n /** A world-v1 snapshot, or `null` when the test ran without a world helper. */\n readonly world: Record<string, unknown> | null;\n readonly resource: string;\n readonly where?: Record<string, unknown>;\n readonly equals?: number;\n readonly at_most?: number;\n readonly at_least?: number;\n readonly fields?: string[];\n readonly field?: string;\n}\n\nexport interface ContentSpec {\n readonly type: \"content\";\n readonly target: string;\n readonly check: string;\n readonly value?: string;\n readonly values?: string[];\n readonly case_sensitive?: boolean;\n readonly soft?: boolean;\n}\n\nexport interface EmbeddingSpec {\n readonly type: \"embedding\";\n readonly target: string;\n readonly reference: string;\n readonly threshold: number | \"dynamic\";\n readonly model?: string;\n readonly soft: boolean;\n}\n\nexport interface LlmJudgeSpec {\n readonly type: \"llm_judge\";\n readonly target: string;\n readonly criteria: string;\n readonly rubric: string;\n readonly threshold: number | \"dynamic\";\n readonly model?: string;\n readonly soft: boolean;\n}\n\nexport interface TraceTreeSpec {\n readonly type: \"trace_tree\";\n readonly check: string;\n readonly [key: string]: unknown;\n}\n\nexport interface PluginSpec {\n readonly type: \"plugin\";\n readonly plugin_id: string;\n readonly config?: Record<string, unknown>;\n readonly soft: boolean;\n}\n\nexport type AssertionSpec =\n | SchemaSpec\n | ConstraintSpec\n | TraceSpec\n | EffectSpec\n | ContentSpec\n | EmbeddingSpec\n | LlmJudgeSpec\n | TraceTreeSpec\n | PluginSpec;\n\n// ---------------------------------------------------------------------------\n// Core protocol types\n// ---------------------------------------------------------------------------\n\nexport interface TraceMetadata {\n readonly total_tokens?: number;\n readonly cost_usd?: number;\n readonly latency_ms?: number;\n readonly model?: string;\n readonly timestamp?: string;\n}\n\n/** Trace v2: a step whose span ended in error. */\nexport interface StepError {\n readonly type: string;\n readonly message?: string;\n}\n\n/** Trace v2: a recorded model request/response pair. */\nexport interface Exchange {\n readonly request: Record<string, unknown>;\n readonly response: Record<string, unknown>;\n}\n\n/** Trace v2: one conversation turn and the indices of its steps. */\nexport interface Turn {\n readonly index: number;\n readonly span_id?: string;\n readonly input?: unknown;\n readonly output?: unknown;\n readonly step_indices: readonly number[];\n}\n\n/** Trace v2: control passing from one agent to another at an agent_call step. */\nexport interface Handoff {\n readonly from_agent: string;\n readonly to_agent: string;\n readonly step_index: number;\n}\n\nexport interface Step {\n readonly type: string;\n readonly name: string;\n readonly args?: Record<string, unknown>;\n readonly result?: Record<string, unknown>;\n readonly sub_trace?: Trace;\n readonly metadata?: Record<string, unknown>;\n readonly started_at_ms?: number;\n readonly ended_at_ms?: number;\n readonly agent_id?: string;\n readonly agent_role?: string;\n // Trace v2 (schema_version 2) fields.\n readonly span_id?: string;\n readonly parent_span_id?: string;\n readonly tool_call_id?: string;\n readonly retry_of?: number;\n readonly error?: StepError;\n readonly exchange?: Exchange;\n}\n\nexport interface Trace {\n readonly trace_id: string;\n readonly output: Record<string, unknown>;\n readonly schema_version?: number;\n readonly agent_id?: string;\n readonly input?: Record<string, unknown>;\n readonly steps: readonly Step[];\n readonly metadata?: TraceMetadata;\n readonly parent_trace_id?: string;\n // Trace v2 (schema_version 2) fields.\n readonly conversation_id?: string;\n readonly turns?: readonly Turn[];\n readonly handoffs?: readonly Handoff[];\n}\n\nexport interface Assertion {\n readonly assertion_id: string;\n readonly type: string;\n readonly spec: Record<string, unknown>;\n readonly request_id?: string;\n}\n\n/**\n * Audit trail for an LLM-judge evaluation. Mirrors\n * engine/pkg/types/assertion.go::JudgeMetadata so report v2 payloads\n * round-trip without losing the model / rubric / variance evidence\n * reviewers need to triage a judge failure.\n */\nexport interface JudgeMetadata {\n readonly provider?: string;\n readonly model?: string;\n readonly rubric_name?: string;\n readonly rubric_version?: string;\n readonly prompt_hash?: string;\n readonly sample_scores?: readonly number[];\n readonly score_mean?: number;\n readonly score_stddev?: number;\n readonly high_variance?: boolean;\n readonly bias_probes?: readonly BiasProbe[];\n readonly calibration?: JudgeAgreement;\n}\n\n/**\n * One judge-bias probe result. Score is the score the judge produced on\n * the mutated input; delta is `score - baseline`. A well-calibrated\n * judge has |delta| close to zero. Mirrors\n * engine/pkg/types/assertion.go::BiasProbe.\n */\nexport interface BiasProbe {\n readonly name: string;\n readonly score: number;\n readonly delta: number;\n}\n\n/**\n * Calibration agreement summary keyed by\n * (rubric_name, rubric_version, prompt_hash). Mirrors\n * engine/pkg/types/assertion.go::JudgeAgreement.\n */\nexport interface JudgeAgreement {\n readonly label_count: number;\n readonly agreement: number;\n readonly cohen_kappa: number;\n readonly roc_auc?: number;\n}\n\nexport interface AssertionResult {\n readonly assertion_id: string;\n readonly status: string;\n readonly score: number;\n readonly explanation: string;\n readonly cost?: number;\n readonly duration_ms?: number;\n readonly request_id?: string;\n /** Set only when status is \"not_evaluated\" (REASON_* constants). */\n readonly reason?: string;\n readonly threshold_source?: string;\n readonly layer?: number;\n readonly type?: string;\n readonly trace_node_path?: string;\n readonly expected?: string;\n readonly actual?: string;\n readonly suggested_action?: string;\n readonly judge_metadata?: JudgeMetadata;\n /**\n * Heuristic root-cause label set by the engine\n * (broken_code / flaky_judge / bad_rubric / missing_trace_data /\n * stochastic_variance). Empty/undefined for passes and any result the\n * engine declined to label. Mirrors\n * engine/pkg/types/failure_class.go.\n */\n readonly failure_class?: string;\n}\n\n/**\n * FailureClass values mirror engine/pkg/types/failure_class.go. Use\n * these constants when matching on AssertionResult.failure_class so a\n * typo in either codebase fails fast.\n */\nexport const FailureClass = {\n BrokenCode: \"broken_code\",\n FlakyJudge: \"flaky_judge\",\n BadRubric: \"bad_rubric\",\n MissingTraceData: \"missing_trace_data\",\n StochasticVariance: \"stochastic_variance\",\n} as const;\nexport type FailureClass = (typeof FailureClass)[keyof typeof FailureClass];\n\n/**\n * Map an assertion-type string to its pipeline layer (1–8). Returns 0\n * when the type is unknown so callers can route uncategorised results\n * into their own bucket.\n */\nexport function layerForType(assertionType: string | undefined): number {\n switch (assertionType) {\n case \"schema\":\n return 1;\n case \"constraint\":\n return 2;\n case \"trace\":\n case \"trace_tree\":\n case \"effect\":\n return 3;\n case \"content\":\n return 4;\n case \"embedding\":\n return 5;\n case \"llm_judge\":\n return 6;\n case \"plugin\":\n return 8;\n default:\n return 0;\n }\n}\n\nexport interface ErrorData {\n readonly error_type: string;\n readonly retryable: boolean;\n readonly detail: string;\n}\n\nexport interface RPCError {\n readonly code: number;\n readonly message: string;\n readonly data?: ErrorData;\n}\n\nexport interface RPCRequest {\n readonly jsonrpc: \"2.0\";\n readonly id: number;\n readonly method: string;\n readonly params: Record<string, unknown>;\n}\n\nexport interface RPCResponse {\n readonly jsonrpc: \"2.0\";\n readonly id: number;\n readonly result?: unknown;\n readonly error?: RPCError;\n}\n\nexport interface InitializeParams {\n readonly sdk_name: string;\n readonly sdk_version: string;\n readonly protocol_version: number;\n readonly required_capabilities: readonly string[];\n readonly preferred_encoding?: string;\n}\n\nexport interface InitializeResult {\n readonly engine_version: string;\n readonly protocol_version: number;\n readonly capabilities: readonly string[];\n readonly missing: readonly string[];\n readonly compatible: boolean;\n readonly encoding?: string;\n readonly max_concurrent_requests?: number;\n readonly max_trace_size_bytes?: number;\n readonly max_steps_per_trace?: number;\n}\n\n/**\n * Limits for one evaluate_batch call on top of the session budget. A judge or\n * embedding call that cannot reserve against them is not sent and its\n * assertion is not_evaluated with reason \"budget_exhausted\".\n */\nexport interface BatchBudget {\n readonly max_judge_calls?: number;\n readonly max_cost_usd?: number;\n}\n\nexport interface EvaluateBatchParams {\n readonly trace: Trace;\n readonly assertions: readonly Assertion[];\n /** Omitted when no per-batch budget applies. */\n readonly budget?: BatchBudget;\n}\n\n/**\n * Attest-initiated model usage (embeddings, judges, judge repeats, bias\n * probes, simulated-user messages). Agent calls not routed through attest\n * are not counted.\n */\nexport interface Usage {\n readonly model_calls: number;\n /** Judge-provider requests, the part of model_calls that max_judge_calls limits. */\n readonly judge_calls: number;\n readonly input_tokens: number;\n readonly output_tokens: number;\n readonly cached_tokens: number;\n readonly cost_usd: number;\n readonly retry_cost_usd: number;\n readonly unpriced_calls: number;\n readonly budget_refused: number;\n}\n\nexport interface EvaluateBatchResult {\n readonly results: readonly AssertionResult[];\n readonly total_cost?: number;\n readonly total_duration_ms?: number;\n /** Always sent by the engine; validated by AttestClient.evaluateBatch. */\n readonly usage: Usage;\n /**\n * True when this result was produced by an SDK simulation shim rather\n * than a real engine evaluation. Engine-produced results always carry\n * simulated=false. CI gates can fail builds that accidentally evaluate\n * against the simulator by checking this flag.\n */\n readonly simulated?: boolean;\n}\n\nexport interface ShutdownResult {\n readonly sessions_completed: number;\n readonly assertions_evaluated: number;\n}\n\nexport interface SubmitPluginResultParams {\n readonly trace_id: string;\n readonly plugin_name: string;\n readonly assertion_id: string;\n readonly result: AssertionResult;\n}\n\n// ---------------------------------------------------------------------------\n// Drift detection types\n// ---------------------------------------------------------------------------\n\nexport interface DriftReport {\n readonly assertion_id: string;\n readonly mean: number;\n readonly stddev: number;\n readonly count: number;\n readonly latest_score: number;\n readonly deviation: number;\n readonly status: string;\n}\n\nexport interface QueryDriftParams {\n readonly assertion_id: string;\n readonly window_size: number;\n}\n\nexport interface QueryDriftResult {\n readonly report: DriftReport;\n}\n\n// ---------------------------------------------------------------------------\n// Simulation types\n// ---------------------------------------------------------------------------\n\nexport interface SimulatePersona {\n readonly name: string;\n readonly system_prompt: string;\n readonly style: string;\n readonly temperature: number;\n readonly max_tokens?: number;\n}\n\nexport interface SimulateFaultConfig {\n readonly error_rate: number;\n readonly latency_jitter_ms: number;\n readonly content_corruption: boolean;\n readonly timeout_after_ms: number;\n}\n\nexport interface ConversationMessage {\n readonly role: string;\n readonly content: string;\n}\n\nexport interface GenerateUserMessageParams {\n readonly persona: SimulatePersona;\n readonly conversation_history: readonly ConversationMessage[];\n readonly fault_config?: SimulateFaultConfig;\n}\n\nexport interface GenerateUserMessageResult {\n readonly message: string;\n}\n","import type { ErrorData } from \"./types.js\";\nimport type { ProtocolDiagnostic } from \"./diagnostics.js\";\n\nexport class ProtocolError extends Error {\n readonly code: number;\n readonly errorMessage: string;\n readonly data: ErrorData | undefined;\n\n constructor(code: number, message: string, data?: ErrorData) {\n super(message);\n this.name = \"ProtocolError\";\n this.code = code;\n this.errorMessage = message;\n this.data = data;\n }\n}\n\nexport class EngineTimeoutError extends Error {\n readonly method: string;\n readonly timeoutMs: number;\n\n constructor(method: string, timeoutMs: number) {\n super(\n `Engine request '${method}' timed out after ${timeoutMs}ms. ` +\n \"Set ATTEST_ENGINE_TIMEOUT to increase the limit.\",\n );\n this.name = \"EngineTimeoutError\";\n this.method = method;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Raised when the reader loop detects that engine output has lost\n * framing or contains repeated unparseable lines. All in-flight requests\n * are rejected with this error so callers see a visible failure rather\n * than a hung promise.\n */\nexport class ProtocolDesyncError extends Error {\n readonly diagnostics: readonly ProtocolDiagnostic[];\n\n constructor(message: string, diagnostics: readonly ProtocolDiagnostic[]) {\n super(message);\n this.name = \"ProtocolDesyncError\";\n this.diagnostics = diagnostics;\n }\n}\n\n/**\n * The engine rejected an OTLP/JSON export (`attest-engine trace convert`). The message is\n * the engine's error, which names the offending span or field.\n */\nexport class OTLPConversionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OTLPConversionError\";\n }\n}\n","/**\n * Protocol diagnostic types for client-side observability.\n *\n * The reader loop emits diagnostics whenever it cannot route a response\n * line: malformed JSON, missing id, unknown id, or non-routable protocol\n * errors. Diagnostics are buffered in a bounded ring (32 entries) and\n * trigger a desync error when the rate exceeds the configured threshold.\n */\n\nexport type ProtocolDiagnosticKind =\n | \"malformed_json\"\n | \"non_object_response\"\n | \"invalid_jsonrpc_version\"\n | \"missing_id\"\n | \"unknown_id\"\n | \"non_routable_error\";\n\nexport interface ProtocolDiagnostic {\n readonly kind: ProtocolDiagnosticKind;\n readonly message: string;\n readonly rawLine: string;\n readonly timestampMs: number;\n}\n\nexport interface ProtocolLogger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst DEFAULT_BUFFER_SIZE = 32;\nconst MAX_LINE_PREVIEW = 512;\n\nexport class ProtocolDiagnosticBuffer {\n private readonly capacity: number;\n private readonly entries: ProtocolDiagnostic[] = [];\n\n constructor(capacity: number = DEFAULT_BUFFER_SIZE) {\n if (capacity <= 0) {\n throw new Error(\n `ProtocolDiagnosticBuffer capacity must be positive, got ${capacity}`,\n );\n }\n this.capacity = capacity;\n }\n\n push(diagnostic: ProtocolDiagnostic): void {\n if (this.entries.length >= this.capacity) {\n this.entries.shift();\n }\n this.entries.push(diagnostic);\n }\n\n snapshot(): readonly ProtocolDiagnostic[] {\n return this.entries.slice();\n }\n\n countWithin(windowMs: number, nowMs: number): number {\n const cutoff = nowMs - windowMs;\n let count = 0;\n for (let i = this.entries.length - 1; i >= 0; i -= 1) {\n if (this.entries[i]!.timestampMs >= cutoff) {\n count += 1;\n } else {\n break;\n }\n }\n return count;\n }\n\n clear(): void {\n this.entries.length = 0;\n }\n}\n\nexport function previewLine(line: string): string {\n if (line.length <= MAX_LINE_PREVIEW) return line;\n return line.slice(0, MAX_LINE_PREVIEW) + \"…\";\n}\n","import type { ErrorData, RPCResponse } from \"./types.js\";\nimport { ProtocolError } from \"./errors.js\";\n\n/**\n * Encode a JSON-RPC 2.0 request as an NDJSON line.\n */\nexport function encodeRequest(\n id: number,\n method: string,\n params: Record<string, unknown>,\n): string {\n const msg = {\n jsonrpc: \"2.0\" as const,\n id,\n method,\n params,\n };\n return JSON.stringify(msg) + \"\\n\";\n}\n\n/**\n * Decode a JSON-RPC 2.0 response from an NDJSON line.\n * Throws ProtocolError if the response contains an error.\n * Throws Error for malformed JSON or invalid responses.\n */\nexport function decodeResponse(line: string): RPCResponse {\n const text = line.trim();\n if (!text) {\n throw new Error(\"empty response line\");\n }\n\n let data: unknown;\n try {\n data = JSON.parse(text);\n } catch (e) {\n throw new Error(`malformed JSON response: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n throw new Error(`expected JSON object, got ${Array.isArray(data) ? \"array\" : typeof data}`);\n }\n\n const obj = data as Record<string, unknown>;\n\n if (obj.jsonrpc !== \"2.0\") {\n throw new Error(`invalid jsonrpc version: ${String(obj.jsonrpc)}`);\n }\n\n if (obj.error != null) {\n const err = obj.error as Record<string, unknown>;\n let errorData: ErrorData | undefined;\n\n if (err.data != null) {\n const raw = err.data as Record<string, unknown>;\n errorData = {\n error_type: (raw.error_type as string) ?? \"\",\n retryable: (raw.retryable as boolean) ?? false,\n detail: (raw.detail as string) ?? \"\",\n };\n }\n\n throw new ProtocolError(\n (err.code as number) ?? -1,\n (err.message as string) ?? \"unknown error\",\n errorData,\n );\n }\n\n return obj as unknown as RPCResponse;\n}\n\n/**\n * Extract the result field from a decoded response.\n */\nexport function extractResult(response: RPCResponse): unknown {\n if (response.result === undefined) {\n throw new Error(\"response missing 'result' field\");\n }\n return response.result;\n}\n\n/**\n * Extract the request ID from a decoded response.\n */\nexport function extractId(response: RPCResponse): number {\n if (response.id === undefined) {\n throw new Error(\"response missing 'id' field\");\n }\n return Number(response.id);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/proto/index.ts","../../../src/proto/constants.ts","../../../src/proto/types.ts","../../../src/proto/errors.ts","../../../src/proto/diagnostics.ts","../../../src/proto/codec.ts"],"sourcesContent":["export * from \"./constants.js\";\nexport * from \"./types.js\";\nexport * from \"./errors.js\";\nexport {\n ProtocolDiagnosticBuffer,\n previewLine,\n} from \"./diagnostics.js\";\nexport type {\n ProtocolDiagnostic,\n ProtocolDiagnosticKind,\n ProtocolLogger,\n} from \"./diagnostics.js\";\nexport { encodeRequest, decodeResponse, extractResult, extractId } from \"./codec.js\";\n","// Step type constants\nexport const STEP_LLM_CALL = \"llm_call\" as const;\nexport const STEP_TOOL_CALL = \"tool_call\" as const;\nexport const STEP_RETRIEVAL = \"retrieval\" as const;\nexport const STEP_AGENT_CALL = \"agent_call\" as const;\n\n// Status constants\nexport const STATUS_PASS = \"pass\" as const;\nexport const STATUS_SOFT_FAIL = \"soft_fail\" as const;\nexport const STATUS_HARD_FAIL = \"hard_fail\" as const;\nexport const STATUS_NOT_EVALUATED = \"not_evaluated\" as const;\n\n// Reasons carried by a not_evaluated result (AssertionResult.reason)\nexport const REASON_PROVIDER_UNAVAILABLE = \"provider_unavailable\" as const;\nexport const REASON_PROVIDER_NOT_CONFIGURED = \"provider_not_configured\" as const;\nexport const REASON_SIMULATION = \"simulation\" as const;\nexport const REASON_MISSING_EVIDENCE = \"missing_evidence\" as const;\nexport const REASON_SHORT_CIRCUITED = \"short_circuited\" as const;\nexport const REASON_BUDGET_EXHAUSTED = \"budget_exhausted\" as const;\nexport const REASON_JUDGE_ABSTAINED = \"judge_abstained\" as const;\nexport const REASON_REPLAY_MISS = \"replay_miss\" as const;\n\n// Test outcomes derived from a batch of assertion results (AgentResult.outcome)\nexport const OUTCOME_PASS = \"pass\" as const;\nexport const OUTCOME_FAIL = \"fail\" as const;\nexport const OUTCOME_SKIP = \"skip\" as const;\nexport type Outcome = typeof OUTCOME_PASS | typeof OUTCOME_FAIL | typeof OUTCOME_SKIP;\n\n// Assertion type constants\nexport const TYPE_SCHEMA = \"schema\" as const;\nexport const TYPE_CONSTRAINT = \"constraint\" as const;\nexport const TYPE_TRACE = \"trace\" as const;\nexport const TYPE_EFFECT = \"effect\" as const;\nexport const TYPE_CONTENT = \"content\" as const;\nexport const TYPE_EMBEDDING = \"embedding\" as const;\nexport const TYPE_LLM_JUDGE = \"llm_judge\" as const;\nexport const TYPE_TRACE_TREE = \"trace_tree\" as const;\nexport const TYPE_PLUGIN = \"plugin\" as const;\n\n// Error code constants\nexport const ERR_INVALID_TRACE = 1001 as const;\nexport const ERR_ASSERTION_ERROR = 1002 as const;\nexport const ERR_PROVIDER_ERROR = 2001 as const;\nexport const ERR_ENGINE_ERROR = 3001 as const;\nexport const ERR_TIMEOUT = 3002 as const;\nexport const ERR_SESSION_ERROR = 3003 as const;\n","// ---------------------------------------------------------------------------\n// Branded ID types (T6)\n// ---------------------------------------------------------------------------\n\ndeclare const __brand: unique symbol;\ntype Brand<T, B extends string> = T & { readonly [__brand]: B };\n\nexport type TraceId = Brand<string, \"TraceId\">;\nexport type AssertionId = Brand<string, \"AssertionId\">;\nexport type AgentId = Brand<string, \"AgentId\">;\n\nexport function traceId(id: string): TraceId {\n return id as TraceId;\n}\n\nexport function assertionId(id: string): AssertionId {\n return id as AssertionId;\n}\n\nexport function agentId(id: string): AgentId {\n return id as AgentId;\n}\n\n// ---------------------------------------------------------------------------\n// Assertion spec discriminated unions (T5)\n// ---------------------------------------------------------------------------\n\nexport interface SchemaSpec {\n readonly type: \"schema\";\n readonly target: string;\n readonly schema: Record<string, unknown>;\n}\n\nexport interface ConstraintSpec {\n readonly type: \"constraint\";\n readonly field: string;\n readonly operator: string;\n readonly value?: number;\n readonly min?: number;\n readonly max?: number;\n readonly soft: boolean;\n}\n\nexport interface TraceSpec {\n readonly type: \"trace\";\n readonly check: string;\n readonly tools?: string[];\n readonly tool?: string;\n readonly max_repetitions?: number;\n readonly soft: boolean;\n}\n\nexport interface EffectSpec {\n readonly type: \"effect\";\n readonly check: \"count\" | \"unique\" | \"idempotent\";\n /** A world-v1 snapshot, or `null` when the test ran without a world helper. */\n readonly world: Record<string, unknown> | null;\n readonly resource: string;\n readonly where?: Record<string, unknown>;\n readonly equals?: number;\n readonly at_most?: number;\n readonly at_least?: number;\n readonly fields?: string[];\n readonly field?: string;\n}\n\nexport interface ContentSpec {\n readonly type: \"content\";\n readonly target: string;\n readonly check: string;\n readonly value?: string;\n readonly values?: string[];\n readonly case_sensitive?: boolean;\n readonly soft?: boolean;\n}\n\nexport interface EmbeddingSpec {\n readonly type: \"embedding\";\n readonly target: string;\n readonly reference: string;\n readonly threshold: number | \"dynamic\";\n readonly model?: string;\n readonly soft: boolean;\n}\n\nexport interface LlmJudgeSpec {\n readonly type: \"llm_judge\";\n readonly target: string;\n readonly criteria: string;\n readonly rubric: string;\n readonly threshold: number | \"dynamic\";\n readonly model?: string;\n readonly soft: boolean;\n}\n\nexport interface TraceTreeSpec {\n readonly type: \"trace_tree\";\n readonly check: string;\n readonly [key: string]: unknown;\n}\n\nexport interface PluginSpec {\n readonly type: \"plugin\";\n readonly plugin_id: string;\n readonly config?: Record<string, unknown>;\n readonly soft: boolean;\n}\n\nexport type AssertionSpec =\n | SchemaSpec\n | ConstraintSpec\n | TraceSpec\n | EffectSpec\n | ContentSpec\n | EmbeddingSpec\n | LlmJudgeSpec\n | TraceTreeSpec\n | PluginSpec;\n\n// ---------------------------------------------------------------------------\n// Core protocol types\n// ---------------------------------------------------------------------------\n\nexport interface TraceMetadata {\n readonly total_tokens?: number;\n readonly cost_usd?: number;\n readonly latency_ms?: number;\n readonly model?: string;\n readonly timestamp?: string;\n}\n\n/** Trace v2: a step whose span ended in error. */\nexport interface StepError {\n readonly type: string;\n readonly message?: string;\n}\n\n/** Trace v2: a recorded model request/response pair. */\nexport interface Exchange {\n readonly request: Record<string, unknown>;\n readonly response: Record<string, unknown>;\n}\n\n/** Trace v2: one conversation turn and the indices of its steps. */\nexport interface Turn {\n readonly index: number;\n readonly span_id?: string;\n readonly input?: unknown;\n readonly output?: unknown;\n readonly step_indices: readonly number[];\n}\n\n/** Trace v2: control passing from one agent to another at an agent_call step. */\nexport interface Handoff {\n readonly from_agent: string;\n readonly to_agent: string;\n readonly step_index: number;\n}\n\nexport interface Step {\n readonly type: string;\n readonly name: string;\n readonly args?: Record<string, unknown>;\n readonly result?: Record<string, unknown>;\n readonly sub_trace?: Trace;\n readonly metadata?: Record<string, unknown>;\n readonly started_at_ms?: number;\n readonly ended_at_ms?: number;\n readonly agent_id?: string;\n readonly agent_role?: string;\n // Trace v2 (schema_version 2) fields.\n readonly span_id?: string;\n readonly parent_span_id?: string;\n readonly tool_call_id?: string;\n readonly retry_of?: number;\n readonly error?: StepError;\n readonly exchange?: Exchange;\n}\n\nexport interface Trace {\n readonly trace_id: string;\n readonly output: Record<string, unknown>;\n readonly schema_version?: number;\n readonly agent_id?: string;\n readonly input?: Record<string, unknown>;\n readonly steps: readonly Step[];\n readonly metadata?: TraceMetadata;\n readonly parent_trace_id?: string;\n // Trace v2 (schema_version 2) fields.\n readonly conversation_id?: string;\n readonly turns?: readonly Turn[];\n readonly handoffs?: readonly Handoff[];\n}\n\nexport interface Assertion {\n readonly assertion_id: string;\n readonly type: string;\n readonly spec: Record<string, unknown>;\n readonly request_id?: string;\n}\n\n/**\n * Audit trail for an LLM-judge evaluation. Mirrors\n * engine/pkg/types/assertion.go::JudgeMetadata so report v2 payloads\n * round-trip without losing the model / rubric / variance evidence\n * reviewers need to triage a judge failure.\n */\nexport interface JudgeMetadata {\n readonly provider?: string;\n readonly model?: string;\n readonly rubric_name?: string;\n readonly rubric_version?: string;\n readonly prompt_hash?: string;\n readonly sample_scores?: readonly number[];\n readonly score_mean?: number;\n readonly score_stddev?: number;\n readonly high_variance?: boolean;\n readonly bias_probes?: readonly BiasProbe[];\n readonly calibration?: JudgeAgreement;\n}\n\n/**\n * One judge-bias probe result. Score is the score the judge produced on\n * the mutated input; delta is `score - baseline`. A well-calibrated\n * judge has |delta| close to zero. Mirrors\n * engine/pkg/types/assertion.go::BiasProbe.\n */\nexport interface BiasProbe {\n readonly name: string;\n readonly score: number;\n readonly delta: number;\n}\n\n/**\n * Calibration agreement summary keyed by\n * (rubric_name, rubric_version, prompt_hash). Mirrors\n * engine/pkg/types/assertion.go::JudgeAgreement.\n */\nexport interface JudgeAgreement {\n readonly label_count: number;\n readonly agreement: number;\n readonly cohen_kappa: number;\n readonly roc_auc?: number;\n}\n\nexport interface AssertionResult {\n readonly assertion_id: string;\n readonly status: string;\n readonly score: number;\n readonly explanation: string;\n readonly cost?: number;\n readonly duration_ms?: number;\n readonly request_id?: string;\n /** Set only when status is \"not_evaluated\" (REASON_* constants). */\n readonly reason?: string;\n readonly threshold_source?: string;\n readonly layer?: number;\n readonly type?: string;\n readonly trace_node_path?: string;\n readonly expected?: string;\n readonly actual?: string;\n readonly suggested_action?: string;\n readonly judge_metadata?: JudgeMetadata;\n /**\n * Heuristic root-cause label set by the engine\n * (broken_code / flaky_judge / bad_rubric / missing_trace_data /\n * stochastic_variance). Empty/undefined for passes and any result the\n * engine declined to label. Mirrors\n * engine/pkg/types/failure_class.go.\n */\n readonly failure_class?: string;\n}\n\n/**\n * FailureClass values mirror engine/pkg/types/failure_class.go. Use\n * these constants when matching on AssertionResult.failure_class so a\n * typo in either codebase fails fast.\n */\nexport const FailureClass = {\n BrokenCode: \"broken_code\",\n FlakyJudge: \"flaky_judge\",\n BadRubric: \"bad_rubric\",\n MissingTraceData: \"missing_trace_data\",\n StochasticVariance: \"stochastic_variance\",\n} as const;\nexport type FailureClass = (typeof FailureClass)[keyof typeof FailureClass];\n\n/**\n * Map an assertion-type string to its pipeline layer (1–8). Returns 0\n * when the type is unknown so callers can route uncategorised results\n * into their own bucket.\n */\nexport function layerForType(assertionType: string | undefined): number {\n switch (assertionType) {\n case \"schema\":\n return 1;\n case \"constraint\":\n return 2;\n case \"trace\":\n case \"trace_tree\":\n case \"effect\":\n return 3;\n case \"content\":\n return 4;\n case \"embedding\":\n return 5;\n case \"llm_judge\":\n return 6;\n case \"plugin\":\n return 8;\n default:\n return 0;\n }\n}\n\nexport interface ErrorData {\n readonly error_type: string;\n readonly retryable: boolean;\n readonly detail: string;\n}\n\nexport interface RPCError {\n readonly code: number;\n readonly message: string;\n readonly data?: ErrorData;\n}\n\nexport interface RPCRequest {\n readonly jsonrpc: \"2.0\";\n readonly id: number;\n readonly method: string;\n readonly params: Record<string, unknown>;\n}\n\nexport interface RPCResponse {\n readonly jsonrpc: \"2.0\";\n readonly id: number;\n readonly result?: unknown;\n readonly error?: RPCError;\n}\n\nexport interface InitializeParams {\n readonly sdk_name: string;\n readonly sdk_version: string;\n readonly protocol_version: number;\n readonly required_capabilities: readonly string[];\n readonly preferred_encoding?: string;\n}\n\nexport interface InitializeResult {\n readonly engine_version: string;\n readonly protocol_version: number;\n readonly capabilities: readonly string[];\n readonly missing: readonly string[];\n readonly compatible: boolean;\n readonly encoding?: string;\n readonly max_concurrent_requests?: number;\n readonly max_trace_size_bytes?: number;\n readonly max_steps_per_trace?: number;\n}\n\n/**\n * Limits for one evaluate_batch call on top of the session budget. A judge or\n * embedding call that cannot reserve against them is not sent and its\n * assertion is not_evaluated with reason \"budget_exhausted\".\n */\nexport interface BatchBudget {\n readonly max_judge_calls?: number;\n readonly max_cost_usd?: number;\n}\n\n/**\n * The test an evaluate_batch call belongs to. The engine records it next to\n * each assertion spec when ATTEST_CONTRACTS_DIR is set and uses it for\n * nothing else.\n */\nexport interface BatchContext {\n readonly test_id?: string;\n readonly file?: string;\n /** 1-based line the test starts on. */\n readonly line?: number;\n}\n\nexport interface EvaluateBatchParams {\n readonly trace: Trace;\n readonly assertions: readonly Assertion[];\n /** Omitted when no per-batch budget applies. */\n readonly budget?: BatchBudget;\n /** Omitted outside a test. */\n readonly context?: BatchContext;\n}\n\n/**\n * Attest-initiated model usage (embeddings, judges, judge repeats, bias\n * probes, simulated-user messages). Agent calls not routed through attest\n * are not counted.\n */\nexport interface Usage {\n readonly model_calls: number;\n /** Judge-provider requests, the part of model_calls that max_judge_calls limits. */\n readonly judge_calls: number;\n readonly input_tokens: number;\n readonly output_tokens: number;\n readonly cached_tokens: number;\n readonly cost_usd: number;\n readonly retry_cost_usd: number;\n readonly unpriced_calls: number;\n readonly budget_refused: number;\n}\n\nexport interface EvaluateBatchResult {\n readonly results: readonly AssertionResult[];\n readonly total_cost?: number;\n readonly total_duration_ms?: number;\n /** Always sent by the engine; validated by AttestClient.evaluateBatch. */\n readonly usage: Usage;\n /**\n * True when this result was produced by an SDK simulation shim rather\n * than a real engine evaluation. Engine-produced results always carry\n * simulated=false. CI gates can fail builds that accidentally evaluate\n * against the simulator by checking this flag.\n */\n readonly simulated?: boolean;\n}\n\nexport interface ShutdownResult {\n readonly sessions_completed: number;\n readonly assertions_evaluated: number;\n}\n\nexport interface SubmitPluginResultParams {\n readonly trace_id: string;\n readonly plugin_name: string;\n readonly assertion_id: string;\n readonly result: AssertionResult;\n}\n\n// ---------------------------------------------------------------------------\n// Drift detection types\n// ---------------------------------------------------------------------------\n\nexport interface DriftReport {\n readonly assertion_id: string;\n readonly mean: number;\n readonly stddev: number;\n readonly count: number;\n readonly latest_score: number;\n readonly deviation: number;\n readonly status: string;\n}\n\nexport interface QueryDriftParams {\n readonly assertion_id: string;\n readonly window_size: number;\n}\n\nexport interface QueryDriftResult {\n readonly report: DriftReport;\n}\n\n// ---------------------------------------------------------------------------\n// Simulation types\n// ---------------------------------------------------------------------------\n\nexport interface SimulatePersona {\n readonly name: string;\n readonly system_prompt: string;\n readonly style: string;\n readonly temperature: number;\n readonly max_tokens?: number;\n}\n\nexport interface SimulateFaultConfig {\n readonly error_rate: number;\n readonly latency_jitter_ms: number;\n readonly content_corruption: boolean;\n readonly timeout_after_ms: number;\n}\n\nexport interface ConversationMessage {\n readonly role: string;\n readonly content: string;\n}\n\nexport interface GenerateUserMessageParams {\n readonly persona: SimulatePersona;\n readonly conversation_history: readonly ConversationMessage[];\n readonly fault_config?: SimulateFaultConfig;\n}\n\nexport interface GenerateUserMessageResult {\n readonly message: string;\n}\n","import type { ErrorData } from \"./types.js\";\nimport type { ProtocolDiagnostic } from \"./diagnostics.js\";\n\nexport class ProtocolError extends Error {\n readonly code: number;\n readonly errorMessage: string;\n readonly data: ErrorData | undefined;\n\n constructor(code: number, message: string, data?: ErrorData) {\n super(message);\n this.name = \"ProtocolError\";\n this.code = code;\n this.errorMessage = message;\n this.data = data;\n }\n}\n\nexport class EngineTimeoutError extends Error {\n readonly method: string;\n readonly timeoutMs: number;\n\n constructor(method: string, timeoutMs: number) {\n super(\n `Engine request '${method}' timed out after ${timeoutMs}ms. ` +\n \"Set ATTEST_ENGINE_TIMEOUT to increase the limit.\",\n );\n this.name = \"EngineTimeoutError\";\n this.method = method;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Raised when the reader loop detects that engine output has lost\n * framing or contains repeated unparseable lines. All in-flight requests\n * are rejected with this error so callers see a visible failure rather\n * than a hung promise.\n */\nexport class ProtocolDesyncError extends Error {\n readonly diagnostics: readonly ProtocolDiagnostic[];\n\n constructor(message: string, diagnostics: readonly ProtocolDiagnostic[]) {\n super(message);\n this.name = \"ProtocolDesyncError\";\n this.diagnostics = diagnostics;\n }\n}\n\n/**\n * The engine rejected an OTLP/JSON export (`attest-engine trace convert`). The message is\n * the engine's error, which names the offending span or field.\n */\nexport class OTLPConversionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OTLPConversionError\";\n }\n}\n","/**\n * Protocol diagnostic types for client-side observability.\n *\n * The reader loop emits diagnostics whenever it cannot route a response\n * line: malformed JSON, missing id, unknown id, or non-routable protocol\n * errors. Diagnostics are buffered in a bounded ring (32 entries) and\n * trigger a desync error when the rate exceeds the configured threshold.\n */\n\nexport type ProtocolDiagnosticKind =\n | \"malformed_json\"\n | \"non_object_response\"\n | \"invalid_jsonrpc_version\"\n | \"missing_id\"\n | \"unknown_id\"\n | \"non_routable_error\";\n\nexport interface ProtocolDiagnostic {\n readonly kind: ProtocolDiagnosticKind;\n readonly message: string;\n readonly rawLine: string;\n readonly timestampMs: number;\n}\n\nexport interface ProtocolLogger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nconst DEFAULT_BUFFER_SIZE = 32;\nconst MAX_LINE_PREVIEW = 512;\n\nexport class ProtocolDiagnosticBuffer {\n private readonly capacity: number;\n private readonly entries: ProtocolDiagnostic[] = [];\n\n constructor(capacity: number = DEFAULT_BUFFER_SIZE) {\n if (capacity <= 0) {\n throw new Error(\n `ProtocolDiagnosticBuffer capacity must be positive, got ${capacity}`,\n );\n }\n this.capacity = capacity;\n }\n\n push(diagnostic: ProtocolDiagnostic): void {\n if (this.entries.length >= this.capacity) {\n this.entries.shift();\n }\n this.entries.push(diagnostic);\n }\n\n snapshot(): readonly ProtocolDiagnostic[] {\n return this.entries.slice();\n }\n\n countWithin(windowMs: number, nowMs: number): number {\n const cutoff = nowMs - windowMs;\n let count = 0;\n for (let i = this.entries.length - 1; i >= 0; i -= 1) {\n if (this.entries[i]!.timestampMs >= cutoff) {\n count += 1;\n } else {\n break;\n }\n }\n return count;\n }\n\n clear(): void {\n this.entries.length = 0;\n }\n}\n\nexport function previewLine(line: string): string {\n if (line.length <= MAX_LINE_PREVIEW) return line;\n return line.slice(0, MAX_LINE_PREVIEW) + \"…\";\n}\n","import type { ErrorData, RPCResponse } from \"./types.js\";\nimport { ProtocolError } from \"./errors.js\";\n\n/**\n * Encode a JSON-RPC 2.0 request as an NDJSON line.\n */\nexport function encodeRequest(\n id: number,\n method: string,\n params: Record<string, unknown>,\n): string {\n const msg = {\n jsonrpc: \"2.0\" as const,\n id,\n method,\n params,\n };\n return JSON.stringify(msg) + \"\\n\";\n}\n\n/**\n * Decode a JSON-RPC 2.0 response from an NDJSON line.\n * Throws ProtocolError if the response contains an error.\n * Throws Error for malformed JSON or invalid responses.\n */\nexport function decodeResponse(line: string): RPCResponse {\n const text = line.trim();\n if (!text) {\n throw new Error(\"empty response line\");\n }\n\n let data: unknown;\n try {\n data = JSON.parse(text);\n } catch (e) {\n throw new Error(`malformed JSON response: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n if (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n throw new Error(`expected JSON object, got ${Array.isArray(data) ? \"array\" : typeof data}`);\n }\n\n const obj = data as Record<string, unknown>;\n\n if (obj.jsonrpc !== \"2.0\") {\n throw new Error(`invalid jsonrpc version: ${String(obj.jsonrpc)}`);\n }\n\n if (obj.error != null) {\n const err = obj.error as Record<string, unknown>;\n let errorData: ErrorData | undefined;\n\n if (err.data != null) {\n const raw = err.data as Record<string, unknown>;\n errorData = {\n error_type: (raw.error_type as string) ?? \"\",\n retryable: (raw.retryable as boolean) ?? false,\n detail: (raw.detail as string) ?? \"\",\n };\n }\n\n throw new ProtocolError(\n (err.code as number) ?? -1,\n (err.message as string) ?? \"unknown error\",\n errorData,\n );\n }\n\n return obj as unknown as RPCResponse;\n}\n\n/**\n * Extract the result field from a decoded response.\n */\nexport function extractResult(response: RPCResponse): unknown {\n if (response.result === undefined) {\n throw new Error(\"response missing 'result' field\");\n }\n return response.result;\n}\n\n/**\n * Extract the request ID from a decoded response.\n */\nexport function extractId(response: RPCResponse): number {\n if (response.id === undefined) {\n throw new Error(\"response missing 'id' field\");\n }\n return Number(response.id);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -321,11 +321,24 @@ interface BatchBudget {
|
|
|
321
321
|
readonly max_judge_calls?: number;
|
|
322
322
|
readonly max_cost_usd?: number;
|
|
323
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* The test an evaluate_batch call belongs to. The engine records it next to
|
|
326
|
+
* each assertion spec when ATTEST_CONTRACTS_DIR is set and uses it for
|
|
327
|
+
* nothing else.
|
|
328
|
+
*/
|
|
329
|
+
interface BatchContext {
|
|
330
|
+
readonly test_id?: string;
|
|
331
|
+
readonly file?: string;
|
|
332
|
+
/** 1-based line the test starts on. */
|
|
333
|
+
readonly line?: number;
|
|
334
|
+
}
|
|
324
335
|
interface EvaluateBatchParams {
|
|
325
336
|
readonly trace: Trace;
|
|
326
337
|
readonly assertions: readonly Assertion[];
|
|
327
338
|
/** Omitted when no per-batch budget applies. */
|
|
328
339
|
readonly budget?: BatchBudget;
|
|
340
|
+
/** Omitted outside a test. */
|
|
341
|
+
readonly context?: BatchContext;
|
|
329
342
|
}
|
|
330
343
|
/**
|
|
331
344
|
* Attest-initiated model usage (embeddings, judges, judge repeats, bias
|
|
@@ -489,4 +502,4 @@ declare function extractResult(response: RPCResponse): unknown;
|
|
|
489
502
|
declare function extractId(response: RPCResponse): number;
|
|
490
503
|
|
|
491
504
|
export { ERR_ASSERTION_ERROR, ERR_ENGINE_ERROR, ERR_INVALID_TRACE, ERR_PROVIDER_ERROR, ERR_SESSION_ERROR, ERR_TIMEOUT, EngineTimeoutError, FailureClass, OTLPConversionError, OUTCOME_FAIL, OUTCOME_PASS, OUTCOME_SKIP, ProtocolDesyncError, ProtocolDiagnosticBuffer, ProtocolError, REASON_BUDGET_EXHAUSTED, REASON_JUDGE_ABSTAINED, REASON_MISSING_EVIDENCE, REASON_PROVIDER_NOT_CONFIGURED, REASON_PROVIDER_UNAVAILABLE, REASON_REPLAY_MISS, REASON_SHORT_CIRCUITED, REASON_SIMULATION, STATUS_HARD_FAIL, STATUS_NOT_EVALUATED, STATUS_PASS, STATUS_SOFT_FAIL, STEP_AGENT_CALL, STEP_LLM_CALL, STEP_RETRIEVAL, STEP_TOOL_CALL, TYPE_CONSTRAINT, TYPE_CONTENT, TYPE_EFFECT, TYPE_EMBEDDING, TYPE_LLM_JUDGE, TYPE_PLUGIN, TYPE_SCHEMA, TYPE_TRACE, TYPE_TRACE_TREE, agentId, assertionId, decodeResponse, encodeRequest, extractId, extractResult, layerForType, previewLine, traceId };
|
|
492
|
-
export type { AgentId, Assertion, AssertionId, AssertionResult, AssertionSpec, BatchBudget, BiasProbe, ConstraintSpec, ContentSpec, ConversationMessage, DriftReport, EffectSpec, EmbeddingSpec, ErrorData, EvaluateBatchParams, EvaluateBatchResult, Exchange, GenerateUserMessageParams, GenerateUserMessageResult, Handoff, InitializeParams, InitializeResult, JudgeAgreement, JudgeMetadata, LlmJudgeSpec, Outcome, PluginSpec, ProtocolDiagnostic, ProtocolDiagnosticKind, ProtocolLogger, QueryDriftParams, QueryDriftResult, RPCError, RPCRequest, RPCResponse, SchemaSpec, ShutdownResult, SimulateFaultConfig, SimulatePersona, Step, StepError, SubmitPluginResultParams, Trace, TraceId, TraceMetadata, TraceSpec, TraceTreeSpec, Turn, Usage };
|
|
505
|
+
export type { AgentId, Assertion, AssertionId, AssertionResult, AssertionSpec, BatchBudget, BatchContext, BiasProbe, ConstraintSpec, ContentSpec, ConversationMessage, DriftReport, EffectSpec, EmbeddingSpec, ErrorData, EvaluateBatchParams, EvaluateBatchResult, Exchange, GenerateUserMessageParams, GenerateUserMessageResult, Handoff, InitializeParams, InitializeResult, JudgeAgreement, JudgeMetadata, LlmJudgeSpec, Outcome, PluginSpec, ProtocolDiagnostic, ProtocolDiagnosticKind, ProtocolLogger, QueryDriftParams, QueryDriftResult, RPCError, RPCRequest, RPCResponse, SchemaSpec, ShutdownResult, SimulateFaultConfig, SimulatePersona, Step, StepError, SubmitPluginResultParams, Trace, TraceId, TraceMetadata, TraceSpec, TraceTreeSpec, Turn, Usage };
|
package/dist/esm/cli.d.ts
CHANGED
|
@@ -21,9 +21,11 @@
|
|
|
21
21
|
declare function engineCommands(engine: string, timeoutMs?: number): Map<string, string> | null;
|
|
22
22
|
/** Map a child's exit to a shell exit status (signal N → 128 + N). */
|
|
23
23
|
declare function exitStatus(status: number | null, signal: NodeJS.Signals | null): number;
|
|
24
|
+
/** Print the engine's `help --json` document with the SDK's `init` command added. */
|
|
25
|
+
declare function helpJson(engine: string): number;
|
|
24
26
|
/** True when `attest capture` args select a mode whose fixture the CLI drafts a test for. */
|
|
25
27
|
declare function captureWritesFixture(args: string[]): boolean;
|
|
26
28
|
/** Dispatch `attest` arguments and resolve to the process exit code. */
|
|
27
29
|
declare function main(argv?: string[]): Promise<number>;
|
|
28
30
|
|
|
29
|
-
export { captureWritesFixture, engineCommands, exitStatus, main };
|
|
31
|
+
export { captureWritesFixture, engineCommands, exitStatus, helpJson, main };
|
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-rc.
|
|
12
|
-
var ENGINE_VERSION = "1.0.0-rc.
|
|
11
|
+
var VERSION = "1.0.0-rc.4";
|
|
12
|
+
var ENGINE_VERSION = "1.0.0-rc.4";
|
|
13
13
|
|
|
14
14
|
// src/engine-manager.ts
|
|
15
15
|
import { spawn, spawnSync } from "child_process";
|
|
@@ -359,28 +359,36 @@ jobs:
|
|
|
359
359
|
echo "::error::vitest failed; see the Run tests step"
|
|
360
360
|
exit 1
|
|
361
361
|
`;
|
|
362
|
-
function write(
|
|
362
|
+
function write(targetDir, rel, content, result, quiet) {
|
|
363
|
+
const file = path2.join(targetDir, ...rel.split("/"));
|
|
363
364
|
if (fs2.existsSync(file)) {
|
|
364
|
-
|
|
365
|
+
result.skipped.push(rel);
|
|
366
|
+
if (!quiet) process.stderr.write(`Skipped (exists): ${file}
|
|
365
367
|
`);
|
|
366
368
|
return;
|
|
367
369
|
}
|
|
368
370
|
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
369
371
|
fs2.writeFileSync(file, content);
|
|
370
|
-
|
|
372
|
+
result.created.push(rel);
|
|
373
|
+
if (!quiet) process.stdout.write(`Created: ${file}
|
|
371
374
|
`);
|
|
372
375
|
}
|
|
373
376
|
function scaffoldProject(targetDir, options2 = {}) {
|
|
374
|
-
|
|
375
|
-
|
|
377
|
+
const quiet = options2.quiet ?? false;
|
|
378
|
+
const result = { created: [], skipped: [] };
|
|
379
|
+
write(targetDir, "tests/my-agent.test.ts", SAMPLE_TEST_TEMPLATE, result, quiet);
|
|
380
|
+
write(targetDir, "attest.policy.yaml", POLICY_TEMPLATE, result, quiet);
|
|
376
381
|
if (options2.ci === "github") {
|
|
377
|
-
write(
|
|
382
|
+
write(targetDir, ".github/workflows/attest.yml", GITHUB_WORKFLOW_TEMPLATE, result, quiet);
|
|
378
383
|
}
|
|
379
|
-
|
|
380
|
-
|
|
384
|
+
if (!quiet) {
|
|
385
|
+
process.stdout.write(
|
|
386
|
+
`
|
|
381
387
|
Next: run \`npx vitest run\`. Then change the line marked ${DEMO_MARKER} in tests/my-agent.test.ts and run it again to see a failure.
|
|
382
388
|
`
|
|
383
|
-
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return result;
|
|
384
392
|
}
|
|
385
393
|
|
|
386
394
|
// src/capture.ts
|
|
@@ -608,23 +616,7 @@ function emitVitest(fixturePath) {
|
|
|
608
616
|
|
|
609
617
|
// src/cli.ts
|
|
610
618
|
var HELP_FLAGS = /* @__PURE__ */ new Set(["-h", "--help"]);
|
|
611
|
-
var SDK_USAGE = "usage: attest <command> [args]\n\nSDK commands:\n init [--ci github]
|
|
612
|
-
var INIT_USAGE = "usage: attest init [--ci github] (scaffolds into the current directory)";
|
|
613
|
-
function cmdInit(args) {
|
|
614
|
-
if (args.some((a) => HELP_FLAGS.has(a))) {
|
|
615
|
-
process.stdout.write(`${INIT_USAGE}
|
|
616
|
-
`);
|
|
617
|
-
return 0;
|
|
618
|
-
}
|
|
619
|
-
const joined = args.join(" ");
|
|
620
|
-
if (args.length > 0 && joined !== "--ci github" && joined !== "--ci=github") {
|
|
621
|
-
process.stderr.write(`${INIT_USAGE}
|
|
622
|
-
`);
|
|
623
|
-
return 2;
|
|
624
|
-
}
|
|
625
|
-
scaffoldProject(process.cwd(), args.length > 0 ? { ci: "github" } : {});
|
|
626
|
-
return 0;
|
|
627
|
-
}
|
|
619
|
+
var SDK_USAGE = "usage: attest <command> [args]\n\nSDK commands:\n init [--ci github] [--skills] [--mcp] [--json]\n scaffold a sample test and merge policy here\n (--ci github also writes .github/workflows/attest.yml;\n --skills installs the agent skills with attest-engine;\n --mcp writes the MCP client configs (.mcp.json, .cursor/mcp.json,\n .codex/config.toml) with attest-engine;\n --json prints {created, updated, skipped} paths as JSON)\n\n`attest capture` (engine) also drafts tests/attest/<name>.test.ts from a verified\nfixture, unless that file exists.\n\noptions:\n --version print the SDK version and the engine version it requires\n --help print this help\n";
|
|
628
620
|
var HELP_PROBE_TIMEOUT_MS = 1e4;
|
|
629
621
|
function errorMessage(err) {
|
|
630
622
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -682,24 +674,69 @@ function exitStatus(status, signal) {
|
|
|
682
674
|
if (signal !== null) return 128 + (os2.constants.signals[signal] ?? 0);
|
|
683
675
|
return 1;
|
|
684
676
|
}
|
|
685
|
-
async function
|
|
677
|
+
async function engineProviding(command) {
|
|
686
678
|
let engine;
|
|
687
679
|
try {
|
|
688
680
|
engine = await resolveEngine();
|
|
689
681
|
} catch (err) {
|
|
690
682
|
process.stderr.write(`attest: ${errorMessage(err)}
|
|
691
683
|
`);
|
|
692
|
-
return
|
|
684
|
+
return null;
|
|
693
685
|
}
|
|
694
|
-
const command = args[0] ?? "";
|
|
695
686
|
const commands = engineCommands(engine);
|
|
696
687
|
if (commands === null || command !== "help" && !commands.has(command)) {
|
|
697
688
|
process.stderr.write(
|
|
698
689
|
`attest: attest-engine at ${engine} (version ${ENGINE_VERSION}) predates \`attest ${command}\`: its help does not list that command. Set ATTEST_ENGINE_PATH to an engine built from this release (make engine), or install a release whose engine provides it.
|
|
699
690
|
`
|
|
700
691
|
);
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
return engine;
|
|
695
|
+
}
|
|
696
|
+
var INIT_HELP_ENTRY = {
|
|
697
|
+
name: "init",
|
|
698
|
+
summary: "scaffold a sample test and policy; --ci github, --skills, --mcp, --json",
|
|
699
|
+
schema: "cli/init.schema.json",
|
|
700
|
+
exit_codes: [
|
|
701
|
+
{ code: 0, meaning: "success" },
|
|
702
|
+
{
|
|
703
|
+
code: 1,
|
|
704
|
+
meaning: "--skills or --mcp could not install: the engine is missing, too old or failed"
|
|
705
|
+
},
|
|
706
|
+
{ code: 2, meaning: "usage error" }
|
|
707
|
+
]
|
|
708
|
+
};
|
|
709
|
+
function helpJson(engine) {
|
|
710
|
+
const proc = spawnSync2(engine, ["help", "--json"], {
|
|
711
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
712
|
+
encoding: "utf-8"
|
|
713
|
+
});
|
|
714
|
+
if (proc.error) throw proc.error;
|
|
715
|
+
if (proc.status !== 0) {
|
|
716
|
+
process.stderr.write(proc.stderr);
|
|
717
|
+
return exitStatus(proc.status, proc.signal);
|
|
718
|
+
}
|
|
719
|
+
let doc;
|
|
720
|
+
try {
|
|
721
|
+
doc = JSON.parse(proc.stdout);
|
|
722
|
+
if (!Array.isArray(doc.commands)) throw new Error("no commands array");
|
|
723
|
+
} catch (err) {
|
|
724
|
+
process.stderr.write(`attest: \`${engine} help --json\` printed an unexpected document: ${errorMessage(err)}
|
|
725
|
+
`);
|
|
701
726
|
return 1;
|
|
702
727
|
}
|
|
728
|
+
doc.commands = [...doc.commands, INIT_HELP_ENTRY].sort(
|
|
729
|
+
(a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0
|
|
730
|
+
);
|
|
731
|
+
process.stdout.write(`${JSON.stringify(doc, null, 2)}
|
|
732
|
+
`);
|
|
733
|
+
return 0;
|
|
734
|
+
}
|
|
735
|
+
async function forward(args) {
|
|
736
|
+
const command = args[0] ?? "";
|
|
737
|
+
const engine = await engineProviding(command);
|
|
738
|
+
if (engine === null) return 1;
|
|
739
|
+
if (args.length === 2 && command === "help" && args[1] === "--json") return helpJson(engine);
|
|
703
740
|
if (command === "capture" && captureWritesFixture(args.slice(1))) {
|
|
704
741
|
return captureAndEmit(engine, args.slice(1));
|
|
705
742
|
}
|
|
@@ -761,6 +798,167 @@ function captureAndEmit(engine, args) {
|
|
|
761
798
|
);
|
|
762
799
|
return code;
|
|
763
800
|
}
|
|
801
|
+
var INIT_USAGE = "usage: attest init [--ci github] [--skills] [--mcp] [--json] (scaffolds into the current directory)";
|
|
802
|
+
var INIT_KINDS = ["created", "updated", "skipped"];
|
|
803
|
+
var INIT_KINDS_WITH_CONFLICT = [...INIT_KINDS, "conflict"];
|
|
804
|
+
var SKILLS_KINDS = [
|
|
805
|
+
["created", "created"],
|
|
806
|
+
["updated", "updated"],
|
|
807
|
+
["unchanged", "skipped"]
|
|
808
|
+
];
|
|
809
|
+
var MCP_KINDS = [
|
|
810
|
+
["created", "created"],
|
|
811
|
+
["updated", "updated"],
|
|
812
|
+
["unchanged", "skipped"],
|
|
813
|
+
["conflict", "conflict"]
|
|
814
|
+
];
|
|
815
|
+
function parseInitArgs(args) {
|
|
816
|
+
const parsed = { ci: false, skills: false, mcp: false, json: false };
|
|
817
|
+
for (let i = 0; i < args.length; i++) {
|
|
818
|
+
const arg = args[i];
|
|
819
|
+
if (arg === "--ci" && args[i + 1] === "github" && !parsed.ci) {
|
|
820
|
+
parsed.ci = true;
|
|
821
|
+
i++;
|
|
822
|
+
} else if (arg === "--ci=github" && !parsed.ci) {
|
|
823
|
+
parsed.ci = true;
|
|
824
|
+
} else if (arg === "--skills" && !parsed.skills) {
|
|
825
|
+
parsed.skills = true;
|
|
826
|
+
} else if (arg === "--mcp" && !parsed.mcp) {
|
|
827
|
+
parsed.mcp = true;
|
|
828
|
+
} else if (arg === "--json" && !parsed.json) {
|
|
829
|
+
parsed.json = true;
|
|
830
|
+
} else {
|
|
831
|
+
return null;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return parsed;
|
|
835
|
+
}
|
|
836
|
+
function emptyInitResult() {
|
|
837
|
+
return { created: [], updated: [], skipped: [], conflict: [] };
|
|
838
|
+
}
|
|
839
|
+
function runEngineInstall(engine, subcommand, kinds, what) {
|
|
840
|
+
const argv = [...subcommand, "--json"];
|
|
841
|
+
const shown = [engine, ...argv].join(" ");
|
|
842
|
+
const proc = spawnSync2(engine, argv, {
|
|
843
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
844
|
+
encoding: "utf-8"
|
|
845
|
+
});
|
|
846
|
+
if (proc.error) throw proc.error;
|
|
847
|
+
if (proc.status !== 0) {
|
|
848
|
+
const detail = proc.stderr.trim();
|
|
849
|
+
throw new Error(
|
|
850
|
+
`${what} failed (\`${shown}\` exited ${String(exitStatus(proc.status, proc.signal))})` + (detail === "" ? "" : `: ${detail}`)
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
process.stderr.write(proc.stderr);
|
|
854
|
+
let doc;
|
|
855
|
+
try {
|
|
856
|
+
doc = JSON.parse(proc.stdout);
|
|
857
|
+
} catch (err) {
|
|
858
|
+
throw new Error(`\`${shown}\` printed invalid JSON: ${errorMessage(err)}`);
|
|
859
|
+
}
|
|
860
|
+
if (typeof doc !== "object" || doc === null || Array.isArray(doc)) {
|
|
861
|
+
throw new Error(`\`${shown}\` printed ${JSON.stringify(doc)}, not an object`);
|
|
862
|
+
}
|
|
863
|
+
const record = doc;
|
|
864
|
+
const result = emptyInitResult();
|
|
865
|
+
for (const [engineKind, initKind] of kinds) {
|
|
866
|
+
const paths = record[engineKind];
|
|
867
|
+
if (!Array.isArray(paths) || !paths.every((p) => typeof p === "string")) {
|
|
868
|
+
throw new Error(`\`${shown}\` printed no \`${engineKind}\` list of paths: ${proc.stdout}`);
|
|
869
|
+
}
|
|
870
|
+
result[initKind].push(...paths);
|
|
871
|
+
}
|
|
872
|
+
return result;
|
|
873
|
+
}
|
|
874
|
+
function installSkills(engine, root) {
|
|
875
|
+
return runEngineInstall(engine, ["skills", "install", "--dir", root], SKILLS_KINDS, "skills install");
|
|
876
|
+
}
|
|
877
|
+
function mcpLaunchCommand(root) {
|
|
878
|
+
return fs4.existsSync(path4.join(root, "pnpm-lock.yaml")) ? ["pnpm", "exec", "attest", "mcp"] : ["npx", "--no", "attest", "mcp"];
|
|
879
|
+
}
|
|
880
|
+
function installMcp(engine, root) {
|
|
881
|
+
return runEngineInstall(
|
|
882
|
+
engine,
|
|
883
|
+
["mcp", "install", "--dir", root, "--command", JSON.stringify(mcpLaunchCommand(root))],
|
|
884
|
+
MCP_KINDS,
|
|
885
|
+
"mcp install"
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
function printSkills(root, skills) {
|
|
889
|
+
const abs = (rel) => path4.join(root, ...rel.split("/"));
|
|
890
|
+
for (const rel of skills.created) process.stdout.write(`Created: ${abs(rel)}
|
|
891
|
+
`);
|
|
892
|
+
for (const rel of skills.updated) process.stdout.write(`Updated: ${abs(rel)}
|
|
893
|
+
`);
|
|
894
|
+
for (const rel of skills.skipped) process.stderr.write(`Skipped (unchanged): ${abs(rel)}
|
|
895
|
+
`);
|
|
896
|
+
for (const rel of skills.conflict) {
|
|
897
|
+
process.stderr.write(
|
|
898
|
+
`Conflict (a different attest entry, left as it is; \`attest-engine mcp install --force\` replaces it): ${abs(rel)}
|
|
899
|
+
`
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
async function runInit(parsed, root) {
|
|
904
|
+
const result = emptyInitResult();
|
|
905
|
+
const installs = [
|
|
906
|
+
[parsed.skills, "skills", installSkills],
|
|
907
|
+
[parsed.mcp, "mcp", installMcp]
|
|
908
|
+
];
|
|
909
|
+
for (const [wanted, command, install] of installs) {
|
|
910
|
+
if (!wanted) continue;
|
|
911
|
+
const engine = await engineProviding(command);
|
|
912
|
+
if (engine === null) return null;
|
|
913
|
+
let installed;
|
|
914
|
+
try {
|
|
915
|
+
installed = install(engine, root);
|
|
916
|
+
} catch (err) {
|
|
917
|
+
process.stderr.write(`attest: ${errorMessage(err)}
|
|
918
|
+
`);
|
|
919
|
+
return null;
|
|
920
|
+
}
|
|
921
|
+
if (!parsed.json) printSkills(root, installed);
|
|
922
|
+
for (const kind of INIT_KINDS_WITH_CONFLICT) result[kind].push(...installed[kind]);
|
|
923
|
+
}
|
|
924
|
+
const scaffolded = scaffoldProject(root, {
|
|
925
|
+
...parsed.ci ? { ci: "github" } : {},
|
|
926
|
+
quiet: parsed.json
|
|
927
|
+
});
|
|
928
|
+
result.created.push(...scaffolded.created);
|
|
929
|
+
result.skipped.push(...scaffolded.skipped);
|
|
930
|
+
return result;
|
|
931
|
+
}
|
|
932
|
+
async function cmdInit(args) {
|
|
933
|
+
if (args.some((a) => HELP_FLAGS.has(a))) {
|
|
934
|
+
process.stdout.write(`${INIT_USAGE}
|
|
935
|
+
`);
|
|
936
|
+
return 0;
|
|
937
|
+
}
|
|
938
|
+
const parsed = parseInitArgs(args);
|
|
939
|
+
if (parsed === null) {
|
|
940
|
+
process.stderr.write(`${INIT_USAGE}
|
|
941
|
+
`);
|
|
942
|
+
return 2;
|
|
943
|
+
}
|
|
944
|
+
const root = process.cwd();
|
|
945
|
+
if (!parsed.json) return await runInit(parsed, root) === null ? 1 : 0;
|
|
946
|
+
const stdoutWrite = process.stdout.write;
|
|
947
|
+
process.stdout.write = process.stderr.write.bind(process.stderr);
|
|
948
|
+
let result;
|
|
949
|
+
try {
|
|
950
|
+
result = await runInit(parsed, root);
|
|
951
|
+
} finally {
|
|
952
|
+
process.stdout.write = stdoutWrite;
|
|
953
|
+
}
|
|
954
|
+
if (result === null) return 1;
|
|
955
|
+
const done = result;
|
|
956
|
+
const kinds = parsed.mcp ? INIT_KINDS_WITH_CONFLICT : INIT_KINDS;
|
|
957
|
+
const sorted = Object.fromEntries(kinds.map((k) => [k, [...done[k]].sort()]));
|
|
958
|
+
process.stdout.write(`${JSON.stringify(sorted)}
|
|
959
|
+
`);
|
|
960
|
+
return 0;
|
|
961
|
+
}
|
|
764
962
|
async function main(argv = process.argv.slice(2)) {
|
|
765
963
|
const [command] = argv;
|
|
766
964
|
if (command === void 0 || HELP_FLAGS.has(command) || command === "help" && argv.length === 1) {
|
|
@@ -801,6 +999,7 @@ export {
|
|
|
801
999
|
captureWritesFixture,
|
|
802
1000
|
engineCommands,
|
|
803
1001
|
exitStatus,
|
|
1002
|
+
helpJson,
|
|
804
1003
|
main
|
|
805
1004
|
};
|
|
806
1005
|
//# sourceMappingURL=cli.js.map
|