2323 lines · 97.4 KB · Zig
RawDownload
const std = @import("std");const agent_runtime = @import("../agent/agent_runtime.zig");const agent_stream_provider = @import("../agent/stream_provider.zig");const command_admission = @import("../permissions/command_admission.zig");const permission_auto_classifier = @import("../permissions/auto_classifier.zig");const auth_runtime = @import("../auth/auth_runtime.zig");const credentials = @import("../auth/credentials.zig");const model_capabilities = @import("../config/model_capabilities.zig");const input_completion_runtime = @import("input_completion_runtime.zig");const core_input_runtime = @import("../input/runtime.zig");const app_worker_runtime = @import("app_worker_runtime.zig");const app_session_runtime = @import("app_session_runtime.zig");const change_tracker_mod = @import("../workspace/change_tracker.zig");const debug_trace = @import("../shared/debug_trace.zig");const diagnostics = @import("../workspace/diagnostics.zig");const diff_mod = @import("../output/diff.zig");const file_mutation = @import("../tooling/file_mutation.zig");const file_mutation_contract = @import("../tooling/file_mutation_contract.zig");const command_output_content = @import("../tooling/command_output_content.zig");const tool_admission = @import("../tooling/tool_admission.zig");const gateway_error_format = @import("../shared/gateway_error_format.zig");const io_mod = @import("../shared/io.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 parent_delivery_projector = @import("../subagent/parent_delivery_projector.zig");const task_helpers = @import("../tasks/task_helpers.zig");const types = @import("../shared/types.zig");const worker_runtime = @import("../agent/worker_runtime.zig");const assistant_presentation = @import("../agent/assistant_presentation.zig");const activity_runtime = @import("../output/activity_runtime.zig");const assistant_pacer = @import("../../ui/assistant/pacer.zig");const ui_render = @import("../../ui/render.zig");const render_request = @import("../../ui/render_request.zig");const transcript_runtime = @import("../../ui/transcript/runtime.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 ToolExecutionResult = agent_runtime.ToolExecutionResult;const WorkerEvent = worker_runtime.WorkerEvent; const reset_style = ui_render.reset_style; fn preparedDiffPayload(    alloc: Allocator,    handoff: file_mutation.CommittedFileHandoff,) !diff_mod.DiffEntryPayload {    return preparedDiffPayloadWithFullAllocator(alloc, alloc, handoff);} fn preparedDiffPayloadWithFullAllocator(    alloc: Allocator,    full_alloc: Allocator,    handoff: file_mutation.CommittedFileHandoff,) !diff_mod.DiffEntryPayload {    return diff_mod.formatFileChangePayload(        alloc,        full_alloc,        handoff.preview,        handoff.tracker.previous_content,        if (handoff.full_view) |snapshot| .{            .after_content = snapshot.after_content,            .lifecycle_id = snapshot.lifecycle_id,        } else null,        .{            .added_fg = ui_render.diff_added_style,            .removed_fg = ui_render.diff_removed_style,            .context_fg = ui_render.dim_style,            .added_marker_fg = ui_render.diff_added_marker_style,            .removed_marker_fg = ui_render.diff_removed_marker_style,            .reset = ui_render.reset_style,        },    );} test "prepared preview formatter preserves context and informative elision" {    const preview: diff_mod.FileChangePreview = .{        .path = "note.txt",        .lines = &.{            .{                .op = .context,                .old_line = 1,                .new_line = 1,                .text = "alpha",            },            .{                .op = .deletion,                .old_line = 2,                .text = "before",            },            .{                .op = .addition,                .new_line = 2,                .text = "after",            },            .{                .op = .elision,                .text = "⋯ +2 -1 omitted",            },        },        .additions = 3,        .deletions = 2,        .truncated = true,    };    const formatted = try diff_mod.formatFileChangePreview(        std.testing.allocator,        preview,        .{            .added_fg = "",            .removed_fg = "",            .context_fg = "",            .reset = "",        },    );    defer std.testing.allocator.free(formatted);     try std.testing.expect(std.mem.find(u8, formatted, "alpha") != null);    try std.testing.expect(        std.mem.find(u8, formatted, "⋯ +2 -1 omitted") != null,    );} test "prepared diff payload keeps compact elision and retains the complete approved review" {    const alloc = std.testing.allocator;    var after: std.ArrayList(u8) = .empty;    defer after.deinit(alloc);    for (1..121) |line_number| {        var line: [32]u8 = undefined;        try after.appendSlice(            alloc,            try std.fmt.bufPrint(&line, "full-review-{d:0>3}\n", .{line_number}),        );    }     const preview_lines = [_]diff_mod.PreviewLine{        .{ .op = .addition, .new_line = 1, .text = "full-review-001" },        .{ .op = .elision, .text = "⋯ +118 omitted" },        .{ .op = .addition, .new_line = 120, .text = "full-review-120" },    };    const handoff = file_mutation.CommittedFileHandoff.init(        .{            .path = "full-review.txt",            .lines = &preview_lines,            .additions = 120,            .deletions = 0,            .truncated = true,        },        .{            .kind = .write,            .raw_path = "/tmp/full-review.txt",            .previous_content = null,            .committed_at_ms = 0,        },    );    var enriched_handoff = handoff;    enriched_handoff.full_view = .{        .after_content = after.items,        .lifecycle_id = .{ .turn_id = 39, .call_id = "full-review" },    };     const payload = try preparedDiffPayload(alloc, enriched_handoff);    defer diff_mod.freeDiffEntryPayload(alloc, payload);     try std.testing.expect(std.mem.indexOf(u8, payload.preview, "⋯ +118 omitted") != null);    const full = payload.full orelse return error.TestExpectedFullDiff;    try std.testing.expect(std.mem.indexOf(u8, full.content, "full-review-001") != null);    try std.testing.expect(std.mem.indexOf(u8, full.content, "full-review-120") != null);    try std.testing.expect(std.mem.indexOf(u8, full.content, "⋯ +118 omitted") == null);} test "prepared diff payload keeps compact output when full formatting is unavailable" {    const handoff = testCommittedFileHandoff();    var enriched_handoff = handoff;    enriched_handoff.full_view = .{        .after_content = "after\n",        .lifecycle_id = .{ .turn_id = 40, .call_id = "full-format-fallback" },    };    var failing = std.testing.FailingAllocator.init(        std.testing.allocator,        .{ .fail_index = 0 },    );     const payload = try preparedDiffPayloadWithFullAllocator(        std.testing.allocator,        failing.allocator(),        enriched_handoff,    );    defer diff_mod.freeDiffEntryPayload(std.testing.allocator, payload);     try std.testing.expect(payload.full == null);    try std.testing.expect(std.mem.indexOf(u8, payload.preview, "after") != null);} test "full diff formatter renders unchanged review elisions" {    const before =        "same-01\n" ++        "same-02\n" ++        "same-03\n" ++        "same-04\n" ++        "same-05\n" ++        "same-06\n" ++        "same-07\n" ++        "same-08\n" ++        "same-09\n" ++        "same-10\n" ++        "old\n";    const after =        "same-01\n" ++        "same-02\n" ++        "same-03\n" ++        "same-04\n" ++        "same-05\n" ++        "same-06\n" ++        "same-07\n" ++        "same-08\n" ++        "same-09\n" ++        "same-10\n" ++        "new\n";    const preview_lines = [_]diff_mod.PreviewLine{        .{ .op = .deletion, .old_line = 11, .text = "old" },        .{ .op = .addition, .new_line = 11, .text = "new" },    };    var handoff = file_mutation.CommittedFileHandoff.init(        .{            .path = "elision.txt",            .lines = &preview_lines,            .additions = 1,            .deletions = 1,            .truncated = false,        },        .{            .kind = .edit,            .raw_path = "/tmp/elision.txt",            .previous_content = before,            .committed_at_ms = 0,        },    );    handoff.full_view = .{        .after_content = after,        .lifecycle_id = .{ .turn_id = 41, .call_id = "context-elision" },    };     const snapshot = handoff.full_view orelse return error.TestExpectedFullDiff;    const full = (try diff_mod.formatFileChangeFullDiff(        std.testing.allocator,        handoff.tracker.previous_content,        .{            .after_content = snapshot.after_content,            .lifecycle_id = snapshot.lifecycle_id,        },        .{},    )) orelse        return error.TestExpectedFullDiff;    defer full.deinit(std.testing.allocator);    try std.testing.expect(std.mem.indexOf(u8, full.content, "5 unchanged lines ⋯") != null);    try std.testing.expect(std.mem.indexOf(u8, full.content, "old") != null);    try std.testing.expect(std.mem.indexOf(u8, full.content, "new") != null);} pub fn Bindings(comptime App: type) type {    return struct {        pub fn agentRuntimeDeps(app: *App) agent_runtime.AgentRuntimeDeps {            var deps: agent_runtime.AgentRuntimeDeps = .{                .ctx = @ptrCast(app),                .agent_stream_provider = if (comptime @hasDecl(App, "agentStreamProvider"))                    app.agentStreamProvider()                else                    agent_stream_provider.unavailable_provider,                .cooperative_transport_pulse = if (comptime @hasDecl(App, "cooperativeTransportPulse")) .{                    .ctx = @ptrCast(app),                    .run = cooperativeTransportPulse,                } else null,                .tool_registry = if (comptime @hasDecl(App, "toolRegistry")) app.toolRegistry() else .{},                .context_registry = if (comptime @hasDecl(App, "contextRegistry")) app.contextRegistry() else null,                .context_enabled = if (comptime @hasField(App, "context_enabled")) app.context_enabled else false,                .finalize_turn = agentFinalizeTurn,                .prepare_parent_turn_context = agentPrepareParentTurnContext,                .acknowledge_parent_turn_context = agentAcknowledgeParentTurnContext,                .append_runtime_context = agentAppendRuntimeContext,                .append_static_context = agentAppendStaticContext,                .validate_tool_call = agentValidateToolCall,                .check_tool_availability = agentCheckToolAvailability,                .request_tool_permission = agentRequestToolPermission,                .request_prepared_file_mutation_permission = agentRequestPreparedFileMutationPermission,                .describe_tool_action = agentDescribeToolAction,                .describe_tool_action_completed = agentDescribeToolActionCompleted,                .describe_tool_action_denied = agentDescribeToolActionDenied,                .permission_target_for_call = agentPermissionTargetForCall,                .execute_tool_call = agentExecuteToolCall,                .publish_committed_file_handoff = agentPublishCommittedFileHandoff,                .propagate_history_turn = agentPropagateHistoryTurn,                .recovery_checkpoint = if (comptime @hasField(App, "session_persistence"))                    if (app.session_persistence.writable != null)                        .{                            .set = agentSetRecoveryCheckpoint,                        }                    else                        null                else                    null,                .propagate_grant = agentPropagateGrant,                .push_event = agentPushEvent,                .push_text = agentPushText,                .push_tool_lifecycle = agentPushToolLifecycle,                .push_diff_block = agentPushDiffBlock,                .push_system_notice = agentPushSystemNotice,                .push_interactive_notice = agentPushInteractiveNotice,                .push_context_notice = agentPushContextNotice,                .push_route_recovery_status = agentPushRouteRecoveryStatus,                .push_command_output_complete = agentPushCommandOutputComplete,                .push_http_error = agentPushHttpError,                .refresh_gateway_credential = if (comptime @hasField(App, "auth"))                    refreshGatewayCredential                else                    null,                .request_route_recovery = if (comptime @hasDecl(@TypeOf(app.worker), "requestRouteRecoveryAnswerBlocking"))                    agentRequestRouteRecovery                else                    null,                .available_model_capabilities = agentAvailableModelCapabilities,                .resolve_model_capabilities = agentResolveModelCapabilities,                .format_tool_execution_error = agentFormatToolExecutionError,                .record_tool_call_rejected = agentRecordToolCallRejected,                .report_usage = agentReportUsage,                .report_inner_tool_usage = agentReportInnerToolUsage,                .usage_allocator = app.alloc,                .diff_marker_styles = .{                    .added = ui_render.diff_added_marker_style,                    .removed = ui_render.diff_removed_marker_style,                },            };            if (comptime @hasField(@TypeOf(app.session), "usage")) {                deps.usage = &app.session.usage;                if (comptime @hasField(App, "session_persistence") and                    @hasField(@TypeOf(app.session_persistence), "writable"))                {                    app.session.usage.configureCheckpointSink(                        if (app.session_persistence.writable != null)                            .{                                .context = @ptrCast(app),                                .allocator = app.alloc,                                .persist = agentPersistUsageCheckpoint,                            }                        else                            null,                    );                }            }            if (comptime @hasDecl(App, "requestSandboxWideningSyncWithAdvertised")) {                deps.request_sandbox_widening = agentRequestSandboxWidening;            }            return deps;        }         fn refreshGatewayCredential(            raw_ctx: *anyopaque,            alloc: std.mem.Allocator,            source: credentials.Source,            mode: auth_runtime.CredentialRefreshMode,        ) !?[]u8 {            const app: *App = @ptrCast(@alignCast(raw_ctx));            return auth_runtime.refreshFxLoginToken(                app.auth.oauthTransport(),                alloc,                source,                mode,            );        }         pub fn modelCapabilityResolver(app: *App) model_capabilities.Resolver {            return .{                .ctx = @ptrCast(app),                .resolve_fn = agentResolveModelCapabilities,            };        }         pub fn semanticPresentationSink(app: *App) agent_runtime.SemanticPresentationSink {            return .{                .ctx = @ptrCast(app),                .table = agentPushTable,                .code_block = agentPushCodeBlock,                .thematic_rule = agentPushThematicRule,            };        }         pub fn workerEventHandlers(app: *App) app_worker_runtime.WorkerEventHandlers {            return .{                .ctx = @ptrCast(app),                .tool_lifecycle = worker_tool_lifecycle_presenter(app),                .write_user_prompt = workerBridgeWriteUserPrompt,                .write_user_prompt_with_skill_bindings = workerBridgeWriteUserPromptWithSkillBindings,                .append_text = workerBridgeAppendText,                .append_table = workerBridgeAppendTable,                .append_code_block = workerBridgeAppendCodeBlock,                .append_thematic_rule = workerBridgeAppendThematicRule,                .drain_assistant_text = workerBridgeDrainAssistantText,                .open_model_picker = workerBridgeOpenModelPicker,                .semantic_notice = workerBridgeSemanticNotice,                .command_output = workerBridgeCommandOutput,                .command_output_complete = workerBridgeCommandOutputComplete,                .diff_block = workerBridgeDiffBlock,                .append_history_turn = workerBridgeAppendHistoryTurn,                .session_grant = workerBridgeSessionGrant,                .error_text = workerBridgeErrorText,            };        }         pub fn worker_tool_lifecycle_presenter(            app: *App,        ) activity_runtime.LifecyclePresenter {            return .{                .ctx = @ptrCast(app),                .snapshot_fn = worker_tool_lifecycle_snapshot,                .record_fn = worker_tool_lifecycle_record,                .apply_fn = worker_apply_tool_lifecycle,                .finish_batch_fn = worker_finish_tool_lifecycle_batch,            };        }         fn worker_tool_lifecycle_snapshot(            raw_ctx: *anyopaque,        ) activity_runtime.LifecycleSnapshot {            const app: *App = @ptrCast(@alignCast(raw_ctx));            return .{                .finalized_turn_watermark = app.shell.finalizedToolTurnWatermark(),                .active_tool_count = app.shell.activeToolActivityCount(),                .focused_entry_id = app.shell.focusedToolEntryId(),                .focused_activity_kind = app.shell.focusedToolActivityKind(),                .activity = app.shell.activityProjection(),            };        }         fn worker_tool_lifecycle_record(            raw_ctx: *anyopaque,            id: types.ToolLifecycleId,        ) ?activity_runtime.ToolPresentationRecord {            const app: *App = @ptrCast(@alignCast(raw_ctx));            return app.shell.toolActivityRecord(id);        }         fn worker_apply_tool_lifecycle(            raw_ctx: *anyopaque,            alloc: std.mem.Allocator,            event: types.ToolLifecycleEvent,        ) !activity_runtime.LifecycleTransition {            const app: *App = @ptrCast(@alignCast(raw_ctx));            const previous_focused_entry_id = app.shell.focusedToolEntryId();            const preserve_normal_buffer_anchor = if (comptime @hasField(App, "terminal"))                app.terminal.alternate_screen_owner != .none            else                false;            const applied_activity_kind = if (preserve_normal_buffer_anchor)                try app.shell.applyToolLifecyclePreservingNormalBufferAnchor(alloc, event)            else                try app.shell.applyToolLifecycle(alloc, event);            return .{                .previous_focused_entry_id = previous_focused_entry_id,                .snapshot = worker_tool_lifecycle_snapshot(raw_ctx),                .applied_activity_kind = applied_activity_kind,                .terminal_record = switch (event) {                    .terminal => |terminal| app.shell.toolActivityRecord(terminal.id),                    .provisional, .authoritative_started, .progress, .turn_finished => null,                },            };        }         fn worker_finish_tool_lifecycle_batch(            raw_ctx: *anyopaque,            alloc: std.mem.Allocator,        ) !void {            const app: *App = @ptrCast(@alignCast(raw_ctx));            try app.shell.finishLifecycleBatch(alloc);        }         pub fn onCommandOutputChunk(ctx: *anyopaque, lifecycle_id: ?types.ToolLifecycleId, stream: command_output_content.Stream, chunk: []const u8) !void {            const app: *App = @ptrCast(@alignCast(ctx));            if (app.worker.worker_cancel_requested.load(.seq_cst)) return;            try app_worker_runtime.Runtime(App).pushCommandOutput(app, lifecycle_id, stream, chunk);        }         pub fn onMcpProgress(ctx: *anyopaque, lifecycle_id: types.ToolLifecycleId, text: []const u8) void {            const app: *App = @ptrCast(@alignCast(ctx));            var label_buf: [512]u8 = undefined;            const label = std.fmt.bufPrint(                &label_buf,                "{s}● {s}{s}",                .{ ui_render.bold_style, text, reset_style },            ) catch ui_render.bold_style ++ "● MCP progress" ++ reset_style;            app_worker_runtime.Runtime(App).pushToolLifecycle(app, .{ .progress = .{                .id = lifecycle_id,                .text = label,            } }) catch |err| {                debug_trace.logf("mcp", "failed to publish MCP tool progress err={s}", .{@errorName(err)});                return;            };            debug_trace.logf("mcp", "queued MCP tool progress turn_id={d}", .{lifecycle_id.turn_id});

Lines 1–500 of 2323.