graphlit-client
Version:
Graphlit API Client for TypeScript
245 lines (244 loc) • 8.76 kB
TypeScript
import { ConversationMessage, ConversationMessageInput, ConversationToolCall, EntityReferenceInput, ContentCriteriaInput, ToolDefinitionInput, Specification, ToolExecutionStatus } from "../generated/graphql-types.js";
import type { AgentStreamEvent } from "./ui-events.js";
export interface ArtifactCollector {
addPending(promise: Promise<{
id: string;
} | undefined>): void;
resolve(): Promise<{
id: string;
}[]>;
}
export type ToolHandler = (args: any, artifacts?: ArtifactCollector, abortSignal?: AbortSignal) => Promise<any>;
export interface ContextStrategy {
/** Max tokens for any single tool result. Results exceeding this are truncated. Default: 8192 */
toolResultTokenLimit?: number;
/** Max tool call/response rounds to keep in context. Older rounds are dropped FIFO. Default: 10 */
toolRoundLimit?: number;
/** Fraction of token budget (0.0-1.0) at which client-side windowing is triggered. Default: 0.75 */
rebudgetThreshold?: number;
}
export interface AgentOptions {
maxToolRounds?: number;
timeout?: number;
contextStrategy?: ContextStrategy;
}
export interface AgentMetrics {
totalTime: number;
llmTime?: number;
toolTime?: number;
ttft?: number;
tokensPerSecond?: number;
toolExecutions?: number;
rounds?: number;
}
export interface ContextWindowUsage {
usedTokens: number;
maxTokens: number;
percentage: number;
remainingTokens: number;
}
export type ContextManagementAction = {
type: "truncated_tool_result";
toolName: string;
originalTokens: number;
truncatedTokens: number;
} | {
type: "windowed_tool_rounds";
droppedRounds: number;
keptRounds: number;
};
export interface AgentResult {
message: string;
conversationId: string;
conversationMessage?: ConversationMessage;
toolCalls?: ConversationToolCall[];
toolResults?: ToolCallResult[];
metrics?: AgentMetrics;
usage?: UsageInfo;
contextWindow?: ContextWindowUsage;
contextActions?: ContextManagementAction[];
error?: AgentError;
}
export interface StreamAgentOptions {
maxToolRounds?: number;
abortSignal?: AbortSignal;
smoothingEnabled?: boolean;
chunkingStrategy?: "character" | "word" | "sentence";
smoothingDelay?: number;
contextStrategy?: ContextStrategy;
/** Default eligible OpenAI GPT-5.4+ models to Responses; false forces legacy Chat Completions. */
useResponsesApi?: boolean;
/** Harness-injected instructions appended to the formatted conversation (e.g. wind-down, stuck intervention). */
instructions?: string;
/** Harness-injected scratchpad text, merged with conversation scratchpad. Placed right before user-prompt. */
scratchpad?: string;
/** Skill references to inject into the agent's context window. Retrieved via querySkills, passed by reference. */
skills?: EntityReferenceInput[];
/** Stable, caller-supplied system-channel content to append after the specification system prompt. */
additionalSystemInstructions?: string;
/** Ordered fallback specifications to try for native streaming after retryable provider failures. */
fallbacks?: EntityReferenceInput[];
}
export interface ToolCallResult {
id: string;
name: string;
arguments: any;
result?: any;
error?: string;
startedAt?: string;
completedAt?: string;
durationMs?: number;
failedAt?: string;
status?: ToolExecutionStatus;
/** @deprecated Use durationMs instead. */
duration?: number;
}
export interface UsageInfo {
promptTokens: number;
completionTokens: number;
totalTokens: number;
cost?: number;
model?: string;
/** Provider-reported cached input tokens, when available. */
cachedInputTokens?: number;
/** Anthropic cache-write tokens, when available. */
cacheCreationInputTokens?: number;
/** Anthropic cache-read tokens, when available. */
cacheReadInputTokens?: number;
/** Provider-specific usage details. */
metadata?: Record<string, unknown>;
}
export interface AgentError {
message: string;
code?: string;
recoverable: boolean;
details?: Record<string, unknown>;
}
/** Terminal status of a runAgent execution. */
export type HarnessStatus = "completed" | "budget_exhausted" | "stuck" | "error" | "cancelled";
/** Per-turn data captured by the harness. */
export interface TurnResult {
turnNumber: number;
prompt: string;
responseText: string;
toolCalls: string[];
toolCallCount: number;
durationMs: number;
taskComplete?: boolean;
contextWindowUsage?: ContextWindowUsage;
contextActions?: ContextManagementAction[];
errors?: string[];
/** Token usage for this turn (from native LLM provider). */
usage?: UsageInfo;
}
/** Budget snapshot passed to the onBudgetWarning callback. */
export interface BudgetSnapshot {
turnsUsed: number;
turnsRemaining: number;
toolCallsUsed: number;
toolCallsRemaining: number;
wallClockMs: number;
wallClockMsRemaining: number;
contextWindowPercent?: number;
}
/** Result of stuck-pattern evaluation for a single turn. */
export interface StuckEvaluation {
stuck: boolean;
pattern?: string;
firstOccurrence?: boolean;
}
/** Options for the runAgent multi-turn harness. */
export interface RunAgentOptions {
conversationId?: string;
tools?: ToolDefinitionInput[];
toolHandlers?: Record<string, ToolHandler>;
persona?: EntityReferenceInput;
augmentedFilter?: ContentCriteriaInput;
maxTurns?: number;
maxWallClockMs?: number;
maxToolCalls?: number;
windDownTurns?: number;
onTurnComplete?: (turn: TurnResult) => void;
onBudgetWarning?: (snapshot: BudgetSnapshot) => void;
onStreamEvent?: (event: AgentStreamEvent) => void;
abortSignal?: AbortSignal;
contextStrategy?: ContextStrategy;
instructions?: string;
correlationId?: string;
qualityAssessment?: boolean;
qualityAssessmentSpecification?: EntityReferenceInput;
smoothingEnabled?: boolean;
chunkingStrategy?: "character" | "word" | "sentence";
smoothingDelay?: number;
useResponsesApi?: boolean;
/** Skill references to inject into the agent's context window. Retrieved via querySkills, passed by reference. */
skills?: EntityReferenceInput[];
/** Stable, caller-supplied system-channel content to append after the specification system prompt. */
additionalSystemInstructions?: string;
}
/** Quality assessment scores from LLM-as-judge post-run evaluation. */
export interface QualityAssessment {
completeness: number;
quality: number;
efficiency: number;
overall: number;
issues: string[];
}
/** Full result returned by runAgent. */
export interface RunAgentResult {
agentId: string;
conversationId: string;
status: HarnessStatus;
finalMessage: string;
turns: number;
totalToolCalls: number;
wallClockMs: number;
contextWindowAtEnd?: ContextWindowUsage;
turnResults: TurnResult[];
error?: string;
stuckPattern?: string;
qualityAssessment?: QualityAssessment;
/** Accumulated token usage across all turns (from native LLM provider). */
usage?: UsageInfo;
}
import type { ReasoningMetadata } from "./ui-events.js";
import type { TokenBudgetTracker } from "../helpers/context-management.js";
import type { UIEventAdapter } from "../streaming/ui-event-adapter.js";
/** Configuration passed to the extracted executeStreamingLoop. */
export interface StreamingLoopConfig {
conversationId: string;
specification: Specification;
messages: ConversationMessage[];
tools: ToolDefinitionInput[] | undefined;
toolHandlers: Record<string, ToolHandler> | undefined;
uiAdapter: UIEventAdapter;
budgetTracker: TokenBudgetTracker | undefined;
contextStrategy: {
toolResultTokenLimit: number;
toolRoundLimit: number;
rebudgetThreshold: number;
};
maxRounds: number;
abortSignal: AbortSignal | undefined;
useResponsesApi?: boolean;
correlationId?: string;
persona?: EntityReferenceInput;
mimeType?: string;
data?: string;
additionalSystemInstructions?: string;
fallbackSpecifications?: Specification[];
}
/** Result returned from executeStreamingLoop. */
export interface StreamingLoopResult {
fullMessage: string;
finalAssistantMessage: string;
toolCallCount: number;
toolCallNames: string[];
errors: string[];
contextWindow?: ContextWindowUsage;
contextActions: ContextManagementAction[];
reasoning?: ReasoningMetadata;
intermediateMessages: ConversationMessageInput[];
lastRoundReasoning?: ReasoningMetadata;
usedSpecification?: Specification;
}