zidane 5.7.8 → 5.8.2

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 (64) hide show
  1. package/README.md +4 -1
  2. package/dist/{agent-BSPhByzT.d.ts → agent-acjWZ_4E.d.ts} +145 -2
  3. package/dist/agent-acjWZ_4E.d.ts.map +1 -0
  4. package/dist/chat/pure.d.ts +3 -3
  5. package/dist/chat.d.ts +6 -6
  6. package/dist/chat.js +2 -2
  7. package/dist/{headless-CEtk5dzV.js → headless-CJFFU6DI.js} +16 -3
  8. package/dist/headless-CJFFU6DI.js.map +1 -0
  9. package/dist/headless.d.ts +1 -1
  10. package/dist/headless.js +1 -1
  11. package/dist/{index-DmbrQjOk.d.ts → index-Cgr_mbMJ.d.ts} +2 -2
  12. package/dist/{index-DmbrQjOk.d.ts.map → index-Cgr_mbMJ.d.ts.map} +1 -1
  13. package/dist/{index-DEqGfnZr.d.ts → index-zy4OtFSv.d.ts} +17 -3
  14. package/dist/index-zy4OtFSv.d.ts.map +1 -0
  15. package/dist/index.d.ts +4 -4
  16. package/dist/index.js +5 -296
  17. package/dist/index.js.map +1 -1
  18. package/dist/{login-C8Kc4gH0.js → login-BjY_sBdn.js} +301 -4
  19. package/dist/login-BjY_sBdn.js.map +1 -0
  20. package/dist/{mcp-Kqzz-Rs_.js → mcp-Br3b1Xm3.js} +50 -8
  21. package/dist/mcp-Br3b1Xm3.js.map +1 -0
  22. package/dist/mcp.d.ts +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/dist/{presets-DTxFbEZ5.js → presets-BmsTNxjR.js} +2 -2
  25. package/dist/{presets-DTxFbEZ5.js.map → presets-BmsTNxjR.js.map} +1 -1
  26. package/dist/presets.d.ts +2 -2
  27. package/dist/presets.js +1 -1
  28. package/dist/providers.d.ts +1 -1
  29. package/dist/restate.d.ts +1 -1
  30. package/dist/session/sqlite.d.ts +1 -1
  31. package/dist/session.d.ts +1 -1
  32. package/dist/skills.d.ts +2 -2
  33. package/dist/{tool-formatters-fUAp2Nr4.d.ts → tool-formatters-B5UNV_sy.d.ts} +2 -2
  34. package/dist/{tool-formatters-fUAp2Nr4.d.ts.map → tool-formatters-B5UNV_sy.d.ts.map} +1 -1
  35. package/dist/tools/fetch-url.d.ts +1 -1
  36. package/dist/tools/web-search.d.ts +1 -1
  37. package/dist/{tools-dkB_jARJ.js → tools-BzQtic6M.js} +211 -7
  38. package/dist/tools-BzQtic6M.js.map +1 -0
  39. package/dist/tools.d.ts +2 -2
  40. package/dist/tools.js +1 -1
  41. package/dist/{transcript-anchors-Cl7lbbeP.js → transcript-anchors-C571npbs.js} +46 -6
  42. package/dist/transcript-anchors-C571npbs.js.map +1 -0
  43. package/dist/{transcript-anchors-BBN7jlvp.d.ts → transcript-anchors-Dtz6U4GW.d.ts} +5 -5
  44. package/dist/transcript-anchors-Dtz6U4GW.d.ts.map +1 -0
  45. package/dist/tui.d.ts +14 -4
  46. package/dist/tui.d.ts.map +1 -1
  47. package/dist/tui.js +284 -78
  48. package/dist/tui.js.map +1 -1
  49. package/dist/{turn-operations-CE1prnuP.d.ts → turn-operations-CqJAEzoe.d.ts} +3 -3
  50. package/dist/{turn-operations-CE1prnuP.d.ts.map → turn-operations-CqJAEzoe.d.ts.map} +1 -1
  51. package/dist/types-BPw_i5vb.js.map +1 -1
  52. package/dist/types.d.ts +3 -3
  53. package/docs/ARCHITECTURE.md +4 -2
  54. package/docs/CHAT.md +19 -1
  55. package/docs/SKILL.md +1 -0
  56. package/package.json +1 -1
  57. package/dist/agent-BSPhByzT.d.ts.map +0 -1
  58. package/dist/headless-CEtk5dzV.js.map +0 -1
  59. package/dist/index-DEqGfnZr.d.ts.map +0 -1
  60. package/dist/login-C8Kc4gH0.js.map +0 -1
  61. package/dist/mcp-Kqzz-Rs_.js.map +0 -1
  62. package/dist/tools-dkB_jARJ.js.map +0 -1
  63. package/dist/transcript-anchors-BBN7jlvp.d.ts.map +0 -1
  64. package/dist/transcript-anchors-Cl7lbbeP.js.map +0 -1
package/dist/tui.js CHANGED
@@ -1,20 +1,20 @@
1
- import { $ as useMcpAuthDispatch, $t as deriveSessionTitle, A as runOAuthLogin, An as buildUpdateHint, At as clampFps, B as refreshMcpToolsCatalog, Bn as AUTO_COMPACT_MIN_GROWTH_FRACTION, Ct as listProjectFiles, D as formatPathForCwd, Dn as tryOpenBrowser, Dt as SETTINGS_CHOICES, En as useCompletion, Et as SETTINGS_CATEGORIES, Ft as resolveTheme, Gt as useDiscovery, H as subscribeMcpToolsCache, Hn as detectAuth, J as parentServerName, Jn as setProviderCredential, Jt as useConfig, K as buildVisibleMcpRows, Kt as useDiscoveryOptional, M as buildMcpServers, Mr as buildBuildSystem, Nr as buildPlanSystem, O as fetchOAuthRedirect, Ot as SETTINGS_TOGGLES, P as discoverProjectMcps, Pr as envSection, Pt as resolveChipColor, Q as McpAuthProvider, Qn as findGitRoot, R as loadMcpToolsCache, T as suggestSafelistEntry, Tt as DEFAULT_SETTINGS, Ut as createDiscoverySlot, Vn as shouldAutoCompact, W as useMcpToolToggleMap, Wt as DiscoveryProvider, Xn as discoverAgentsMd, Y as createFileMcpCredentialStore, Yt as resolveConfig, _ as useSafeModeQueue, _n as ensureKeybindingsFile, _t as hintsLength, a as useSurfaces, ar as accentColor, at as InteractionsProvider, b as getSafelist, bn as keybindingsPath, bt as generateSessionTitle, c as useStreamBuffer, cn as sumRunCosts, ct as createInteractionTools, d as discoverProjectSkills, dn as toolResultText, dr as TODO_STATUS_GLYPHS, dt as pendingInteractionsFromTurns, en as eventsFromTurns, et as useMcpAuthState, fn as updateToolEventOutcomes, g as useSafeModeActions, gn as KEYBINDING_KEY_COL_WIDTH, gt as clipHintsToWidth, h as SafeModeProvider, ht as EMPTY_HINTS, i as useSelectStyle, in as marginTopFor, j as supportsOAuth, jn as useUpdateCheck, jt as useSettings, k as oauthUsesManualCodePaste, kn as bootTick, kt as SettingsProvider, l as buildSkillsConfig, m as writeSessionExport, mn as KEYBINDING_DEFS, mt as useInteractionsQueue, n as ThemeProvider, nn as listSessionMeta, on as serverToolResultSummary, pt as useInteractionsActions, q as indexOfServerRow, qt as ConfigProvider, r as useColors, rt as splitMarkdownCodeBlocks, s as useTheme, sn as stripSpawnTokensLine, st as buildResumedToolResultsTurn, t as computeTurnAnchors, tn as lastContextSizeFromTurns, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as toolCallPreview, ut as makeRequestInteraction, vn as formatBindingForDisplay, vt as truncateTrailing, wt as useEnabledToggleSet, x as isOnSafelist, xn as matchesBinding, xr as useActiveTodos, xt as buildHints, y as addToSafelist, yn as groupBindings } from "./transcript-anchors-Cl7lbbeP.js";
2
- import { B as enabledModelOptions, E as cleanupPersistedSession, F as OUTPUT_RESERVE_TOKENS, G as modelSupportsReasoning, O as resolvePersistDir, V as getContextWindow, W as modelOptionsFor, X as restoreModelOptions, Y as piIdOf, d as createAgent, k as resolveTasksDir, z as effectiveContextWindow } from "./tools-dkB_jARJ.js";
1
+ import { $ as useMcpAuthDispatch, $t as deriveSessionTitle, A as runOAuthLogin, An as buildUpdateHint, At as clampFps, B as refreshMcpToolsCatalog, Bn as AUTO_COMPACT_MIN_GROWTH_FRACTION, Ct as listProjectFiles, D as formatPathForCwd, Dn as tryOpenBrowser, Dt as SETTINGS_CHOICES, En as useCompletion, Et as SETTINGS_CATEGORIES, Ft as resolveTheme, Gt as useDiscovery, H as subscribeMcpToolsCache, Hn as detectAuth, J as parentServerName, Jn as setProviderCredential, Jt as useConfig, K as buildVisibleMcpRows, Kt as useDiscoveryOptional, M as buildMcpServers, Mr as buildBuildSystem, Nr as buildPlanSystem, O as fetchOAuthRedirect, Ot as SETTINGS_TOGGLES, P as discoverProjectMcps, Pr as envSection, Pt as resolveChipColor, Q as McpAuthProvider, Qn as findGitRoot, R as loadMcpToolsCache, T as suggestSafelistEntry, Tt as DEFAULT_SETTINGS, Ut as createDiscoverySlot, Vn as shouldAutoCompact, W as useMcpToolToggleMap, Wt as DiscoveryProvider, Xn as discoverAgentsMd, Y as createFileMcpCredentialStore, Yt as resolveConfig, _ as useSafeModeQueue, _n as ensureKeybindingsFile, _t as hintsLength, a as useSurfaces, ar as accentColor, at as InteractionsProvider, b as getSafelist, bn as keybindingsPath, bt as generateSessionTitle, c as useStreamBuffer, cn as sumRunCosts, ct as createInteractionTools, d as discoverProjectSkills, dn as toolResultText, dr as TODO_STATUS_GLYPHS, dt as pendingInteractionsFromTurns, en as eventsFromTurns, et as useMcpAuthState, fn as updateToolEventOutcomes, g as useSafeModeActions, gn as KEYBINDING_KEY_COL_WIDTH, gt as clipHintsToWidth, h as SafeModeProvider, ht as EMPTY_HINTS, i as useSelectStyle, in as marginTopFor, j as supportsOAuth, jn as useUpdateCheck, jt as useSettings, k as oauthUsesManualCodePaste, kn as bootTick, kt as SettingsProvider, l as buildSkillsConfig, m as writeSessionExport, mn as KEYBINDING_DEFS, mt as useInteractionsQueue, n as ThemeProvider, nn as listSessionMeta, on as serverToolResultSummary, pt as useInteractionsActions, q as indexOfServerRow, qt as ConfigProvider, r as useColors, rt as splitMarkdownCodeBlocks, s as useTheme, sn as stripSpawnTokensLine, st as buildResumedToolResultsTurn, t as computeTurnAnchors, tn as lastContextSizeFromTurns, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as toolCallPreview, ut as makeRequestInteraction, vn as formatBindingForDisplay, vt as truncateTrailing, wt as useEnabledToggleSet, x as isOnSafelist, xn as matchesBinding, xr as useActiveTodos, xt as buildHints, y as addToSafelist, yn as groupBindings } from "./transcript-anchors-C571npbs.js";
2
+ import { A as resolveTasksDir, B as effectiveContextWindow, E as cleanupPersistedSession, G as modelOptionsFor, H as getContextWindow, I as OUTPUT_RESERVE_TOKENS, K as modelSupportsReasoning, O as resolveMcpWarningsDir, V as enabledModelOptions, X as piIdOf, Z as restoreModelOptions, d as createAgent, k as resolvePersistDir } from "./tools-BzQtic6M.js";
3
3
  import { a as compactPath, c as formatTaskStatus, d as shortId, i as ageString, l as formatTaskSummary, o as fmtTokens, s as formatDuration, u as previewLine } from "./edit-utils-DnfNoj16.js";
4
4
  import { l as errorMessage } from "./errors-CoQnKRf1.js";
5
5
  import { A as replaceDynamicSection } from "./messages-CvRQTdbR.js";
6
6
  import { n as sniffImageMediaType } from "./image-sniff-B7uFSNO1.js";
7
7
  import { n as createProcessContext } from "./contexts-BD2U_xpi.js";
8
- import { s as McpOAuthProvider, t as connectMcpServers } from "./mcp-Kqzz-Rs_.js";
8
+ import { c as McpOAuthProvider, n as connectMcpServers } from "./mcp-Br3b1Xm3.js";
9
9
  import { r as formatTokenUsage, t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
10
- import { a as selectFilesFromSession, b as summaryToTurn, r as buildPostCompactAttachments, s as compactConversation, t as loginMcpServer } from "./login-C8Kc4gH0.js";
10
+ import { d as compactConversation, i as createLogger, l as selectFilesFromSession, r as consoleSink, s as buildPostCompactAttachments, t as loginMcpServer, w as summaryToTurn } from "./login-BjY_sBdn.js";
11
11
  import { n as loadSession, t as createSession } from "./session-BzLou2_-.js";
12
12
  import { createTuiStore } from "./session/sqlite.js";
13
13
  import { B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, F as mergeApprovalAndBodyOutcomes, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, I as parseEditOutcomesFromResult, L as resolveApprovalForPayload, N as buildEditOutcomesAnnotation, O as filetypeFromPath, Q as buildLinearRamp, R as rewriteMultiEditHeader, U as uniqueSkillNamesFromReferences, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, g as EDIT_TOOL_NAMES, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, r as truncateTurnsAt, s as formatToolCall, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible, z as stripEditOutcomesAnnotation } from "./turn-operations-CCHfR9eC.js";
14
14
  import { basename, join, relative } from "node:path";
15
15
  import { Buffer } from "node:buffer";
16
16
  import * as fs from "node:fs";
17
- import { readFileSync, readdirSync, statSync } from "node:fs";
17
+ import { createWriteStream, mkdirSync, readFileSync, readdirSync, statSync } from "node:fs";
18
18
  import { spawn } from "node:child_process";
19
19
  import { homedir } from "node:os";
20
20
  import { createContext, createElement, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
@@ -22,6 +22,54 @@ import { Fzf, byLengthAsc } from "fzf";
22
22
  import { BoxRenderable, CodeRenderable, RGBA, SyntaxStyle, TextRenderable, addDefaultParsers, createCliRenderer, decodePasteBytes, defaultTextareaKeyBindings, getTreeSitterClient, stripAnsiSequences } from "@opentui/core";
23
23
  import { createRoot, useKeyboard, useRenderer, useSelectionHandler, useTerminalDimensions } from "@opentui/react";
24
24
  import { Fragment, jsx, jsxs } from "@opentui/react/jsx-runtime";
25
+ //#region src/mcp/warn-log.ts
26
+ /**
27
+ * Subscribe to `mcp:warn`
28
+ * (stdio child stderr lines, see `attachStderrWarnPump` in ./index.ts)
29
+ * and append each to `<dir>/warnings.log`.
30
+ *
31
+ * The stream opens lazily on the first warning so
32
+ * a healthy session never touches disk.
33
+ */
34
+ function attachMcpWarnLog(hooks, opts) {
35
+ let stream = null;
36
+ let logger = null;
37
+ const ensureLogger = () => {
38
+ if (logger) return logger;
39
+ try {
40
+ mkdirSync(opts.dir, { recursive: true });
41
+ const s = createWriteStream(join(opts.dir, "warnings.log"), { flags: "a" });
42
+ s.on("error", () => {});
43
+ stream = s;
44
+ logger = createLogger(consoleSink({
45
+ stream: s,
46
+ minLevel: "warn"
47
+ }));
48
+ return logger;
49
+ } catch {
50
+ return null;
51
+ }
52
+ };
53
+ const unhook = hooks.hook("mcp:warn", ({ name, message }) => {
54
+ ensureLogger()?.warn("mcp warn", {
55
+ server: name,
56
+ message
57
+ });
58
+ });
59
+ return { close: async () => {
60
+ unhook();
61
+ const s = stream;
62
+ stream = null;
63
+ logger = null;
64
+ if (!s) return;
65
+ await new Promise((resolve) => {
66
+ s.once("close", () => resolve());
67
+ s.once("error", () => resolve());
68
+ s.end();
69
+ });
70
+ } };
71
+ }
72
+ //#endregion
25
73
  //#region src/tui/modal.tsx
26
74
  const ModalContext = createContext(null);
27
75
  function ModalRoot({ children }) {
@@ -602,7 +650,7 @@ function CrushThrobber({ label, size = 15, from, to, labelColor }) {
602
650
  * rather than reading as "punched out" rectangles. Top-level keys
603
651
  * absent from the base theme become brand-new entries.
604
652
  */
605
- function buildMdStyle(theme, overrides) {
653
+ function buildMdStyle(theme, overrides, flattenFg) {
606
654
  const styles = {};
607
655
  for (const [token, style] of Object.entries(theme.syntax)) {
608
656
  const out = {};
@@ -612,6 +660,11 @@ function buildMdStyle(theme, overrides) {
612
660
  if (style.italic) out.italic = true;
613
661
  if (style.underline) out.underline = true;
614
662
  if (style.dim) out.dim = true;
663
+ if (flattenFg) {
664
+ out.fg = flattenFg;
665
+ out.bold = false;
666
+ out.underline = false;
667
+ }
615
668
  styles[token] = out;
616
669
  }
617
670
  if (overrides) for (const [token, patch] of Object.entries(overrides)) styles[token] = {
@@ -630,7 +683,8 @@ function MdStyleProvider({ children }) {
630
683
  selected: buildMdStyle(theme, {
631
684
  "markup.raw": { bg: selectionBg },
632
685
  "markup.raw.block": { bg: selectionBg }
633
- })
686
+ }),
687
+ dimmed: buildMdStyle(theme, void 0, RGBA.fromHex(theme.colors.dim))
634
688
  };
635
689
  }, [theme]);
636
690
  return createElement(MdStyleContext.Provider, { value: bundle }, children);
@@ -652,6 +706,7 @@ function MdStyleProvider({ children }) {
652
706
  function useMdStyle(opts = {}) {
653
707
  const bundle = useContext(MdStyleContext);
654
708
  if (!bundle) throw new Error("useMdStyle must be used inside <MdStyleProvider>");
709
+ if (opts.dimmed) return bundle.dimmed;
655
710
  return opts.selected ? bundle.selected : bundle.regular;
656
711
  }
657
712
  const CHIP_TOKEN_PREFIX = "completion.reference";
@@ -781,6 +836,7 @@ const EventLine = memo(({ event, previous, depthOffset = 0, selected = false, an
781
836
  },
782
837
  children: /* @__PURE__ */ jsx(EventLineImpl, {
783
838
  event,
839
+ previous,
784
840
  depthOffset,
785
841
  hideChildLabel,
786
842
  selected
@@ -1194,17 +1250,20 @@ function Transcript({ events, settings, selectedTurnId = null, busy = false }) {
1194
1250
  foregroundColor: COLOR.mute
1195
1251
  }
1196
1252
  },
1197
- children: [items.map((item, i) => item.kind === "event" ? /* @__PURE__ */ jsx(EventLine, {
1198
- event: item.event,
1199
- previous: item.previous,
1200
- selected: isTurnHighlighted(item.event, selectedTurnId, ownership),
1201
- anchorId: anchors.ids[i][0]
1202
- }, i) : /* @__PURE__ */ jsx(SubagentBlock, {
1203
- events: item.events,
1204
- previous: item.previous,
1205
- selectedTurnId,
1206
- anchorIds: anchors.ids[i]
1207
- }, i)), showThrobber && /* @__PURE__ */ jsx("box", {
1253
+ children: [items.map((item, i) => {
1254
+ if (item.kind === "event") return /* @__PURE__ */ jsx(EventLine, {
1255
+ event: item.event,
1256
+ previous: item.previous,
1257
+ selected: isTurnHighlighted(item.event, selectedTurnId, ownership),
1258
+ anchorId: anchors.ids[i][0]
1259
+ }, i);
1260
+ return /* @__PURE__ */ jsx(SubagentBlock, {
1261
+ events: item.events,
1262
+ previous: item.previous,
1263
+ selectedTurnId,
1264
+ anchorIds: anchors.ids[i]
1265
+ }, i);
1266
+ }), showThrobber && /* @__PURE__ */ jsx("box", {
1208
1267
  style: { marginTop: items.length > 0 ? 1 : 0 },
1209
1268
  children: /* @__PURE__ */ jsx(CrushThrobber, {
1210
1269
  label: throbberLabel,
@@ -1319,6 +1378,7 @@ function EmptyState() {
1319
1378
  }
1320
1379
  /** Left-pad applied per depth level (in columns). */
1321
1380
  const INDENT_PER_DEPTH = 2;
1381
+ const THINKING_GUTTER_WIDTH = 4;
1322
1382
  function indentFor(depth) {
1323
1383
  return depth && depth > 0 ? depth * INDENT_PER_DEPTH : 0;
1324
1384
  }
@@ -1342,7 +1402,7 @@ function rowStyle(paddingLeft) {
1342
1402
  alignSelf: "stretch"
1343
1403
  };
1344
1404
  }
1345
- function EventLineImpl({ event, depthOffset = 0, hideChildLabel = false, selected = false }) {
1405
+ function EventLineImpl({ event, previous, depthOffset = 0, hideChildLabel = false, selected = false }) {
1346
1406
  const COLOR = useColors();
1347
1407
  const { settings } = useSettings();
1348
1408
  const safeText = event.text === "" ? " " : event.text;
@@ -1362,13 +1422,41 @@ function EventLineImpl({ event, depthOffset = 0, hideChildLabel = false, selecte
1362
1422
  children: safeText
1363
1423
  })
1364
1424
  });
1365
- case "thinking": return /* @__PURE__ */ jsx("box", {
1366
- style: row,
1367
- children: /* @__PURE__ */ jsx("text", {
1368
- fg: COLOR.dim,
1369
- children: safeText
1370
- })
1371
- });
1425
+ case "thinking": {
1426
+ const startsRun = !(previous?.kind === "thinking" && previous.childId === event.childId);
1427
+ const thinkingText = safeText.replace(/\*\*([^*]+)\*\*/g, "$1");
1428
+ return /* @__PURE__ */ jsx("box", {
1429
+ style: row,
1430
+ children: /* @__PURE__ */ jsxs("box", {
1431
+ style: {
1432
+ flexDirection: "row",
1433
+ alignSelf: "stretch",
1434
+ flexShrink: 0
1435
+ },
1436
+ children: [/* @__PURE__ */ jsx("box", {
1437
+ style: {
1438
+ width: THINKING_GUTTER_WIDTH,
1439
+ flexShrink: 0,
1440
+ flexDirection: "column"
1441
+ },
1442
+ children: /* @__PURE__ */ jsx("text", {
1443
+ fg: startsRun ? COLOR.accent : COLOR.mute,
1444
+ children: startsRun ? "🧠" : " "
1445
+ })
1446
+ }), /* @__PURE__ */ jsx("box", {
1447
+ style: {
1448
+ flexGrow: 1,
1449
+ flexShrink: 1,
1450
+ flexDirection: "column"
1451
+ },
1452
+ children: /* @__PURE__ */ jsx("text", {
1453
+ fg: COLOR.dim,
1454
+ children: thinkingText
1455
+ })
1456
+ })]
1457
+ })
1458
+ });
1459
+ }
1372
1460
  case "tool":
1373
1461
  if (event.edit && settings.showEditDiffs) return /* @__PURE__ */ jsx("box", {
1374
1462
  style: row,
@@ -2020,7 +2108,10 @@ function parseBlockIndex(id) {
2020
2108
  const MarkdownBlock = memo(({ text, dim, selected = false }) => {
2021
2109
  const COLOR = useColors();
2022
2110
  const SURFACE = useSurfaces();
2023
- const mdStyle = useMdStyle({ selected });
2111
+ const mdStyle = useMdStyle({
2112
+ selected,
2113
+ dimmed: dim
2114
+ });
2024
2115
  const renderer = useRenderer();
2025
2116
  const content = text.replace(/^\n+|\n+$/g, "");
2026
2117
  const bag = useRef({
@@ -5038,8 +5129,50 @@ function InteractionShell({ title, maxHeight, children }) {
5038
5129
  children
5039
5130
  });
5040
5131
  }
5041
- /** Number of plan-body lines rendered inline before we truncate. */
5132
+ /** Number of plan-body lines rendered inline in the collapsed preview. */
5042
5133
  const PLAN_BODY_MAX_LINES = 8;
5134
+ const PLAN_PREVIEW_MIN_COLUMNS = 20;
5135
+ /**
5136
+ * Cap the plan picker at ~60% of the terminal when the user expands a
5137
+ * long plan, so the transcript above stays readable. The inner scrollbox
5138
+ * handles overflow so the full plan is reachable before committing — the
5139
+ * decision picker stays pinned below the scrollable region.
5140
+ */
5141
+ const PLAN_EXPANDED_MAX_HEIGHT = "60%";
5142
+ function estimatedVisualRows(line, columns) {
5143
+ if (line.length === 0) return 1;
5144
+ return Math.max(1, Math.ceil(line.length / columns));
5145
+ }
5146
+ function buildPlanPreview(plan, columns) {
5147
+ const width = Math.max(PLAN_PREVIEW_MIN_COLUMNS, Math.floor(columns));
5148
+ const lines = plan.split("\n");
5149
+ const preview = [];
5150
+ let usedRows = 0;
5151
+ for (let i = 0; i < lines.length; i++) {
5152
+ const line = lines[i] ?? "";
5153
+ const rows = estimatedVisualRows(line, width);
5154
+ if (usedRows + rows <= PLAN_BODY_MAX_LINES) {
5155
+ preview.push(line);
5156
+ usedRows += rows;
5157
+ continue;
5158
+ }
5159
+ const remainingRows = Math.max(0, PLAN_BODY_MAX_LINES - usedRows);
5160
+ if (remainingRows > 0) {
5161
+ const maxChars = Math.max(1, remainingRows * width);
5162
+ preview.push(line.length > maxChars ? line.slice(0, maxChars).trimEnd() : line);
5163
+ }
5164
+ return {
5165
+ previewText: preview.join("\n"),
5166
+ overflow: true,
5167
+ hiddenLineCount: lines.length - i - 1
5168
+ };
5169
+ }
5170
+ return {
5171
+ previewText: plan,
5172
+ overflow: false,
5173
+ hiddenLineCount: 0
5174
+ };
5175
+ }
5043
5176
  const PLAN_OPTIONS = [
5044
5177
  {
5045
5178
  id: "approve",
@@ -5061,28 +5194,40 @@ function PlanInteractionBlock({ request, onResolve }) {
5061
5194
  const COLOR = useColors();
5062
5195
  const mdStyle = useMdStyle();
5063
5196
  const focused = useModalAwareFocus();
5197
+ const { width: terminalWidth } = useTerminalDimensions();
5064
5198
  const [stage, setStage] = useState("pick");
5065
5199
  const [decision, setDecision] = useState(null);
5200
+ const [expanded, setExpanded] = useState(false);
5066
5201
  const textareaRef = useRef(null);
5202
+ const scrollboxRef = useRef(null);
5067
5203
  const { title, plan, steps } = request.payload;
5204
+ const { previewText, overflow, hiddenLineCount } = useMemo(() => {
5205
+ return buildPlanPreview(plan, terminalWidth - 8);
5206
+ }, [plan, terminalWidth]);
5068
5207
  useKeyboard((key) => {
5069
5208
  if (!focused) return;
5070
- if (key.name !== "tab" || !key.shift) return;
5071
5209
  if (key.ctrl || key.meta || key.option) return;
5072
- if (stage !== "comment") return;
5073
- setStage("pick");
5074
- });
5075
- const { bodyText, truncated } = useMemo(() => {
5076
- const lines = plan.split("\n");
5077
- if (lines.length <= PLAN_BODY_MAX_LINES) return {
5078
- bodyText: plan,
5079
- truncated: false
5080
- };
5081
- return {
5082
- bodyText: lines.slice(0, PLAN_BODY_MAX_LINES).join("\n"),
5083
- truncated: true
5084
- };
5085
- }, [plan]);
5210
+ if (key.name === "tab") {
5211
+ if (key.shift) {
5212
+ if (stage !== "comment") return;
5213
+ setStage("pick");
5214
+ return;
5215
+ }
5216
+ if (stage !== "pick" || !overflow) return;
5217
+ setExpanded((e) => !e);
5218
+ return;
5219
+ }
5220
+ if (key.shift) return;
5221
+ if (key.name !== "pageup" && key.name !== "pagedown") return;
5222
+ if (stage !== "pick" || !expanded) return;
5223
+ const sb = scrollboxRef.current;
5224
+ if (!sb) return;
5225
+ const page = Math.max(1, sb.viewport.height - 1);
5226
+ sb.scrollBy({
5227
+ x: 0,
5228
+ y: key.name === "pageup" ? -page : page
5229
+ });
5230
+ });
5086
5231
  const onPick = useCallback((value) => {
5087
5232
  if (value === "approve") {
5088
5233
  onResolve({
@@ -5157,15 +5302,60 @@ function PlanInteractionBlock({ request, onResolve }) {
5157
5302
  })
5158
5303
  ]
5159
5304
  });
5305
+ const stepsBlock = steps && steps.length > 0 ? /* @__PURE__ */ jsxs("box", {
5306
+ style: {
5307
+ flexDirection: "column",
5308
+ marginTop: 1
5309
+ },
5310
+ children: [/* @__PURE__ */ jsx("text", {
5311
+ fg: COLOR.mute,
5312
+ children: "steps:"
5313
+ }), steps.map((step, i) => /* @__PURE__ */ jsxs("text", {
5314
+ fg: COLOR.dim,
5315
+ wrapMode: "word",
5316
+ children: [
5317
+ /* @__PURE__ */ jsx("span", {
5318
+ fg: COLOR.warn,
5319
+ children: ` ${i + 1}. `
5320
+ }),
5321
+ /* @__PURE__ */ jsx("span", {
5322
+ fg: COLOR.brand,
5323
+ children: step.title
5324
+ }),
5325
+ step.description && /* @__PURE__ */ jsx("span", {
5326
+ fg: COLOR.mute,
5327
+ children: ` — ${step.description}`
5328
+ })
5329
+ ]
5330
+ }, step.id))]
5331
+ }) : null;
5160
5332
  return /* @__PURE__ */ jsxs(InteractionShell, {
5161
5333
  title: " approve plan · esc to abort run ",
5334
+ maxHeight: expanded ? PLAN_EXPANDED_MAX_HEIGHT : void 0,
5162
5335
  children: [
5163
5336
  /* @__PURE__ */ jsx("text", {
5164
5337
  fg: COLOR.brand,
5165
5338
  wrapMode: "none",
5339
+ style: { flexShrink: 0 },
5166
5340
  children: title
5167
5341
  }),
5168
- /* @__PURE__ */ jsxs("box", {
5342
+ expanded ? /* @__PURE__ */ jsxs("scrollbox", {
5343
+ ref: scrollboxRef,
5344
+ focusable: false,
5345
+ style: {
5346
+ flexGrow: 1,
5347
+ flexShrink: 1,
5348
+ marginTop: 1,
5349
+ marginBottom: 1
5350
+ },
5351
+ children: [/* @__PURE__ */ jsx("markdown", {
5352
+ content: plan,
5353
+ syntaxStyle: mdStyle,
5354
+ streaming: false,
5355
+ internalBlockMode: "coalesced",
5356
+ fg: COLOR.dim
5357
+ }), stepsBlock]
5358
+ }) : /* @__PURE__ */ jsxs("box", {
5169
5359
  style: {
5170
5360
  flexDirection: "column",
5171
5361
  marginTop: 1,
@@ -5173,43 +5363,41 @@ function PlanInteractionBlock({ request, onResolve }) {
5173
5363
  },
5174
5364
  children: [
5175
5365
  /* @__PURE__ */ jsx("markdown", {
5176
- content: bodyText,
5366
+ content: previewText,
5177
5367
  syntaxStyle: mdStyle,
5178
5368
  streaming: false,
5179
5369
  internalBlockMode: "coalesced",
5180
5370
  fg: COLOR.dim
5181
5371
  }),
5182
- truncated && /* @__PURE__ */ jsx("text", {
5372
+ overflow && /* @__PURE__ */ jsxs("text", {
5183
5373
  fg: COLOR.mute,
5184
- children: `… plan body truncated (${plan.split("\n").length - PLAN_BODY_MAX_LINES} more lines). Open the session details to see full content.`
5374
+ wrapMode: "word",
5375
+ children: [
5376
+ hiddenLineCount > 0 ? `… ${hiddenLineCount} more line${hiddenLineCount === 1 ? "" : "s"} · ` : "… more content · ",
5377
+ /* @__PURE__ */ jsx("span", {
5378
+ fg: COLOR.warn,
5379
+ children: "↹"
5380
+ }),
5381
+ " to expand and scroll"
5382
+ ]
5185
5383
  }),
5186
- steps && steps.length > 0 && /* @__PURE__ */ jsxs("box", {
5187
- style: {
5188
- flexDirection: "column",
5189
- marginTop: 1
5190
- },
5191
- children: [/* @__PURE__ */ jsx("text", {
5192
- fg: COLOR.mute,
5193
- children: "steps:"
5194
- }), steps.map((step, i) => /* @__PURE__ */ jsxs("text", {
5195
- fg: COLOR.dim,
5196
- wrapMode: "word",
5197
- children: [
5198
- /* @__PURE__ */ jsx("span", {
5199
- fg: COLOR.warn,
5200
- children: ` ${i + 1}. `
5201
- }),
5202
- /* @__PURE__ */ jsx("span", {
5203
- fg: COLOR.brand,
5204
- children: step.title
5205
- }),
5206
- step.description && /* @__PURE__ */ jsx("span", {
5207
- fg: COLOR.mute,
5208
- children: ` — ${step.description}`
5209
- })
5210
- ]
5211
- }, step.id))]
5212
- })
5384
+ stepsBlock
5385
+ ]
5386
+ }),
5387
+ expanded && /* @__PURE__ */ jsxs("text", {
5388
+ fg: COLOR.mute,
5389
+ style: { flexShrink: 0 },
5390
+ children: [
5391
+ /* @__PURE__ */ jsx("span", {
5392
+ fg: COLOR.warn,
5393
+ children: "↹"
5394
+ }),
5395
+ " to collapse · ",
5396
+ /* @__PURE__ */ jsx("span", {
5397
+ fg: COLOR.warn,
5398
+ children: "pgup/pgdn"
5399
+ }),
5400
+ " to scroll"
5213
5401
  ]
5214
5402
  }),
5215
5403
  /* @__PURE__ */ jsx(OptionList, {
@@ -11034,6 +11222,7 @@ function AppShell() {
11034
11222
  queueSelectionIndexRef.current = queueSelectionIndex;
11035
11223
  const agentRef = useRef(null);
11036
11224
  const sessionRef = useRef(null);
11225
+ const warnLogRef = useRef(null);
11037
11226
  useEffect(() => {
11038
11227
  const handle = agentRef.current?.handle;
11039
11228
  if (handle) handle.cwd = cwd;
@@ -11352,6 +11541,10 @@ function AppShell() {
11352
11541
  ctx.result = result;
11353
11542
  if (mergedOutcomes) applyEditAnnotationsToStream(ctx.callId, mergedOutcomes);
11354
11543
  });
11544
+ warnLogRef.current = attachMcpWarnLog(agent.hooks, { dir: resolveMcpWarningsDir({
11545
+ userDir: cacheDir,
11546
+ sessionId: session.id
11547
+ }) });
11355
11548
  agent.hooks.hook("mcp:auth:required", ({ name, reason }) => {
11356
11549
  dispatchAuthRef.current({
11357
11550
  type: "auth-required",
@@ -11693,6 +11886,10 @@ function AppShell() {
11693
11886
  await agentRef.current?.destroy().catch((err) => debugLog("agent.destroy failed", err));
11694
11887
  agentRef.current = null;
11695
11888
  sessionRef.current = null;
11889
+ if (warnLogRef.current) {
11890
+ await warnLogRef.current.close().catch((err) => debugLog("teardown: warnLog.close failed", err));
11891
+ warnLogRef.current = null;
11892
+ }
11696
11893
  autoCompactAbortRef.current?.abort();
11697
11894
  autoCompactAbortRef.current = null;
11698
11895
  autoCompactInFlightRef.current = null;
@@ -12301,10 +12498,11 @@ function AppShell() {
12301
12498
  const session = sessionRef.current;
12302
12499
  const p = pickedRef.current;
12303
12500
  if (!session || !p) return;
12304
- const fresh = buildAgentRef.current(session, p.provider.key);
12305
12501
  const stale = agentRef.current;
12306
- agentRef.current = fresh;
12502
+ const staleWarnLog = warnLogRef.current;
12503
+ agentRef.current = buildAgentRef.current(session, p.provider.key);
12307
12504
  if (stale) await stale.destroy().catch((err) => debugLog("rebuildActiveAgent: destroy failed", err));
12505
+ if (staleWarnLog) await staleWarnLog.close().catch((err) => debugLog("rebuildActiveAgent: warnLog.close failed", err));
12308
12506
  }, []);
12309
12507
  const onLoginMcp = useCallback(async (name) => {
12310
12508
  const entry = mcpsCatalogRef.current.find((d) => d.config.name === name);
@@ -12521,6 +12719,10 @@ function AppShell() {
12521
12719
  userDir: cacheDir,
12522
12720
  sessionId: id
12523
12721
  }));
12722
+ cleanupPersistedSession(resolveMcpWarningsDir({
12723
+ userDir: cacheDir,
12724
+ sessionId: id
12725
+ }));
12524
12726
  const wasCurrent = id === currentSession?.id;
12525
12727
  if (wasCurrent) {
12526
12728
  await teardown();
@@ -12892,6 +13094,10 @@ function AppShell() {
12892
13094
  return;
12893
13095
  }
12894
13096
  }
13097
+ if (matchesBinding(key, keybindings.newSession) && screen === "chat" && picked && !busy) {
13098
+ onCreateSession();
13099
+ return;
13100
+ }
12895
13101
  if (matchesBinding(key, keybindings.openModelPicker) && screen === "chat" && picked && !busy) {
12896
13102
  modal.open(/* @__PURE__ */ jsx(ModelPickerModal, {
12897
13103
  providers: availableProviders,
@@ -12995,7 +13201,7 @@ function AppShell() {
12995
13201
  setQuitConfirmSelected("cancel");
12996
13202
  return;
12997
13203
  }
12998
- if (key.name === "c" && key.ctrl) {
13204
+ if (key.name === "c" && key.ctrl && !key.shift) {
12999
13205
  renderer.destroy();
13000
13206
  return;
13001
13207
  }
@@ -13013,7 +13219,7 @@ function AppShell() {
13013
13219
  }
13014
13220
  return;
13015
13221
  }
13016
- if (key.name === "c" && key.ctrl) {
13222
+ if (key.name === "c" && key.ctrl && !key.shift) {
13017
13223
  const mode = settingsRef.current.ctrlCBehavior;
13018
13224
  if (mode === "quit") {
13019
13225
  renderer.destroy();