9053 lines · 357.2 KB · Zig
RawDownload
const std = @import("std");const std_builtin = @import("builtin");const command_admission = @import("../permissions/command_admission.zig");const agent_runtime = @import("../agent/agent_runtime.zig");const app_lifecycle = @import("../app/app_lifecycle.zig");const app_runtime_setup = @import("../app/app_runtime_setup.zig");const auth_runtime = @import("../auth/auth_runtime.zig");const credentials = @import("../auth/credentials.zig");const oauth_transport = @import("../auth/oauth_transport.zig");const background_runtime = @import("../background/background_runtime.zig");const terminal_client_runtime = @import("../terminal/client.zig");const background_store = @import("../background/background_store.zig");const process_supervisor = @import("../background/process_supervisor.zig");const context_contract = @import("../workspace/context_contract.zig");const devbox_executor = @import("../execution/devbox_executor.zig");const gateway_provider = @import("../gateway/gateway_provider.zig");const background_process_provider = @import(    "../execution/background_process_provider.zig",);const host = @import("../hosts/host.zig");const pathing = @import("../workspace/pathing.zig");const workspace_access = @import("../workspace/workspace_access.zig");const debug_trace = @import("../shared/debug_trace.zig");const diff_mod = @import("../output/diff.zig");const file_mutation = @import("../tooling/file_mutation.zig");const gateway_error_format = @import("../shared/gateway_error_format.zig");const image_attachments = @import("../images/image_attachments.zig");const hooks = @import("../hooks/hooks.zig");const notification_sound = @import("../notifications/sound.zig");const io_mod = @import("../shared/io.zig");const config_runtime = @import("../config/config_runtime.zig");const model_capabilities = @import("../config/model_capabilities.zig");const mcp_elicitation_interaction = @import("../mcp/elicitation_interaction.zig");const mcp_elicitation = @import("../mcp/elicitation.zig");const mcp_access_policy = @import("../mcp/access_policy.zig");const mcp_model_catalog = @import("../mcp/model_catalog.zig");const mcp_runtime = @import("../mcp/mcp_runtime.zig");const mode_registry = @import("../modes/mode_registry.zig");const permission_auto_classifier = @import("../permissions/auto_classifier.zig");const prompt_policy = @import("../config/prompt_policy.zig");const auto_classifier_context = @import("../permissions/auto_classifier_context.zig");const permission_gate = @import("../permissions/permission_gate.zig");const permission_request = @import("../permissions/permission_request.zig");const permissions = @import("../permissions/permissions.zig");const sandbox = @import("../permissions/sandbox.zig");const session_runtime = @import("../session/session.zig");const session_codec = @import("../session/session_codec.zig");const session_usage = @import("../session/session_usage.zig");const usage_report = @import("../session/usage_report.zig");const session_store = @import("../session/session_store.zig");const skill_contract = @import("../skills/skill_contract.zig");const skill_runtime = @import("../skills/skill_runtime.zig");const subagent_agent_adapter = @import("../subagent/agent_adapter.zig");const subagent_authority = @import("../subagent/authority.zig");const subagent_domain = @import("../subagent/domain.zig");const subagent_execution = @import("../subagent/execution.zig");const subagent_manager = @import("../subagent/manager.zig");const subagent_resume_admission = @import("../subagent/resume_admission.zig");const parent_delivery_projector = @import("../subagent/parent_delivery_projector.zig");const subagent_tool_host = @import("../subagent/tool_host.zig");const text_utils = @import("../shared/text_utils.zig");const test_builtin_gateway = if (std_builtin.is_test)    @import("../../builtins/gateway.zig")else    struct {};const test_builtin_tools = @import("../../builtins/tools.zig");const tool_advertisement = @import("../tooling/tool_advertisement.zig");const tool_admission = @import("../tooling/tool_admission.zig");const tool_args = @import("../tooling/tool_args.zig");const tool_dispatch = @import("../tooling/tool_dispatch.zig");const command_output_content = @import("../tooling/command_output_content.zig");const tool_mcp_runtime = @import("../tooling/tool_mcp_runtime.zig");const tool_presentation = @import("../tooling/tool_presentation.zig");const tool_result_errors = @import("../tooling/tool_result_errors.zig");const tool_runtime = @import("../tooling/tool_runtime.zig");const tool_set_contract = @import("../tooling/tool_set.zig");const tool_specs = @import("../tooling/tool_specs.zig");const skill_invocation = @import("../skills/skill_invocation.zig");const web_fetch_runtime = @import("../tooling/web_fetch_runtime.zig");const web_search_runtime = @import("../tooling/web_search_runtime.zig");const types = @import("../shared/types.zig");const worker_runtime = @import("../agent/worker_runtime.zig");const ask_presentation = @import("../../ui/ask_presentation.zig");const url_opener = @import("../hosts/url_opener.zig"); const Allocator = std.mem.Allocator;const BackgroundRuntime = background_runtime.BackgroundRuntime;const ChatMessage = types.ChatMessage;const HistoryTurn = types.HistoryTurn;const ImageAttachment = types.ImageAttachment;const PermissionGrant = types.PermissionGrant;const PermissionMode = types.PermissionMode;const SessionRuntime = session_runtime.SessionRuntime;const ToolCall = types.ToolCall;const ToolExecutionResult = agent_runtime.ToolExecutionResult;const ToolPermissionDecision = types.ToolPermissionDecision;const WorkerEvent = worker_runtime.WorkerEvent;const WorkerRuntime = worker_runtime.WorkerRuntime;const McpHasToolFn = tool_mcp_runtime.HasToolFn; const supports_headless_interrupt = switch (std_builtin.os.tag) {    .windows, .wasi, .freestanding => false,    else => true,}; const HeadlessInterruptInstallError = error{HeadlessInterruptBusy};const headless_interrupt_exit_code: u8 = 130;const headless_termination_exit_code: u8 = 143; const headless_interrupt = if (supports_headless_interrupt) struct {    var coordinator_mutex: std.Io.Mutex = .init;    var coordinator_active = false;    var cancel_requested = std.atomic.Value(bool).init(false);    var requested_signal = std.atomic.Value(u8).init(0);    var test_after_reset_before_install: if (std_builtin.is_test) ?*const fn () void else void =        if (std_builtin.is_test) null else {};    var test_after_restore: if (std_builtin.is_test) ?*const fn () void else void =        if (std_builtin.is_test) null else {};     fn handle(signal: std.posix.SIG) callconv(.c) void {        _ = requested_signal.cmpxchgStrong(            0,            @intCast(@intFromEnum(signal)),            .seq_cst,            .seq_cst,        );        cancel_requested.store(true, .seq_cst);    }     fn exitCode() u8 {        return switch (@as(std.posix.SIG, @enumFromInt(requested_signal.load(.seq_cst)))) {            std.posix.SIG.TERM => headless_termination_exit_code,            else => headless_interrupt_exit_code,        };    }     const Scope = struct {        old_sigint_action: std.posix.Sigaction = undefined,        old_sigterm_action: std.posix.Sigaction = undefined,        installed: bool = false,         fn install(enabled: bool) HeadlessInterruptInstallError!Scope {            if (!enabled) return .{};            coordinator_mutex.lockUncancelable(io_mod.getIo());            defer coordinator_mutex.unlock(io_mod.getIo());            if (coordinator_active) return error.HeadlessInterruptBusy;             const action: std.posix.Sigaction = .{                .handler = .{ .handler = handle },                .mask = std.posix.sigemptyset(),                .flags = 0,            };            var scope = Scope{};            requested_signal.store(0, .seq_cst);            cancel_requested.store(false, .seq_cst);            if (std_builtin.is_test) {                if (test_after_reset_before_install) |hook| hook();            }            std.posix.sigaction(std.posix.SIG.INT, &action, &scope.old_sigint_action);            std.posix.sigaction(std.posix.SIG.TERM, &action, &scope.old_sigterm_action);            coordinator_active = true;            scope.installed = true;            return scope;        }         fn restore(self: *Scope, redeliver: bool) void {            if (!self.installed) return;            coordinator_mutex.lockUncancelable(io_mod.getIo());            defer coordinator_mutex.unlock(io_mod.getIo());            std.debug.assert(coordinator_active);            std.posix.sigaction(std.posix.SIG.INT, &self.old_sigint_action, null);            std.posix.sigaction(std.posix.SIG.TERM, &self.old_sigterm_action, null);            if (std_builtin.is_test) {                if (test_after_restore) |hook| hook();            }            if (redeliver and cancel_requested.load(.seq_cst)) {                const signal: std.posix.SIG = @enumFromInt(requested_signal.load(.seq_cst));                _ = std.c.raise(signal);            }            coordinator_active = false;            self.installed = false;        }         fn deinit(self: *Scope) void {            self.restore(false);        }         fn restoreAndRedeliver(self: *Scope) void {            self.restore(true);        }         fn requested(self: *const Scope) bool {            return self.installed and cancel_requested.load(.seq_cst);        }    };} else struct {    fn exitCode() u8 {        return headless_interrupt_exit_code;    }     const Scope = struct {        fn install(_: bool) HeadlessInterruptInstallError!Scope {            return .{};        }         fn deinit(_: *Scope) void {}         fn restoreAndRedeliver(_: *Scope) void {}         fn requested(_: *const Scope) bool {            return false;        }    };}; pub const Config = struct {    command_usage: []const u8,    default_model: []const u8,    default_agent_step_limit: usize,    gateway_retry_count: usize,    gateway_chat_url: []const u8,    gateway_models_path: []const u8,    gateway_provider: gateway_provider.Provider,    background_process_provider: background_process_provider.Provider =        background_process_provider.unavailable_provider,    secret_store: host.SecretStore,    prompt_policy: prompt_policy.Policy,    skill_root_policy: skill_contract.RootPolicy,    ignored_list_entries: []const []const u8,    max_list_entries: usize,    max_read_file_bytes: usize,    max_read_file_lines: usize,    max_read_file_line_len: usize,    max_command_output_bytes: usize,    max_tool_result_bytes: usize,    max_history_turns: usize,    mode_registry: mode_registry.Registry,    load_mcp_runtime: mcp_runtime.LoadRuntimeFn,    devbox_provider: ?devbox_executor.Provider = null,    permission_reviewer_provider: ?permission_auto_classifier.Provider = null,    context_limit_overrides: []const config_runtime.context_limits.Override = &.{},    additional_directories: []const []const u8 = &.{},    saved_directories_suppressed: bool = false,}; fn runAskChild(    raw: ?*anyopaque,    turn: *subagent_execution.TurnContext,    message: subagent_domain.QueuedMessage,    admission: subagent_domain.AdmissionSnapshot,    cancel: *std.atomic.Value(bool),) subagent_execution.ServiceError!subagent_execution.RunOutcome {    const ctx: *AskContext = @ptrCast(@alignCast(raw.?));    var child_projection = ctx.cfg.mode_registry.buildGatewayToolProjection(        ctx.alloc,        ctx.deps.tool_set,        ctx.mode_id,        .{            .permission_mode = admission.permission_mode,            .permission_rules = admission.rules,            .mcp_runtime = ctx.mcp,            .subagent_available = true,        },    ) catch return error.OutOfMemory;    defer child_projection.deinit(ctx.alloc);    return subagent_agent_adapter.run(.{        .host = ctx.subagent_host orelse return error.ProviderFailed,        .tool_context = ctx.toolContext(),        .system_prompt = ctx.cfg.prompt_policy.system_prompt,        .model_prompt_overlay = ctx.cfg.prompt_policy.modelPromptOverlay(admission.model),        .skills_prompt_section = ctx.subagent_skills_prompt,        .explicit_skills_prompt_section = ctx.subagent_explicit_skills_prompt,        .gateway_tools_json = child_projection.tools_json,        .custom_tool_guidance = child_projection.custom_guidance,        .context_registry = ctx.deps.context_registry,        .context_enabled = ctx.context_enabled,        .project_context = ctx.modelVisibleProjectContext(),        .lifecycle_view = ctx.lifecycle_view,    }, turn, message, admission, cancel);} pub const PromptRunResult = struct {    exit_code: u8,    assistant_output: []u8,    interrupted: bool = false,    model: []u8 = &.{},    session_id: []u8 = &.{},    tool_calls: []ToolCallRecord = &.{},    step_count: usize = 0,    error_code: ?[]const u8 = null,    auth_failure: ?auth_runtime.FailureSnapshot = null,    recovery: ?types.RouteRecoveryStatus = null,    recovery_durable: bool = false,     pub fn deinit(self: PromptRunResult, alloc: Allocator) void {        alloc.free(self.assistant_output);        if (self.model.len > 0) alloc.free(self.model);        if (self.session_id.len > 0) alloc.free(self.session_id);        freeToolCallRecords(alloc, self.tool_calls);    }}; /// Resume selector parsed from fx ask --resume.const ResumeTarget = session_store.ResumeTarget; const AskOptions = struct {    prompt: []u8,    resume_target: ?ResumeTarget = null,    permission_override: ?PermissionMode = null,    image_paths: std.ArrayList([]u8) = .empty,    images: std.ArrayList(ImageAttachment) = .empty,    system_prompt_override: ?[]u8 = null,    json_output: bool = false,    timeout_ms: ?usize = null,    quiet: bool = false,    verbose: bool = false,    no_save: bool = false,    no_color: bool = false,    continue_recovery: bool = false,     fn deinit(self: *AskOptions, alloc: Allocator) void {        alloc.free(self.prompt);        for (self.image_paths.items) |p| alloc.free(p);        self.image_paths.deinit(alloc);        for (self.images.items) |image| types.freeImageAttachment(alloc, image);        self.images.deinit(alloc);        if (self.system_prompt_override) |s| alloc.free(s);    }}; const ToolCallRecord = struct {    name: []u8,    status: []u8,    command_result_json: ?[]u8 = null,    ask_question_text: ?[]u8 = null,    web_search_completion: ?types.WebSearchCompletion = null,    web_fetch_completion: ?types.WebFetchCompletion = null,}; const PendingToolProgress = struct {    call_id: []u8,    tool_name: []u8,    text: ?[]u8 = null,    visible: bool = false,     fn deinit(self: PendingToolProgress, alloc: Allocator) void {        alloc.free(self.call_id);        alloc.free(self.tool_name);        if (self.text) |text| alloc.free(text);    }}; fn freeToolCallRecord(alloc: Allocator, record: ToolCallRecord) void {    alloc.free(record.name);    alloc.free(record.status);    if (record.command_result_json) |json| alloc.free(json);    if (record.ask_question_text) |text| alloc.free(text);} fn freeToolCallRecords(alloc: Allocator, records: []ToolCallRecord) void {    for (records) |record| freeToolCallRecord(alloc, record);    if (records.len > 0) alloc.free(records);} const WriteFn = *const fn (?*anyopaque, []const u8) anyerror!void;const PermissionApprovalPromptResult = enum {    approve,    deny,    unavailable,};const NotifyAttentionFn = *const fn (?*anyopaque) void;const PermissionApprovalPromptFn = *const fn (?*anyopaque, ?*anyopaque, WriteFn, []const u8, ?*anyopaque, NotifyAttentionFn) anyerror!PermissionApprovalPromptResult;const IsTtyFn = *const fn (?*anyopaque) bool;const LoadStartupStateFn = *const fn (Allocator, oauth_transport.Provider, host.SecretStore, []const u8, usize) anyerror!app_lifecycle.StartupState;const InitializeSessionStoresFn = *const fn (*AskContext) anyerror!void;const LoadSkillsFn = *const fn (    Allocator,    []const u8,    skill_contract.RootPolicy,) app_runtime_setup.LoadSkillsError!app_runtime_setup.LoadedSkills;const ProcessQueuedPromptFn = *const fn (*const agent_runtime.AgentRuntimeDeps, ?agent_runtime.SemanticPresentationSink, agent_runtime.LifecycleContext, agent_runtime.Config, worker_runtime.QueuedPrompt) anyerror!void;const DiscardPristineSessionFn = *const fn (?*anyopaque, *AskContext, *session_store.LoadedWritableSession) session_store.PristineDiscardDisposition;const PersistYoloAcknowledgmentFn = *const fn (Allocator) config_runtime.CommitAttempt; const RunDeps = struct {    stdin_ctx: ?*anyopaque = null,    stdout_ctx: ?*anyopaque = null,    stderr_ctx: ?*anyopaque = null,    permission_approval_prompt_ctx: ?*anyopaque = null,    write_stdout: WriteFn = writeRealStdout,    write_stderr: WriteFn = writeRealStderr,    permission_approval_prompt: PermissionApprovalPromptFn = promptRealPermissionApproval,    stdin_is_tty: IsTtyFn = realStdinIsTty,    stdout_is_tty: IsTtyFn = realStdoutIsTty,    stderr_is_tty: IsTtyFn = realStderrIsTty,    load_startup_state: LoadStartupStateFn = loadStartupStateDefault,    initialize_session_stores: InitializeSessionStoresFn = initializeSessionStoresDefault,    load_skills: LoadSkillsFn = app_runtime_setup.loadSkills,    context_registry: context_contract.Registry,    tool_set: tool_set_contract.ToolSet,    load_mcp_runtime: mcp_runtime.LoadRuntimeFn,    process_queued_prompt: ProcessQueuedPromptFn = processQueuedPromptDefault,    persist_yolo_acknowledgment: PersistYoloAcknowledgmentFn = persistYoloAcknowledgmentDefault,    discard_pristine_session_ctx: ?*anyopaque = null,    discard_pristine_session: DiscardPristineSessionFn = discardPristineSessionDefault,    install_headless_interrupt: bool = false,    start_subagent_background_recovery: bool = true,    stdin_source: StdinSource = .real,}; const OutputMode = enum {    quiet,    json,    raw,    terminal,    terminal_no_color,     fn isTerminal(self: OutputMode) bool {        return self == .terminal or self == .terminal_no_color;    }     fn capturesJson(self: OutputMode) bool {        return self == .json;    }     fn permitsPermissionPrompt(self: OutputMode) bool {        return self == .raw or self.isTerminal();    }}; const RunOptions = struct {    output_mode: OutputMode,    images: []const ImageAttachment = &.{},    command_timeout_ms: ?usize = null,    save_session: bool = true,    resume_target: ?ResumeTarget = null,    color_enabled: bool = true,    continue_recovery: bool = false,    deps: RunDeps,}; const StdinSource = union(enum) {    real,    tty,    bytes: []const u8,    read_error,}; const stdin_prompt_resource_byte_limit: usize = 8 * 1024 * 1024; const AskContext = struct {    alloc: Allocator,    cfg: Config,    deps: RunDeps,    workspace_root: []const u8,    workspace_access: workspace_access.WorkspaceAccess = .{},    api_key: []const u8 = "",    gateway_team: ?[]const u8 = null,    credential_source: ?types.CredentialSource = null,    model_catalog_access: credentials.CatalogAccess = .{ .public_only = .no_credential },    model: []const u8 = "",    agent_step_limit: usize = 0,    max_tool_result_bytes: usize = 64 * 1024,    context_limits: config_runtime.context_limits.Values = .{},    fast_mode: bool = false,    effort: types.ReasoningEffort = .auto,    first_call_tool_choice: types.ToolChoice = .auto,    permission_mode: PermissionMode = .ask,    permission_rules: types.PermissionRuleSet = .{},    mode_id: []const u8,    auto_classifier: permission_auto_classifier.Classifier =        permission_auto_classifier.Classifier.disabled(),    sandbox_backend: sandbox.BackendKind = .none,    worker: WorkerRuntime = .{},    use_process_interrupt_flag: bool = false,    background: BackgroundRuntime = .{},    terminal_client: terminal_client_runtime.Runtime = .{},    subagent_host: ?*subagent_tool_host.Runtime = null,    subagent_skills_prompt: []u8 = &.{},    subagent_explicit_skills_prompt: []u8 = &.{},    store: ?session_store.Store = null,    writable: ?session_store.LoadedWritableSession = null,    session_write_mutex: std.Io.Mutex = .init,    requested_resume: ?ResumeTarget = null,    seed_model: []const u8 = "",    command_timeout_ms: ?usize = null,    session: SessionRuntime,    skills_dir: []u8 = &.{},    context_snapshot: context_contract.GatheredContextSnapshot = .{},    context_enabled: bool = true,    mcp: ?*mcp_runtime.McpRuntime = null,    mcp_elicitation_capabilities: @import("../mcp/elicitation.zig").Capabilities = .{},    failed: bool = false,    typed_error_code: ?[]const u8 = null,    auth_failure: ?auth_runtime.FailureSnapshot = null,    output_mode: OutputMode = .raw,    presenter: ?*ask_presentation.Runtime = null,    pending_tool_progress: std.ArrayList(PendingToolProgress) = .empty,    deferred_tool_progress: std.ArrayList([]u8) = .empty,    pending_tool_progress_mutex: std.Io.Mutex = .init,

Lines 1–500 of 9053.