const std = @import("std");const builtin = @import("builtin");const agent_stream_provider = @import("../../stream_provider.zig");const command_admission = @import("../../../permissions/command_admission.zig");const permission_auto_classifier = @import("../../../permissions/auto_classifier.zig");const types = @import("../../../shared/types.zig");const permissions = @import("../../../permissions/permissions.zig");const worker_runtime = @import("../../worker_runtime.zig");const background_runtime = @import("../../../background/background_runtime.zig");const builtin_context = @import("../../../../builtins/context.zig");const builtin_gateway = @import("../../../../builtins/gateway.zig");const gateway_client = @import("../../../../gateway/client.zig");const builtin_tools = @import("../../../../builtins/tools.zig");const session_runtime = @import("../../../session/session.zig");const session_codec = @import("../../../session/session_codec.zig");const command_replay_store = @import("../../../session/command_replay_store.zig");const session_child_store = @import("../../../session/session_child_store.zig");const gateway_json = @import("../../../gateway/gateway_json.zig");const gateway_failure_diagnostics = @import("../../../gateway/gateway_failure_diagnostics.zig");const lifecycle_hooks = @import("../../../hooks/hooks.zig");const model_capabilities = @import("../../../config/model_capabilities.zig");const file_mutation = @import("../../../tooling/file_mutation.zig");const file_mutation_contract = @import("../../../tooling/file_mutation_contract.zig");const context_contract = @import("../../../workspace/context_contract.zig");const io_mod = @import("../../../shared/io.zig");const pathing = @import("../../../workspace/pathing.zig");const tool_dispatch = @import("../../../tooling/tool_dispatch.zig");const tool_runtime = @import("../../../tooling/tool_runtime.zig");const command_output_content = @import("../../../tooling/command_output_content.zig");const testing_write_file = if (builtin.is_test) @import("../../../../tools/filesystem/write_file.zig")else struct {};const testing_edit_file = if (builtin.is_test) @import("../../../../tools/filesystem/edit_file.zig")else struct {}; const runtime_config = @import("../config.zig");const runtime_deps = @import("../deps.zig");const runtime_lifecycle = @import("../lifecycle.zig");const model_response_recovery = @import("../model_response_recovery.zig");const runtime_orchestrator = @import("../orchestrator.zig");const runtime_tool_contracts = @import("../tool_contracts.zig"); const Allocator = std.mem.Allocator;const ChatMessage = types.ChatMessage;const HistoryTurn = types.HistoryTurn;const PermissionGrant = types.PermissionGrant;const PermissionMode = types.PermissionMode;const ToolCall = types.ToolCall;const ToolPermissionDecision = types.ToolPermissionDecision;const QueuedPrompt = worker_runtime.QueuedPrompt;const WorkerEvent = worker_runtime.WorkerEvent;const AgentRuntimeDeps = runtime_deps.AgentRuntimeDeps;const Config = runtime_config.Config;const ToolExecutionResult = runtime_tool_contracts.ToolExecutionResult;const ToolExecutionRequest = runtime_tool_contracts.ToolExecutionRequest;const SandboxScopeRequired = runtime_tool_contracts.SandboxScopeRequired;const ToolCallValidationResult = runtime_tool_contracts.ToolCallValidationResult;const DiffEntryPayload = runtime_tool_contracts.DiffEntryPayload;const SecondaryPublicationReport = runtime_tool_contracts.SecondaryPublicationReport; pub const vision_agent_test_tools = [_]tool_dispatch.Tool{builtin_tools.vision}; pub const VisionAgentToolRuntime = struct { alloc: Allocator, workspace_root: []const u8 = "/tmp/workspace", session_id: ?[]const u8 = null, agent_stream_provider: agent_stream_provider.Provider = agent_stream_provider.unavailable_provider, result_allocator_override: ?Allocator = null, execution_count: usize = 0, result_count: usize = 0, worker: worker_runtime.WorkerRuntime = .{}, background: background_runtime.BackgroundRuntime = .{}, session: session_runtime.SessionRuntime = .{ .max_history_turns = 8 }, pub fn deinit(self: *VisionAgentToolRuntime) void { self.worker.deinit(self.alloc); self.background.deinit(self.alloc); self.session.deinit(self.alloc); } pub fn delegate(self: *VisionAgentToolRuntime) ExecuteDelegate { return .{ .ctx = self, .run = execute, .set_agent_stream_provider = setAgentStreamProvider, }; } fn setAgentStreamProvider(raw: *anyopaque, provider: agent_stream_provider.Provider) void { const self: *VisionAgentToolRuntime = @ptrCast(@alignCast(raw)); self.agent_stream_provider = provider; } fn execute(raw: *anyopaque, request: ToolExecutionRequest) !ToolExecutionResult { const self: *VisionAgentToolRuntime = @ptrCast(@alignCast(raw)); self.execution_count += 1; var effective_request = request; effective_request.result_allocator = self.result_allocator_override orelse request.result_allocator; const result = try tool_runtime.executeToolCallAuthorized( self.context(), effective_request, ); self.result_count += 1; return result; } fn context(self: *VisionAgentToolRuntime) tool_runtime.Context { return .{ .workspace_root = self.workspace_root, .ignored_list_entries = &.{}, .max_list_entries = 100, .max_read_file_bytes = 64 * 1024, .max_read_file_lines = 400, .max_read_file_line_len = 2000, .max_command_output_bytes = 64 * 1024, .max_tool_result_bytes = 64 * 1024, .api_key = "key", .agent_stream_provider = self.agent_stream_provider, .model = "anthropic/claude-opus-4.6", .gateway_retry_count = 1, .gateway_chat_url = "https://example.invalid", .agent_step_limit = 8, .tool_registry = .{ .tools = vision_agent_test_tools[0..] }, .permission_mode = .ask, .permission_grants = &.{}, .permission_rules = .{}, .worker = &self.worker, .background = &self.background, .session = &self.session, .session_allocator = self.alloc, .context_limits = .{ .image_adapter_output_bytes = .{ .value = .{ .bytes = 64 * 1024 }, .source = .command_line, } }, .context_registry = .{ .default_provider = builtin_context.provider }, .lifecycle_scope = .{ .kind = .interactive, .workspace_root = self.workspace_root, .session_id = self.session_id, }, .output_chunk_ctx = undefined, .on_output_chunk = discardVisionToolOutput, .background_url_ctx = undefined, .on_background_url_ready = discardVisionBackgroundUrl, }; }}; fn discardVisionToolOutput( _: *anyopaque, _: ?types.ToolLifecycleId, _: command_output_content.Stream, _: []const u8,) anyerror!void {} fn discardVisionBackgroundUrl(_: *anyopaque, _: u64, _: []const u8) void {} const test_tools = [_]tool_dispatch.Tool{ builtin_tools.list_files, builtin_tools.glob_files, builtin_tools.grep_files, builtin_tools.read_file, builtin_tools.write_file, builtin_tools.edit_file, builtin_tools.delete_file, builtin_tools.rename_file, builtin_tools.copy_file, builtin_tools.create_folder, builtin_tools.file_info, builtin_tools.memory, builtin_tools.semantic_search, builtin_tools.open_file, builtin_tools.web_fetch, builtin_tools.web_search, builtin_tools.terminal, builtin_tools.skill, builtin_tools.install_skill, builtin_tools.subagent, builtin_tools.mcp_search_tools, builtin_tools.mcp_select_tool, builtin_tools.ask_user_question, builtin_tools.read_tool_result,};const test_tool_registry = tool_dispatch.Registry{ .tools = test_tools[0..] }; fn testExecutionAuthority(call: ToolCall) command_admission.ToolExecutionAuthority { return testExecutionAuthorityWithScope(call, .restricted);} fn testExecutionAuthorityWithScope( call: ToolCall, scope: permission_auto_classifier.SandboxScope,) command_admission.ToolExecutionAuthority { if (!std.mem.eql(u8, call.name, "terminal")) return .ordinary; return .{ .run_command = .{ .shell_allowed = .{ .fingerprint = .{ .command = call.arguments_json, .resolved_cwd = "", .background = false, .resolved_backend = .none, .target_os = builtin.os.tag, .scope = scope, }, .source = .interactive_once, } } };} pub const FakeCompletion = struct { status: std.http.Status = .ok, err_body: ?[]const u8 = null, retry_after_seconds: ?u64 = null, pre_send_error: ?anyerror = null, stream_error: ?anyerror = null, stream_error_after_chunks: ?anyerror = null, stream_error_after_tool_starts: ?anyerror = null, chunks: []const []const u8 = &.{}, reasoning_chunks: []const []const u8 = &.{}, content: ?[]const u8 = null, tool_calls: []const ToolCall = &.{}, streamed_tool_starts: []const ToolCall = &.{}, provider_result_identity_failure: ?types.ProviderResultIdentityFailure = null, provider_failure_detail: ?[]const u8 = null, finish_reason: ?types.ProviderFinishReason = null, omit_finish: bool = false, usage: types.Usage = .{}, delivery_ambiguous: bool = false, pause_before_output: bool = false, cancel_before_output: bool = false, cancel_after_chunks: bool = false, cancel_during_tool_stream: bool = false,}; pub const FakeGateway = struct { alloc: Allocator, completions: []const FakeCompletion, index: usize = 0, request_bodies: std.ArrayList([]u8) = .empty, request_models: std.ArrayList([]u8) = .empty, request_api_keys: std.ArrayList([]u8) = .empty, request_session_ids: std.ArrayList(?[]u8) = .empty, recovery_pause_flag: ?*std.atomic.Value(bool) = null, pub fn init(alloc: Allocator, completions: []const FakeCompletion) FakeGateway { return .{ .alloc = alloc, .completions = completions }; } pub fn deinit(self: *FakeGateway) void { for (self.request_bodies.items) |body| self.alloc.free(body); self.request_bodies.deinit(self.alloc); for (self.request_models.items) |model| self.alloc.free(model); self.request_models.deinit(self.alloc); for (self.request_api_keys.items) |api_key| self.alloc.free(api_key); self.request_api_keys.deinit(self.alloc); for (self.request_session_ids.items) |session_id| { if (session_id) |id| self.alloc.free(id); } self.request_session_ids.deinit(self.alloc); } pub fn provider(self: *FakeGateway) agent_stream_provider.Provider { var result = builtin_gateway.agent_stream_provider; result.context = self; result.stream_fn = fakeGatewayStream; return result; } fn stream( self: *FakeGateway, alloc: Allocator, request: agent_stream_provider.Request, ) !agent_stream_provider.Result { try self.request_bodies.append(self.alloc, try self.alloc.dupe(u8, request.payload)); try self.request_models.append(self.alloc, try self.alloc.dupe(u8, request.model)); try self.request_api_keys.append(self.alloc, try self.alloc.dupe(u8, request.api_key)); const session_id = if (request.session_id) |id| try self.alloc.dupe(u8, id) else null; errdefer if (session_id) |id| self.alloc.free(id); try self.request_session_ids.append(self.alloc, session_id); if (self.index >= self.completions.len) return error.TestUnexpectedGatewayRequest; const completion = self.completions[self.index]; self.index += 1; if (completion.pre_send_error) |err| { recordNetworkFailureEvidence(request, err); return err; } request.delivery.markPossiblySent(); if (completion.stream_error) |err| { recordNetworkFailureEvidence(request, err); return err; } if (completion.pause_before_output) { if (self.recovery_pause_flag) |flag| flag.store(true, .seq_cst); request.cancel_flag.store(true, .seq_cst); return error.Cancelled; } if (completion.cancel_before_output) { request.cancel_flag.store(true, .seq_cst); return .{ .status = .ok }; } if (request.on_reasoning_chunk) |reasoning| { for (completion.reasoning_chunks) |chunk| reasoning(request.callback_ctx, chunk); } for (completion.chunks) |chunk| { request.on_content_chunk(request.callback_ctx, chunk); } if (completion.cancel_after_chunks) request.cancel_flag.store(true, .seq_cst); if (completion.stream_error_after_chunks) |err| { recordNetworkFailureEvidence(request, err); return err; } if (request.on_tool_start) |start| { for (completion.streamed_tool_starts) |call| { start(request.callback_ctx, call.id, call.name, null); } } if (completion.stream_error_after_tool_starts) |err| { recordNetworkFailureEvidence(request, err); return err; } if (completion.cancel_during_tool_stream) { request.cancel_flag.store(true, .seq_cst); return error.Cancelled; } if (completion.status != .ok) { const err_body = if (completion.err_body) |body| try alloc.dupe(u8, body) else null; const diagnostics = gateway_failure_diagnostics.collect(alloc, request.payload, err_body); return .{ .status = completion.status, .err_body = err_body, .retry_after_seconds = completion.retry_after_seconds, .failure_schema = diagnostics.schema, .failure_request_shape = diagnostics.request_shape, .ownership = .owned, }; } return .{ .status = .ok, .completion = .{ .content = completion.content, .tool_calls = completion.tool_calls, .provider_result_identity_failure = completion.provider_result_identity_failure, .provider_failure_detail = completion.provider_failure_detail, .delivery_ambiguous = completion.delivery_ambiguous, .finish_reason = if (completion.omit_finish) null else completion.finish_reason orelse if (completion.tool_calls.len > 0) .tool_calls else .stop, .usage = completion.usage, }, .generation_origin = "https://ai-gateway.vercel.sh", }; } fn recordNetworkFailureEvidence( request: agent_stream_provider.Request, err: anyerror, ) void { request.attempt_evidence.network_failure = gateway_client.networkFailureEvidence( err, request.delivery.load(), ); }}; pub const ModelCapabilityOverride = struct { model: []const u8, capabilities: model_capabilities.Capabilities,}; fn fakeGatewayStream( context: ?*anyopaque, alloc: Allocator, request: agent_stream_provider.Request,) !agent_stream_provider.Result { const gateway: *FakeGateway = @ptrCast(@alignCast(context.?)); return gateway.stream(alloc, request);} pub const FakeExecPlan = union(enum) { result: ToolExecutionResult, err: anyerror,}; pub const ExecuteDelegate = struct { ctx: *anyopaque, run: *const fn (*anyopaque, ToolExecutionRequest) anyerror!ToolExecutionResult, set_agent_stream_provider: ?*const fn (*anyopaque, agent_stream_provider.Provider) void = null,}; pub const PermissionRequestOverride = struct { context: *anyopaque, request_fn: *const fn ( *anyopaque, Allocator, ToolCall, permission_auto_classifier.ReviewTurnContext, PermissionMode, []const PermissionGrant, ?runtime_tool_contracts.LiveToolAuthority, ?runtime_tool_contracts.LivePermissionRevalidation, []const []const u8, ) anyerror!command_admission.PermissionOutcome,}; pub const SandboxWideningRequestOverride = struct { context: *anyopaque, request_fn: *const fn ( *anyopaque, Allocator, ToolCall, permission_auto_classifier.ReviewTurnContext, PermissionMode, []const PermissionGrant, ?runtime_tool_contracts.LiveToolAuthority, []const []const u8, SandboxScopeRequired, ) anyerror!command_admission.PermissionOutcome,}; pub const ToolExecutionOverride = struct { context: *anyopaque, execute_fn: *const fn ( *anyopaque, ToolExecutionRequest, ) anyerror!ToolExecutionResult,}; fn captureReviewAuthority( alloc: Allocator, review_turn: permission_auto_classifier.ReviewTurnContext,) ![]u8 { var captured: std.ArrayList(u8) = .empty; errdefer captured.deinit(alloc); if (review_turn.current_root_request.len > 0) { try captured.appendSlice(alloc, review_turn.current_root_request); try captured.append(alloc, '\n'); } return captured.toOwnedSlice(alloc);} pub const FakeAgentRuntimeDeps = struct { alloc: Allocator, agent_stream_provider: agent_stream_provider.Provider = agent_stream_provider.unavailable_provider, live_tool_authority: ?runtime_deps.LiveToolAuthorityProvider = null, tool_activity_recorder: ?runtime_deps.ToolActivityRecorder = null, tool_registry: tool_dispatch.Registry = test_tool_registry, context_registry: ?context_contract.Registry = null, context_enabled: bool = false, execute_mutex: std.Io.Mutex = .init, log: std.ArrayList([]u8) = .empty, texts: std.ArrayList([]u8) = .empty, system_notices: std.ArrayList([]u8) = .empty, interactive_notices: std.ArrayList(types.SemanticNotice) = .empty, context_notices: std.ArrayList([]u8) = .empty, route_recovery_statuses: std.ArrayList(types.RouteRecoveryStatus) = .empty, permission_names: std.ArrayList([]u8) = .empty, permission_call_ids: std.ArrayList([]u8) = .empty, permission_user_intent_contexts: std.ArrayList([]u8) = .empty, permission_review_models: std.ArrayList([]u8) = .empty, permission_review_target_call_ids: std.ArrayList([]u8) = .empty, permission_review_origins: std.ArrayList(permission_auto_classifier.ReviewOrigin) = .empty, permission_review_root_authority_counts: std.ArrayList(usize) = .empty, permission_review_feedback_counts: std.ArrayList(usize) = .empty, permission_review_pending_call_counts: std.ArrayList(usize) = .empty, sandbox_widening_user_intent_contexts: std.ArrayList([]u8) = .empty, executed_names: std.ArrayList([]u8) = .empty, executed_call_ids: std.ArrayList([]u8) = .empty, rejected_names: std.ArrayList([]u8) = .empty, inner_usage_names: std.ArrayList([]u8) = .empty, inner_usages: std.ArrayList(types.ToolUsage) = .empty, validated_names: std.ArrayList([]u8) = .empty, availability_checked_names: std.ArrayList([]u8) = .empty, execution_classification_complete: std.ArrayList(bool) = .empty, last_validated_arguments: ?[]u8 = null, last_permission_arguments: ?[]u8 = null, last_executed_arguments: ?[]u8 = null, last_execute_root_user_intent_context: ?[]u8 = null, last_execute_root_user_messages: std.ArrayList([]u8) = .empty, last_execute_root_user_evidence_complete: bool = false, propagated_grants: std.ArrayList(PermissionGrant) = .empty, event_grants: std.ArrayList(PermissionGrant) = .empty, last_execute_grants: std.ArrayList(PermissionGrant) = .empty, last_live_authority_generation: ?u64 = null, last_live_authority_sandbox: ?types.BackendKind = null, last_live_authority_tool_count: usize = 0, last_live_authority_integration_count: usize = 0, last_live_authority_rule_count: usize = 0, last_live_authority_grant_count: usize = 0, last_frozen_file_grants: std.ArrayList(PermissionGrant) = .empty, permission_decisions: []const ToolPermissionDecision = &.{}, permission_auto_review_results: []const ?permission_auto_classifier.Result = &.{}, permission_denial_reasons: []const types.ToolPermissionDenialReason = &.{},Lines 1–500 of 2094. Load more
const std = @import("std"); const builtin = @import("builtin"); const agent_stream_provider = @import("../../stream_provider.zig"); const command_admission = @import("../../../permissions/command_admission.zig"); const permission_auto_classifier = @import("../../../permissions/auto_classifier.zig"); const types = @import("../../../shared/types.zig"); const permissions = @import("../../../permissions/permissions.zig"); const worker_runtime = @import("../../worker_runtime.zig"); const background_runtime = @import("../../../background/background_runtime.zig"); const builtin_context = @import("../../../../builtins/context.zig"); const builtin_gateway = @import("../../../../builtins/gateway.zig"); const gateway_client = @import("../../../../gateway/client.zig"); const builtin_tools = @import("../../../../builtins/tools.zig"); const session_runtime = @import("../../../session/session.zig"); const session_codec = @import("../../../session/session_codec.zig"); const command_replay_store = @import("../../../session/command_replay_store.zig"); const session_child_store = @import("../../../session/session_child_store.zig"); const gateway_json = @import("../../../gateway/gateway_json.zig"); const gateway_failure_diagnostics = @import("../../../gateway/gateway_failure_diagnostics.zig"); const lifecycle_hooks = @import("../../../hooks/hooks.zig"); const model_capabilities = @import("../../../config/model_capabilities.zig"); const file_mutation = @import("../../../tooling/file_mutation.zig"); const file_mutation_contract = @import("../../../tooling/file_mutation_contract.zig"); const context_contract = @import("../../../workspace/context_contract.zig"); const io_mod = @import("../../../shared/io.zig"); const pathing = @import("../../../workspace/pathing.zig"); const tool_dispatch = @import("../../../tooling/tool_dispatch.zig"); const tool_runtime = @import("../../../tooling/tool_runtime.zig"); const command_output_content = @import("../../../tooling/command_output_content.zig"); const testing_write_file = if (builtin.is_test) @import("../../../../tools/filesystem/write_file.zig") else struct {}; const testing_edit_file = if (builtin.is_test) @import("../../../../tools/filesystem/edit_file.zig") else struct {}; const runtime_config = @import("../config.zig"); const runtime_deps = @import("../deps.zig"); const runtime_lifecycle = @import("../lifecycle.zig"); const model_response_recovery = @import("../model_response_recovery.zig"); const runtime_orchestrator = @import("../orchestrator.zig"); const runtime_tool_contracts = @import("../tool_contracts.zig"); const Allocator = std.mem.Allocator; const ChatMessage = types.ChatMessage; const HistoryTurn = types.HistoryTurn; const PermissionGrant = types.PermissionGrant; const PermissionMode = types.PermissionMode; const ToolCall = types.ToolCall; const ToolPermissionDecision = types.ToolPermissionDecision; const QueuedPrompt = worker_runtime.QueuedPrompt; const WorkerEvent = worker_runtime.WorkerEvent; const AgentRuntimeDeps = runtime_deps.AgentRuntimeDeps; const Config = runtime_config.Config; const ToolExecutionResult = runtime_tool_contracts.ToolExecutionResult; const ToolExecutionRequest = runtime_tool_contracts.ToolExecutionRequest; const SandboxScopeRequired = runtime_tool_contracts.SandboxScopeRequired; const ToolCallValidationResult = runtime_tool_contracts.ToolCallValidationResult; const DiffEntryPayload = runtime_tool_contracts.DiffEntryPayload; const SecondaryPublicationReport = runtime_tool_contracts.SecondaryPublicationReport; pub const vision_agent_test_tools = [_]tool_dispatch.Tool{builtin_tools.vision}; pub const VisionAgentToolRuntime = struct { alloc: Allocator, workspace_root: []const u8 = "/tmp/workspace", session_id: ?[]const u8 = null, agent_stream_provider: agent_stream_provider.Provider = agent_stream_provider.unavailable_provider, result_allocator_override: ?Allocator = null, execution_count: usize = 0, result_count: usize = 0, worker: worker_runtime.WorkerRuntime = .{}, background: background_runtime.BackgroundRuntime = .{}, session: session_runtime.SessionRuntime = .{ .max_history_turns = 8 }, pub fn deinit(self: *VisionAgentToolRuntime) void { self.worker.deinit(self.alloc); self.background.deinit(self.alloc); self.session.deinit(self.alloc); } pub fn delegate(self: *VisionAgentToolRuntime) ExecuteDelegate { return .{ .ctx = self, .run = execute, .set_agent_stream_provider = setAgentStreamProvider, }; } fn setAgentStreamProvider(raw: *anyopaque, provider: agent_stream_provider.Provider) void { const self: *VisionAgentToolRuntime = @ptrCast(@alignCast(raw)); self.agent_stream_provider = provider; } fn execute(raw: *anyopaque, request: ToolExecutionRequest) !ToolExecutionResult { const self: *VisionAgentToolRuntime = @ptrCast(@alignCast(raw)); self.execution_count += 1; var effective_request = request; effective_request.result_allocator = self.result_allocator_override orelse request.result_allocator; const result = try tool_runtime.executeToolCallAuthorized( self.context(), effective_request, ); self.result_count += 1; return result; } fn context(self: *VisionAgentToolRuntime) tool_runtime.Context { return .{ .workspace_root = self.workspace_root, .ignored_list_entries = &.{}, .max_list_entries = 100, .max_read_file_bytes = 64 * 1024, .max_read_file_lines = 400, .max_read_file_line_len = 2000, .max_command_output_bytes = 64 * 1024, .max_tool_result_bytes = 64 * 1024, .api_key = "key", .agent_stream_provider = self.agent_stream_provider, .model = "anthropic/claude-opus-4.6", .gateway_retry_count = 1, .gateway_chat_url = "https://example.invalid", .agent_step_limit = 8, .tool_registry = .{ .tools = vision_agent_test_tools[0..] }, .permission_mode = .ask, .permission_grants = &.{}, .permission_rules = .{}, .worker = &self.worker, .background = &self.background, .session = &self.session, .session_allocator = self.alloc, .context_limits = .{ .image_adapter_output_bytes = .{ .value = .{ .bytes = 64 * 1024 }, .source = .command_line, } }, .context_registry = .{ .default_provider = builtin_context.provider }, .lifecycle_scope = .{ .kind = .interactive, .workspace_root = self.workspace_root, .session_id = self.session_id, }, .output_chunk_ctx = undefined, .on_output_chunk = discardVisionToolOutput, .background_url_ctx = undefined, .on_background_url_ready = discardVisionBackgroundUrl, }; } }; fn discardVisionToolOutput( _: *anyopaque, _: ?types.ToolLifecycleId, _: command_output_content.Stream, _: []const u8, ) anyerror!void {} fn discardVisionBackgroundUrl(_: *anyopaque, _: u64, _: []const u8) void {} const test_tools = [_]tool_dispatch.Tool{ builtin_tools.list_files, builtin_tools.glob_files, builtin_tools.grep_files, builtin_tools.read_file, builtin_tools.write_file, builtin_tools.edit_file, builtin_tools.delete_file, builtin_tools.rename_file, builtin_tools.copy_file, builtin_tools.create_folder, builtin_tools.file_info, builtin_tools.memory, builtin_tools.semantic_search, builtin_tools.open_file, builtin_tools.web_fetch, builtin_tools.web_search, builtin_tools.terminal, builtin_tools.skill, builtin_tools.install_skill, builtin_tools.subagent, builtin_tools.mcp_search_tools, builtin_tools.mcp_select_tool, builtin_tools.ask_user_question, builtin_tools.read_tool_result, }; const test_tool_registry = tool_dispatch.Registry{ .tools = test_tools[0..] }; fn testExecutionAuthority(call: ToolCall) command_admission.ToolExecutionAuthority { return testExecutionAuthorityWithScope(call, .restricted); } fn testExecutionAuthorityWithScope( call: ToolCall, scope: permission_auto_classifier.SandboxScope, ) command_admission.ToolExecutionAuthority { if (!std.mem.eql(u8, call.name, "terminal")) return .ordinary; return .{ .run_command = .{ .shell_allowed = .{ .fingerprint = .{ .command = call.arguments_json, .resolved_cwd = "", .background = false, .resolved_backend = .none, .target_os = builtin.os.tag, .scope = scope, }, .source = .interactive_once, } } }; } pub const FakeCompletion = struct { status: std.http.Status = .ok, err_body: ?[]const u8 = null, retry_after_seconds: ?u64 = null, pre_send_error: ?anyerror = null, stream_error: ?anyerror = null, stream_error_after_chunks: ?anyerror = null, stream_error_after_tool_starts: ?anyerror = null, chunks: []const []const u8 = &.{}, reasoning_chunks: []const []const u8 = &.{}, content: ?[]const u8 = null, tool_calls: []const ToolCall = &.{}, streamed_tool_starts: []const ToolCall = &.{}, provider_result_identity_failure: ?types.ProviderResultIdentityFailure = null, provider_failure_detail: ?[]const u8 = null, finish_reason: ?types.ProviderFinishReason = null, omit_finish: bool = false, usage: types.Usage = .{}, delivery_ambiguous: bool = false, pause_before_output: bool = false, cancel_before_output: bool = false, cancel_after_chunks: bool = false, cancel_during_tool_stream: bool = false, }; pub const FakeGateway = struct { alloc: Allocator, completions: []const FakeCompletion, index: usize = 0, request_bodies: std.ArrayList([]u8) = .empty, request_models: std.ArrayList([]u8) = .empty, request_api_keys: std.ArrayList([]u8) = .empty, request_session_ids: std.ArrayList(?[]u8) = .empty, recovery_pause_flag: ?*std.atomic.Value(bool) = null, pub fn init(alloc: Allocator, completions: []const FakeCompletion) FakeGateway { return .{ .alloc = alloc, .completions = completions }; } pub fn deinit(self: *FakeGateway) void { for (self.request_bodies.items) |body| self.alloc.free(body); self.request_bodies.deinit(self.alloc); for (self.request_models.items) |model| self.alloc.free(model); self.request_models.deinit(self.alloc); for (self.request_api_keys.items) |api_key| self.alloc.free(api_key); self.request_api_keys.deinit(self.alloc); for (self.request_session_ids.items) |session_id| { if (session_id) |id| self.alloc.free(id); } self.request_session_ids.deinit(self.alloc); } pub fn provider(self: *FakeGateway) agent_stream_provider.Provider { var result = builtin_gateway.agent_stream_provider; result.context = self; result.stream_fn = fakeGatewayStream; return result; } fn stream( self: *FakeGateway, alloc: Allocator, request: agent_stream_provider.Request, ) !agent_stream_provider.Result { try self.request_bodies.append(self.alloc, try self.alloc.dupe(u8, request.payload)); try self.request_models.append(self.alloc, try self.alloc.dupe(u8, request.model)); try self.request_api_keys.append(self.alloc, try self.alloc.dupe(u8, request.api_key)); const session_id = if (request.session_id) |id| try self.alloc.dupe(u8, id) else null; errdefer if (session_id) |id| self.alloc.free(id); try self.request_session_ids.append(self.alloc, session_id); if (self.index >= self.completions.len) return error.TestUnexpectedGatewayRequest; const completion = self.completions[self.index]; self.index += 1; if (completion.pre_send_error) |err| { recordNetworkFailureEvidence(request, err); return err; } request.delivery.markPossiblySent(); if (completion.stream_error) |err| { recordNetworkFailureEvidence(request, err); return err; } if (completion.pause_before_output) { if (self.recovery_pause_flag) |flag| flag.store(true, .seq_cst); request.cancel_flag.store(true, .seq_cst); return error.Cancelled; } if (completion.cancel_before_output) { request.cancel_flag.store(true, .seq_cst); return .{ .status = .ok }; } if (request.on_reasoning_chunk) |reasoning| { for (completion.reasoning_chunks) |chunk| reasoning(request.callback_ctx, chunk); } for (completion.chunks) |chunk| { request.on_content_chunk(request.callback_ctx, chunk); } if (completion.cancel_after_chunks) request.cancel_flag.store(true, .seq_cst); if (completion.stream_error_after_chunks) |err| { recordNetworkFailureEvidence(request, err); return err; } if (request.on_tool_start) |start| { for (completion.streamed_tool_starts) |call| { start(request.callback_ctx, call.id, call.name, null); } } if (completion.stream_error_after_tool_starts) |err| { recordNetworkFailureEvidence(request, err); return err; } if (completion.cancel_during_tool_stream) { request.cancel_flag.store(true, .seq_cst); return error.Cancelled; } if (completion.status != .ok) { const err_body = if (completion.err_body) |body| try alloc.dupe(u8, body) else null; const diagnostics = gateway_failure_diagnostics.collect(alloc, request.payload, err_body); return .{ .status = completion.status, .err_body = err_body, .retry_after_seconds = completion.retry_after_seconds, .failure_schema = diagnostics.schema, .failure_request_shape = diagnostics.request_shape, .ownership = .owned, }; } return .{ .status = .ok, .completion = .{ .content = completion.content, .tool_calls = completion.tool_calls, .provider_result_identity_failure = completion.provider_result_identity_failure, .provider_failure_detail = completion.provider_failure_detail, .delivery_ambiguous = completion.delivery_ambiguous, .finish_reason = if (completion.omit_finish) null else completion.finish_reason orelse if (completion.tool_calls.len > 0) .tool_calls else .stop, .usage = completion.usage, }, .generation_origin = "https://ai-gateway.vercel.sh", }; } fn recordNetworkFailureEvidence( request: agent_stream_provider.Request, err: anyerror, ) void { request.attempt_evidence.network_failure = gateway_client.networkFailureEvidence( err, request.delivery.load(), ); } }; pub const ModelCapabilityOverride = struct { model: []const u8, capabilities: model_capabilities.Capabilities, }; fn fakeGatewayStream( context: ?*anyopaque, alloc: Allocator, request: agent_stream_provider.Request, ) !agent_stream_provider.Result { const gateway: *FakeGateway = @ptrCast(@alignCast(context.?)); return gateway.stream(alloc, request); } pub const FakeExecPlan = union(enum) { result: ToolExecutionResult, err: anyerror, }; pub const ExecuteDelegate = struct { ctx: *anyopaque, run: *const fn (*anyopaque, ToolExecutionRequest) anyerror!ToolExecutionResult, set_agent_stream_provider: ?*const fn (*anyopaque, agent_stream_provider.Provider) void = null, }; pub const PermissionRequestOverride = struct { context: *anyopaque, request_fn: *const fn ( *anyopaque, Allocator, ToolCall, permission_auto_classifier.ReviewTurnContext, PermissionMode, []const PermissionGrant, ?runtime_tool_contracts.LiveToolAuthority, ?runtime_tool_contracts.LivePermissionRevalidation, []const []const u8, ) anyerror!command_admission.PermissionOutcome, }; pub const SandboxWideningRequestOverride = struct { context: *anyopaque, request_fn: *const fn ( *anyopaque, Allocator, ToolCall, permission_auto_classifier.ReviewTurnContext, PermissionMode, []const PermissionGrant, ?runtime_tool_contracts.LiveToolAuthority, []const []const u8, SandboxScopeRequired, ) anyerror!command_admission.PermissionOutcome, }; pub const ToolExecutionOverride = struct { context: *anyopaque, execute_fn: *const fn ( *anyopaque, ToolExecutionRequest, ) anyerror!ToolExecutionResult, }; fn captureReviewAuthority( alloc: Allocator, review_turn: permission_auto_classifier.ReviewTurnContext, ) ![]u8 { var captured: std.ArrayList(u8) = .empty; errdefer captured.deinit(alloc); if (review_turn.current_root_request.len > 0) { try captured.appendSlice(alloc, review_turn.current_root_request); try captured.append(alloc, '\n'); } return captured.toOwnedSlice(alloc); } pub const FakeAgentRuntimeDeps = struct { alloc: Allocator, agent_stream_provider: agent_stream_provider.Provider = agent_stream_provider.unavailable_provider, live_tool_authority: ?runtime_deps.LiveToolAuthorityProvider = null, tool_activity_recorder: ?runtime_deps.ToolActivityRecorder = null, tool_registry: tool_dispatch.Registry = test_tool_registry, context_registry: ?context_contract.Registry = null, context_enabled: bool = false, execute_mutex: std.Io.Mutex = .init, log: std.ArrayList([]u8) = .empty, texts: std.ArrayList([]u8) = .empty, system_notices: std.ArrayList([]u8) = .empty, interactive_notices: std.ArrayList(types.SemanticNotice) = .empty, context_notices: std.ArrayList([]u8) = .empty, route_recovery_statuses: std.ArrayList(types.RouteRecoveryStatus) = .empty, permission_names: std.ArrayList([]u8) = .empty, permission_call_ids: std.ArrayList([]u8) = .empty, permission_user_intent_contexts: std.ArrayList([]u8) = .empty, permission_review_models: std.ArrayList([]u8) = .empty, permission_review_target_call_ids: std.ArrayList([]u8) = .empty, permission_review_origins: std.ArrayList(permission_auto_classifier.ReviewOrigin) = .empty, permission_review_root_authority_counts: std.ArrayList(usize) = .empty, permission_review_feedback_counts: std.ArrayList(usize) = .empty, permission_review_pending_call_counts: std.ArrayList(usize) = .empty, sandbox_widening_user_intent_contexts: std.ArrayList([]u8) = .empty, executed_names: std.ArrayList([]u8) = .empty, executed_call_ids: std.ArrayList([]u8) = .empty, rejected_names: std.ArrayList([]u8) = .empty, inner_usage_names: std.ArrayList([]u8) = .empty, inner_usages: std.ArrayList(types.ToolUsage) = .empty, validated_names: std.ArrayList([]u8) = .empty, availability_checked_names: std.ArrayList([]u8) = .empty, execution_classification_complete: std.ArrayList(bool) = .empty, last_validated_arguments: ?[]u8 = null, last_permission_arguments: ?[]u8 = null, last_executed_arguments: ?[]u8 = null, last_execute_root_user_intent_context: ?[]u8 = null, last_execute_root_user_messages: std.ArrayList([]u8) = .empty, last_execute_root_user_evidence_complete: bool = false, propagated_grants: std.ArrayList(PermissionGrant) = .empty, event_grants: std.ArrayList(PermissionGrant) = .empty, last_execute_grants: std.ArrayList(PermissionGrant) = .empty, last_live_authority_generation: ?u64 = null, last_live_authority_sandbox: ?types.BackendKind = null, last_live_authority_tool_count: usize = 0, last_live_authority_integration_count: usize = 0, last_live_authority_rule_count: usize = 0, last_live_authority_grant_count: usize = 0, last_frozen_file_grants: std.ArrayList(PermissionGrant) = .empty, permission_decisions: []const ToolPermissionDecision = &.{}, permission_auto_review_results: []const ?permission_auto_classifier.Result = &.{}, permission_denial_reasons: []const types.ToolPermissionDenialReason = &.{},