import {z} from 'zod' export type AgentTypeEnum = 'workflow' | 'react'; export type AgentSerializationEnum = 'JsonConfluent' | 'AvroConfluent'; export type AgentInputConfig = {topicPattern: string, inputSerialization?: AgentSerializationEnum | undefined, fields?: (Array | null) | undefined, createTableSQL?: (string | null) | undefined, filterSQL?: (string | null) | undefined}; export type AgentOutputSchemaTypeEnum = 'STRING' | 'DOUBLE' | 'INT32' | 'INT64' | 'BOOLEAN'; export type AgentOutputConfig = {topic: string, deadLetterTopic?: (string | null) | undefined, outputSerialization?: AgentSerializationEnum | undefined, schema?: {[key: string]: AgentOutputSchemaTypeEnum} | undefined}; export type AgentLlmProviderEnum = 'anthropic' | 'openai' | 'openai-responses' | 'ollama' | 'azure' | 'azure-openai' | 'bedrock' | 'qwen' | 'openai-compatible'; export type AgentLlmConfig = {provider: AgentLlmProviderEnum, model: string, apiKey?: string | undefined, llmConnectionId?: (string | null) | undefined, baseUrl?: (string | null) | undefined, temperature?: (number | null) | undefined, maxTokens?: (number | null) | undefined, timeout?: (number | null) | undefined, reasoningEffort?: ('none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | null) | undefined, thinkingBudgetTokens?: (number | null) | undefined, ollamaThink?: (boolean | null) | undefined, maxRetries?: (number | null) | undefined, region?: (string | null) | undefined, strict?: (boolean | null) | undefined, store?: (boolean | null) | undefined, instructions?: (string | null) | undefined, additionalKwargs?: ({[key: string]: unknown} | null) | undefined, apiVersion?: (string | null) | undefined, azureEndpoint?: (string | null) | undefined, azureUrlPathMode?: ('AUTO' | 'LEGACY' | 'UNIFIED' | null) | undefined}; export type AgentPromptConfig = {system?: string | undefined, customInstructions?: string | undefined, user?: string | undefined}; export type AgentMcpServerConfig = {projectKeyId?: (string | null) | undefined, serverUrl?: (string | null) | undefined, headers?: {[key: string]: string} | undefined}; export type AgentToolTypeEnum = 'http' | 'transform' | 'mcp'; export type AgentToolParameterConfig = {name: string, type?: string | undefined, description?: string | undefined}; export type AgentToolConfig = {name: string, type: AgentToolTypeEnum, description?: string | undefined, config?: {[key: string]: unknown} | undefined, parameters?: Array | undefined}; export type AgentShortTermMemoryConfig = {enabled?: boolean | undefined, ttlMs?: number | undefined, maxEntries?: number | undefined}; export type AgentLongTermMemoryConfig = {enabled?: boolean | undefined, vectorStoreConnectionId?: (string | null) | undefined, namespace?: (string | null) | undefined, destinationId?: (string | null) | undefined}; export type AgentMemoryConfig = {keyField?: (string | null) | undefined, shortTerm?: AgentShortTermMemoryConfig | undefined, longTerm?: AgentLongTermMemoryConfig | undefined}; export type AgentKnowledgeBaseRef = {id: string, name?: string | undefined}; export type AgentProcessingConfig = {parallelism?: number | undefined, checkpointIntervalMin?: number | undefined, maxIterations?: number | undefined, maxTokensPerHour?: number | undefined}; export type CreateAgentConfigRequest = {name: string, description?: (string | null) | undefined, enabled?: boolean | undefined, agentType?: AgentTypeEnum | undefined, input: AgentInputConfig, output: AgentOutputConfig, llm: AgentLlmConfig, prompts: AgentPromptConfig, mcpServer?: (AgentMcpServerConfig | null) | undefined, tools?: Array | undefined, memory?: (AgentMemoryConfig | null) | undefined, knowledgeBases?: Array | undefined, processing?: AgentProcessingConfig | undefined}; export type TestRunRequest = {config: CreateAgentConfigRequest, sampleRecord: {[key: string]: unknown}, agentId?: (string | null) | undefined, savedConnectionId?: (string | null) | undefined, skipTools?: boolean | undefined}; export type CreateApiAgentsTestRunArgs = {body: TestRunRequest}; export type CreateApiAgentsTestRunOptions = {baseUrl?: string | undefined, FronteggHTTPAuthentication?: string | undefined, fetch?: typeof fetch | undefined}; export const testRunStep = z.object({kind: z.enum(["llm", "tool"]), model: z.string().nullable().optional(), tokensIn: z.number().int().nullable().optional(), tokensOut: z.number().int().nullable().optional(), stopReason: z.string().nullable().optional(), text: z.string().nullable().optional(), toolCalls: z.array(z.record(z.string(), z.unknown())).nullable().optional(), toolName: z.string().nullable().optional(), toolType: z.string().nullable().optional(), request: z.record(z.string(), z.unknown()).nullable().optional(), result: z.record(z.string(), z.unknown()).nullable().optional(), skipped: z.boolean().nullable().optional(), skippedReason: z.string().nullable().optional(), durationMs: z.number().int().nullable().optional(), error: z.string().nullable().optional()}); export const testRunSuggestion = z.object({kind: z.enum(["missing_output_schema", "tools_not_invoked", "near_empty_response", "skip_instruction_may_apply", "max_tokens_truncated"]), message: z.string()}); export const testRunWarning = z.object({kind: z.enum(["memory_key_field_missing", "input_fields_not_in_record", "max_tokens_clamped"]), message: z.string()}); export const testRunSchemaTypeMismatch = z.object({field: z.string(), expected: z.string(), actual: z.string()}); export const testRunSchemaCheck = z.object({ok: z.boolean(), missing: z.array(z.string()).optional(), extra: z.array(z.string()).optional(), typeMismatches: z.array(testRunSchemaTypeMismatch).optional()}); export const testRunError = z.object({kind: z.string(), message: z.string()}); export const testRunResponse = z.object({steps: z.array(testRunStep), finalOutput: z.unknown(), stoppedReason: z.enum(["completed", "max_iterations", "error", "timeout"]), iterationsUsed: z.number().int(), tokensIn: z.number().int(), tokensOut: z.number().int(), durationMs: z.number().int(), approximations: z.array(z.string()).optional(), suggestions: z.array(testRunSuggestion).optional(), warnings: z.array(testRunWarning).optional(), outputSchemaCheck: testRunSchemaCheck.nullable().optional(), systemPrompt: z.string().nullable().optional(), userMessage: z.string().nullable().optional(), error: testRunError.nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Test Run Agent * * POST /agents/test-run */ export const createApiAgentsTestRun = async (args: CreateApiAgentsTestRunArgs, options?: CreateApiAgentsTestRunOptions) => { const {baseUrl = "https://api.streamkap.com", fetch: fetchFn = fetch, FronteggHTTPAuthentication} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (FronteggHTTPAuthentication !== undefined) headers.set('authorization', `Bearer ${FronteggHTTPAuthentication}`) const url = `${baseUrl.replace(/\/+$/, '')}/agents/test-run${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(testRunResponse, await res.json()) };