zidane 5.0.6 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +37 -1
  2. package/dist/{agent-JhicgLOV.d.ts → agent-B0vrSTQ9.d.ts} +162 -4
  3. package/dist/agent-B0vrSTQ9.d.ts.map +1 -0
  4. package/dist/chat.d.ts +526 -81
  5. package/dist/chat.d.ts.map +1 -1
  6. package/dist/chat.js +2 -2
  7. package/dist/contexts/docker.d.ts +7 -0
  8. package/dist/contexts/docker.d.ts.map +1 -0
  9. package/dist/{contexts-3Arvn7yR.js → contexts/docker.js} +2 -128
  10. package/dist/contexts/docker.js.map +1 -0
  11. package/dist/contexts-BwiHIr2w.js +129 -0
  12. package/dist/contexts-BwiHIr2w.js.map +1 -0
  13. package/dist/contexts.d.ts +3 -2
  14. package/dist/contexts.js +2 -2
  15. package/dist/index-CFxhms_B.d.ts +1303 -0
  16. package/dist/index-CFxhms_B.d.ts.map +1 -0
  17. package/dist/index-DYcymRtr.d.ts +26 -0
  18. package/dist/index-DYcymRtr.d.ts.map +1 -0
  19. package/dist/{index-t_W9i7Ql.d.ts → index-X6Q9PN_A.d.ts} +3 -3
  20. package/dist/{index-t_W9i7Ql.d.ts.map → index-X6Q9PN_A.d.ts.map} +1 -1
  21. package/dist/index.d.ts +6 -5
  22. package/dist/index.js +10 -9
  23. package/dist/index.js.map +1 -1
  24. package/dist/login-BiuHyuEh.js +1276 -0
  25. package/dist/login-BiuHyuEh.js.map +1 -0
  26. package/dist/{mcp-Dw-fRPVk.js → mcp-BgwK6ySj.js} +184 -9
  27. package/dist/mcp-BgwK6ySj.js.map +1 -0
  28. package/dist/mcp.d.ts +2 -2
  29. package/dist/mcp.js +1 -1
  30. package/dist/{messages-xaYMMFlb.js → messages-BAFLvH_z.js} +1 -1
  31. package/dist/{messages-xaYMMFlb.js.map → messages-BAFLvH_z.js.map} +1 -1
  32. package/dist/{presets-BRFH2qsQ.js → presets-CI8_fyvX.js} +2 -2
  33. package/dist/{presets-BRFH2qsQ.js.map → presets-CI8_fyvX.js.map} +1 -1
  34. package/dist/presets.d.ts +2 -2
  35. package/dist/presets.js +1 -1
  36. package/dist/{providers-BCbdv99U.js → providers-C6-vhaVu.js} +2 -2
  37. package/dist/{providers-BCbdv99U.js.map → providers-C6-vhaVu.js.map} +1 -1
  38. package/dist/providers.d.ts +1 -1
  39. package/dist/providers.js +2 -2
  40. package/dist/session/sqlite.d.ts +1 -1
  41. package/dist/{session-791hhrFa.js → session-pS4Vt4dl.js} +1 -1
  42. package/dist/{session-791hhrFa.js.map → session-pS4Vt4dl.js.map} +1 -1
  43. package/dist/session.d.ts +1 -1
  44. package/dist/session.js +2 -2
  45. package/dist/skills.d.ts +2 -2
  46. package/dist/{stats-DZIsGqzu.js → stats-DvCtBRwK.js} +1 -1
  47. package/dist/{stats-DZIsGqzu.js.map → stats-DvCtBRwK.js.map} +1 -1
  48. package/dist/{theme-C3JHZ5y9.d.ts → theme-CcGLMJrn.d.ts} +732 -20
  49. package/dist/theme-CcGLMJrn.d.ts.map +1 -0
  50. package/dist/{tools-CLazLRb4.js → tools-d1yeA6xK.js} +399 -13
  51. package/dist/tools-d1yeA6xK.js.map +1 -0
  52. package/dist/tools.d.ts +2 -2
  53. package/dist/tools.js +1 -1
  54. package/dist/tui.d.ts +421 -39
  55. package/dist/tui.d.ts.map +1 -1
  56. package/dist/tui.js +5755 -2367
  57. package/dist/tui.js.map +1 -1
  58. package/dist/{turn-operations-BfEh-GER.js → turn-operations-BzOIM6Of.js} +1984 -108
  59. package/dist/turn-operations-BzOIM6Of.js.map +1 -0
  60. package/dist/types-Bx_F8jet.js.map +1 -1
  61. package/dist/{index-CXVvqTQj.d.ts → types-OtrV6LJT.d.ts} +2 -27
  62. package/dist/types-OtrV6LJT.d.ts.map +1 -0
  63. package/dist/types.d.ts +4 -3
  64. package/dist/types.js +1 -1
  65. package/package.json +5 -1
  66. package/dist/agent-JhicgLOV.d.ts.map +0 -1
  67. package/dist/contexts-3Arvn7yR.js.map +0 -1
  68. package/dist/index-2yLUyTbc.d.ts +0 -430
  69. package/dist/index-2yLUyTbc.d.ts.map +0 -1
  70. package/dist/index-CXVvqTQj.d.ts.map +0 -1
  71. package/dist/mcp-Dw-fRPVk.js.map +0 -1
  72. package/dist/theme-C3JHZ5y9.d.ts.map +0 -1
  73. package/dist/tools-CLazLRb4.js.map +0 -1
  74. package/dist/turn-operations-BfEh-GER.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { At as ThinkingLevel, Dt as SessionTurn, Nt as ToolResultContent, O as SessionRun, U as Provider, ht as McpServerConfig, k as SessionStore } from "./agent-JhicgLOV.js";
2
- import { t as Preset } from "./index-2yLUyTbc.js";
1
+ import { A as SessionStore, O as SessionData, Ot as SessionTurn, Pt as ToolResultContent, W as Provider, gt as McpServerConfig, jt as ThinkingLevel, k as SessionRun, y as ToolDef } from "./agent-B0vrSTQ9.js";
2
+ import { t as Preset } from "./index-CFxhms_B.js";
3
3
  import { OAuthProviderInterface } from "@mariozechner/pi-ai/oauth";
4
4
  import { ReactNode } from "react";
5
5
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
@@ -29,10 +29,37 @@ interface AgentProfile {
29
29
  accent?: AgentAccent;
30
30
  }
31
31
  type AgentRegistry = Readonly<Record<string, AgentProfile>>;
32
+ /**
33
+ * Tools the chat layer never persists to disk, regardless of output size.
34
+ *
35
+ * Rationale per entry:
36
+ * - `read_file` — our reader is already paginated (`offset` + `limit`).
37
+ * Persisting the slice the model asked for and pointing it at the
38
+ * persisted path is circular; if the model wants more, it pages.
39
+ * - `tool_search` — short metadata envelope. Never large.
40
+ * - `skills_use` / `skills_read` — the `<skill_content>` body is
41
+ * intentionally part of the prompt; persisting it defeats the purpose.
42
+ * - `present_plan` / `ask_user` — short JSON envelopes (decision +
43
+ * answers). Never large.
44
+ * - `spawn` — the subagent's final report IS the value of the call;
45
+ * stubbing it out would defeat the orchestration pattern.
46
+ *
47
+ * Exported so SDK consumers building custom profiles can extend the list
48
+ * (e.g. host-defined `screenshot` tool whose base64 payload should stay
49
+ * inline). Set `behavior.persistExcludeTools` to your own list to fully
50
+ * override.
51
+ */
52
+ declare const DEFAULT_PERSIST_EXCLUDE_TOOLS: readonly string[];
32
53
  /**
33
54
  * Build agent — the default profile. Full read/write/shell access plus
34
55
  * subagent spawning. Mirrors the legacy `basic` preset so existing TUI
35
56
  * behavior is preserved when `agents` is omitted.
57
+ *
58
+ * The system prompt is the cwd-less variant of {@link buildBuildSystem};
59
+ * the TUI overrides it per-session with an env-anchored composition so
60
+ * the prompt carries the current project root + date. SDK consumers
61
+ * calling `createAgent({ ...BUILD_AGENT.preset })` directly get the
62
+ * cwd-less prompt and can wrap their own env section.
36
63
  */
37
64
  declare const BUILD_AGENT: AgentProfile;
38
65
  /**
@@ -195,6 +222,29 @@ declare function getModelInfo(descriptor: ProviderDescriptor, modelId: string):
195
222
  * a registry); callers should hide the context indicator in that case.
196
223
  */
197
224
  declare function getContextWindow(descriptor: ProviderDescriptor, modelId: string): number | null;
225
+ /**
226
+ * Reserved output budget subtracted from the raw context window when
227
+ * computing the effective ceiling for compaction / warning thresholds.
228
+ *
229
+ * Aligned with Claude Code's `COMPACT_MAX_OUTPUT_TOKENS = 20_000`
230
+ * (`utils/context.ts:12`) — covers p99.99 of summary + response output.
231
+ * A turn that consumed N input tokens leaves `effectiveWindow - N`
232
+ * headroom for the next prompt's response; once headroom shrinks
233
+ * below the threshold, auto-compaction fires.
234
+ */
235
+ declare const OUTPUT_RESERVE_TOKENS = 20000;
236
+ /**
237
+ * Effective context window — what the next user turn can actually pack
238
+ * before the provider reserves space for the assistant's reply. Equals
239
+ * `rawWindow - OUTPUT_RESERVE_TOKENS`, clamped to `>= 1` so a tiny
240
+ * (or absurd) window doesn't yield zero / negative thresholds.
241
+ *
242
+ * Used by both the footer's context indicator and the auto-compact
243
+ * trigger so the two surfaces agree on "how full are we, really".
244
+ * Pass `null` through unchanged so callers can pipe `getContextWindow`
245
+ * directly without an intermediate check.
246
+ */
247
+ declare function effectiveContextWindow(rawWindow: number | null): number | null;
198
248
  /**
199
249
  * Whether the given model exposes a reasoning / extended-thinking knob.
200
250
  * Drives the TUI's effort picker visibility — the `ctrl+n` shortcut and
@@ -436,6 +486,149 @@ declare function useCompletion<TItem = unknown>(input: {
436
486
  maxQueryLength?: number;
437
487
  }): CompletionState<TItem>;
438
488
  //#endregion
489
+ //#region src/chat/keybindings.d.ts
490
+ /**
491
+ * Keybindings — a single source of truth for the app's global shortcuts.
492
+ *
493
+ * Every customizable action is declared once in {@link KEYBINDING_DEFS}
494
+ * with its default trigger, label, and description. The TUI imports
495
+ * `DEFAULT_KEYBINDINGS` for the baked-in defaults; on launch we load
496
+ * `<userDir>/keybindings.json` (when present) and merge user overrides
497
+ * on top so the user can rebind any action without recompiling.
498
+ *
499
+ * Scope (deliberate):
500
+ *
501
+ * - We expose only the **global, action-opening** shortcuts here —
502
+ * "open the Settings modal", "cycle agent profile", "enter
503
+ * select-turn mode", etc. Modal-internal letter shortcuts (`f`
504
+ * fork, `d` delete, `c` copy on the turn-details modal) and
505
+ * universal navigation (`↑/↓/↵/⎋`) stay hardcoded — they live
506
+ * too close to a renderable's input contract to remap safely.
507
+ *
508
+ * - Storage lives at the **user level** (`<userDir>/keybindings.json`),
509
+ * never inside a project's `.{prefix}/`. Shortcut muscle memory is
510
+ * a per-user concern, not a per-repo one.
511
+ *
512
+ * Format on disk: JSON with `//` and `/* … *\/` comments allowed
513
+ * (parsed via a small JSONC stripper). Each entry maps an action id
514
+ * to a binding spec string. Specs are parsed by {@link parseBindingSpec};
515
+ * unknown / malformed entries fall back to the default for that action
516
+ * (with a debug log under `ZIDANE_DEBUG`) so a syntax slip never bricks
517
+ * the TUI.
518
+ */
519
+ /**
520
+ * Every action the keybindings system can drive. Adding a new action
521
+ * here forces every consumer (TUI keyboard handler, hint rows, settings
522
+ * UI) to handle it, and ships a default that the user can override.
523
+ */
524
+ type KeyAction = 'openSettings' | 'openSessionDetails' | 'openModelPicker' | 'openEffortPicker' | 'cycleAgent' | 'enterSelectTurnMode' | 'enterQueueSelection' | 'pushQueuedMessage' | 'dropQueuedMessage' | 'turnFork' | 'turnDelete' | 'turnCopy' | 'sessionDelete' | 'sessionCopyId' | 'sessionGenerateTitle' | 'sessionExportMarkdown' | 'sessionExportJson' | 'sessionCompact';
525
+ /** Resolved keybindings — every action has a current spec string. */
526
+ type KeyBindings = Record<KeyAction, string>;
527
+ /** Static metadata for one action — used by the loader, hint rows, settings UI. */
528
+ interface KeyBindingDef {
529
+ /** Stable identifier — JSON key + TS union member. */
530
+ action: KeyAction;
531
+ /** Default trigger spec (e.g. `'ctrl+o'`). */
532
+ default: string;
533
+ /** Short label used in shortcut hint rows. */
534
+ label: string;
535
+ /** Longer description for the settings UI and the annotated JSON file. */
536
+ description: string;
537
+ }
538
+ /**
539
+ * The canonical action catalog. Order is the source of truth for the
540
+ * generated keybindings file and the settings UI.
541
+ */
542
+ declare const KEYBINDING_DEFS: readonly KeyBindingDef[];
543
+ /** Index by action for O(1) lookup of label / description / default. */
544
+ declare const KEYBINDING_DEF_BY_ACTION: Readonly<Record<KeyAction, KeyBindingDef>>;
545
+ /** Defaults, derived from {@link KEYBINDING_DEFS} so the two never drift. */
546
+ declare const DEFAULT_KEYBINDINGS: KeyBindings;
547
+ /** Parsed shape of a `"ctrl+shift+o"` spec. */
548
+ interface ParsedBinding {
549
+ ctrl: boolean;
550
+ shift: boolean;
551
+ alt: boolean;
552
+ meta: boolean;
553
+ /** The key name (e.g. `'o'`, `'tab'`, `'escape'`). Always lowercase. */
554
+ name: string;
555
+ }
556
+ /**
557
+ * Parse a `'ctrl+shift+o'`-style spec into structured fields. Returns
558
+ * `null` for empty / malformed inputs; the caller falls back to the
559
+ * default for that action.
560
+ *
561
+ * Tolerant by design:
562
+ * - Case-insensitive (`Ctrl+O` → same as `ctrl+o`).
563
+ * - Modifier order doesn't matter (`shift+ctrl+o` works).
564
+ * - Mixed `+` and `-` separators allowed (`ctrl-o`, `ctrl+o`).
565
+ * - Trailing / leading whitespace is stripped.
566
+ * - Duplicate modifiers collapse silently.
567
+ */
568
+ declare function parseBindingSpec(spec: string | undefined | null): ParsedBinding | null;
569
+ /**
570
+ * Test a KeyEvent against a parsed-or-string binding. Accepts either
571
+ * form so callers can pre-parse (hot path) or pass the raw spec for
572
+ * one-off checks.
573
+ *
574
+ * Modifier semantics: ALL declared modifiers must be pressed AND no
575
+ * extra modifiers may be pressed. So `'o'` does NOT match `ctrl+o`,
576
+ * and `'ctrl+o'` does NOT match `ctrl+shift+o`. This avoids surprises
577
+ * where a binding that should be specific accidentally fires for a
578
+ * superset of key combinations.
579
+ */
580
+ declare function matchesBinding(event: {
581
+ name?: string;
582
+ ctrl?: boolean;
583
+ shift?: boolean;
584
+ meta?: boolean;
585
+ option?: boolean;
586
+ alt?: boolean;
587
+ }, spec: string | ParsedBinding): boolean;
588
+ /**
589
+ * Merge a partial map of user overrides into the defaults. Unknown
590
+ * action keys are dropped (a future TUI version may have retired the
591
+ * action); invalid spec strings (parse fails) fall back to the default
592
+ * for that action.
593
+ */
594
+ declare function mergeKeybindings(overrides: Readonly<Record<string, unknown>> | null | undefined): KeyBindings;
595
+ /** Path of the user-level keybindings file. */
596
+ declare function keybindingsPath(userDir: string): string;
597
+ /**
598
+ * Load + merge the user's keybindings file (when present). Always
599
+ * returns a fully-resolved {@link KeyBindings} — defaults fill in for
600
+ * any missing / invalid entries so consumers can treat the result as
601
+ * total.
602
+ *
603
+ * Failure modes (all tolerated, all fall back to defaults):
604
+ * - File missing
605
+ * - File not valid JSON / JSONC (after comment stripping)
606
+ * - Top-level is not an object
607
+ * - Individual entries have invalid spec strings
608
+ */
609
+ declare function readKeybindings(userDir: string): KeyBindings;
610
+ /**
611
+ * Create the user-level `keybindings.json` if it doesn't exist,
612
+ * prefilled with every default. Returns the absolute file path either
613
+ * way so the caller can open it in `$EDITOR`. Idempotent: an existing
614
+ * user file is NEVER overwritten — the user's customizations are
615
+ * sacred.
616
+ */
617
+ declare function ensureKeybindingsFile(userDir: string): string;
618
+ /**
619
+ * Strip `//` line comments and `/* … *\/` block comments from a JSONC
620
+ * source string. Stays out of string literals so a `"foo // bar"` value
621
+ * keeps its slashes. Exported for unit-tests; the only runtime caller
622
+ * is {@link readKeybindings}.
623
+ *
624
+ * Trade-off: this is a tiny state-machine, not a full JSONC parser. It
625
+ * doesn't understand `\\` outside strings (irrelevant for JSON) and
626
+ * doesn't track line numbers in error messages. Good enough for a
627
+ * config file — corruption in production gracefully falls back to the
628
+ * defaults via the try/catch in `readKeybindings`.
629
+ */
630
+ declare function stripJsonComments(input: string): string;
631
+ //#endregion
439
632
  //#region src/chat/types.d.ts
440
633
  type Screen = 'auth' | 'sessions' | 'chat';
441
634
  /** Identifies the agent that produced a streaming event. */
@@ -456,8 +649,34 @@ interface StreamEvent {
456
649
  * Generic informational banner — status notice, transient message.
457
650
  * Reserved for non-user content; user prompts use `'user-prompt'`.
458
651
  */
459
- | 'info' | 'separator' | 'markdown' | 'spawn-start' | 'spawn-end';
652
+ | 'info' | 'separator' | 'markdown' | 'spawn-start' | 'spawn-end'
653
+ /**
654
+ * Compaction boundary — produced by `eventsFromTurns` when a turn
655
+ * carries a `compact-summary` block. Marks the point at which the
656
+ * model's view of history was replaced by an LLM-generated summary.
657
+ * `text` is the summary body; `compact` carries the extra metadata
658
+ * needed for the visual card (replaced-turn count, model, usage).
659
+ *
660
+ * The renderer is free to style this as a collapsed card; the user
661
+ * can still scroll above the marker to see the original turns —
662
+ * compaction never deletes from disk.
663
+ */
664
+ | 'compact-summary';
460
665
  text: string;
666
+ /**
667
+ * Compaction metadata — only set on `compact-summary` events. Mirrors
668
+ * the underlying `SessionContentBlock` shape but flattened to numbers
669
+ * so the renderer doesn't need to import the agent's TurnUsage type.
670
+ */
671
+ compact?: {
672
+ /** Number of turns the summary replaces (renderer shows "N turns compacted"). */replacedCount: number; /** Model used for the summary call. */
673
+ model: string; /** Unix-ms when compaction completed. */
674
+ compactedAt: number; /** Token usage from the summary call. Renderer formats for display. */
675
+ inputTokens: number;
676
+ outputTokens: number;
677
+ cacheReadTokens: number;
678
+ cacheCreationTokens: number;
679
+ };
461
680
  /**
462
681
  * For `markdown` events: true while the block is still receiving deltas.
463
682
  * Renderers keep their markdown parser in streaming mode while this is
@@ -477,6 +696,21 @@ interface StreamEvent {
477
696
  * same stats. Absent for non-tool events.
478
697
  */
479
698
  tool?: string;
699
+ /**
700
+ * Raw tool input arguments — only set on `tool` events. Carried so the
701
+ * renderer can run per-tool formatters (e.g. `↳ Read src/foo.ts L10-25`)
702
+ * without parsing JSON back out of `text`. Plain object, same shape the
703
+ * model emitted; renderers must treat unexpected fields as optional.
704
+ */
705
+ input?: Record<string, unknown>;
706
+ /**
707
+ * Structured payload for `edit` / `multi_edit` / `write_file` tool calls,
708
+ * extracted from the model's `input` and (for `write_file`) paired with
709
+ * a pre-write snapshot read at hook time. Drives the `EditDiffBlock`
710
+ * renderer when {@link Settings.showEditDiffs} is on; absent means
711
+ * "render as a plain `↳ name(args)` line" (the unstructured fallback).
712
+ */
713
+ edit?: EditPayload;
480
714
  /**
481
715
  * Highlighted spans within `text`, in source order. Used by the renderer
482
716
  * to colorize completion references in submitted prompts (`user-prompt`
@@ -504,6 +738,38 @@ interface StreamEvent {
504
738
  */
505
739
  turnId?: string;
506
740
  }
741
+ /**
742
+ * Structured edit data attached to a `tool` event for `edit` /
743
+ * `multi_edit` / `write_file`. Lets the renderer compute a unified diff
744
+ * without re-parsing the JSON input string.
745
+ *
746
+ * - `edit` produces one hunk with `replaceAll` defaulting to false.
747
+ * - `multi_edit` produces one hunk per `edits[]` step (in order).
748
+ * - `write_file` produces a single hunk where `oldString` is the
749
+ * pre-write file content (empty for a fresh create) and `newString`
750
+ * is the new content; `replaceAll` is meaningless here and absent.
751
+ *
752
+ * Live capture happens in the TUI's `tool:before` hook (where the
753
+ * pre-write snapshot can be read off disk before the tool runs).
754
+ * Historical replay from persisted turns can only reconstruct the
755
+ * edit/multi_edit shape — write_file historical events have no
756
+ * pre-write content and render with `oldString: ''` (= every line is
757
+ * an addition), matching git's "new file" diff convention.
758
+ */
759
+ interface EditPayload {
760
+ /** Tool name that produced this payload — drives the header glyph + result-suppression matrix. */
761
+ tool: 'edit' | 'multi_edit' | 'write_file';
762
+ /** Workspace-relative file path. Used as the diff header. */
763
+ path: string;
764
+ /** Ordered list of `(old, new)` pairs. Each rendered as one hunk. */
765
+ hunks: readonly EditHunk[];
766
+ }
767
+ interface EditHunk {
768
+ oldString: string;
769
+ newString: string;
770
+ /** Mirrored from the tool's `replace_all` flag — surfaced as `× N` in the hunk header. */
771
+ replaceAll?: boolean;
772
+ }
507
773
  interface Picked {
508
774
  provider: ProviderAuth;
509
775
  model: string;
@@ -533,10 +799,30 @@ interface SessionMeta {
533
799
  projectRoot?: string;
534
800
  updatedAt: number;
535
801
  }
802
+ /**
803
+ * How `tool` events render in the transcript. Drives `Settings.toolCallDisplay`.
804
+ *
805
+ * - `'hidden'` — `tool` events filtered out entirely (the matching
806
+ * `tool-result` block still shows unless its own toggle suppresses
807
+ * it). Use when the transcript should read like a chat log.
808
+ * - `'formatted'` (default) — each tool renders a clean per-tool
809
+ * summary line (e.g. `↳ Read src/foo.ts`, `↳ Shell git status`).
810
+ * Native tools have curated formatters; unknown / MCP tools fall
811
+ * back to a compact `↳ <name>` line.
812
+ * - `'full'` — debug view: `↳ <name>` header plus the entire raw
813
+ * `input` rendered as syntax-highlighted JSON. Useful for
814
+ * inspecting what the model actually sent.
815
+ */
816
+ type ToolCallDisplay = 'hidden' | 'formatted' | 'full';
536
817
  /** Persisted, user-toggleable transcript filters and modes. */
537
818
  interface Settings {
538
819
  showThinking: boolean;
539
- showToolCalls: boolean;
820
+ /**
821
+ * Rendering mode for `tool` events. See {@link ToolCallDisplay}.
822
+ * Replaces the legacy `showToolCalls: boolean` (TUI auto-migrates
823
+ * old `state.json` files on first launch).
824
+ */
825
+ toolCallDisplay: ToolCallDisplay;
540
826
  showToolResults: boolean;
541
827
  /**
542
828
  * Safe mode — when enabled, every tool call requires explicit user
@@ -569,6 +855,78 @@ interface Settings {
569
855
  * leaving the TUI. Per-row project labels appear when on.
570
856
  */
571
857
  showAllProjects: boolean;
858
+ /**
859
+ * Auto-resume the previously-active session on launch. Default: on.
860
+ * When off, the TUI always lands on the sessions list (or a fresh
861
+ * session if the list is empty), regardless of what `state.json`
862
+ * remembers as the last session id.
863
+ *
864
+ * The setting is read once on launch — toggling it mid-session
865
+ * affects the NEXT start, not the current one. `state.lastSessionId`
866
+ * is still tracked underneath so flipping the setting back on
867
+ * restores the resume behavior without losing the pointer.
868
+ */
869
+ resumeLastSession: boolean;
870
+ /**
871
+ * Persist large `tool_result` outputs to disk and substitute a
872
+ * `<persisted-output>` stub (preview + filesystem path) inline. Built-in
873
+ * profiles default to 8 KiB threshold via `behavior.persistThreshold`;
874
+ * this setting is the user-facing kill-switch. When off, the TUI
875
+ * overrides `behavior.persistThreshold = 0` at agent build time so the
876
+ * loop's persistence branch never fires.
877
+ *
878
+ * The setting takes effect on the next session activation — toggling
879
+ * mid-stream doesn't tear down an in-flight tool call. Persisted blobs
880
+ * already on disk stay readable via `read_file`; only future tool
881
+ * results are affected by the flip.
882
+ *
883
+ * Default: on.
884
+ */
885
+ persistToolResults: boolean;
886
+ /**
887
+ * Fire {@link compactConversation} automatically when the latest turn's
888
+ * input-token usage crosses {@link Settings.autoCompactThreshold} of the
889
+ * model's effective context window (raw window minus a fixed output
890
+ * reserve — see `OUTPUT_RESERVE_TOKENS` in `chat/providers.ts`).
891
+ *
892
+ * When the trigger fires, the TUI:
893
+ * - Appends an `info` event to the transcript announcing the compaction.
894
+ * - Runs `compactConversation` in the background — the prompt area stays
895
+ * visible so the user can compose the next message while it runs.
896
+ * - The next prompt submission `await`s the in-flight compaction before
897
+ * calling `agent.run()`, so the new run sees the post-compaction
898
+ * message history (no race with the summary's `appendTurns`).
899
+ * - Does NOT auto-continue the conversation after compaction completes
900
+ * — the user controls when the next turn fires.
901
+ *
902
+ * Default: on.
903
+ */
904
+ autoCompact: boolean;
905
+ /**
906
+ * Threshold for {@link Settings.autoCompact}, expressed as a fraction of
907
+ * the effective context window. `0.8` means "fire when the latest turn
908
+ * used 80% of the effective window". Values outside `(0, 1)` are
909
+ * treated as misconfiguration and skip the trigger.
910
+ *
911
+ * The settings modal cycles through `0.6 / 0.7 / 0.8 / 0.9` — coarse
912
+ * enough that users don't get lost, fine enough to tune for verbose
913
+ * workflows (lower) versus context-heavy ones (higher).
914
+ *
915
+ * Default: `0.8`.
916
+ */
917
+ autoCompactThreshold: number;
918
+ /**
919
+ * Render `edit` / `multi_edit` / `write_file` tool calls as a clean
920
+ * unified diff (red `-` / green `+` lines) instead of the raw
921
+ * `↳ name({"path":"…","old_string":"…"})` JSON dump. When on, the
922
+ * paired successful `tool-result` ("Edited path: …") is suppressed
923
+ * too since the diff already conveys success; errors still show.
924
+ *
925
+ * Off falls back to the unstructured `↳ name(args)` line + the
926
+ * regular `tool-result` block — same display the TUI had before
927
+ * the diff feature shipped. Default: on.
928
+ */
929
+ showEditDiffs: boolean;
572
930
  /**
573
931
  * Allowlist of skill names to expose to the agent + slash-command picker.
574
932
  * `undefined` means "every discovered skill" (default). An empty array
@@ -868,6 +1226,13 @@ interface ResolvedConfig {
868
1226
  initialSettings: Partial<Settings>;
869
1227
  resumeProvider: ProviderAuth | null;
870
1228
  initialPicked: Picked | null;
1229
+ /**
1230
+ * Effective keybindings — defaults merged with the user-level
1231
+ * `<userDir>/keybindings.json` (when present). Always fully-resolved
1232
+ * so consumers can treat the record as total. See `./keybindings.ts`
1233
+ * for the action catalog + spec format.
1234
+ */
1235
+ keybindings: KeyBindings;
871
1236
  }
872
1237
  /** Resolve user options into a fully-bound runtime config. Pure aside from disk reads. */
873
1238
  declare function resolveConfig(options: ChatOptions): ResolvedConfig;
@@ -915,6 +1280,223 @@ declare function useEnabledToggleSet<T>(opts: {
915
1280
  settingKey: EnabledAllowlistKey;
916
1281
  }): EnabledToggleSet;
917
1282
  //#endregion
1283
+ //#region src/chat/interactions.d.ts
1284
+ declare const PRESENT_PLAN_TOOL = "present_plan";
1285
+ declare const ASK_USER_TOOL = "ask_user";
1286
+ /** True when `name` is one of the interaction tool canonical names. */
1287
+ declare function isInteractionTool(name: string): boolean;
1288
+ interface PlanStep {
1289
+ id: string;
1290
+ title: string;
1291
+ description?: string;
1292
+ }
1293
+ interface PlanPayload {
1294
+ /** Short headline summary — used as the modal title. */
1295
+ title: string;
1296
+ /** Full plan body. Markdown. */
1297
+ plan: string;
1298
+ /** Optional structured step list — surfaced as a checklist preview. */
1299
+ steps?: readonly PlanStep[];
1300
+ }
1301
+ interface QuestionChoice {
1302
+ id: string;
1303
+ label: string;
1304
+ description?: string;
1305
+ }
1306
+ /**
1307
+ * One question in an `ask_user` batch. Discriminated by `type`:
1308
+ *
1309
+ * - `text` — single-line free-text answer (rendered via `<input>`).
1310
+ * - `textarea` — multi-line free-text answer (rendered via `<textarea>`).
1311
+ * - `select` — single pick from a fixed set of `choices`.
1312
+ * - `confirm` — yes/no boolean (rendered as a 2-option select).
1313
+ *
1314
+ * The model batches related clarifications into one tool call instead of
1315
+ * pinging the user N times with N round-trips.
1316
+ */
1317
+ type QuestionType = 'text' | 'textarea' | 'select' | 'confirm';
1318
+ interface BaseQuestion {
1319
+ /** Stable id — keys the response back to the model. */
1320
+ id: string;
1321
+ /** Question text shown above the input (Markdown allowed). */
1322
+ prompt: string;
1323
+ /** Optional helper text under the prompt. */
1324
+ description?: string;
1325
+ /**
1326
+ * Whether the answer is required (non-empty). Default: `true` for
1327
+ * `select` / `confirm` (no sensible empty), `false` for free-text
1328
+ * (skipping = empty string). Free-text questions still accept an
1329
+ * answer; the flag only gates submission.
1330
+ */
1331
+ required?: boolean;
1332
+ }
1333
+ interface TextQuestion extends BaseQuestion {
1334
+ type: 'text' | 'textarea';
1335
+ /** Placeholder shown when the input is empty. */
1336
+ placeholder?: string;
1337
+ /** Pre-fill the input with this value (still editable). */
1338
+ default?: string;
1339
+ }
1340
+ interface SelectQuestion extends BaseQuestion {
1341
+ type: 'select';
1342
+ choices: readonly QuestionChoice[];
1343
+ }
1344
+ interface ConfirmQuestion extends BaseQuestion {
1345
+ type: 'confirm';
1346
+ /** Label for the affirmative option. Default: `'yes'`. */
1347
+ affirmLabel?: string;
1348
+ /** Label for the negative option. Default: `'no'`. */
1349
+ denyLabel?: string;
1350
+ }
1351
+ type Question = TextQuestion | SelectQuestion | ConfirmQuestion;
1352
+ interface QuestionPayload {
1353
+ /** Optional intro / context shown above every question (Markdown). */
1354
+ intro?: string;
1355
+ /** One or more questions for the user to answer in one form. */
1356
+ questions: readonly Question[];
1357
+ }
1358
+ /** Per-question answer value — `string` for text/textarea/select, `boolean` for confirm. */
1359
+ type AnswerValue = string | boolean;
1360
+ interface BaseRequest {
1361
+ /** Stable id — the `tool_call.id` from the model. */
1362
+ id: string;
1363
+ /** Tool canonical name. */
1364
+ tool: string;
1365
+ /** Run that emitted the call, when known. */
1366
+ runId?: string;
1367
+ /** Turn id the call lives in. */
1368
+ turnId?: string;
1369
+ /** Unix ms when the request was raised. */
1370
+ createdAt: number;
1371
+ }
1372
+ interface PlanRequest extends BaseRequest {
1373
+ kind: 'plan';
1374
+ tool: typeof PRESENT_PLAN_TOOL;
1375
+ payload: PlanPayload;
1376
+ }
1377
+ interface QuestionRequest extends BaseRequest {
1378
+ kind: 'question';
1379
+ tool: typeof ASK_USER_TOOL;
1380
+ payload: QuestionPayload;
1381
+ }
1382
+ type InteractionRequest = PlanRequest | QuestionRequest;
1383
+ type PlanDecision = 'approve' | 'reject' | 'revise';
1384
+ interface PlanResponse {
1385
+ kind: 'plan';
1386
+ decision: PlanDecision;
1387
+ /** Optional free-text feedback — shown to the model verbatim. */
1388
+ comment?: string;
1389
+ }
1390
+ interface QuestionResponse {
1391
+ kind: 'question';
1392
+ /**
1393
+ * Map of `Question.id → AnswerValue` for every question the user
1394
+ * answered. Missing keys = question skipped (only possible when
1395
+ * `required: false`).
1396
+ */
1397
+ answers: Readonly<Record<string, AnswerValue>>;
1398
+ }
1399
+ type InteractionResponse = PlanResponse | QuestionResponse;
1400
+ /**
1401
+ * Format an {@link InteractionResponse} as the tool_result content. JSON
1402
+ * keeps the envelope parseable and explicit. Empty fields are stripped so
1403
+ * the model doesn't waste tokens reading absent values.
1404
+ */
1405
+ declare function serializeInteractionResponse(response: InteractionResponse): string;
1406
+ /**
1407
+ * Build a protocol-valid user `SessionTurn` that closes a batch of
1408
+ * resumed pending interactions.
1409
+ *
1410
+ * - `requests` MUST be the same list returned by
1411
+ * {@link pendingInteractionsFromTurns} for the session, in order.
1412
+ * - `responses` MUST contain an entry for every request id; throws
1413
+ * otherwise (caller bug — flush before all answers collected).
1414
+ *
1415
+ * Pure / total. Tested in isolation so the batching invariant doesn't
1416
+ * regress without the resumed-flow integration noticing.
1417
+ */
1418
+ declare function buildResumedToolResultsTurn(requests: readonly InteractionRequest[], responses: ReadonlyMap<string, InteractionResponse>, options: {
1419
+ /** Turn id minted by the session store. */turnId: string;
1420
+ /**
1421
+ * Run id that emitted the pending tool calls — when known, attaching
1422
+ * it ties the resumed turn back to the originating `SessionRun` row
1423
+ * so consumers grouping turns by run keep clean ancestry across the
1424
+ * close/reopen boundary.
1425
+ */
1426
+ runId?: string; /** `createdAt` timestamp. Defaults to `Date.now()`. */
1427
+ createdAt?: number;
1428
+ }): SessionTurn;
1429
+ /**
1430
+ * Scan `turns` and return every interaction tool call without a matching
1431
+ * `tool_result`, ordered by turn appearance. Works equally for live mid-run
1432
+ * inspection and reload-from-disk.
1433
+ *
1434
+ * Malformed payloads (input that doesn't match the tool's schema) are
1435
+ * skipped silently — the call still lives in the persisted history, but
1436
+ * the renderer wouldn't know how to display it. The next `agent.run()` on
1437
+ * the session will see the orphan and synthesize an error tool_result via
1438
+ * the loop's normal recovery path.
1439
+ */
1440
+ declare function pendingInteractionsFromTurns(turns: readonly SessionTurn[]): InteractionRequest[];
1441
+ interface CreateInteractionToolsOptions {
1442
+ /**
1443
+ * Called when the agent invokes one of the interaction tools. Resolves
1444
+ * with the user's response (forwarded to the model as the tool_result);
1445
+ * reject to signal denial / abort (the model receives
1446
+ * `Tool error: <message>` as the result).
1447
+ */
1448
+ requestInteraction: (request: InteractionRequest) => Promise<InteractionResponse>;
1449
+ }
1450
+ /**
1451
+ * Create the `present_plan` and `ask_user` tools as a record, ready to
1452
+ * spread into `createAgent({ tools })` or composed into a {@link Preset}.
1453
+ */
1454
+ declare function createInteractionTools(opts: CreateInteractionToolsOptions): Record<string, ToolDef>;
1455
+ interface PendingInteractionEntry {
1456
+ request: InteractionRequest;
1457
+ /** The user picked something — forward to the live tool Promise or the resumed tool_result writer. */
1458
+ resolve: (response: InteractionResponse) => void;
1459
+ /**
1460
+ * The user / system cancelled — distinct from `resolve` so renderers can
1461
+ * differentiate "user picked something" from "user gave up / aborted".
1462
+ * Live entries reject the tool's Promise; resumed entries decide what
1463
+ * to persist as the cancelled tool_result.
1464
+ */
1465
+ cancel: (reason?: string) => void;
1466
+ }
1467
+ interface InteractionsActions {
1468
+ /** Add a request to the FIFO queue. */
1469
+ enqueue: (entry: PendingInteractionEntry) => void;
1470
+ /** Resolve the head request with `response`. */
1471
+ resolveHead: (response: InteractionResponse) => void;
1472
+ /**
1473
+ * Cancel the head request. Reserved for future per-call cancel
1474
+ * affordances (a "skip this" button, a GUI's close-modal-X) — the
1475
+ * built-in TUI currently cancels via the run-level `cancelAll` path
1476
+ * only. Kept on the public API so consumer renderers can wire it
1477
+ * without a follow-up surface change.
1478
+ */
1479
+ cancelHead: (reason?: string) => void;
1480
+ /** Cancel every queued request. Used by abort / session teardown. */
1481
+ cancelAll: (reason?: string) => void;
1482
+ }
1483
+ declare function InteractionsProvider({
1484
+ children
1485
+ }: {
1486
+ children: ReactNode;
1487
+ }): _$react_jsx_runtime0.JSX.Element;
1488
+ /** Read the live queue (re-renders on every push/pop). */
1489
+ declare function useInteractionsQueue(): readonly PendingInteractionEntry[];
1490
+ /** Read the stable actions object. */
1491
+ declare function useInteractionsActions(): InteractionsActions;
1492
+ /**
1493
+ * Build the `requestInteraction` callback for `createInteractionTools` from
1494
+ * the React-side {@link InteractionsActions}. Each call adds a fresh entry
1495
+ * to the queue whose `resolve` / `cancel` route back to one Promise that
1496
+ * the tool's `execute` awaits.
1497
+ */
1498
+ declare function makeRequestInteraction(actions: InteractionsActions): CreateInteractionToolsOptions['requestInteraction'];
1499
+ //#endregion
918
1500
  //#region src/chat/mcps-discovery.d.ts
919
1501
  /**
920
1502
  * One entry in the discovered list. `path` is the source file so a Settings
@@ -939,34 +1521,65 @@ declare function defaultMcpsConfigPaths(opts?: {
939
1521
  source: 'project' | 'user';
940
1522
  }[];
941
1523
  /**
942
- * Parse one `mcps.json` file. Accepts:
943
- * - A raw `McpServerConfig[]` array — host-SDK convention.
944
- * - An object with `{ "mcpServers": { name: {...} } }` — Claude Desktop
945
- * + many client wrappers. The `mcpServers` value is unwrapped before
946
- * normalization (otherwise `normalizeMcpServers` would treat the whole
947
- * wrapper as a single server).
948
- * - A name-keyed map (`{ fs: {...}, github: {...} }`) — host-SDK
949
- * convenience shape.
1524
+ * Parse one `mcps.json` file. Canonical zidane shape is a flat array; the
1525
+ * other shapes exist for copy-paste from neighboring tools:
1526
+ *
1527
+ * - `McpServerConfig[]` flat array (recommended).
1528
+ * - `{ name: {...} }` name-keyed map.
1529
+ * - `{ "mcpServers": { name: {...} } }` — Claude Desktop / Claude Code /
1530
+ * Cursor wrapper. Unwrapped before normalization (otherwise
1531
+ * `normalizeMcpServers` would treat the whole wrapper as a single server).
1532
+ *
1533
+ * Per-entry `enabled: false` (Cursor runtime state) drops the entry — same
1534
+ * intent as the source tool. Use the TUI toggle list for "show but disabled".
1535
+ *
1536
+ * Tolerant to common copy-paste artifacts: when strict `JSON.parse` fails,
1537
+ * retries after normalizing invisible whitespace that's valid Unicode but
1538
+ * not valid JSON whitespace (BOM, NBSP, zero-width spaces, line/paragraph
1539
+ * separators) — only OUTSIDE string literals, so user data isn't mutated.
1540
+ * If the sanitized version still fails, throws the original error with a
1541
+ * targeted hint when NBSPs are present.
950
1542
  *
951
1543
  * Validation flows through `normalizeMcpServers` so the result matches
952
- * what `createAgent` accepts. Throws on malformed JSON; the caller decides
953
- * whether to surface or swallow.
1544
+ * what `createAgent` accepts. Throws on truly malformed JSON; the caller
1545
+ * decides whether to surface or swallow.
954
1546
  */
955
1547
  declare function parseMcpsFile(text: string): McpServerConfig[];
1548
+ /**
1549
+ * Per-file failure surfaced from {@link discoverProjectMcps}. The TUI shows
1550
+ * these in the MCP settings empty / preamble state so a malformed
1551
+ * `mcps.json` doesn't look identical to a missing one.
1552
+ */
1553
+ interface DiscoveryError {
1554
+ path: string;
1555
+ source: 'project' | 'user';
1556
+ message: string;
1557
+ }
1558
+ /**
1559
+ * Result of {@link discoverProjectMcps}. `servers` is the per-source-priority
1560
+ * merged list (project beats user, first-found wins on name collision).
1561
+ * `errors` is one entry per file that existed but failed to parse — empty
1562
+ * on the happy path.
1563
+ */
1564
+ interface DiscoveryResult {
1565
+ servers: DiscoveredMcp[];
1566
+ errors: DiscoveryError[];
1567
+ }
956
1568
  /**
957
1569
  * Walk the default config paths, parse every file that exists, and return
958
- * `DiscoveredMcp[]` in source-priority order. Project entries appear
1570
+ * `{ servers, errors }` in source-priority order. Project entries appear
959
1571
  * before user entries; first occurrence of a `name` wins (later
960
1572
  * duplicates dropped).
961
1573
  *
962
- * Parse errors are logged under `ZIDANE_DEBUG` and the file skipped so a
963
- * single malformed `mcps.json` can't take down the picker.
1574
+ * Parse failures are captured into `errors` rather than thrown the picker
1575
+ * surfaces them while still showing whatever DID parse. A `ZIDANE_DEBUG`
1576
+ * log line is also emitted for ops visibility.
964
1577
  */
965
1578
  declare function discoverProjectMcps(opts?: {
966
1579
  cwd?: string;
967
1580
  home?: string;
968
1581
  prefix?: string;
969
- }): DiscoveredMcp[];
1582
+ }): DiscoveryResult;
970
1583
  /**
971
1584
  * Map a user-toggled enable list onto the `mcpServers` array the agent
972
1585
  * receives. Conventions match `buildSkillsConfig`:
@@ -1075,6 +1688,80 @@ declare function SafeModeProvider({
1075
1688
  declare function useSafeModeQueue(): readonly ApprovalRequest[];
1076
1689
  declare function useSafeModeActions(): SafeModeActions;
1077
1690
  //#endregion
1691
+ //#region src/chat/session-export.d.ts
1692
+ /** File format supported by the exporter. */
1693
+ type SessionExportFormat = 'markdown' | 'json';
1694
+ /**
1695
+ * Anchor for the resolved destination directory:
1696
+ * - `project` — the nearest enclosing git repository (`<repoRoot>/.{prefix}/sessions`)
1697
+ * - `home` — fallback when no repo was found (`~/.{prefix}/sessions`)
1698
+ */
1699
+ type SessionExportAnchor = 'project' | 'home';
1700
+ /** Resolved file destination for a session export. */
1701
+ interface SessionExportTarget {
1702
+ /** Absolute directory holding the file. May not exist yet — `writeSessionExport` creates it on demand. */
1703
+ dir: string;
1704
+ /** Absolute path of the file (`dir/{id}.{ext}`). */
1705
+ filepath: string;
1706
+ /** Where the destination was anchored. */
1707
+ anchor: SessionExportAnchor;
1708
+ }
1709
+ /** Options shared by every resolve / write entry-point. */
1710
+ interface ResolveOptions {
1711
+ /** Discovery cwd. Defaults to `process.cwd()`. */
1712
+ cwd?: string;
1713
+ /** User home directory. Defaults to `os.homedir()`. */
1714
+ home?: string;
1715
+ /**
1716
+ * Storage prefix. Leading dot tolerated (`zidane` and `.zidane` are
1717
+ * equivalent). Defaults to `'.zidane'`.
1718
+ */
1719
+ prefix?: string;
1720
+ }
1721
+ /**
1722
+ * Resolve the export target for a session id + format. Pure: no fs
1723
+ * write happens here, the caller decides whether to `existsSync` the
1724
+ * directory or hand the path to `writeSessionExport`.
1725
+ *
1726
+ * Anchor selection walks upward from `cwd` looking for a `.git` entry;
1727
+ * the first hit anchors to that repo's root (`project`). When the walk
1728
+ * exits without finding `.git`, the destination anchors to `home`.
1729
+ *
1730
+ * @throws RangeError when `sessionId` would resolve to an empty / `..`
1731
+ * filename — defensive guard against malicious or buggy callers
1732
+ * crossing into a sibling directory via the id.
1733
+ */
1734
+ declare function resolveSessionExportTarget(opts: {
1735
+ sessionId: string;
1736
+ format: SessionExportFormat;
1737
+ } & ResolveOptions): SessionExportTarget;
1738
+ /**
1739
+ * Render a session into a string in the requested format.
1740
+ *
1741
+ * `markdown` produces a human-readable transcript: a YAML-free header
1742
+ * block with the title and a one-line `id · created · turns` summary,
1743
+ * a stats section (turns / runs / tokens / cost / status), then a
1744
+ * `## Conversation` block where each turn renders as `### N. role ·
1745
+ * run_X · ISO-date` with text, thinking, tool calls, and tool results
1746
+ * formatted as appropriate fenced blocks. Useful for sharing a session
1747
+ * with a teammate or pasting into an issue tracker.
1748
+ *
1749
+ * `json` returns a 2-space-indented, deterministic dump of the full
1750
+ * `SessionData` blob. Useful for re-importing into the store or for
1751
+ * post-hoc analysis tooling.
1752
+ */
1753
+ declare function renderSession(session: SessionData, format: SessionExportFormat): string;
1754
+ /**
1755
+ * Render `session` and write the resulting bytes to disk. Returns the
1756
+ * resolved target so the caller can show the user where the file
1757
+ * landed. The parent directory is created on demand (`recursive: true`)
1758
+ * — first-time exports don't need any pre-flight setup.
1759
+ */
1760
+ declare function writeSessionExport(opts: {
1761
+ session: SessionData;
1762
+ format: SessionExportFormat;
1763
+ } & ResolveOptions): Promise<SessionExportTarget>;
1764
+ //#endregion
1078
1765
  //#region src/chat/theme.d.ts
1079
1766
  /**
1080
1767
  * Renderer-agnostic theme system.
@@ -1174,6 +1861,31 @@ interface ThemeSurfaces {
1174
1861
  * light flavor (Latte) so the same visual role works there.
1175
1862
  */
1176
1863
  selection: string;
1864
+ /**
1865
+ * Edit-diff color block. Drives the native `<diff>` renderable used
1866
+ * by {@link Settings.showEditDiffs}. Pre-mixed against each theme's
1867
+ * primary surface so terminals without true alpha-blend get a
1868
+ * legible "subtle red / subtle green" effect rather than a flat
1869
+ * saturated band.
1870
+ *
1871
+ * - `*Bg` row-level paint (gutter + content)
1872
+ * - `*ContentBg` content-only paint (overrides `*Bg` on the text
1873
+ * column). Set when a deeper hue should punch
1874
+ * through behind the syntax-highlighted code; omit
1875
+ * to let `*Bg` carry the full row.
1876
+ * - `*Fg` color for the `+` / `-` glyph in the sign gutter.
1877
+ */
1878
+ diff: DiffSurfaces;
1879
+ }
1880
+ /** Per-row paints used by the native `<diff>` renderable. */
1881
+ interface DiffSurfaces {
1882
+ addBg: string;
1883
+ removeBg: string;
1884
+ contextBg?: string;
1885
+ addContentBg?: string;
1886
+ removeContentBg?: string;
1887
+ addFg: string;
1888
+ removeFg: string;
1177
1889
  }
1178
1890
  /**
1179
1891
  * One entry in a `SyntaxStyles` map — what OpenTUI's `SyntaxStyle.fromStyles`
@@ -1226,5 +1938,5 @@ declare const BUILTIN_THEMES: Readonly<Record<string, Theme>>;
1226
1938
  /** Resolve a theme id to its full `Theme`, falling back to default on unknown ids. */
1227
1939
  declare function resolveTheme(id: string | undefined): Theme;
1228
1940
  //#endregion
1229
- export { Settings as $, useEnabledToggleSet as A, AgentProfile as At, lastContextSizeFromTurns as B, DiscoveredMcp as C, getModelInfo as Ct, parseMcpsFile as D, openrouterDescriptor as Dt, discoverProjectMcps as E, openaiDescriptor as Et, StateStoreApi as F, PLAN_AGENT as Ft, stripSpawnTokensLine as G, loadState as H, TuiState as I, resolveAgentId as It, toolResultText as J, titleFromTurns as K, createStateStore as L, singleAgentRegistry as Lt, ProviderRegistry as M, BUILD_AGENT as Mt, ResolvedConfig as N, BUILTIN_AGENTS as Nt, EnabledAllowlistKey as O, piIdOf as Ot, resolveConfig as P, DEFAULT_AGENT_ID as Pt, SessionMeta as Q, deriveSessionTitle as R, splitPromptSegments as S, getContextWindow as St, defaultMcpsConfigPaths as T, modelsForDescriptor as Tt, saveState as U, listSessionMeta as V, selectableTurnIds as W, Picked as X, Owner as Y, Screen as Z, SafeModeProvider as _, ModelInfo as _t, SyntaxStyles as a, CompletionReference as at, PromptSegment as b, cerebrasDescriptor as bt, ThemeColors as c, collectReferences as ct, resolveChipColor as d, useCompletion as dt, StreamEvent as et, resolveTheme as f, AuthMethod as ft, SafeModeActions as g, BUILTIN_PROVIDERS as gt, RequestApproval as h, detectAuth as ht, DEFAULT_THEME as i, CompletionProvider as it, ChatOptions as j, AgentRegistry as jt, EnabledToggleSet as k, AgentAccent as kt, ThemeSelect as l, findActiveTrigger as lt, ApprovalRequest as m, ProviderKey as mt, ChipColor as n, CompletionContext as nt, SyntaxTokenStyle as o, CompletionState as ot, ApprovalDecision as p, ProviderAuth as pt, toolCallPreview as q, ChipColorMap as r, CompletionItem as rt, Theme as s, applyInsert as st, BUILTIN_THEMES as t, ActiveTrigger as tt, ThemeSurfaces as u, mergeReferences as ut, useSafeModeActions as v, ProviderDescriptor as vt, buildMcpServers as w, modelSupportsReasoning as wt, PromptSegmentRef as x, credKeyOf as xt, useSafeModeQueue as y, anthropicDescriptor as yt, eventsFromTurns as z };
1230
- //# sourceMappingURL=theme-C3JHZ5y9.d.ts.map
1941
+ export { QuestionPayload as $, readKeybindings as $t, DiscoveryError as A, piIdOf as An, stripSpawnTokensLine as At, InteractionRequest as B, singleAgentRegistry as Bn, StreamEvent as Bt, SafeModeProvider as C, effectiveContextWindow as Cn, deriveSessionTitle as Ct, PromptSegmentRef as D, modelsForDescriptor as Dn, loadState as Dt, PromptSegment as E, modelSupportsReasoning as En, listSessionMeta as Et, parseMcpsFile as F, BUILTIN_AGENTS as Fn, Owner as Ft, PendingInteractionEntry as G, KeyBindingDef as Gt, InteractionsActions as H, KEYBINDING_DEFS as Ht, ASK_USER_TOOL as I, DEFAULT_AGENT_ID as In, Picked as It, PlanRequest as J, ensureKeybindingsFile as Jt, PlanDecision as K, KeyBindings as Kt, AnswerValue as L, DEFAULT_PERSIST_EXCLUDE_TOOLS as Ln, Screen as Lt, buildMcpServers as M, AgentProfile as Mn, toolCallPreview as Mt, defaultMcpsConfigPaths as N, AgentRegistry as Nn, toolResultText as Nt, splitPromptSegments as O, openaiDescriptor as On, saveState as Ot, discoverProjectMcps as P, BUILD_AGENT as Pn, EditPayload as Pt, QuestionChoice as Q, parseBindingSpec as Qt, ConfirmQuestion as R, PLAN_AGENT as Rn, SessionMeta as Rt, SafeModeActions as S, credKeyOf as Sn, createStateStore as St, useSafeModeQueue as T, getModelInfo as Tn, lastContextSizeFromTurns as Tt, InteractionsProvider as U, KEYBINDING_DEF_BY_ACTION as Ut, InteractionResponse as V, DEFAULT_KEYBINDINGS as Vt, PRESENT_PLAN_TOOL as W, KeyAction as Wt, PlanStep as X, matchesBinding as Xt, PlanResponse as Y, keybindingsPath as Yt, Question as Z, mergeKeybindings as Zt, resolveSessionExportTarget as _, ModelInfo as _n, ProviderRegistry as _t, SyntaxStyles as a, CompletionReference as an, buildResumedToolResultsTurn as at, ApprovalRequest as b, anthropicDescriptor as bn, StateStoreApi as bt, ThemeColors as c, collectReferences as cn, makeRequestInteraction as ct, resolveChipColor as d, useCompletion as dn, useInteractionsActions as dt, stripJsonComments as en, QuestionRequest as et, resolveTheme as f, AuthMethod as fn, useInteractionsQueue as ft, renderSession as g, BUILTIN_PROVIDERS as gn, ChatOptions as gt, SessionExportTarget as h, detectAuth as hn, useEnabledToggleSet as ht, DEFAULT_THEME as i, CompletionProvider as in, TextQuestion as it, DiscoveryResult as j, AgentAccent as jn, titleFromTurns as jt, DiscoveredMcp as k, openrouterDescriptor as kn, selectableTurnIds as kt, ThemeSelect as l, findActiveTrigger as ln, pendingInteractionsFromTurns as lt, SessionExportFormat as m, ProviderKey as mn, EnabledToggleSet as mt, ChipColor as n, CompletionContext as nn, QuestionType as nt, SyntaxTokenStyle as o, CompletionState as on, createInteractionTools as ot, SessionExportAnchor as p, ProviderAuth as pn, EnabledAllowlistKey as pt, PlanPayload as q, ParsedBinding as qt, ChipColorMap as r, CompletionItem as rn, SelectQuestion as rt, Theme as s, applyInsert as sn, isInteractionTool as st, BUILTIN_THEMES as t, ActiveTrigger as tn, QuestionResponse as tt, ThemeSurfaces as u, mergeReferences as un, serializeInteractionResponse as ut, writeSessionExport as v, OUTPUT_RESERVE_TOKENS as vn, ResolvedConfig as vt, useSafeModeActions as w, getContextWindow as wn, eventsFromTurns as wt, RequestApproval as x, cerebrasDescriptor as xn, TuiState as xt, ApprovalDecision as y, ProviderDescriptor as yn, resolveConfig as yt, CreateInteractionToolsOptions as z, resolveAgentId as zn, Settings as zt };
1942
+ //# sourceMappingURL=theme-CcGLMJrn.d.ts.map