import { type KeyValueStorage, type StandardSchemaV1, type StreamStorage, type VectorStorage, type SandboxService, type QueueService, type EmailService, type ScheduleService, type TaskStorage, type InferInput, type InferOutput } from '@agentuity/core';
import { type Tracer } from '@opentelemetry/api';
import type { Context, MiddlewareHandler } from 'hono';
import type { Handler } from 'hono/types';
import { AGENT_RUNTIME } from './_config';
import type { Logger } from './logger';
import type { Eval, EvalFunction } from './eval';
import type { Thread, Session } from './session';
import type { AppState } from './index';
export type AgentEventName = 'started' | 'completed' | 'errored';
export type AgentEventCallback<TAgent extends Agent<any, any, any>> = ((eventName: 'started', agent: TAgent, context: AgentContext<any, any, any>) => Promise<void> | void) | ((eventName: 'completed', agent: TAgent, context: AgentContext<any, any, any>) => Promise<void> | void) | ((eventName: 'errored', agent: TAgent, context: AgentContext<any, any, any>, data: Error) => Promise<void> | void);
/**
 * Runtime state container for agents and event listeners.
 * Isolates global state into context for better testing.
 */
export interface AgentRuntimeState {
    agents: Map<string, Agent<any, any, any, any, any>>;
    agentConfigs: Map<string, unknown>;
    agentEventListeners: WeakMap<Agent<any, any, any, any, any>, Map<AgentEventName, Set<AgentEventCallback<any>>>>;
}
/**
 * Context object passed to every agent handler providing access to runtime services and state.
 *
 * @template TAgentRegistry - Registry of all available agents (auto-generated, strongly-typed)
 * @template TConfig - Agent-specific configuration type from setup function
 * @template TAppState - Application-wide state type from createApp
 *
 * @example
 * ```typescript
 * const agent = createAgent('my-agent', {
 *   handler: async (ctx, input) => {
 *     // Logging
 *     ctx.logger.info('Processing request', { input });
 *
 *     // Call another agent (import it directly)
 *     import otherAgent from './other-agent';
 *     const result = await otherAgent.run({ data: input });
 *
 *     // Store data
 *     await ctx.kv.set('key', { value: result });
 *
 *     // Access config from setup
 *     const cache = ctx.config.cache;
 *
 *     // Background task
 *     ctx.waitUntil(async () => {
 *       await ctx.logger.info('Cleanup complete');
 *     });
 *
 *     return result;
 *   }
 * });
 * ```
 */
export interface AgentContext<_TAgentRegistry extends AgentRegistry = AgentRegistry, TConfig = unknown, TAppState = Record<string, never>> {
    /**
     * Internal runtime state (agents, configs, event listeners).
     * Stored with Symbol key to prevent accidental access.
     * Use getAgentRuntime(ctx) to access.
     * @internal
     */
    [AGENT_RUNTIME]: AgentRuntimeState;
    /**
     * Schedule a background task that continues after the response is sent.
     * Useful for cleanup, logging, or async operations that don't block the response.
     *
     * @param promise - Promise or function that returns void or Promise<void>
     *
     * @example
     * ```typescript
     * ctx.waitUntil(async () => {
     *   await ctx.kv.set('processed', Date.now());
     *   ctx.logger.info('Background task complete');
     * });
     * ```
     */
    waitUntil: (promise: Promise<void> | (() => void | Promise<void>)) => void;
    /**
     * Structured logger with OpenTelemetry integration.
     * Logs are automatically correlated with traces.
     *
     * @example
     * ```typescript
     * ctx.logger.info('Processing started', { userId: input.id });
     * ctx.logger.warn('Rate limit approaching', { remaining: 10 });
     * ctx.logger.error('Operation failed', { error: err.message });
     * ```
     */
    logger: Logger;
    /**
     * Unique session identifier for this request. Consistent across agent calls in the same session.
     */
    sessionId: string;
    /**
     * OpenTelemetry tracer for creating custom spans and tracking performance.
     *
     * @example
     * ```typescript
     * const span = ctx.tracer.startSpan('database-query');
     * try {
     *   const result = await database.query();
     *   span.setStatus({ code: SpanStatusCode.OK });
     *   return result;
     * } finally {
     *   span.end();
     * }
     * ```
     */
    tracer: Tracer;
    /**
     * Key-value storage for simple data persistence.
     *
     * @example
     * ```typescript
     * await ctx.kv.set('user:123', { name: 'Alice', age: 30 });
     * const user = await ctx.kv.get('user:123');
     * await ctx.kv.delete('user:123');
     * const keys = await ctx.kv.list('user:*');
     * ```
     */
    kv: KeyValueStorage;
    /**
     * Stream storage for real-time data streams and logs.
     *
     * @example
     * ```typescript
     * const stream = await ctx.stream.create('agent-logs');
     * await ctx.stream.write(stream.id, 'Processing step 1');
     * await ctx.stream.write(stream.id, 'Processing step 2');
     * ```
     */
    stream: StreamStorage;
    /**
     * Vector storage for embeddings and similarity search.
     *
     * @example
     * ```typescript
     * await ctx.vector.upsert('docs', [
     *   { id: '1', values: [0.1, 0.2, 0.3], metadata: { text: 'Hello' } }
     * ]);
     * const results = await ctx.vector.query('docs', [0.1, 0.2, 0.3], { topK: 5 });
     * ```
     */
    vector: VectorStorage;
    /**
     * Sandbox service for creating and running isolated code execution environments.
     *
     * @example
     * ```typescript
     * // One-shot execution
     * const result = await ctx.sandbox.run({
     *   command: {
     *     exec: ['bun', 'run', 'index.ts'],
     *     files: [{ path: 'index.ts', content: Buffer.from('console.log("hello")') }]
     *   }
     * });
     * console.log('Exit:', result.exitCode);
     *
     * // Interactive sandbox
     * const sandbox = await ctx.sandbox.create({
     *   resources: { memory: '1Gi', cpu: '1000m' }
     * });
     * await sandbox.execute({ command: ['bun', 'init'] });
     * await sandbox.execute({ command: ['bun', 'add', 'zod'] });
     * await sandbox.destroy();
     * ```
     */
    sandbox: SandboxService;
    /**
     * Queue service for publishing messages to queues.
     *
     * @example
     * ```typescript
     * const result = await ctx.queue.publish('my-queue', { event: 'user.created', userId: '123' });
     * console.log('Message ID:', result.id);
     * ```
     */
    queue: QueueService;
    /**
     * Email service for managing email addresses, destinations, and sending/receiving emails.
     *
     * @example
     * ```typescript
     * // Create an email address
     * const address = await ctx.email.createAddress('support');
     *
     * // Send an email
     * const result = await ctx.email.send({
     *   from: address.email,
     *   to: ['user@example.com'],
     *   subject: 'Hello!',
     *   text: 'Welcome to our platform.',
     * });
     *
     * // List inbound emails
     * const inbound = await ctx.email.listInbound(address.id);
     * ```
     */
    email: EmailService;
    /**
     * Schedule service for managing cron-based scheduled tasks with
     * destinations and delivery tracking.
     *
     * @see https://agentuity.dev/services/schedule
     */
    schedule: ScheduleService;
    /**
     * Task service for agent-driven issue tracking.
     *
     * @example
     * ```typescript
     * const task = await ctx.task.create({
     *   title: 'Investigate API error',
     *   type: 'bug',
     *   created_id: ctx.current.id,
     * });
     * await ctx.task.update(task.id, { status: 'in_progress' });
     * ```
     */
    task: TaskStorage;
    /**
     * In-memory state storage scoped to the current request.
     * Use for passing data between middleware and handlers.
     *
     * @example
     * ```typescript
     * ctx.state.set('startTime', Date.now());
     * const duration = Date.now() - (ctx.state.get('startTime') as number);
     * ```
     */
    state: Map<string, unknown>;
    /**
     * Thread information for multi-turn conversations.
     */
    thread: Thread;
    /**
     * Session information for the current request.
     */
    session: Session;
    /**
     * Agent-specific configuration returned from the setup function.
     * Type is inferred from your setup function's return value.
     *
     * @example
     * ```typescript
     * createAgent({
     *   setup: async () => ({ cache: new Map(), db: await connectDB() }),
     *   handler: async (ctx, input) => {
     *     ctx.config.cache.set('key', 'value'); // Strongly typed!
     *     await ctx.config.db.query('SELECT * FROM users');
     *   }
     * });
     * ```
     */
    config: TConfig;
    /**
     * Application-wide state returned from createApp setup function.
     * Shared across all agents in the application.
     *
     * @example
     * ```typescript
     * const app = createApp({
     *   setup: async () => ({ db: await connectDB(), redis: await connectRedis() })
     * });
     *
     * // Later in any agent:
     * handler: async (ctx, input) => {
     *   await ctx.app.db.query('SELECT 1');
     *   await ctx.app.redis.set('key', 'value');
     * }
     * ```
     */
    app: TAppState;
    /**
     * Metadata about the currently executing agent.
     * Provides access to the agent's id, name, and other properties.
     *
     * @example
     * ```typescript
     * handler: async (ctx, input) => {
     *   // Use agent ID for namespaced state keys
     *   const stateKey = `${ctx.current.id}_counter`;
     *   await ctx.thread.state.set(stateKey, value);
     *
     *   // Log agent info
     *   ctx.logger.info('Running agent', { name: ctx.current.name });
     * }
     * ```
     */
    current: AgentMetadata;
    /**
     * Authentication context when request is authenticated.
     * Available when auth middleware is configured on the Hono app.
     *
     * Will be `null` for:
     * - Unauthenticated requests
     * - Cron jobs
     * - Agent-to-agent calls without auth propagation
     *
     * @example
     * ```typescript
     * handler: async (ctx, input) => {
     *   if (!ctx.auth) {
     *     return { error: 'Please sign in' };
     *   }
     *
     *   // Access user info
     *   const user = await ctx.auth.getUser();
     *   ctx.logger.info(`Request from ${user.email}`);
     *
     *   // Check organization role
     *   if (await ctx.auth.hasOrgRole('admin')) {
     *     // Admin-only logic
     *   }
     *
     *   return { userId: user.id };
     * }
     * ```
     */
    auth: import('@agentuity/core').AuthInterface | null;
}
type InternalAgentMetadata = {
    /**
     * the unique name for the agent (user-provided).
     */
    name: string;
    /**
     * the unique identifier for this project, agent and deployment.
     */
    id: string;
    /**
     * the unique identifier for this agent across multiple deployments
     */
    agentId: string;
    /**
     * the relative path to the agent from the root project directory.
     */
    filename: string;
    /**
     * a unique version for the agent. computed as the SHA256 contents of the file.
     */
    version: string;
    /**
     * the source code for the input schema.
     */
    inputSchemaCode?: string;
    /**
     * the source code for the output schema.
     */
    outputSchemaCode?: string;
};
type ExternalAgentMetadata = {
    /**
     * the human readable description for the agent
     */
    description?: string;
};
export type AgentMetadata = InternalAgentMetadata & ExternalAgentMetadata;
/**
 * Configuration object for creating an agent evaluation function.
 *
 * @template TInput - Input schema type from the agent
 * @template TOutput - Output schema type from the agent
 */
export interface CreateEvalConfig<TInput extends StandardSchemaV1 | undefined = any, TOutput extends StandardSchemaV1 | undefined = any> {
    /**
     * Optional description of what this evaluation does.
     *
     * @example
     * ```typescript
     * description: 'Ensures output is greater than zero'
     * ```
     */
    description?: string;
    /**
     * Evaluation handler function that tests the agent's behavior.
     * Return true if the evaluation passes, false if it fails.
     *
     * @param run - Evaluation run context containing input and metadata
     * @param result - The output from the agent handler
     * @returns Boolean indicating pass/fail, or evaluation result object
     *
     * @example
     * ```typescript
     * handler: async (run, result) => {
     *   // Assert that output is positive
     *   if (result <= 0) {
     *     return false; // Evaluation failed
     *   }
     *   return true; // Evaluation passed
     * }
     * ```
     *
     * @example
     * ```typescript
     * // With detailed result
     * handler: async (run, result) => {
     *   const passed = result.length > 5;
     *   return {
     *     passed,
     *     score: passed ? 1.0 : 0.0,
     *     message: passed ? 'Output length is valid' : 'Output too short'
     *   };
     * }
     * ```
     */
    handler: EvalFunction<TInput extends StandardSchemaV1 ? InferOutput<TInput> : undefined, TOutput extends StandardSchemaV1 ? InferOutput<TOutput> : undefined>;
}
export type PresetEvalConfig<TInput extends StandardSchemaV1 | undefined = any, TOutput extends StandardSchemaV1 | undefined = any> = CreateEvalConfig<TInput, TOutput> & {
    name: string;
};
type CreateEvalMethod<TInput extends StandardSchemaV1 | undefined = any, TOutput extends StandardSchemaV1 | undefined = any> = {
    (config: PresetEvalConfig<TInput, TOutput>): Eval<TInput, TOutput>;
    (name: string, config: CreateEvalConfig<TInput, TOutput>): Eval<TInput, TOutput>;
};
/**
 * Validator function type with method overloads for different validation scenarios.
 * Provides type-safe validation middleware that integrates with Hono's type system.
 *
 * This validator automatically validates incoming JSON request bodies using StandardSchema-compatible
 * schemas (Zod, Valibot, ArkType, etc.) and provides full TypeScript type inference for validated data
 * accessible via `c.req.valid('json')`.
 *
 * The validator returns 400 Bad Request with validation error details if validation fails.
 *
 * @template TInput - Agent's input schema type (StandardSchemaV1 or undefined)
 * @template _TOutput - Agent's output schema type (reserved for future output validation)
 *
 * @example Basic usage with agent's schema
 * ```typescript
 * router.post('/', agent.validator(), async (c) => {
 *   const data = c.req.valid('json'); // Fully typed from agent's input schema
 *   return c.json(data);
 * });
 * ```
 *
 * @example Override with custom input schema
 * ```typescript
 * router.post('/custom', agent.validator({ input: z.object({ id: z.string() }) }), async (c) => {
 *   const data = c.req.valid('json'); // Typed as { id: string }
 *   return c.json(data);
 * });
 * ```
 */
export interface AgentValidator<TInput extends StandardSchemaV1 | undefined, _TOutput extends StandardSchemaV1 | undefined> {
    /**
     * Validates using the agent's input schema (no override).
     * Returns Hono middleware handler that validates JSON request body.
     *
     * @returns Middleware handler with type inference for validated data
     *
     * @example
     * ```typescript
     * // Agent has schema: { input: z.object({ name: z.string() }) }
     * router.post('/', agent.validator(), async (c) => {
     *   const data = c.req.valid('json'); // { name: string }
     *   return c.json({ received: data.name });
     * });
     * ```
     */
    (): TInput extends StandardSchemaV1 ? Handler<any, any, {
        in: {};
        out: {
            json: InferInput<TInput>;
        };
    }> : Handler<any, any, any>;
    /**
     * Output-only validation override.
     * Validates only the response body (no input validation).
     *
     * Useful for GET routes or routes where input validation is handled elsewhere.
     * The middleware validates the JSON response body and throws 500 Internal Server Error
     * if validation fails.
     *
     * @template TOverrideOutput - Custom output schema type
     * @param override - Object containing output schema
     * @returns Middleware handler that validates response output
     *
     * @example GET route with output validation
     * ```typescript
     * router.get('/', agent.validator({ output: z.array(z.object({ id: z.string() })) }), async (c) => {
     *   // Returns array of objects - validated against schema
     *   return c.json([{ id: '123' }, { id: '456' }]);
     * });
     * ```
     */
    <TOverrideOutput extends StandardSchemaV1>(override: {
        output: TOverrideOutput;
    }): Handler<any, any, {
        in: {};
        out: {
            json: InferOutput<TOverrideOutput>;
        };
    }>;
    /**
     * Validates with custom input and optional output schemas (POST/PUT/PATCH/DELETE).
     * Overrides the agent's schema for this specific route.
     *
     * @template TOverrideInput - Custom input schema type
     * @template TOverrideOutput - Optional custom output schema type
     * @param override - Object containing input (required) and output (optional) schemas
     * @returns Middleware handler with type inference from custom schemas
     *
     * @example Custom input schema
     * ```typescript
     * router.post('/users', agent.validator({
     *   input: z.object({ email: z.string().email(), name: z.string() })
     * }), async (c) => {
     *   const data = c.req.valid('json'); // { email: string, name: string }
     *   return c.json({ id: '123', ...data });
     * });
     * ```
     *
     * @example Custom input and output schemas
     * ```typescript
     * router.post('/convert', agent.validator({
     *   input: z.string(),
     *   output: z.number()
     * }), async (c) => {
     *   const data = c.req.valid('json'); // string
     *   return c.json(123);
     * });
     * ```
     */
    <TOverrideInput extends StandardSchemaV1, TOverrideOutput extends StandardSchemaV1 | undefined = undefined>(override: {
        input: TOverrideInput;
        output?: TOverrideOutput;
    }): Handler<any, any, {
        in: {};
        out: {
            json: InferInput<TOverrideInput>;
        };
    }>;
}
/**
 * Agent instance type returned by createAgent().
 * Represents a fully configured agent with metadata, handler, lifecycle hooks, and event listeners.
 *
 * @template TInput - Input schema type (StandardSchemaV1 or undefined)
 * @template TOutput - Output schema type (StandardSchemaV1 or undefined)
 * @template TStream - Whether the agent returns a stream (true/false)
 * @template TConfig - Agent-specific configuration type from setup function
 * @template TAppState - Application state type from createApp
 *
 * @example
 * ```typescript
 * const agent = createAgent({
 *   metadata: { name: 'My Agent' },
 *   schema: { input: z.string(), output: z.number() },
 *   handler: async (ctx, input) => input.length
 * });
 *
 * // Access agent properties
 * console.log(agent.metadata.name); // "My Agent"
 *
 * // Add event listeners
 * agent.addEventListener('started', (eventName, agent, ctx) => {
 *   console.log('Agent started:', ctx.sessionId);
 * });
 *
 * // Create evals for testing
 * const eval1 = agent.createEval('check-positive', {
 *   description: 'Ensures result is greater than 5',
 *   handler: async (run, result) => {
 *     return result > 5; // Assert output is greater than 5
 *   }
 * });
 * ```
 */
export type Agent<TInput extends StandardSchemaV1 | undefined = any, TOutput extends StandardSchemaV1 | undefined = any, TStream extends boolean = false, TConfig = unknown, TAppState = Record<string, never>> = {
    /**
     * Agent metadata including name, description, id, version, and filename.
     */
    metadata: AgentMetadata;
    /**
     * The main handler function that processes agent requests.
     * Gets AgentContext from AsyncLocalStorage, receives validated input, returns output or stream.
     */
    handler: (...args: any[]) => any | Promise<any>;
    /**
     * Creates a type-safe validation middleware for routes using StandardSchema validation.
     *
     * This method validates incoming JSON request bodies against the agent's **input schema**
     * and optionally validates outgoing JSON responses against the **output schema**.
     * Provides full TypeScript type inference for validated input data accessible via `c.req.valid('json')`.
     *
     * **Validation behavior:**
     * - **Input**: Validates request JSON body, returns 400 Bad Request on failure
     * - **Output**: Validates response JSON body (if output schema provided), throws 500 on failure
     * - Passes validated input data to handler via `c.req.valid('json')`
     * - Full TypeScript type inference for validated input data
     *
     * **Supported schema libraries:**
     * - Zod (z.object, z.string, etc.)
     * - Valibot (v.object, v.string, etc.)
     * - ArkType (type({ ... }))
     * - Any StandardSchema-compatible library
     *
     * **Method overloads:**
     * - `agent.validator()` - Validates using agent's input/output schemas
     * - `agent.validator({ output: schema })` - Output-only validation (no input validation)
     * - `agent.validator({ input: schema })` - Custom input schema override (skips agent's output validation)
     * - `agent.validator({ input: schema, output: schema })` - Both input and output validated
     *
     * @returns Hono middleware handler with proper type inference
     *
     * @example Automatic validation using agent's schema
     * ```typescript
     * // Agent defined with: schema: { input: z.object({ name: z.string(), age: z.number() }) }
     * router.post('/', agent.validator(), async (c) => {
     *   const data = c.req.valid('json'); // Fully typed: { name: string, age: number }
     *   return c.json({ greeting: `Hello ${data.name}, age ${data.age}` });
     * });
     * ```
     *
     * @example Override with custom schema per-route
     * ```typescript
     * router.post('/email', agent.validator({
     *   input: z.object({ email: z.string().email() })
     * }), async (c) => {
     *   const data = c.req.valid('json'); // Typed as { email: string }
     *   return c.json({ sent: data.email });
     * });
     * ```
     *
     * @example Works with any StandardSchema library
     * ```typescript
     * import * as v from 'valibot';
     *
     * router.post('/valibot', agent.validator({
     *   input: v.object({ count: v.number() })
     * }), async (c) => {
     *   const data = c.req.valid('json'); // Typed correctly
     *   return c.json({ count: data.count });
     * });
     * ```
     *
     * @example Validation error response (400)
     * ```typescript
     * // Request: { "name": "Bob" } (missing 'age')
     * // Response: {
     * //   "error": "Validation failed",
     * //   "message": "age: Invalid input: expected number, received undefined",
     * //   "issues": [{ "message": "...", "path": ["age"] }]
     * // }
     * ```
     */
    validator: AgentValidator<TInput, TOutput>;
    /**
     * Array of evaluation functions created via agent.createEval().
     * Used for testing and validating agent behavior.
     */
    evals?: Eval[];
    /**
     * Create an evaluation function for testing this agent.
     * Evals can assert correctness of agent input/output during test runs.
     *
     * @param config - Eval configuration
     * @param config.metadata - Optional eval metadata (name, description)
     * @param config.handler - Eval handler function receiving run context and result
     *
     * @example
     * ```typescript
     * const agent = createAgent({
     *   schema: { input: z.string(), output: z.number() },
     *   handler: async (ctx, input) => input.length
     * });
     *
     * // Create eval to validate output
     * agent.createEval('check-positive', {
     *   description: 'Ensures output is a positive number',
     *   handler: async (run, result) => {
     *     return result > 0; // Assert output is positive
     *   }
     * });
     * ```
     */
    createEval: CreateEvalMethod<TInput, TOutput>;
    /**
     * Optional setup function called once when app starts.
     * Returns agent-specific configuration available via ctx.config.
     */
    setup?: (app: TAppState) => Promise<TConfig> | TConfig;
    /**
     * Optional shutdown function called when app stops.
     * Receives app state and agent config for cleanup.
     */
    shutdown?: (app: TAppState, config: TConfig) => Promise<void> | void;
    /**
     * Register an event listener for when the agent starts execution.
     *
     * @param eventName - Must be 'started'
     * @param callback - Function called when agent execution begins
     *
     * @example
     * ```typescript
     * agent.addEventListener('started', (eventName, agent, ctx) => {
     *   console.log(`${agent.metadata.name} started at ${new Date()}`);
     * });
     * ```
     */
    addEventListener(eventName: 'started', callback: (eventName: 'started', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>) => Promise<void> | void): void;
    /**
     * Register an event listener for when the agent completes successfully.
     *
     * @param eventName - Must be 'completed'
     * @param callback - Function called when agent execution completes
     *
     * @example
     * ```typescript
     * agent.addEventListener('completed', (eventName, agent, ctx) => {
     *   console.log(`${agent.metadata.name} completed successfully`);
     * });
     * ```
     */
    addEventListener(eventName: 'completed', callback: (eventName: 'completed', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>) => Promise<void> | void): void;
    /**
     * Register an event listener for when the agent throws an error.
     *
     * @param eventName - Must be 'errored'
     * @param callback - Function called when agent execution fails
     *
     * @example
     * ```typescript
     * agent.addEventListener('errored', (eventName, agent, ctx, error) => {
     *   console.error(`${agent.metadata.name} failed:`, error.message);
     * });
     * ```
     */
    addEventListener(eventName: 'errored', callback: (eventName: 'errored', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>, data: Error) => Promise<void> | void): void;
    /**
     * Remove a previously registered 'started' event listener.
     *
     * @param eventName - Must be 'started'
     * @param callback - The callback function to remove
     */
    removeEventListener(eventName: 'started', callback: (eventName: 'started', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>) => Promise<void> | void): void;
    /**
     * Remove a previously registered 'completed' event listener.
     *
     * @param eventName - Must be 'completed'
     * @param callback - The callback function to remove
     */
    removeEventListener(eventName: 'completed', callback: (eventName: 'completed', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>) => Promise<void> | void): void;
    /**
     * Remove a previously registered 'errored' event listener.
     *
     * @param eventName - Must be 'errored'
     * @param callback - The callback function to remove
     */
    removeEventListener(eventName: 'errored', callback: (eventName: 'errored', agent: Agent<TInput, TOutput, TStream, TConfig, TAppState>, context: AgentContext<any, TConfig, TAppState>, data: Error) => Promise<void> | void): void;
} & (TInput extends StandardSchemaV1 ? {
    inputSchema: TInput;
} : {
    inputSchema?: never;
}) & (TOutput extends StandardSchemaV1 ? {
    outputSchema: TOutput;
} : {
    outputSchema?: never;
}) & (TStream extends true ? {
    stream: true;
} : {
    stream?: false;
});
type InferSchemaInput<T> = T extends StandardSchemaV1 ? InferOutput<T> : never;
type InferStreamOutput<TOutput, TStream extends boolean> = TStream extends true ? TOutput extends StandardSchemaV1 ? ReadableStream<InferOutput<TOutput>> : ReadableStream<unknown> : TOutput extends StandardSchemaV1 ? InferOutput<TOutput> : void;
type SchemaInput<TSchema> = TSchema extends {
    input: infer I;
} ? I : undefined;
type SchemaOutput<TSchema> = TSchema extends {
    output: infer O;
} ? O : undefined;
type SchemaStream<TSchema> = TSchema extends {
    stream: infer S;
} ? S extends boolean ? S : false : false;
type SchemaHandlerReturn<TSchema> = SchemaStream<TSchema> extends true ? SchemaOutput<TSchema> extends StandardSchemaV1 ? ReadableStream<InferOutput<SchemaOutput<TSchema>>> : ReadableStream<unknown> : SchemaOutput<TSchema> extends StandardSchemaV1 ? InferOutput<SchemaOutput<TSchema>> : void;
type AgentHandlerFromConfig<TSchema, TSetupReturn, TAppState = AppState> = SchemaInput<TSchema> extends infer I ? I extends StandardSchemaV1 ? (ctx: AgentContext<any, TSetupReturn, TAppState>, input: InferOutput<I>) => Promise<SchemaHandlerReturn<TSchema>> | SchemaHandlerReturn<TSchema> : (ctx: AgentContext<any, TSetupReturn, TAppState>) => Promise<SchemaHandlerReturn<TSchema>> | SchemaHandlerReturn<TSchema> : (ctx: AgentContext<any, TSetupReturn, TAppState>) => Promise<SchemaHandlerReturn<TSchema>> | SchemaHandlerReturn<TSchema>;
/**
 * Configuration object for creating an agent with automatic type inference.
 *
 * Passed as the second parameter to createAgent(name, config).
 *
 * @template TSchema - Schema definition object containing optional input, output, and stream properties
 * @template TConfig - Function type that returns agent-specific configuration from setup
 *
 * @example
 * ```typescript
 * const agent = createAgent('greeting', {
 *   description: 'Generates personalized greetings',
 *   schema: {
 *     input: z.object({ name: z.string(), age: z.number() }),
 *     output: z.string()
 *   },
 *   handler: async (ctx, { name, age }) => {
 *     return `Hello, ${name}! You are ${age} years old.`;
 *   }
 * });
 * ```
 */
export interface CreateAgentConfig<TSchema extends {
    input?: StandardSchemaV1;
    output?: StandardSchemaV1;
    stream?: boolean;
} | undefined = undefined, TConfig extends (app: AppState) => any = any> {
    /**
     * Optional schema validation using Zod or any StandardSchemaV1 compatible library.
     *
     * @example
     * ```typescript
     * schema: {
     *   input: z.object({ name: z.string(), age: z.number() }),
     *   output: z.string(),
     *   stream: false
     * }
     * ```
     */
    schema?: TSchema;
    /**
     * Optional description of what this agent does, visible in the Agentuity platform.
     *
     * @example
     * ```typescript
     * description: 'Returns personalized greetings'
     * ```
     */
    description?: string;
    /**
     * Optional metadata object (typically injected by build plugin during compilation).
     * Contains agent identification and versioning information.
     *
     * @internal - Usually populated by build tooling, not manually set
     */
    metadata?: Partial<AgentMetadata>;
    /**
     * Optional async function called once on app startup to initialize agent-specific resources.
     * The returned value is available in the handler via `ctx.config`.
     *
     * @param app - Application state from createApp setup function
     * @returns Agent-specific configuration object
     *
     * @example
     * ```typescript
     * setup: async (app) => {
     *   const cache = new Map();
     *   const db = await connectDB();
     *   return { cache, db };
     * }
     * ```
     */
    setup?: TConfig;
    /**
     * The main agent logic that processes requests.
     * Receives AgentContext and validated input (if schema.input is defined), returns output or stream.
     *
     * @param ctx - Agent context with logger, storage, and other runtime services
     * @param input - Validated input (only present if schema.input is defined)
     * @returns Output matching schema.output type, or ReadableStream if schema.stream is true
     *
     * @example
     * ```typescript
     * handler: async (ctx, { name, age }) => {
     *   ctx.logger.info(`Processing for ${name}`);
     *   await ctx.kv.set('lastUser', name);
     *   return `Hello, ${name}! You are ${age} years old.`;
     * }
     * ```
     */
    handler: AgentHandlerFromConfig<TSchema, TConfig extends (app: AppState) => infer R ? Awaited<R> : undefined, AppState>;
    /**
     * Optional async cleanup function called on app shutdown.
     * Use this to close connections, flush buffers, etc.
     *
     * @param app - Application state from createApp
     * @param config - Agent config returned from setup function
     *
     * @example
     * ```typescript
     * shutdown: async (app, config) => {
     *   await config.db.close();
     *   config.cache.clear();
     * }
     * ```
     */
    shutdown?: (app: AppState, config: TConfig extends (app: AppState) => infer R ? Awaited<R> : undefined) => Promise<void> | void;
}
/**
 * The public interface returned by createAgent().
 * Provides methods to run the agent, create evaluations, and manage event listeners.
 *
 * @template TInput - Input schema type (StandardSchemaV1 or undefined if no input)
 * @template TOutput - Output schema type (StandardSchemaV1 or undefined if no output)
 * @template TStream - Whether the agent returns a stream (true/false)
 *
 * @example
 * ```typescript
 * const agent = createAgent('greeting', {
 *   schema: {
 *     input: z.object({ name: z.string() }),
 *     output: z.string()
 *   },
 *   handler: async (ctx, { name }) => `Hello, ${name}!`
 * });
 *
 * // Run the agent
 * const result = await agent.run({ name: 'Alice' });
 *
 * // Create evaluation
 * const evalDef = agent.createEval('greeting-accuracy', {
 *   description: 'Checks if greeting includes the user name',
 *   handler: async (ctx, input, output) => {
 *     return { score: output.includes(input.name) ? 1 : 0 };
 *   }
 * });
 *
 * // Listen to events
 * agent.addEventListener('completed', async (eventName, agent, context) => {
 *   console.log('Agent completed successfully');
 * });
 * ```
 */
export interface AgentRunner<TInput extends StandardSchemaV1 | undefined = any, TOutput extends StandardSchemaV1 | undefined = any, TStream extends boolean = false> {
    /** Agent metadata (id, name, description, etc.) */
    metadata: AgentMetadata;
    /**
     * Execute the agent with validated input.
     * If agent has no input schema, call with no arguments.
     * If agent has input schema, pass validated input object.
     *
     * @example
     * ```typescript
     * // Agent with input
     * const result = await agent.run({ name: 'Alice' });
     *
     * // Agent without input
     * const result = await agent.run();
     * ```
     */
    run: undefined extends TInput ? () => Promise<InferStreamOutput<Exclude<TOutput, undefined>, TStream>> : (input: InferSchemaInput<Exclude<TInput, undefined>>) => Promise<InferStreamOutput<Exclude<TOutput, undefined>, TStream>>;
    /**
     * Create Hono validator middleware for this agent.
     * Automatically validates request input against the agent's schema.
     *
     * @example
     * ```typescript
     * import myAgent from './my-agent';
     * router.post('/', myAgent.validator(), async (c) => {
     *   const data = c.req.valid('json'); // Fully typed!
     *   return c.json(await myAgent.run(data));
     * });
     * ```
     */
    validator: AgentValidator<TInput, TOutput>;
    /** Input schema (if defined) */
    inputSchema?: TInput;
    /** Output schema (if defined) */
    outputSchema?: TOutput;
    /** Whether agent returns a stream */
    stream?: TStream;
    /**
     * Create an evaluation for this agent.
     * Evaluations run automatically after the agent completes.
     *
     * @example
     * ```typescript
     * const accuracyEval = agent.createEval('accuracy', {
     *   description: 'Validates output length is non-zero',
     *   handler: async (ctx, input, output) => ({
     *     score: output.length > 0 ? 1 : 0,
     *     metadata: { outputLength: output.length }
     *   })
     * });
     * ```
     */
    createEval: CreateEvalMethod<TInput, TOutput>;
    /**
     * Add event listener for 'started' or 'completed' events.
     * Listeners fire sequentially in the order they were added.
     *
     * @param eventName - 'started' or 'completed'
     * @param callback - Function to call when event fires
     *
     * @example
     * ```typescript
     * agent.addEventListener('started', async (eventName, agent, context) => {
     *   context.logger.info('Agent execution started');
     * });
     * ```
     */
    addEventListener(eventName: 'started' | 'completed', callback: (eventName: 'started' | 'completed', agent: Agent<TInput, TOutput, TStream, any, any>, context: AgentContext<any, any, any>) => Promise<void> | void): void;
    /**
     * Add event listener for 'errored' event.
     * Fires when agent handler throws an error.
     *
     * @param eventName - 'errored'
     * @param callback - Function to call when error occurs
     *
     * @example
     * ```typescript
     * agent.addEventListener('errored', async (eventName, agent, context, error) => {
     *   context.logger.error('Agent failed', { error: error.message });
     * });
     * ```
     */
    addEventListener(eventName: 'errored', callback: (eventName: 'errored', agent: Agent<TInput, TOutput, TStream, any, any>, context: AgentContext<any, any, any>, error: Error) => Promise<void> | void): void;
    /**
     * Remove event listener for 'started' or 'completed' events.
     *
     * @param eventName - 'started' or 'completed'
     * @param callback - The same callback function that was added
     */
    removeEventListener(eventName: 'started' | 'completed', callback: (eventName: 'started' | 'completed', agent: Agent<TInput, TOutput, TStream, any, any>, context: AgentContext<any, any, any>) => Promise<void> | void): void;
    /**
     * Remove event listener for 'errored' event.
     *
     * @param eventName - 'errored'
     * @param callback - The same callback function that was added
     */
    removeEventListener(eventName: 'errored', callback: (eventName: 'errored', agent: Agent<TInput, TOutput, TStream, any, any>, context: AgentContext<any, any, any>, error: Error) => Promise<void> | void): void;
}
/**
 * Get the global runtime state (for production use).
 * In tests, use TestAgentContext which has isolated runtime state.
 */
export declare function getGlobalRuntimeState(): AgentRuntimeState;
/**
 * Get the runtime state from an AgentContext.
 * @internal
 */
export declare function getAgentRuntime(ctx: AgentContext<any, any, any>): AgentRuntimeState;
/**
 * Union type of all registered agent names.
 * Falls back to `string` when no agents are registered (before augmentation).
 * After augmentation, this becomes a strict union of agent names for full type safety.
 */
export type AgentName = keyof AgentRegistry extends never ? string : keyof AgentRegistry;
/**
 * Agent registry interface.
 * This interface is augmented by generated code to provide strongly-typed agent access.
 */
export interface AgentRegistry {
}
export declare const registerAgent: (name: AgentName, agent: Agent<any, any, any, any, any>) => void;
export declare const setAgentConfig: (name: AgentName, config: unknown) => void;
export declare const getAgentConfig: (name: AgentName) => unknown;
/**
 * Configuration object for creating an agent with explicit type parameters.
 *
 * @template TInput - Input schema type (StandardSchemaV1 or undefined)
 * @template TOutput - Output schema type (StandardSchemaV1 or undefined)
 * @template TStream - Whether agent returns a stream (true/false)
 * @template TConfig - Type returned by setup function
 * @template TAppState - Custom app state type from createApp
 */
export interface CreateAgentConfigExplicit<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TStream extends boolean = false, TConfig = unknown, TAppState = AppState> {
    /**
     * Optional schema validation.
     *
     * @example
     * ```typescript
     * schema: {
     *   input: z.object({ name: z.string() }),
     *   output: z.string(),
     *   stream: false,
     * }
     * ```
     */
    schema?: {
        /** Input validation schema */
        input?: TInput;
        /** Output validation schema */
        output?: TOutput;
        /** Whether the agent returns a ReadableStream */
        stream?: TStream;
    };
    /**
     * Optional description of what this agent does.
     *
     * @example
     * ```typescript
     * description: 'Does something useful'
     * ```
     */
    description?: string;
    /**
     * Optional metadata object (typically injected by build plugin during compilation).
     * Contains agent identification and versioning information.
     *
     * @internal - Usually populated by build tooling, not manually set
     */
    metadata?: Partial<AgentMetadata>;
    /**
     * Optional setup function receiving app state, returns agent config.
     * The returned value is available in the handler via `ctx.config`.
     *
     * @param app - Application state from createApp
     * @returns Agent-specific configuration
     *
     * @example
     * ```typescript
     * setup: async (app) => ({ cache: new Map() })
     * ```
     */
    setup?: (app: TAppState) => Promise<TConfig> | TConfig;
    /**
     * Optional cleanup function called on app shutdown.
     *
     * @param app - Application state from createApp
     * @param config - Agent config returned from setup
     *
     * @example
     * ```typescript
     * shutdown: async (app, config) => {
     *   config.cache.clear();
     * }
     * ```
     */
    shutdown?: (app: TAppState, config: TConfig) => Promise<void> | void;
    /**
     * Agent handler function.
     * Type is automatically inferred based on schema definitions.
     *
     * @param ctx - Agent context
     * @param input - Validated input (only present if schema.input is defined)
     * @returns Output or ReadableStream based on schema
     *
     * @example
     * ```typescript
     * handler: async (ctx, input) => {
     *   return `Hello, ${input.name}!`;
     * }
     * ```
     */
    handler: TInput extends StandardSchemaV1 ? TStream extends true ? TOutput extends StandardSchemaV1 ? (c: AgentContext<any, TConfig, TAppState>, input: InferOutput<TInput>) => Promise<ReadableStream<InferOutput<TOutput>>> | ReadableStream<InferOutput<TOutput>> : (c: AgentContext<any, TConfig, TAppState>, input: InferOutput<TInput>) => Promise<ReadableStream<unknown>> | ReadableStream<unknown> : TOutput extends StandardSchemaV1 ? (c: AgentContext<any, TConfig, TAppState>, input: InferOutput<TInput>) => Promise<InferOutput<TOutput>> | InferOutput<TOutput> : (c: AgentContext<any, TConfig, TAppState>, input: InferOutput<TInput>) => Promise<void> | void : TStream extends true ? TOutput extends StandardSchemaV1 ? (c: AgentContext<any, TConfig, TAppState>) => Promise<ReadableStream<InferOutput<TOutput>>> | ReadableStream<InferOutput<TOutput>> : (c: AgentContext<any, TConfig, TAppState>) => Promise<ReadableStream<unknown>> | ReadableStream<unknown> : TOutput extends StandardSchemaV1 ? (c: AgentContext<any, TConfig, TAppState>) => Promise<InferOutput<TOutput>> | InferOutput<TOutput> : (c: AgentContext<any, TConfig, TAppState>) => Promise<void> | void;
}
/**
 * Creates an agent with schema validation and lifecycle hooks.
 *
 * This is the recommended way to create agents with automatic type inference from schemas.
 *
 * @template TSchema - Schema definition object containing optional input, output, and stream properties
 * @template TConfig - Function type that returns agent-specific configuration from setup
 *
 * @param name - Unique agent name (must be unique within the project)
 * @param config - Agent configuration object
 *
 * @returns AgentRunner with a run method for executing the agent
 *
 * @example
 * ```typescript
 * const agent = createAgent('greeting-agent', {
 *   description: 'Returns personalized greetings',
 *   schema: {
 *     input: z.object({ name: z.string(), age: z.number() }),
 *     output: z.string()
 *   },
 *   handler: async (ctx, { name, age }) => {
 *     ctx.logger.info(`Processing greeting for ${name}`);
 *     return `Hello, ${name}! You are ${age} years old.`;
 *   }
 * });
 *
 * // Call the agent directly
 * const result = await agent.run({ name: 'Alice', age: 30 });
 * ```
 */
export declare function createAgent<TSchema extends {
    input?: StandardSchemaV1;
    output?: StandardSchemaV1;
    stream?: boolean;
} | undefined = undefined, TConfig extends (app: AppState) => any = any>(name: string, config: CreateAgentConfig<TSchema, TConfig>): AgentRunner<SchemaInput<TSchema>, SchemaOutput<TSchema>, SchemaStream<TSchema>>;
/**
 * Creates an agent with explicit generic type parameters.
 *
 * Use this overload when you need explicit control over types or working with custom app state.
 *
 * @template TInput - Input schema type (StandardSchemaV1 or undefined)
 * @template TOutput - Output schema type (StandardSchemaV1 or undefined)
 * @template TStream - Whether agent returns a stream (true/false)
 * @template TConfig - Type returned by setup function
 * @template TAppState - Custom app state type from createApp
 *
 * @param name - Unique agent name (must be unique within the project)
 * @param config - Agent configuration object
 *
 * @returns AgentRunner with explicit types and a run method
 *
 * @example
 * ```typescript
 * interface MyAppState { db: Database }
 * interface MyConfig { cache: Map<string, any> }
 *
 * const agent = createAgent<
 *   z.ZodObject<any>, // TInput
 *   z.ZodString,      // TOutput
 *   false            // TStream
 * >('custom-agent', {
 *   setup: async (app) => ({ cache: new Map() }),
 *   handler: async (ctx, input) => {
 *     const db = ctx.app.db;
 *     const cache = ctx.config.cache;
 *     return 'result';
 *   }
 * });
 * ```
 */
export declare function createAgent<TInput extends StandardSchemaV1 | undefined = undefined, TOutput extends StandardSchemaV1 | undefined = undefined, TStream extends boolean = false, TConfig = unknown, TAppState = AppState>(name: string, config: CreateAgentConfigExplicit<TInput, TOutput, TStream, TConfig, TAppState>): AgentRunner<TInput, TOutput, TStream>;
/**
 * Populate the agents object with all registered agents
 * Keys are converted to camelCase to match the generated TypeScript types
 */
export declare const populateAgentsRegistry: (ctx: Context) => any;
export declare const createAgentMiddleware: (agentName: AgentName | "") => MiddlewareHandler;
export declare const getAgents: () => Map<string, Agent<any, any, any, any, any>>;
export declare const runAgentSetups: (appState: AppState) => Promise<void>;
export declare const runAgentShutdowns: (appState: AppState) => Promise<void>;
/**
 * Run an agent within a specific AgentContext.
 * Sets up AsyncLocalStorage with the provided context and executes the agent.
 *
 * This is the recommended way to test agents in unit tests. It automatically:
 * - Registers the agent in the runtime state so event listeners fire
 * - Sets up AsyncLocalStorage so getAgentContext() works inside the agent
 * - Handles both agents with input and agents without input
 *
 * **Use cases:**
 * - Unit testing agents with TestAgentContext
 * - Running agents outside HTTP request flow
 * - Custom agent execution environments
 * - Testing event listeners and evaluations
 *
 * @template TInput - Type of the input parameter
 * @template TOutput - Type of the return value
 *
 * @param ctx - The AgentContext to use (typically TestAgentContext in tests)
 * @param agent - The AgentRunner to execute (returned from createAgent)
 * @param input - Input data (required if agent has input schema, omit otherwise)
 *
 * @returns Promise resolving to the agent's output
 *
 * @example
 * ```typescript
 * import { runInAgentContext, TestAgentContext } from '@agentuity/runtime/test';
 *
 * test('greeting agent', async () => {
 *   const ctx = new TestAgentContext();
 *   const result = await runInAgentContext(ctx, greetingAgent, {
 *     name: 'Alice',
 *     age: 30
 *   });
 *   expect(result).toBe('Hello, Alice! You are 30 years old.');
 * });
 *
 * test('no-input agent', async () => {
 *   const ctx = new TestAgentContext();
 *   const result = await runInAgentContext(ctx, statusAgent);
 *   expect(result).toEqual({ status: 'ok' });
 * });
 * ```
 */
export declare function runInAgentContext<TInput, TOutput>(ctx: AgentContext<any, any, any>, agent: AgentRunner<any, any, any>, input?: TInput): Promise<TOutput>;
export {};
//# sourceMappingURL=agent.d.ts.map