@linxiraos/pi-agent-core 1.1.8 → 1.1.9
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/CHANGELOG.md +4 -6
- package/package.json +73 -79
- package/src/agent-loop.ts +80 -15
- package/src/compaction/compaction-v2-streaming.ts +43 -32
- package/src/compaction/compaction.ts +88 -17
- package/src/compaction/openai.ts +3 -0
- package/src/telemetry.ts +2 -2
- package/src/types.ts +34 -7
- package/THIRD-PARTY-NOTICES.txt +0 -22909
- package/dist/types/agent-loop.d.ts +0 -150
- package/dist/types/agent.d.ts +0 -472
- package/dist/types/append-only-context.d.ts +0 -131
- package/dist/types/compaction/branch-summarization.d.ts +0 -102
- package/dist/types/compaction/compaction-v2-streaming.d.ts +0 -85
- package/dist/types/compaction/compaction.d.ts +0 -341
- package/dist/types/compaction/entries.d.ts +0 -120
- package/dist/types/compaction/errors.d.ts +0 -38
- package/dist/types/compaction/index.d.ts +0 -14
- package/dist/types/compaction/message-cache.d.ts +0 -25
- package/dist/types/compaction/messages.d.ts +0 -103
- package/dist/types/compaction/openai.d.ts +0 -118
- package/dist/types/compaction/pruning.d.ts +0 -106
- package/dist/types/compaction/shake.d.ts +0 -104
- package/dist/types/compaction/tool-protection.d.ts +0 -19
- package/dist/types/compaction/transcript-tokens.d.ts +0 -76
- package/dist/types/compaction/utils.d.ts +0 -63
- package/dist/types/compaction.d.ts +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/pause.d.ts +0 -46
- package/dist/types/proxy.d.ts +0 -91
- package/dist/types/replay-policy.d.ts +0 -5
- package/dist/types/run-collector.d.ts +0 -196
- package/dist/types/telemetry.d.ts +0 -625
- package/dist/types/thinking.d.ts +0 -18
- package/dist/types/tokenizer.d.ts +0 -78
- package/dist/types/types.d.ts +0 -786
- package/dist/types/utils/yield.d.ts +0 -71
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider-anchored transcript token accounting.
|
|
3
|
-
*
|
|
4
|
-
* Local tokenization is the expensive way to answer "how big is this
|
|
5
|
-
* conversation?" — and usually the wrong one, because the provider already
|
|
6
|
-
* answered it. Every settled assistant turn carries `usage` covering the exact
|
|
7
|
-
* prompt it was sent: the system prompt, the tool schemas, and every message up
|
|
8
|
-
* to and including itself. The only genuinely unaccounted-for text is the tail
|
|
9
|
-
* appended *after* that turn.
|
|
10
|
-
*
|
|
11
|
-
* These helpers locate the newest trustworthy usage report and tokenize only
|
|
12
|
-
* that tail, so a long session pays counting proportional to one turn instead
|
|
13
|
-
* of to the whole transcript, every turn.
|
|
14
|
-
*
|
|
15
|
-
* Trust rules for an anchor (mirroring the provider contract):
|
|
16
|
-
* - Assistant role only — nothing else carries `usage`.
|
|
17
|
-
* - Not `aborted` / `error`: those turns report partial or zero usage.
|
|
18
|
-
* - `hasContextTokenUsage(usage)`: the report must carry usable context numbers.
|
|
19
|
-
*/
|
|
20
|
-
import type { AssistantMessage } from "@linxiraos/pi-ai";
|
|
21
|
-
import type { Tokenizer } from "../tokenizer.js";
|
|
22
|
-
import type { AgentMessage } from "../types.js";
|
|
23
|
-
/** A provider usage report that accounts for a prefix of the transcript. */
|
|
24
|
-
export interface TranscriptUsageAnchor {
|
|
25
|
-
/** Index in the scanned array; messages at or before it are provider-accounted. */
|
|
26
|
-
index: number;
|
|
27
|
-
/** The anchoring assistant turn. */
|
|
28
|
-
message: AssistantMessage;
|
|
29
|
-
/** Conversation tokens the provider reported for that prompt. */
|
|
30
|
-
tokens: number;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Whether this message's provider usage may anchor transcript accounting.
|
|
34
|
-
*
|
|
35
|
-
* The single home for the trust rules — every anchor scan MUST route through
|
|
36
|
-
* it so a stale-usage rule can never drift between the transcript walkers and
|
|
37
|
-
* the session-entry walkers.
|
|
38
|
-
*/
|
|
39
|
-
export declare function isTranscriptUsageAnchor(message: AgentMessage): message is AssistantMessage;
|
|
40
|
-
/**
|
|
41
|
-
* Newest assistant turn in `messages[fromIndex..]` whose usage can anchor the
|
|
42
|
-
* transcript, or `undefined` when none qualifies (fresh context, or every
|
|
43
|
-
* recent turn aborted/errored).
|
|
44
|
-
*
|
|
45
|
-
* `fromIndex` excludes turns whose usage is stale — anything a compaction
|
|
46
|
-
* summarized away describes a prompt that is no longer sent.
|
|
47
|
-
*/
|
|
48
|
-
export declare function findTranscriptUsageAnchor(messages: readonly AgentMessage[], fromIndex?: number): TranscriptUsageAnchor | undefined;
|
|
49
|
-
/** Options for {@link estimateTranscriptTokens}. */
|
|
50
|
-
export interface TranscriptTokenOptions {
|
|
51
|
-
/**
|
|
52
|
-
* Gates the anchor search only: usage at or before this index is stale (a
|
|
53
|
-
* compaction rewrote the prompt it describes) and must not anchor. Content
|
|
54
|
-
* accounting is governed separately by {@link countFromIndex}.
|
|
55
|
-
*/
|
|
56
|
-
anchorFromIndex?: number;
|
|
57
|
-
/**
|
|
58
|
-
* First message whose content is counted locally when no anchor is found.
|
|
59
|
-
* Defaults to 0 (count the whole transcript), which is what a floor
|
|
60
|
-
* estimate wants; pass the compaction boundary to skip summarized-away
|
|
61
|
-
* messages entirely.
|
|
62
|
-
*/
|
|
63
|
-
countFromIndex?: number;
|
|
64
|
-
/** Forwarded to {@link Tokenizer.countMessage} for every locally counted message. */
|
|
65
|
-
excludeEncryptedReasoning?: boolean;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Conversation tokens for `messages`: the provider's own report for everything
|
|
69
|
-
* it already covers, plus a local count of only the unaccounted-for tail.
|
|
70
|
-
*
|
|
71
|
-
* An anchored result already includes the non-message prefix (system prompt +
|
|
72
|
-
* tool schemas) because the provider charged it; an unanchored result is a
|
|
73
|
-
* message-only sum. Callers that add non-message tokens on top MUST branch on
|
|
74
|
-
* {@link findTranscriptUsageAnchor} rather than assuming one shape.
|
|
75
|
-
*/
|
|
76
|
-
export declare function estimateTranscriptTokens(messages: readonly AgentMessage[], tokenizer: Tokenizer, options?: TranscriptTokenOptions): number;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared utilities for compaction and branch summarization.
|
|
3
|
-
*/
|
|
4
|
-
import type { Message } from "@linxiraos/pi-ai";
|
|
5
|
-
import { type Dialect } from "@linxiraos/pi-ai/dialect";
|
|
6
|
-
import type { AgentMessage } from "../types.js";
|
|
7
|
-
export interface FileOperations {
|
|
8
|
-
read: Set<string>;
|
|
9
|
-
written: Set<string>;
|
|
10
|
-
edited: Set<string>;
|
|
11
|
-
}
|
|
12
|
-
export declare function createFileOps(): FileOperations;
|
|
13
|
-
/**
|
|
14
|
-
* Split a read-tool path into its base path and trailing selector, mirroring the
|
|
15
|
-
* read tool's own splitter. Single source of the grammar in this package: the
|
|
16
|
-
* file-operations list strips selectors via {@link stripReadSelector}, and the
|
|
17
|
-
* supersede-prune pass keys on both parts via `readToolSupersedeKey`.
|
|
18
|
-
*/
|
|
19
|
-
export declare function splitReadSelector(path: string): {
|
|
20
|
-
path: string;
|
|
21
|
-
sel?: string;
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Strip a trailing read-tool selector (`:50-200`, `:raw`, `:1-50:raw`, `:conflicts`, …)
|
|
25
|
-
* so the same file read with different line ranges dedupes to one `<files>` entry
|
|
26
|
-
* and matches its write/edit path when computing Read/Write/RW markers.
|
|
27
|
-
*/
|
|
28
|
-
export declare function stripReadSelector(path: string): string;
|
|
29
|
-
/**
|
|
30
|
-
* Whether `path` references a `scheme://` URL (internal URI or web URL) rather
|
|
31
|
-
* than a filesystem path that belongs in the compaction `<files>` summary.
|
|
32
|
-
*/
|
|
33
|
-
export declare function isUrlSchemePath(path: string): boolean;
|
|
34
|
-
/**
|
|
35
|
-
* Extract file operations from tool calls in an assistant message.
|
|
36
|
-
*/
|
|
37
|
-
export declare function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void;
|
|
38
|
-
/**
|
|
39
|
-
* Compute final file lists from file operations.
|
|
40
|
-
* Returns readFiles (files only read, not modified) and modifiedFiles.
|
|
41
|
-
*/
|
|
42
|
-
export declare function computeFileLists(fileOps: FileOperations): {
|
|
43
|
-
readFiles: string[];
|
|
44
|
-
modifiedFiles: string[];
|
|
45
|
-
};
|
|
46
|
-
export declare function formatFileOperations(readFiles: string[], modifiedFiles: string[], readSet?: ReadonlySet<string>): string;
|
|
47
|
-
export declare function upsertFileOperations(summary: string, readFiles: string[], modifiedFiles: string[], readSet?: ReadonlySet<string>): string;
|
|
48
|
-
/**
|
|
49
|
-
* Truncate tool results to the same representation used in summarization prompts.
|
|
50
|
-
*/
|
|
51
|
-
export declare function truncateToolResultForSummary(text: string): string;
|
|
52
|
-
/** Keep untrusted summary input from closing or impersonating harness-owned boundaries. */
|
|
53
|
-
export declare function escapeSummaryBoundaryTags(text: string): string;
|
|
54
|
-
/**
|
|
55
|
-
* Serialize LLM messages as plain summary input without provider control tokens.
|
|
56
|
-
*/
|
|
57
|
-
export declare function serializeConversationForSummary(messages: Message[], dialect?: Dialect): string;
|
|
58
|
-
/**
|
|
59
|
-
* Serialize LLM messages to transcript text.
|
|
60
|
-
* Call convertToLlm() first to handle custom message types.
|
|
61
|
-
*/
|
|
62
|
-
export declare function serializeConversation(messages: Message[], dialect?: Dialect): string;
|
|
63
|
-
export declare const SUMMARIZATION_SYSTEM_PROMPT: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./compaction/index.js";
|
package/dist/types/index.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export * from "./agent.js";
|
|
2
|
-
export * from "./agent-loop.js";
|
|
3
|
-
export * from "./append-only-context.js";
|
|
4
|
-
export * from "./compaction.js";
|
|
5
|
-
export * from "./pause.js";
|
|
6
|
-
export * from "./proxy.js";
|
|
7
|
-
export * from "./replay-policy.js";
|
|
8
|
-
export * from "./run-collector.js";
|
|
9
|
-
export * from "./telemetry.js";
|
|
10
|
-
export * from "./thinking.js";
|
|
11
|
-
export * from "./tokenizer.js";
|
|
12
|
-
export * from "./types.js";
|
|
13
|
-
export * from "./utils/yield.js";
|
package/dist/types/pause.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Process-global pause gate for agent loops.
|
|
3
|
-
*
|
|
4
|
-
* Every agent in a process — main session, in-process subagents, advisor —
|
|
5
|
-
* funnels through {@link ../agent-loop!agentLoop}, which polls this gate at its
|
|
6
|
-
* two action boundaries: before each model call and before each tool call
|
|
7
|
-
* starts. Engaging the gate therefore freezes all of them at the next safe
|
|
8
|
-
* point without aborting anything: in-flight provider streams and
|
|
9
|
-
* already-started tool executions run to completion, then every loop parks
|
|
10
|
-
* until {@link AgentPauseGate.resume}. Queued steering/follow-up messages stay
|
|
11
|
-
* queued and deliver normally after resume.
|
|
12
|
-
*
|
|
13
|
-
* A run's own `AbortSignal` still unwinds a parked loop immediately: the park
|
|
14
|
-
* releases on abort (without releasing the gate), so cancelling one run never
|
|
15
|
-
* requires resuming the whole process.
|
|
16
|
-
*
|
|
17
|
-
* Hosts drive the singleton {@link agentPauseGate} (e.g. the TUI `/pause`
|
|
18
|
-
* command); library code only ever reads it.
|
|
19
|
-
*/
|
|
20
|
-
/** Listener invoked with the new state on every pause/resume transition. */
|
|
21
|
-
export type AgentPauseListener = (paused: boolean) => void;
|
|
22
|
-
/** Freeze switch shared by every agent loop in the process. See module docs. */
|
|
23
|
-
export declare class AgentPauseGate {
|
|
24
|
-
#private;
|
|
25
|
-
/** True while the gate is engaged. */
|
|
26
|
-
get paused(): boolean;
|
|
27
|
-
/** Epoch ms when the current pause began; undefined when running. */
|
|
28
|
-
get pausedAt(): number | undefined;
|
|
29
|
-
/** Engage the gate. Returns false (and does nothing) when already paused. */
|
|
30
|
-
pause(): boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Release the gate, waking every parked loop. Returns the pause duration in
|
|
33
|
-
* ms, or undefined when the gate was not engaged.
|
|
34
|
-
*/
|
|
35
|
-
resume(): number | undefined;
|
|
36
|
-
/** Subscribe to pause/resume transitions. Returns an unsubscribe function. */
|
|
37
|
-
onChange(listener: AgentPauseListener): () => void;
|
|
38
|
-
/**
|
|
39
|
-
* Park until the gate is released. Resolves immediately when not paused.
|
|
40
|
-
* An abort on `signal` releases only this wait — the gate stays engaged —
|
|
41
|
-
* so a cancelled run unwinds while the rest of the process stays frozen.
|
|
42
|
-
*/
|
|
43
|
-
waitUntilResumed(signal?: AbortSignal): Promise<void>;
|
|
44
|
-
}
|
|
45
|
-
/** The process-wide gate polled by the agent loop. */
|
|
46
|
-
export declare const agentPauseGate: AgentPauseGate;
|
package/dist/types/proxy.d.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Proxy stream function for apps that route LLM calls through a server.
|
|
3
|
-
* The server manages auth and proxies requests to LLM providers.
|
|
4
|
-
*/
|
|
5
|
-
import { type AssistantMessage, type AssistantMessageEvent, type Context, EventStream, type FetchImpl, type ImageContent, type Model, type SimpleStreamOptions, type StopReason } from "@linxiraos/pi-ai";
|
|
6
|
-
export declare class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
|
7
|
-
constructor();
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Proxy event types - server sends these with partial field stripped to reduce bandwidth.
|
|
11
|
-
*/
|
|
12
|
-
export type ProxyAssistantMessageEvent = {
|
|
13
|
-
type: "start";
|
|
14
|
-
} | {
|
|
15
|
-
type: "text_start";
|
|
16
|
-
contentIndex: number;
|
|
17
|
-
} | {
|
|
18
|
-
type: "text_delta";
|
|
19
|
-
contentIndex: number;
|
|
20
|
-
delta: string;
|
|
21
|
-
} | {
|
|
22
|
-
type: "text_end";
|
|
23
|
-
contentIndex: number;
|
|
24
|
-
contentSignature?: string;
|
|
25
|
-
} | {
|
|
26
|
-
type: "thinking_start";
|
|
27
|
-
contentIndex: number;
|
|
28
|
-
} | {
|
|
29
|
-
type: "thinking_delta";
|
|
30
|
-
contentIndex: number;
|
|
31
|
-
delta: string;
|
|
32
|
-
} | {
|
|
33
|
-
type: "thinking_end";
|
|
34
|
-
contentIndex: number;
|
|
35
|
-
contentSignature?: string;
|
|
36
|
-
} | {
|
|
37
|
-
type: "image_end";
|
|
38
|
-
contentIndex: number;
|
|
39
|
-
content: ImageContent;
|
|
40
|
-
} | {
|
|
41
|
-
type: "toolcall_start";
|
|
42
|
-
contentIndex: number;
|
|
43
|
-
id: string;
|
|
44
|
-
toolName: string;
|
|
45
|
-
} | {
|
|
46
|
-
type: "toolcall_delta";
|
|
47
|
-
contentIndex: number;
|
|
48
|
-
delta: string;
|
|
49
|
-
} | {
|
|
50
|
-
type: "toolcall_end";
|
|
51
|
-
contentIndex: number;
|
|
52
|
-
} | {
|
|
53
|
-
type: "done";
|
|
54
|
-
reason: Extract<StopReason, "stop" | "length" | "toolUse">;
|
|
55
|
-
usage: AssistantMessage["usage"];
|
|
56
|
-
content?: AssistantMessage["content"];
|
|
57
|
-
} | {
|
|
58
|
-
type: "error";
|
|
59
|
-
reason: Extract<StopReason, "aborted" | "error">;
|
|
60
|
-
errorMessage?: string;
|
|
61
|
-
usage: AssistantMessage["usage"];
|
|
62
|
-
content?: AssistantMessage["content"];
|
|
63
|
-
};
|
|
64
|
-
export interface ProxyStreamOptions extends SimpleStreamOptions {
|
|
65
|
-
/** Auth token for the proxy server */
|
|
66
|
-
authToken: string;
|
|
67
|
-
/** Proxy server URL (e.g., "https://genai.example.com") */
|
|
68
|
-
proxyUrl: string;
|
|
69
|
-
/** Optional fetch implementation; defaults to global fetch. */
|
|
70
|
-
fetch?: FetchImpl;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Stream function that proxies through a server instead of calling LLM providers directly.
|
|
74
|
-
* The server strips the partial field from delta events to reduce bandwidth.
|
|
75
|
-
* We reconstruct the partial message client-side.
|
|
76
|
-
*
|
|
77
|
-
* Use this as the `streamFn` option when creating an Agent that needs to go through a proxy.
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* ```typescript
|
|
81
|
-
* const agent = new Agent({
|
|
82
|
-
* streamFn: (model, context, options) =>
|
|
83
|
-
* streamProxy(model, context, {
|
|
84
|
-
* ...options,
|
|
85
|
-
* authToken: await getAuthToken(),
|
|
86
|
-
* proxyUrl: "https://genai.example.com",
|
|
87
|
-
* }),
|
|
88
|
-
* });
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
export declare function streamProxy(model: Model, context: Context, options: ProxyStreamOptions): ProxyMessageEventStream;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { AssistantMessage, Message } from "@linxiraos/pi-ai";
|
|
2
|
-
/** Detects API-level provider refusals that are terminal errors, not dialogue to replay. */
|
|
3
|
-
export declare function isProviderRefusalMessage(message: AssistantMessage): boolean;
|
|
4
|
-
/** Removes API-level provider refusals from live provider replay while preserving other messages. */
|
|
5
|
-
export declare function filterProviderReplayMessages(messages: readonly Message[]): Message[];
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-invocation run aggregator. Buffers per-chat and per-tool records as the
|
|
3
|
-
* loop executes and folds them into a single {@link AgentRunSummary} +
|
|
4
|
-
* {@link AgentRunCoverage} value at the end.
|
|
5
|
-
*
|
|
6
|
-
* One collector lives on each {@link AgentTelemetry} handle, which is
|
|
7
|
-
* constructed once per `agentLoop` invocation in {@link resolveTelemetry}.
|
|
8
|
-
* Collector lookups use the live `Span` as a `WeakMap` key — bounded memory,
|
|
9
|
-
* no cross-invoke leakage.
|
|
10
|
-
*
|
|
11
|
-
* The collector is fed exclusively by helpers in `./telemetry.ts`. Loop
|
|
12
|
-
* authors do not interact with it directly except via the public
|
|
13
|
-
* `recordSkippedTool` helper used for the two skip paths that bypass spans
|
|
14
|
-
* entirely (pre-run interrupt and the tail-sweep for tool calls that never
|
|
15
|
-
* produced a result message).
|
|
16
|
-
*/
|
|
17
|
-
import type { AssistantMessage, Model, StopReason } from "@linxiraos/pi-ai";
|
|
18
|
-
import type { Span } from "@opentelemetry/api";
|
|
19
|
-
/** Terminal status reported by an `execute_tool` span. */
|
|
20
|
-
export type ToolStatus = "ok" | "error" | "skipped" | "blocked" | "timeout" | "aborted";
|
|
21
|
-
/** Raw record for a single `chat` step, finalized by `finishChatSpan`. */
|
|
22
|
-
export interface ChatRecord {
|
|
23
|
-
readonly stepNumber: number;
|
|
24
|
-
readonly model: string;
|
|
25
|
-
readonly provider: string;
|
|
26
|
-
readonly stopReason: StopReason | undefined;
|
|
27
|
-
readonly latencyMs: number;
|
|
28
|
-
readonly inputTokens: number;
|
|
29
|
-
readonly outputTokens: number;
|
|
30
|
-
readonly cachedInputTokens: number;
|
|
31
|
-
readonly cacheWriteTokens: number;
|
|
32
|
-
readonly reasoningOutputTokens: number;
|
|
33
|
-
readonly totalTokens: number;
|
|
34
|
-
readonly costUsd: number | undefined;
|
|
35
|
-
readonly costUnavailableReason: string | undefined;
|
|
36
|
-
readonly errorType: string | undefined;
|
|
37
|
-
}
|
|
38
|
-
/** Raw record for a single `execute_tool` invocation. */
|
|
39
|
-
export interface ToolRecord {
|
|
40
|
-
readonly toolCallId: string;
|
|
41
|
-
readonly toolName: string;
|
|
42
|
-
readonly status: ToolStatus;
|
|
43
|
-
readonly latencyMs: number;
|
|
44
|
-
readonly errorType: string | undefined;
|
|
45
|
-
}
|
|
46
|
-
/** Per-tool counters surfaced under {@link AgentRunSummary.tools.byName}. */
|
|
47
|
-
export interface ToolCounters {
|
|
48
|
-
readonly total: number;
|
|
49
|
-
readonly ok: number;
|
|
50
|
-
readonly error: number;
|
|
51
|
-
readonly skipped: number;
|
|
52
|
-
readonly blocked: number;
|
|
53
|
-
readonly timeout: number;
|
|
54
|
-
readonly aborted: number;
|
|
55
|
-
readonly totalLatencyMs: number;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Run-level rollup returned in the `agent_end` event and passed to
|
|
59
|
-
* {@link AgentTelemetryConfig.onRunEnd}. Pure aggregation — no references to
|
|
60
|
-
* spans, no callbacks, no live state. Safe to persist / diff / assert.
|
|
61
|
-
*/
|
|
62
|
-
export interface AgentRunSummary {
|
|
63
|
-
readonly chats: {
|
|
64
|
-
readonly total: number;
|
|
65
|
-
/** Bucketed by raw {@link StopReason}; absent reasons omitted. */
|
|
66
|
-
readonly byStopReason: Readonly<Record<string, number>>;
|
|
67
|
-
readonly totalLatencyMs: number;
|
|
68
|
-
};
|
|
69
|
-
readonly tools: {
|
|
70
|
-
readonly total: number;
|
|
71
|
-
readonly ok: number;
|
|
72
|
-
readonly error: number;
|
|
73
|
-
readonly skipped: number;
|
|
74
|
-
readonly blocked: number;
|
|
75
|
-
readonly timeout: number;
|
|
76
|
-
readonly aborted: number;
|
|
77
|
-
readonly totalLatencyMs: number;
|
|
78
|
-
/** Per-tool-name counters; keys sorted by name on snapshot. */
|
|
79
|
-
readonly byName: Readonly<Record<string, ToolCounters>>;
|
|
80
|
-
};
|
|
81
|
-
readonly usage: {
|
|
82
|
-
readonly inputTokens: number;
|
|
83
|
-
readonly outputTokens: number;
|
|
84
|
-
readonly cachedInputTokens: number;
|
|
85
|
-
readonly cacheWriteTokens: number;
|
|
86
|
-
readonly reasoningOutputTokens: number;
|
|
87
|
-
readonly totalTokens: number;
|
|
88
|
-
};
|
|
89
|
-
readonly cost: {
|
|
90
|
-
readonly estimatedUsd: number;
|
|
91
|
-
/** Sorted, deduped. */
|
|
92
|
-
readonly unavailableReasons: readonly string[];
|
|
93
|
-
};
|
|
94
|
-
readonly errors: {
|
|
95
|
-
readonly total: number;
|
|
96
|
-
readonly byType: Readonly<Record<string, number>>;
|
|
97
|
-
};
|
|
98
|
-
readonly stepCount: number;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Coverage rollup: registered-vs-invoked across the run. All arrays are
|
|
102
|
-
* sorted ascending and deduped so the value is stable for diffing.
|
|
103
|
-
*/
|
|
104
|
-
export interface AgentRunCoverage {
|
|
105
|
-
readonly toolsAvailable: readonly string[];
|
|
106
|
-
readonly toolsInvoked: readonly string[];
|
|
107
|
-
readonly toolsUnused: readonly string[];
|
|
108
|
-
readonly modelsUsed: readonly string[];
|
|
109
|
-
readonly providersUsed: readonly string[];
|
|
110
|
-
}
|
|
111
|
-
export declare class AgentRunCollector {
|
|
112
|
-
#private;
|
|
113
|
-
/** True once `markRunEnded()` has been called for this invocation. */
|
|
114
|
-
get runEnded(): boolean;
|
|
115
|
-
/**
|
|
116
|
-
* Mark this run as logically ended. Callers use this to coordinate the
|
|
117
|
-
* `onRunEnd` hook between the success path (fires inside
|
|
118
|
-
* `buildAgentEndEvent`, before `stream.end()`) and the error path (fires
|
|
119
|
-
* inside `finishInvokeAgentSpan`'s finally). Idempotent — returns `true`
|
|
120
|
-
* the first time, `false` on subsequent calls.
|
|
121
|
-
*/
|
|
122
|
-
markRunEnded(): boolean;
|
|
123
|
-
/** Record the tool names exposed on a single chat step. */
|
|
124
|
-
noteAvailableTools(tools: readonly {
|
|
125
|
-
readonly name: string;
|
|
126
|
-
}[] | undefined): void;
|
|
127
|
-
beginChat(span: Span, init: {
|
|
128
|
-
readonly stepNumber: number;
|
|
129
|
-
readonly model: Model;
|
|
130
|
-
readonly provider?: string;
|
|
131
|
-
}): void;
|
|
132
|
-
endChat(span: Span, message: AssistantMessage, fields: {
|
|
133
|
-
readonly costUsd: number | undefined;
|
|
134
|
-
readonly costUnavailableReason: string | undefined;
|
|
135
|
-
}): void;
|
|
136
|
-
/**
|
|
137
|
-
* Stamp the chat span as failed without a finalized AssistantMessage. Used
|
|
138
|
-
* by the `catch` arm of `streamAssistantResponse` so error chats still
|
|
139
|
-
* appear in the run summary.
|
|
140
|
-
*/
|
|
141
|
-
failChat(span: Span, fields: {
|
|
142
|
-
readonly errorType: string;
|
|
143
|
-
}): void;
|
|
144
|
-
beginTool(span: Span, init: {
|
|
145
|
-
readonly toolCallId: string;
|
|
146
|
-
readonly toolName: string;
|
|
147
|
-
}): void;
|
|
148
|
-
endTool(span: Span, fields: {
|
|
149
|
-
readonly status: ToolStatus;
|
|
150
|
-
readonly errorType: string | undefined;
|
|
151
|
-
}): void;
|
|
152
|
-
/**
|
|
153
|
-
* Record a tool that never produced a span — pre-run interrupt or tail
|
|
154
|
-
* sweep. The LLM still asked for it, so it counts toward
|
|
155
|
-
* {@link AgentRunCoverage.toolsInvoked}.
|
|
156
|
-
*/
|
|
157
|
-
recordOrphanTool(record: {
|
|
158
|
-
readonly toolCallId: string;
|
|
159
|
-
readonly toolName: string;
|
|
160
|
-
readonly status: ToolStatus;
|
|
161
|
-
}): void;
|
|
162
|
-
/** Build the immutable summary value from buffered records. */
|
|
163
|
-
snapshot(opts: {
|
|
164
|
-
readonly stepCount: number;
|
|
165
|
-
}): {
|
|
166
|
-
readonly summary: AgentRunSummary;
|
|
167
|
-
readonly coverage: AgentRunCoverage;
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Fold multiple per-run summaries into one. Pure aggregation — useful when a
|
|
172
|
-
* caller (verify pass, benchmark harness) drives the agent loop N times and
|
|
173
|
-
* needs a single rollup across all invocations.
|
|
174
|
-
*
|
|
175
|
-
* Counters sum element-wise. Sets (cost reasons, error types, per-tool
|
|
176
|
-
* counters) merge by key. Numeric totals sum. The output is in the same
|
|
177
|
-
* shape as a single `AgentRunSummary`, so all dashboards and persistence
|
|
178
|
-
* layers handle it uniformly.
|
|
179
|
-
*/
|
|
180
|
-
export declare function aggregateAgentRunSummaries(summaries: readonly AgentRunSummary[]): AgentRunSummary;
|
|
181
|
-
/** Union-merge multiple coverage values, preserving the sorted+deduped invariant. */
|
|
182
|
-
export declare function aggregateAgentRunCoverage(coverages: readonly AgentRunCoverage[]): AgentRunCoverage;
|
|
183
|
-
/** Empty `AgentRunSummary` constant. Exported for tests and default-initializers. */
|
|
184
|
-
export declare function emptyAgentRunSummary(): AgentRunSummary;
|
|
185
|
-
/** Empty `AgentRunCoverage` constant. Exported for tests and default-initializers. */
|
|
186
|
-
export declare function emptyAgentRunCoverage(): AgentRunCoverage;
|
|
187
|
-
/**
|
|
188
|
-
* Distinguishable error class thrown when `beforeToolCall` returns
|
|
189
|
-
* `{ block: true }`. Lets the catch arm of `runTool` set the terminal status
|
|
190
|
-
* on the execute_tool span to `"blocked"` instead of conflating with a real
|
|
191
|
-
* tool exception.
|
|
192
|
-
*/
|
|
193
|
-
export declare class ToolCallBlockedError extends Error {
|
|
194
|
-
readonly name = "ToolCallBlockedError";
|
|
195
|
-
constructor(reason?: string);
|
|
196
|
-
}
|