// contracts §12 + §21 — Tool Contracts + Diagnostic Contracts // File: tool.ts — ToolCategory, ToolDefinition, ToolExecutor, StreamingToolExecutor, // ToolExecutionContext, ToolResultEnvelope, ToolEvent, ToolRegistry, Diagnostic // Merged: diagnostics.ts symbols per DD §3 import type { JsonSchema, JsonObject, UUID, ISOTimeString, SessionID, ProjectID, TaskID, AgentID, MessageID, ArtifactID, EvidenceRefID, CommandRunID } from "./ids.js" import type { AirError } from "./error.js" // ============================================================================= // contracts §12 — Tool Contracts // ============================================================================= export type ToolCategory = | "filesystem" | "shell" | "git" | "project" | "build" | "test" | "debug" | "static_analysis" | "gui" | "network" | "memory" | "context" | "artifact" | "permission" | "doctor" | "internal" export interface ToolPermissionSpec { read_paths?: PathPolicy write_paths?: PathPolicy execute?: boolean network?: boolean system_sensitive?: boolean credentials?: boolean } export interface PathPolicy { allow?: string[] deny?: string[] source?: string } export interface ToolDefinition { name: string version: number description: string input_schema: JsonSchema output_schema: JsonSchema category: ToolCategory permissions: ToolPermissionSpec streaming: boolean } export interface ToolExecutor { execute(input: I, context: ToolExecutionContext): Promise> } export interface StreamingToolExecutor { execute_streaming(input: I, context: ToolExecutionContext): AsyncIterable execute_final(input: I, context: ToolExecutionContext): Promise> } export interface ToolExecutionContext { session_id: SessionID project_id: ProjectID task_id?: TaskID agent_id?: AgentID origin_message_id?: MessageID permission_template: string cwd?: string } export interface ToolResultEnvelope { status: "ok" | "error" | "cancelled" output?: T error?: AirError artifact_ids?: ArtifactID[] evidence_ref_ids?: EvidenceRefID[] metadata?: JsonObject } /** * ToolCall - A request to invoke a tool with arguments. * Used by PermissionEngine to build the permission context for evaluation. */ export interface ToolCall { call_id: string name: string arguments: Record } export interface ToolEvent { type: "progress" | "artifact" | "result" payload: unknown } export interface ToolRegistry { register(definition: ToolDefinition, executor: ToolExecutor): void register_streaming(definition: ToolDefinition, executor: StreamingToolExecutor): void call(name: string, input: I, context: ToolExecutionContext): Promise> call_streaming(name: string, input: I, context: ToolExecutionContext): AsyncIterable> list(): ToolDefinition[] } // ============================================================================= // contracts §21 — Diagnostic Contracts // ============================================================================= export type DiagnosticSeverity = "error" | "warning" | "info" | "hint" export interface Diagnostic { diagnostic_id: UUID task_id?: TaskID agent_id?: AgentID command_run_id?: CommandRunID artifact_id?: ArtifactID language?: string toolchain?: string severity: DiagnosticSeverity file?: string line?: number column?: number code?: string message: string semantic_signature: string created_at: ISOTimeString metadata_json?: JsonObject }