@apo-ai/sdk 0.9.0 → 0.9.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.
@@ -822,6 +822,111 @@ type AgentHistoryPlane = {
822
822
  selfRunId?: string;
823
823
  };
824
824
 
825
+ /**
826
+ * MCP plumbing for apo's two tool planes. The judge's budgeted toolset
827
+ * (`createMcpToolset`) wraps user-declared MCP servers into `t.agent`
828
+ * sessions under the same budget ledger and evidence-manifest discipline as
829
+ * the built-in evidence tools. `connectMcpServers` is the raw connect core
830
+ * shared with adapters — the agent under test is not apo's to budget, so
831
+ * adapters merge the namespaced `mcp__<server>__<tool>` tools themselves.
832
+ *
833
+ * Judge config layers exactly like the judge model config
834
+ * (`resolveJudgeConfig`): env/file (APO_JUDGE_MCP) ← runTask({ judgeTools })
835
+ * ← task.judgeTools ← per-call `t.agent(..., { tools: { mcp } })` — most
836
+ * specific wins, arrays replace, never concat. Task-level `mcpServers`
837
+ * (adapter plane) is a separate declaration honored by adapters that choose
838
+ * to (see TaskDefinition.mcpServers).
839
+ *
840
+ * The MCP client (`@ai-sdk/mcp`) is lazy-loaded: suites that never configure
841
+ * MCP servers must never pay for the dependency (pinned by the
842
+ * lazy-isolation test in tests/judge-mcp.test.ts).
843
+ */
844
+
845
+ /** Stdio transport: the judge's machine spawns the server process. */
846
+ type McpStdioTransport = {
847
+ type: "stdio";
848
+ command: string;
849
+ args?: string[];
850
+ /**
851
+ * Environment for the spawned process. Values support `${VAR}` expansion
852
+ * from the judge process's environment at connect time; an unset variable
853
+ * is a load error, never an empty string.
854
+ */
855
+ env?: Record<string, string>;
856
+ };
857
+ /** HTTP transport: an already-running remote server (Streamable HTTP). */
858
+ type McpHttpTransport = {
859
+ type: "http";
860
+ url: string;
861
+ /** Header values support `${VAR}` expansion like stdio env values. */
862
+ headers?: Record<string, string>;
863
+ };
864
+ /** One user MCP server the judge may call. Mirrors the industry shape. */
865
+ type McpServerConfig = {
866
+ /** Unique server name; its tools are exposed as `mcp__<name>__<tool>`. */
867
+ name: string;
868
+ transport: McpStdioTransport | McpHttpTransport;
869
+ /** Allowlist of raw server tool names (applied before namespacing). */
870
+ tools?: string[];
871
+ /** Denylist applied after the allowlist. */
872
+ excludeTools?: string[];
873
+ /** Per-tool-call timeout in ms. Default 30_000. */
874
+ timeoutMs?: number;
875
+ };
876
+ /** Layered judge-tools config, sibling of `JudgeConfig`. */
877
+ type JudgeToolsConfig = {
878
+ mcp?: McpServerConfig[];
879
+ };
880
+ /**
881
+ * Expand `${VAR}` placeholders in secret-bearing string maps (stdio env,
882
+ * HTTP headers). Unset variables throw naming the variable — a missing
883
+ * credential must fail visibly at load time, never collapse to "".
884
+ */
885
+ declare function expandSecretPlaceholders(values: Record<string, string>): Record<string, string>;
886
+ /**
887
+ * Narrow, locally-owned view of an MCP client, mirroring the engine-facade
888
+ * discipline in agent-session.ts: never let tsc instantiate the library's
889
+ * generics. The real `@ai-sdk/mcp` client is structurally compatible.
890
+ */
891
+ type McpRawTool = {
892
+ description?: unknown;
893
+ inputSchema?: unknown;
894
+ execute?: unknown;
895
+ };
896
+ type McpClientLike = {
897
+ tools: () => Promise<Record<string, McpRawTool>>;
898
+ close: () => Promise<void>;
899
+ };
900
+ type McpClientFactory = (args: {
901
+ server: McpServerConfig;
902
+ timeoutMs: number;
903
+ }) => Promise<McpClientLike>;
904
+ /**
905
+ * Resolve path-like stdio values against a base directory (the task dir):
906
+ * absolute values, "./" and "../" prefixes resolve; bare names stay bare so
907
+ * the spawn resolves them from PATH. Applied to TaskDefinition.mcpServers
908
+ * by adapters AND to layered judgeTools by runTask — "./mcp/server.mjs"
909
+ * means the same thing on both planes, independent of the runner's cwd.
910
+ */
911
+ declare function resolveMcpServerPaths(servers: McpServerConfig[], baseDir: string): McpServerConfig[];
912
+ /**
913
+ * Connects one client per declared server and returns the RAW namespaced
914
+ * tools — no budget wrapping, because the agent under test is not apo's to
915
+ * budget (that discipline is judge-only, in `createMcpToolset` below).
916
+ * Adapters that drive an AI-SDK agent loop merge `tools` into their own tool
917
+ * record; `byServer` maps each server name to its exposed raw tool names.
918
+ *
919
+ * Connect failures throw naming the server after closing what already
920
+ * connected. Duplicate server names throw before anything spawns.
921
+ */
922
+ declare function connectMcpServers(servers: McpServerConfig[], opts?: {
923
+ clientFactory?: McpClientFactory;
924
+ }): Promise<{
925
+ tools: Record<string, unknown>;
926
+ byServer: Record<string, string[]>;
927
+ cleanup: () => Promise<void>;
928
+ }>;
929
+
825
930
  /**
826
931
  * The agentic judge — `t.agent`. A tool-using LLM session that investigates
827
932
  * the run's own evidence (deliverables, trace) before verdicting, powered by
@@ -856,6 +961,7 @@ type AgentJudgeOptions = {
856
961
  /** Tool families; deliverables are always on. `trace: false` drops get_trace. */
857
962
  tools?: {
858
963
  trace?: boolean;
964
+ mcp?: McpServerConfig[];
859
965
  };
860
966
  budget?: AgentBudget;
861
967
  label?: string;
@@ -1042,6 +1148,21 @@ type TaskDefinition<TAdapterName extends string = string, TDeliverable extends s
1042
1148
  * `prompt` that tells the judge what it is grading.
1043
1149
  */
1044
1150
  judge?: Partial<JudgeConfig>;
1151
+ /**
1152
+ * Task-level judge-tools layer: MCP evidence servers for `t.agent` sessions
1153
+ * in this task. Overrides `runTask({ judgeTools })`, is overridden per
1154
+ * `t.agent(..., { tools: { mcp } })` call. Arrays replace, never concat.
1155
+ */
1156
+ judgeTools?: JudgeToolsConfig;
1157
+ /**
1158
+ * MCP servers declared for the AGENT UNDER TEST (the adapter plane — a
1159
+ * separate declaration from `judgeTools`). Adapters that honor it resolve
1160
+ * relative `command`/`args` paths against the task directory and expose
1161
+ * the tools as `mcp__<server>__<tool>`; trace assertions can match those
1162
+ * stable names. Declaring the harness's tool surface here keeps the task
1163
+ * portable across harnesses.
1164
+ */
1165
+ mcpServers?: McpServerConfig[];
1045
1166
  };
1046
1167
  type TaskConfig<TDeliverable extends string = string> = Omit<TaskDefinition<string, TDeliverable>, "adapter">;
1047
1168
  type FileEntry = {
@@ -1486,6 +1607,11 @@ type RunTaskOptions = {
1486
1607
  tracing?: AgentTaskTraceOptions;
1487
1608
  /** LLM judge model config for `t.judge(...)` calls in the task checks. */
1488
1609
  judge?: JudgeConfig;
1610
+ /**
1611
+ * Judge tool config for `t.agent(...)` sessions (MCP evidence servers).
1612
+ * Layered under `TaskDefinition.judgeTools` and per-call `tools.mcp`.
1613
+ */
1614
+ judgeTools?: JudgeToolsConfig;
1489
1615
  onTurn?: (turnNumber: number, userAction: TaskTranscriptTurn["userAction"], agentResponse: unknown) => void;
1490
1616
  /**
1491
1617
  * Skip the internal `loadTask(taskDir)` call and reuse an already-loaded
@@ -1609,6 +1735,7 @@ declare function discoverAgentTaskDirs(rootDir: string): string[];
1609
1735
 
1610
1736
  type AgentTaskRuntime = {
1611
1737
  judge?: JudgeConfig;
1738
+ judgeTools?: JudgeToolsConfig;
1612
1739
  };
1613
1740
  type AgentTaskRunSummary = {
1614
1741
  taskDir: string;
@@ -1870,4 +1997,204 @@ declare function canonicalManifestJson(manifest: TaskRevisionManifestV1): string
1870
1997
  /** SHA-256 (lowercase hex) of the canonical manifest JSON's UTF-8 bytes. */
1871
1998
  declare function contentSha256(manifest: TaskRevisionManifestV1): string;
1872
1999
 
1873
- export { type AISDKResult, type AdapterDefinition, type AdapterRuntimeState, type AdapterSession, type AgentBudget, type AgentEvidence, type AgentJudgeOptions, type AgentJudgeOutcome, type AgentJudgeSession, type AgentJudgeStep, type AgentTaskCliOptions, type AgentTaskRunConfiguration, AgentTaskRunError, type AgentTaskRunSummary, type AgentTaskRuntime, AgentTaskTraceContext, AgentTaskTraceOptions, type AgentTurnResult, type AnthropicMessage, type ApoRunContext, ApoSpanProcessor, type ArtifactUploadConfig, type CheckCompaction, type CheckContext, type CheckGroup, type CleanupContext, type CollectDeliverablesContext, type CollectedDeliverables, type DeliverableDefinition, type DeliverableSummary, type DeliverableValidationResult, type DescribeRegistration, type DurationBudgetOptions, type EvidenceFingerprint, type FileArtifact, type FileArtifactOptions, type FileEntry, type Flow, type FlowEvent, FlowView, type InitializeContext, JUDGE_SEGMENT_LIMIT, type JudgeConfig, type JudgeContext, type JudgePromptBuilder, type JudgeScope, type LoadedTask, type ManifestFile, type ManifestFileInput, type Matcher, type ModeClass, type NameMatcher, type OpenAIMessage, type PreparedTaskResult, RECEIVED_VALUE_LIMIT, type RegisterApoTracingOptions, type RejudgeCheckStability, type RejudgeEndpoints, RejudgeError, type RejudgeOptions, type RejudgeOutcome, type RunTaskOptions, type StartSessionContext, TEST_METHOD_NAMES, type TaskConfig, type TaskDefinition, type TaskEvaluationResult, TaskFiles, type TaskRevisionManifestV1, type TaskRunResult, type TaskScope, type TaskTranscript, type TaskTranscriptTurn, type TestContext, type TestRegistration, type TokenBudgetOptions, type ToolCallOptions, type ToolCallStatus, type TurnContext, type TurnFn, type TurnRecord, type TypedAdapterDefinition, type ValueMatcher, buildManifest, canonicalManifestJson, compactChecksForSubmission, contentSha256, defineAdapter, defineTask, describe, discoverAgentTaskDirs, equals, fileArtifact, filePaths, fromAISDK, fromAnthropicMessages, fromOpenAIMessages, getActiveApoRun, getTaskTurn, includes, isFileArtifact, loadTask, loadTaskRuntime, matchValue, matches, normalizeManifestPath, parseAgentTaskCliArgs, persistFileArtifacts, registerApoTracing, rejudgeTaskRun, resetApoTracing, resetFlowChecks, resetTaskRegistry, resetTaskTurn, resolveTurn, runAgentTaskCli, runTask, runTaskDir, satisfies, sha256Hex, similarity, task, defineCheck as test, turn, withApoRun, withApoRunSync };
2000
+ /**
2001
+ * Normalized transcript model — the common shape every harness transcript
2002
+ * parser produces, and the input to the OTLP translator.
2003
+ *
2004
+ * The model is deliberately lossy-but-sufficient for trace reconstruction:
2005
+ * per turn it keeps the user/assistant text, thinking, tool calls with their
2006
+ * results, model identity, and token usage. Anything the projection cannot
2007
+ * use (streaming chunk boundaries, harness housekeeping) is folded away.
2008
+ */
2009
+ type TranscriptSource = "claude-code" | "codex";
2010
+ type TranscriptUsage = {
2011
+ inputTokens?: number;
2012
+ outputTokens?: number;
2013
+ cacheReadTokens?: number;
2014
+ cacheWriteTokens?: number;
2015
+ reasoningTokens?: number;
2016
+ };
2017
+ type TranscriptToolCall = {
2018
+ callId: string;
2019
+ name: string;
2020
+ /** Arguments exactly as recorded — parsed object when the harness allows, raw string otherwise. */
2021
+ input: unknown;
2022
+ /** Rendered result text or the raw output payload; absent when the transcript never recorded one. */
2023
+ result?: unknown;
2024
+ /** ISO timestamp of the call, when the transcript carries one. */
2025
+ startedAt?: string;
2026
+ /** ISO timestamp of the matching result, when the transcript carries one. */
2027
+ endedAt?: string;
2028
+ };
2029
+ type TranscriptTurn = {
2030
+ /** Zero-based position of the turn within the session. */
2031
+ index: number;
2032
+ /** ISO timestamp of the user message that opened the turn. */
2033
+ startedAt: string;
2034
+ /** ISO timestamp of the last observed event in the turn, when known. */
2035
+ endedAt?: string;
2036
+ model?: string;
2037
+ userMessage?: string;
2038
+ assistantMessage?: string;
2039
+ /** Extended-thinking text (Claude) or reasoning summaries (Codex). */
2040
+ thinkingText?: string;
2041
+ /** Codex commentary-phase messages (progress narration, not reasoning). */
2042
+ commentary?: string[];
2043
+ toolCalls: TranscriptToolCall[];
2044
+ usage?: TranscriptUsage;
2045
+ };
2046
+ type ParsedTranscriptSession = {
2047
+ source: TranscriptSource;
2048
+ sessionId: string;
2049
+ cwd?: string;
2050
+ turns: TranscriptTurn[];
2051
+ /** Non-fatal parse issues: torn lines, unterminated turns, unmatched outputs. */
2052
+ warnings: string[];
2053
+ };
2054
+
2055
+ /**
2056
+ * Claude Code session-transcript parser.
2057
+ *
2058
+ * Claude Code appends one JSON object per line to
2059
+ * ``~/.claude/projects/<project>/<session-id>.jsonl`` for every session:
2060
+ *
2061
+ * { type: "user" | "assistant", timestamp, requestId?, sessionId?, cwd?,
2062
+ * toolUseResult?, message: { id?, role, model?, usage?, stop_reason?,
2063
+ * content: string | Array<text | thinking | tool_use | tool_result> } }
2064
+ *
2065
+ * Two grouping rules do the real work:
2066
+ * - Streamed assistant chunks of one API response share ``message.id``; they
2067
+ * are one logical message, and usage is read from the most complete chunk
2068
+ * (the first chunk's snapshot undercounts the request).
2069
+ * - A user line whose content is a ``tool_result`` block array is the harness
2070
+ * feeding a tool result back to the model, not a new turn.
2071
+ */
2072
+
2073
+ declare function parseClaudeCodeTranscript(content: string): ParsedTranscriptSession;
2074
+
2075
+ /**
2076
+ * Codex CLI session-transcript parser.
2077
+ *
2078
+ * Codex writes rollout files under ``~/.codex/sessions/YYYY/MM/DD/``, one
2079
+ * JSON object per line:
2080
+ *
2081
+ * { type: "session_meta" | "turn_context" | "event_msg" | "response_item",
2082
+ * timestamp, payload }
2083
+ *
2084
+ * - ``event_msg`` payloads: ``task_started``, ``task_complete``,
2085
+ * ``user_message``, ``agent_message`` (phase ``final_answer`` |
2086
+ * ``commentary``), ``token_count`` (``info.last_token_usage``).
2087
+ * - ``response_item`` payloads: ``function_call`` / ``custom_tool_call`` and
2088
+ * their ``*_output`` counterparts (paired by ``call_id``), ``reasoning``
2089
+ * (summary text), ``web_search_call``.
2090
+ *
2091
+ * A turn is bracketed by ``task_started`` … ``task_complete``. A rollout that
2092
+ * ends mid-turn (harness killed, crash) still yields its turn — the activity
2093
+ * happened, the trace should show it — with a warning.
2094
+ */
2095
+
2096
+ declare function parseCodexTranscript(content: string): ParsedTranscriptSession;
2097
+
2098
+ /**
2099
+ * Transcript → OTLP/JSON translator.
2100
+ *
2101
+ * Converts a parsed session into exactly the span vocabulary apo's receiver
2102
+ * already normalizes best. Two rules make replayed traces indistinguishable
2103
+ * from live-OTel ones in the projection:
2104
+ *
2105
+ * 1. Every span carries an explicit ``apo.observation.type`` override — the
2106
+ * priority-1 mapper — so typing (AGENT / GENERATION / TOOL / SPAN) never
2107
+ * depends on the backend's registry guessing from attributes.
2108
+ * 2. Attributes use apo's established GenAI keys (``gen_ai.request.model``,
2109
+ * ``gen_ai.usage.*`` incl. the cache/reasoning buckets the pricing path
2110
+ * reads, ``gen_ai.tool.*``, ``gen_ai.input/output.messages``) — not a
2111
+ * replay-specific dialect.
2112
+ *
2113
+ * IDs are SHA-256-derived from the session identity, so re-exporting the same
2114
+ * transcript is idempotent: the receiver upserts on
2115
+ * ``(project_id, trace_id, span_id)``.
2116
+ */
2117
+
2118
+ type OtlpAttributeValue = {
2119
+ stringValue: string;
2120
+ } | {
2121
+ intValue: string;
2122
+ } | {
2123
+ boolValue: boolean;
2124
+ };
2125
+ type OtlpAttribute = {
2126
+ key: string;
2127
+ value: OtlpAttributeValue;
2128
+ };
2129
+ type OtlpSpan = {
2130
+ traceId: string;
2131
+ spanId: string;
2132
+ parentSpanId?: string;
2133
+ name: string;
2134
+ kind: number;
2135
+ startTimeUnixNano: string;
2136
+ endTimeUnixNano: string;
2137
+ attributes: OtlpAttribute[];
2138
+ status: {
2139
+ code: number;
2140
+ };
2141
+ };
2142
+ type OtlpTracesPayload = {
2143
+ resourceSpans: Array<{
2144
+ resource: {
2145
+ attributes: OtlpAttribute[];
2146
+ };
2147
+ scopeSpans: Array<{
2148
+ scope: {
2149
+ name: string;
2150
+ version: string;
2151
+ };
2152
+ spans: OtlpSpan[];
2153
+ }>;
2154
+ }>;
2155
+ };
2156
+ type TranscriptReplayOptions = {
2157
+ /** Trace id (32 lowercase hex). Default: deterministic from source + session id. */
2158
+ traceId?: string;
2159
+ /** Parent for the first turn's interaction span — adapter capture mode nests it under the live task.turn span. */
2160
+ parentSpanId?: string;
2161
+ /** Run list label (`apo.run.flow_name`). Default: "<source> session <id prefix>". */
2162
+ flowName?: string;
2163
+ /** Run tags (`apo.run.tags`). Default: ["transcript-replay", source]. */
2164
+ tags?: string[];
2165
+ };
2166
+ declare function transcriptSessionToOtlp(session: ParsedTranscriptSession, options?: TranscriptReplayOptions): OtlpTracesPayload;
2167
+
2168
+ /**
2169
+ * OTLP export for replayed transcripts.
2170
+ *
2171
+ * Posts an OTLP/JSON traces payload to apo's public OTLP endpoint using the
2172
+ * same auth the live exporters use. Auth mode decides what the trace becomes:
2173
+ *
2174
+ * - API key (CLI import): the trace lands as an unclaimed project run.
2175
+ * - Attempt/service token (adapter capture): the replayed spans join the live
2176
+ * task run's trace — the runner's root span already carries the claim.
2177
+ *
2178
+ * 5xx and network failures are retried; a 4xx is a caller bug (bad token,
2179
+ * malformed payload) and fails fast with the response body excerpt.
2180
+ */
2181
+
2182
+ declare class TranscriptReplayError extends Error {
2183
+ readonly status?: number;
2184
+ constructor(message: string, status?: number);
2185
+ }
2186
+ type ExportOtlpTracesOptions = {
2187
+ /** apo base URL (e.g. http://localhost:8000); a full …/v1/traces URL is accepted verbatim. */
2188
+ endpoint: string;
2189
+ /** API key or attempt token — sent as the OTLP Authorization bearer. */
2190
+ token: string;
2191
+ /** Per-request timeout. Default 30s. */
2192
+ timeoutMs?: number;
2193
+ /** Extra attempts after the first on 5xx/network failure. Default 2. */
2194
+ retries?: number;
2195
+ };
2196
+ /** Normalize an apo base URL into the public OTLP traces endpoint. */
2197
+ declare function resolveOtlpTracesUrl(base: string): string;
2198
+ declare function exportOtlpTraces(payload: OtlpTracesPayload, options: ExportOtlpTracesOptions): Promise<void>;
2199
+
2200
+ export { type AISDKResult, type AdapterDefinition, type AdapterRuntimeState, type AdapterSession, type AgentBudget, type AgentEvidence, type AgentJudgeOptions, type AgentJudgeOutcome, type AgentJudgeSession, type AgentJudgeStep, type AgentTaskCliOptions, type AgentTaskRunConfiguration, AgentTaskRunError, type AgentTaskRunSummary, type AgentTaskRuntime, AgentTaskTraceContext, AgentTaskTraceOptions, type AgentTurnResult, type AnthropicMessage, type ApoRunContext, ApoSpanProcessor, type ArtifactUploadConfig, type CheckCompaction, type CheckContext, type CheckGroup, type CleanupContext, type CollectDeliverablesContext, type CollectedDeliverables, type DeliverableDefinition, type DeliverableSummary, type DeliverableValidationResult, type DescribeRegistration, type DurationBudgetOptions, type EvidenceFingerprint, type ExportOtlpTracesOptions, type FileArtifact, type FileArtifactOptions, type FileEntry, type Flow, type FlowEvent, FlowView, type InitializeContext, JUDGE_SEGMENT_LIMIT, type JudgeConfig, type JudgeContext, type JudgePromptBuilder, type JudgeScope, type JudgeToolsConfig, type LoadedTask, type ManifestFile, type ManifestFileInput, type Matcher, type McpHttpTransport, type McpServerConfig, type McpStdioTransport, type ModeClass, type NameMatcher, type OpenAIMessage, type OtlpAttribute, type OtlpAttributeValue, type OtlpSpan, type OtlpTracesPayload, type ParsedTranscriptSession, type PreparedTaskResult, RECEIVED_VALUE_LIMIT, type RegisterApoTracingOptions, type RejudgeCheckStability, type RejudgeEndpoints, RejudgeError, type RejudgeOptions, type RejudgeOutcome, type RunTaskOptions, type StartSessionContext, TEST_METHOD_NAMES, type TaskConfig, type TaskDefinition, type TaskEvaluationResult, TaskFiles, type TaskRevisionManifestV1, type TaskRunResult, type TaskScope, type TaskTranscript, type TaskTranscriptTurn, type TestContext, type TestRegistration, type TokenBudgetOptions, type ToolCallOptions, type ToolCallStatus, TranscriptReplayError, type TranscriptReplayOptions, type TranscriptSource, type TranscriptToolCall, type TranscriptTurn, type TranscriptUsage, type TurnContext, type TurnFn, type TurnRecord, type TypedAdapterDefinition, type ValueMatcher, buildManifest, canonicalManifestJson, compactChecksForSubmission, connectMcpServers, contentSha256, defineAdapter, defineTask, describe, discoverAgentTaskDirs, equals, expandSecretPlaceholders, exportOtlpTraces, fileArtifact, filePaths, fromAISDK, fromAnthropicMessages, fromOpenAIMessages, getActiveApoRun, getTaskTurn, includes, isFileArtifact, loadTask, loadTaskRuntime, matchValue, matches, normalizeManifestPath, parseAgentTaskCliArgs, parseClaudeCodeTranscript, parseCodexTranscript, persistFileArtifacts, registerApoTracing, rejudgeTaskRun, resetApoTracing, resetFlowChecks, resetTaskRegistry, resetTaskTurn, resolveMcpServerPaths, resolveOtlpTracesUrl, resolveTurn, runAgentTaskCli, runTask, runTaskDir, satisfies, sha256Hex, similarity, task, defineCheck as test, transcriptSessionToOtlp, turn, withApoRun, withApoRunSync };