8846 lines · 341.4 KB · Zig
RawDownload
const std = @import("std");const debug_trace = @import("../../core/shared/debug_trace.zig");const display_width = @import("../../core/shared/display_width.zig");const text_utils = @import("../../core/shared/text_utils.zig");const types = @import("../../core/shared/types.zig");const domain = @import("../../core/subagent/domain.zig");const execution = @import("../../core/subagent/execution.zig");const diff_mod = @import("../../core/output/diff.zig");const transcript_presentation = @import("../../core/output/transcript_presentation.zig");const worker_runtime = @import("../../core/agent/worker_runtime.zig");const io_mod = @import("../../core/shared/io.zig");const manager_mod = @import("../../core/subagent/manager.zig");const permission_request = @import("../../core/permissions/permission_request.zig");const projection = @import("../../core/subagent/ui_projection.zig");const terminal_projection = @import("../../core/terminal/ui_projection.zig");const skill_contract = @import("../../core/skills/skill_contract.zig");const input_action = @import("../../core/input/input_action.zig");const core_input_runtime = @import("../../core/input/runtime.zig");const subagent_input = @import("../../core/subagent/input_action.zig");const horizontal_navigation = @import("../../core/input/horizontal_navigation.zig");const paste_framing = @import("../../core/input/paste_framing.zig");const ui_input = @import("../input/runtime.zig");const input_visual_layout = @import("../input/visual_layout.zig");const ui_render = @import("../render.zig");const render_request = @import("../render_request.zig");const approval_ui = @import("../footer/approval_ui.zig");const row_text = @import("../footer/row_text.zig");const full_transcript_screen = @import("../full_transcript_screen.zig");const transcript_runtime = @import("../transcript/runtime.zig"); const Allocator = std.mem.Allocator; pub const Status = domain.State; const PhysicalSurface = enum {    manager,    child_conversation,    child_catalog,}; pub const EntryView = struct {    id: []const u8,    label: []const u8,    status: Status,    unread_count: usize,    external_busy: bool,}; pub const SelectedInfo = struct {    id: []const u8,    label: []const u8,    status: Status,    unread_count: usize,    external_busy: bool,}; pub fn statusLabelPublic(status: Status) []const u8 {    return switch (status) {        .awaiting_approval => "approval",        else => @tagName(status),    };} pub const Focus = enum {    child_list,    archived_list,    child_detail,    child_composer,    create_form,    attach_list,    configure_form,    actions,    confirmation,    activity,    notification,    approval,}; pub const Route = union(enum) {    archived,    create,    attach,    child: []u8,    configure: []u8,    actions: []u8,    confirm_close: []u8,    activity: []u8,    notification: struct {        child_id: []u8,        sequence: u64,    },    approval: struct {        child_id: []u8,        approval_id: []u8,    },    main_approval: u64,     fn deinit(self: *Route, alloc: Allocator) void {        switch (self.*) {            .archived, .create, .attach => {},            .child, .configure, .actions, .confirm_close, .activity => |id| alloc.free(id),            .notification => |value| alloc.free(value.child_id),            .approval => |value| {                alloc.free(value.child_id);                alloc.free(value.approval_id);            },            .main_approval => {},        }        self.* = undefined;    }}; pub const Command = subagent_input.Command; const RootSelection = enum { child, terminal }; pub const Action = subagent_input.Action; pub const SubmissionFailure = struct {    code: manager_mod.FailureCode,    retryable: bool,}; pub const ChildInputFailure = enum {    message_too_large,    invalid_utf8,    paste_allocation_failed,    unsafe_paste_boundary,}; const FormField = enum {    name,    model,    initial_message,    milestones,    interval,    duration,    effort,    permission_mode,    notifications,    completed,    failed,    cancelled,}; const FormKind = enum {    none,    create,    configure,}; const FormValidationFailure = enum {    missing_name,    invalid_name,    invalid_model,    invalid_effort,    invalid_initial_message,    invalid_notification_policy,    duplicate_milestone,    invalid_number,    invalid_utf8,    field_too_large,    unsafe_paste_boundary,    no_attach_candidate,    attach_candidate_ineligible,    allocation_failure,}; const MutationFailure = union(enum) {    validation: FormValidationFailure,    manager: manager_mod.Failure,    approval_stale,    approval_commit_failed,}; const MutationKind = enum {    create,    relationship,    configure,    cancel,    @"resume",    close,    reopen,}; const MutationAttempt = struct {    operation_id: ?[]u8 = null,    identity_epoch: u64 = 0,    failure: ?MutationFailure = null,    counter: u64 = 0,     fn deinit(self: *MutationAttempt, alloc: Allocator) void {        if (self.operation_id) |value| alloc.free(value);        self.* = .{};    }     fn edited(self: *MutationAttempt, alloc: Allocator) void {        if (self.operation_id) |value| alloc.free(value);        self.operation_id = null;        self.identity_epoch = 0;        self.failure = null;    }     fn ensureOperationId(        self: *MutationAttempt,        alloc: Allocator,        kind: MutationKind,        target_id: []const u8,        timestamp_ms: i64,    ) ![]const u8 {        if (self.operation_id == null) {            self.counter +%= 1;            self.operation_id = try std.fmt.allocPrint(                alloc,                "manager-ui:{s}:{s}:{d}:{d}",                .{ @tagName(kind), target_id, timestamp_ms, self.counter },            );        }        return self.operation_id.?;    }}; const form_editor_count: usize = 7;const create_fields = [_]FormField{    .name,    .model,    .initial_message,    .milestones,    .interval,    .duration,    .effort,    .permission_mode,    .notifications,    .completed,    .failed,    .cancelled,};const configure_fields = [_]FormField{    .name,    .model,    .milestones,    .interval,    .duration,    .effort,    .permission_mode,    .completed,    .failed,    .cancelled,}; const FormState = struct {    kind: FormKind = .none,    target_id: ?[]u8 = null,    expected_generation: ?u64 = null,    editors: [form_editor_count]core_input_runtime.Runtime = [_]core_input_runtime.Runtime{.{}} ** form_editor_count,    field_index: usize = 0,    permission_mode: types.PermissionMode = .yolo,    notifications_enabled: bool = false,    terminal: domain.TerminalEvents = .{},    paste_field: ?FormField = null,    paste_rejection: ?FormValidationFailure = null,    attempt: MutationAttempt = .{},     fn deinit(self: *FormState, alloc: Allocator) void {        self.clear(alloc);        for (&self.editors) |*editor| editor.deinit(alloc);        self.* = .{};    }     fn clear(self: *FormState, alloc: Allocator) void {        if (self.target_id) |value| alloc.free(value);        self.target_id = null;        for (&self.editors) |*editor| {            editor.inputResetState().clearCurrent(alloc);            editor.paste.resetWithTrace(.session_reset);        }        self.attempt.deinit(alloc);        self.kind = .none;        self.expected_generation = null;        self.field_index = 0;        self.permission_mode = .yolo;        self.notifications_enabled = false;        self.terminal = .{};        self.paste_field = null;        self.paste_rejection = null;    }     fn fields(self: *const FormState) []const FormField {        return switch (self.kind) {            .create => &create_fields,            .configure => &configure_fields,            .none => &.{},        };    }     fn currentField(self: *const FormState) ?FormField {        const available = self.fields();        if (available.len == 0) return null;        return available[@min(self.field_index, available.len - 1)];    }     fn editorForField(self: *FormState, field: FormField) ?*core_input_runtime.Runtime {        const index: ?usize = switch (field) {            .name => 0,            .model => 1,            .initial_message => 2,            .milestones => 3,            .interval => 4,            .duration => 5,            .effort => 6,            .permission_mode, .notifications, .completed, .failed, .cancelled => null,        };        return if (index) |value| &self.editors[value] else null;    }     fn replaceEditor(self: *FormState, alloc: Allocator, field: FormField, value: []const u8) !void {        const editor = self.editorForField(field) orelse return;        editor.inputResetState().clearCurrent(alloc);        try editor.insertionState().insertSlice(alloc, value, .preserve);    }     fn edit(self: *FormState, alloc: Allocator) void {        self.attempt.edited(alloc);        self.paste_rejection = null;        if (self.kind == .create) {            const current_field = self.currentField() orelse return;            switch (current_field) {                .milestones, .interval, .duration, .completed, .failed, .cancelled => self.notifications_enabled = true,                else => {},            }        }    }}; const AttachState = struct {    candidates: std.ArrayList(projection.AttachCandidate) = .empty,    selected: usize = 0,    has_more: bool = false,    loading: bool = false,    selection_stale: bool = false,    attempt: MutationAttempt = .{},     fn deinit(self: *AttachState, alloc: Allocator) void {        self.clear(alloc);        self.candidates.deinit(alloc);        self.* = .{};    }     fn clear(self: *AttachState, alloc: Allocator) void {        for (self.candidates.items) |*candidate| candidate.deinit(alloc);        self.candidates.clearRetainingCapacity();        self.attempt.deinit(alloc);        self.selected = 0;        self.has_more = false;        self.loading = false;        self.selection_stale = false;    }     fn selectedCandidate(self: *const AttachState) ?*const projection.AttachCandidate {        if (self.selected >= self.candidates.items.len) return null;        return &self.candidates.items[self.selected];    }}; const MainApprovalCard = struct {    prompt_id: u64,    child_id: []u8,    child_name: []u8,    approval_id: []u8,    label: []u8,    explanation: ?[]u8,    tool_arguments_preview: ?[]u8 = null,    command: ?[]u8 = null,    file: ?permission_request.FileApprovalRequest = null,     fn deinit(self: *MainApprovalCard, alloc: Allocator) void {        alloc.free(self.child_id);        alloc.free(self.child_name);        alloc.free(self.approval_id);        alloc.free(self.label);        if (self.explanation) |value| alloc.free(value);        if (self.tool_arguments_preview) |value| alloc.free(value);        if (self.command) |value| alloc.free(value);        if (self.file) |value| {            permission_request.deinitFileApprovalRequest(alloc, value);        }        self.* = undefined;    }}; pub const MainApprovalBinding = struct {    child_id: []const u8,    approval_id: []const u8,}; const ViewportMutation = enum {    none,    bottom,    prepend,}; fn validChildMessage(text: []const u8) bool {    return std.unicode.utf8ValidateSlice(text) and        std.mem.findScalar(u8, text, 0) == null;} fn childDraftFailure(text: []const u8) ?ChildInputFailure {    if (text.len > domain.max_message_bytes) return .message_too_large;    if (!validChildMessage(text)) return .invalid_utf8;    return null;} fn childInputFailureTraceLabel(failure: ChildInputFailure) []const u8 {    return switch (failure) {        .message_too_large => "message_too_large",        .invalid_utf8 => "invalid_utf8",        .paste_allocation_failed => "allocation_failure",        .unsafe_paste_boundary => "unsafe_paste_boundary",    };} pub fn childInputFailureDisplay(failure: ChildInputFailure) []const u8 {    return switch (failure) {        .message_too_large => "Message too large",        .invalid_utf8 => "Invalid UTF-8",        .paste_allocation_failed => "Paste allocation failed",        .unsafe_paste_boundary => "Paste contained input after its end marker",    };} const FormParseError = error{    InvalidNotificationPolicy,    DuplicateMilestone,}; fn parseMilestones(    raw: []const u8,    out: *[domain.max_milestones][]const u8,) FormParseError![]const []const u8 {    var count: usize = 0;    var tokens = std.mem.splitScalar(u8, raw, ',');    while (tokens.next()) |token| {        const value = std.mem.trim(u8, token, " \t\r\n");        if (value.len == 0) continue;        if (count == out.len) return error.InvalidNotificationPolicy;        for (out[0..count]) |prior| {            if (std.mem.eql(u8, prior, value)) return error.DuplicateMilestone;        }        out[count] = value;        count += 1;    }    return out[0..count];} fn parseOptionalU64(raw: []const u8) !?u64 {    const value = std.mem.trim(u8, raw, " \t\r\n");    if (value.len == 0) return null;    return try std.fmt.parseInt(u64, value, 10);} fn mapFormValidationError(err: anyerror) FormValidationFailure {    return switch (err) {        error.MissingName => .missing_name,        error.InvalidName => .invalid_name,        error.InvalidModel => .invalid_model,        error.InvalidPrompt, error.InvalidMessage => .invalid_initial_message,        error.InvalidNotificationPolicy => .invalid_notification_policy,        error.DuplicateMilestone => .duplicate_milestone,        error.OutOfMemory => .allocation_failure,        else => .invalid_notification_policy,    };} fn formFieldMaxBytes(field: FormField) usize {    return switch (field) {        .name => domain.max_name_bytes,        .model => domain.max_model_bytes,        .initial_message => domain.max_prompt_bytes,        .milestones => domain.max_milestones * domain.max_name_bytes,        .interval, .duration => 20,        .effort => types.ReasoningEffort.max_name_bytes,        .permission_mode, .notifications, .completed, .failed, .cancelled => 0,    };} fn formValidationDisplay(failure: FormValidationFailure) []const u8 {    return switch (failure) {        .missing_name => "Name is required",        .invalid_name => "Name is invalid",        .invalid_model => "Model is invalid",        .invalid_effort => "Effort is invalid",        .invalid_initial_message => "Initial message is invalid",        .invalid_notification_policy => "Notification policy is invalid",        .duplicate_milestone => "Milestones must be unique",        .invalid_number => "Interval and duration must be positive integers",        .invalid_utf8 => "Field contains invalid UTF-8",        .field_too_large => "Field exceeds its byte limit",        .unsafe_paste_boundary => "Paste contained input after its end marker",        .no_attach_candidate => "No attach candidate is selected",        .attach_candidate_ineligible => "Selected chat is busy or no longer eligible",

Lines 1–500 of 8846.