nolo-cli 0.49.0-alpha.1 → 0.49.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 (71) hide show
  1. package/{_executeModel-4BPV4B2U.js → _executeModel-KE4PQSZ3.js} +19 -19
  2. package/{agentDeleteCommand-KZSETRE3.js → agentDeleteCommand-Z67TJG3W.js} +10 -10
  3. package/{agentEmailCommands-C33KPOFP.js → agentEmailCommands-7LPIK7JE.js} +23 -23
  4. package/{agentListCommands-KVLURCS7.js → agentListCommands-5J2IM3IT.js} +12 -12
  5. package/{agentMachineCommands-ICOLSVID.js → agentMachineCommands-YXH6FXUQ.js} +11 -11
  6. package/{agentRecordCommands-OWKWVY3Y.js → agentRecordCommands-GZLCDVUS.js} +22 -22
  7. package/{agentRunCommand-FINKBYUN.js → agentRunCommand-WYH5Q54Q.js} +22 -22
  8. package/{agentRuntimeLocal-SIQYQGSK.js → agentRuntimeLocal-A6EF3RUY.js} +10 -10
  9. package/{agentSlice-VD3BAJAU.js → agentSlice-ARTDF6VD.js} +1 -1
  10. package/{appDeleteCommands-LSIIQFYN.js → appDeleteCommands-V2B7ZCLC.js} +10 -10
  11. package/{appDeployCommands-VYGKN7HU.js → appDeployCommands-AXQU44RD.js} +10 -10
  12. package/{appDeployStatusCommands-ODFHFUR7.js → appDeployStatusCommands-FWGSC2UM.js} +10 -10
  13. package/{appGetCommands-DPQY67UZ.js → appGetCommands-67R3RFZK.js} +10 -10
  14. package/{appListCommands-EFXENXWX.js → appListCommands-TTASJPGV.js} +10 -10
  15. package/{authCommand-WLWOEVYI.js → authCommand-QOPOEYEK.js} +7 -7
  16. package/{chatQueueReduxAdapter-N5432EP2.js → chatQueueReduxAdapter-6CAHUQ4O.js} +7 -7
  17. package/{chunk-Y7TGWSUN.js → chunk-56W233KG.js} +1 -1
  18. package/{chunk-C2WF2OY7.js → chunk-5WADL4O7.js} +1 -1
  19. package/{chunk-7M72YPM2.js → chunk-6SMMK7MD.js} +2 -2
  20. package/{chunk-4ZL2KBI7.js → chunk-757BGY6Y.js} +1 -1
  21. package/{chunk-IERBSHMR.js → chunk-AVKUDHJO.js} +3 -3
  22. package/{chunk-VKSBVRGP.js → chunk-CVT7L2WZ.js} +1 -1
  23. package/{chunk-MCX2LX27.js → chunk-EURF2SV6.js} +11 -11
  24. package/{chunk-7GRFFW7R.js → chunk-EXDR5D6X.js} +3 -3
  25. package/{chunk-AZ6DT2UD.js → chunk-GBADO3SM.js} +1 -1
  26. package/{chunk-XB7ACJFH.js → chunk-GDGIEGHV.js} +2 -2
  27. package/{chunk-QDNFRWAX.js → chunk-GFD7TIZU.js} +2 -2
  28. package/{chunk-QAG4ZQZ7.js → chunk-GFUOVFQA.js} +1 -1
  29. package/{chunk-RPO6WAZV.js → chunk-HCMFFI2G.js} +2 -2
  30. package/{chunk-4YAMAMNA.js → chunk-HPZL4IBN.js} +11 -10
  31. package/{chunk-S3HB4CQY.js → chunk-IKSFDJXB.js} +112 -19
  32. package/{chunk-W3RZLXMA.js → chunk-IKTHA3JH.js} +2 -2
  33. package/{chunk-VZGLZTG7.js → chunk-IRJVFYOH.js} +255 -79
  34. package/{chunk-6L6UPZNH.js → chunk-K524MUQC.js} +8 -8
  35. package/{chunk-HMMOAG2I.js → chunk-NN3AMBY3.js} +7 -4
  36. package/{chunk-BO3YFOZR.js → chunk-QDHZCAH3.js} +1 -1
  37. package/{chunk-33BBDA67.js → chunk-QUCSAM43.js} +106 -34
  38. package/{chunk-Z7A54NFZ.js → chunk-RU5D3B22.js} +1 -1
  39. package/{chunk-JBL24PK6.js → chunk-SP3DPVBH.js} +2 -2
  40. package/{chunk-F22JQTSX.js → chunk-SW7RCUGA.js} +2 -2
  41. package/{chunk-3YVCM5PE.js → chunk-U5Z7LFZF.js} +1 -1
  42. package/{chunk-OZ4JNDIL.js → chunk-UQWFIWHX.js} +1 -1
  43. package/{chunk-AV4Z57LV.js → chunk-VRJUIUIY.js} +2 -2
  44. package/{chunk-72COHDZR.js → chunk-WKOEOQCI.js} +13 -13
  45. package/{chunk-VFN256RI.js → chunk-WL3UOGYO.js} +25 -0
  46. package/{chunk-5JXRVJAC.js → chunk-WX5E6HZS.js} +3 -3
  47. package/{createAgentAutomationAction-IHKV53QC.js → createAgentAutomationAction-7BBF5YXN.js} +8 -8
  48. package/{createDialogAction-4ARDCKPP.js → createDialogAction-B5URPHP4.js} +9 -9
  49. package/{createPageAction-GQOCPICU.js → createPageAction-ISJKM5Q3.js} +8 -8
  50. package/{dialogCommands-YOTCP26N.js → dialogCommands-XHH4MVA4.js} +10 -10
  51. package/{dialogSlice-NX26W623.js → dialogSlice-NRAN5X7F.js} +7 -7
  52. package/{docCreateCommands-JVAMHES4.js → docCreateCommands-FUN2Z7HQ.js} +10 -10
  53. package/{docDeleteCommands-LW5DWICT.js → docDeleteCommands-OZDPFXPF.js} +10 -10
  54. package/{docReadCommands-AQOZS3I5.js → docReadCommands-FIPK7LE3.js} +10 -10
  55. package/{docStore-YAE7GYHZ.js → docStore-LUS7SWC3.js} +9 -9
  56. package/{docUpdateCommands-FFGGX5RG.js → docUpdateCommands-BZ5GKAN4.js} +10 -10
  57. package/{getPricing-JNOCWYDH.js → getPricing-HAU62AFM.js} +3 -3
  58. package/{handleSendMessageAction-7YKH4UBI.js → handleSendMessageAction-RA4OD2ZH.js} +7 -7
  59. package/index.js +47 -47
  60. package/{machineCommands-X7YMGFMB.js → machineCommands-WDAYEFBE.js} +22 -22
  61. package/{machineWsRunDispatch-KWWJ4HTI.js → machineWsRunDispatch-TPQ2FQVS.js} +22 -22
  62. package/{models-N4NXQ44D.js → models-4QF4BJVY.js} +2 -2
  63. package/package.json +1 -1
  64. package/{readlineWorkspace-GEZVQ7IM.js → readlineWorkspace-HN44KGIF.js} +198 -96
  65. package/{runAgentClientLoop-6NCW5AS6.js → runAgentClientLoop-ZYUI22EA.js} +17 -17
  66. package/{spaceCommands-7MJVL4XR.js → spaceCommands-OJ2567D4.js} +10 -10
  67. package/{spaceSlice-JVVDCGA3.js → spaceSlice-F7JCOZEF.js} +8 -8
  68. package/{streamAgentChatTurn-UAKCHWFN.js → streamAgentChatTurn-FNFMMGNN.js} +20 -20
  69. package/{tools-ROUITGAR.js → tools-QCDR3UMD.js} +12 -12
  70. package/{tuiSummaryLlmCaller-U4EGD2SX.js → tuiSummaryLlmCaller-LCGT62QC.js} +5 -5
  71. package/{updateDialogTitleAction-R4M6ZXCX.js → updateDialogTitleAction-Y3OGJWDB.js} +8 -8
@@ -64,14 +64,14 @@ import {
64
64
  wrapTextToLines,
65
65
  wrapTranscriptLine,
66
66
  wrapTranscriptLineWithLayout
67
- } from "./chunk-VZGLZTG7.js";
67
+ } from "./chunk-IRJVFYOH.js";
68
68
  import {
69
69
  listFavoriteAgentIdsAcrossServers,
70
70
  listLocalCachedAgents,
71
71
  listRemoteAgents,
72
72
  listRemoteAgentsAcrossServers,
73
73
  normalizeListedAgent
74
- } from "./chunk-C2WF2OY7.js";
74
+ } from "./chunk-5WADL4O7.js";
75
75
  import "./chunk-ID4G2MAR.js";
76
76
  import {
77
77
  listUserRecordsFromServers,
@@ -86,8 +86,8 @@ import {
86
86
  readTimestamp,
87
87
  setCliLocale,
88
88
  t
89
- } from "./chunk-33BBDA67.js";
90
- import "./chunk-3YVCM5PE.js";
89
+ } from "./chunk-QUCSAM43.js";
90
+ import "./chunk-U5Z7LFZF.js";
91
91
  import "./chunk-EADNWBAZ.js";
92
92
  import "./chunk-NI2BS6UD.js";
93
93
  import {
@@ -118,14 +118,14 @@ import "./chunk-ATNTHIZI.js";
118
118
  import "./chunk-JEXVIMYZ.js";
119
119
  import {
120
120
  prepareTools
121
- } from "./chunk-RPO6WAZV.js";
121
+ } from "./chunk-HCMFFI2G.js";
122
122
  import "./chunk-HS7MLR74.js";
123
- import "./chunk-4ZL2KBI7.js";
124
- import "./chunk-72COHDZR.js";
123
+ import "./chunk-757BGY6Y.js";
124
+ import "./chunk-WKOEOQCI.js";
125
125
  import "./chunk-5XTOKQLW.js";
126
126
  import "./chunk-NF64D32W.js";
127
127
  import "./chunk-3L2WKC3W.js";
128
- import "./chunk-Z7A54NFZ.js";
128
+ import "./chunk-RU5D3B22.js";
129
129
  import "./chunk-KQHGZWSV.js";
130
130
  import "./chunk-5XCW6RQG.js";
131
131
  import {
@@ -140,7 +140,7 @@ import {
140
140
  shortRunId
141
141
  } from "./chunk-KXKQO4Q6.js";
142
142
  import "./chunk-INZZJSQF.js";
143
- import "./chunk-QDNFRWAX.js";
143
+ import "./chunk-GFD7TIZU.js";
144
144
  import "./chunk-BANYWEYY.js";
145
145
  import "./chunk-HCBQVVFZ.js";
146
146
  import "./chunk-MEYIRKDN.js";
@@ -151,15 +151,15 @@ import {
151
151
  createTurnRequest,
152
152
  normalizeRunCompletionShape
153
153
  } from "./chunk-YPREESF4.js";
154
- import "./chunk-IERBSHMR.js";
155
- import "./chunk-7M72YPM2.js";
154
+ import "./chunk-AVKUDHJO.js";
155
+ import "./chunk-6SMMK7MD.js";
156
156
  import {
157
157
  extractReferenceKeysFromMessage
158
- } from "./chunk-MCX2LX27.js";
158
+ } from "./chunk-EURF2SV6.js";
159
159
  import "./chunk-EVBFYPDC.js";
160
160
  import "./chunk-H2G6JXTR.js";
161
161
  import "./chunk-YYLHWIW6.js";
162
- import "./chunk-5JXRVJAC.js";
162
+ import "./chunk-WX5E6HZS.js";
163
163
  import "./chunk-AGGIDPCZ.js";
164
164
  import "./chunk-SG65C33A.js";
165
165
  import "./chunk-5RGU3J7P.js";
@@ -183,10 +183,10 @@ import {
183
183
  buildLocalWorkspaceToolset,
184
184
  getProcessRegistry,
185
185
  readCommandActionGatePayload
186
- } from "./chunk-S3HB4CQY.js";
187
- import "./chunk-XB7ACJFH.js";
186
+ } from "./chunk-IKSFDJXB.js";
187
+ import "./chunk-GDGIEGHV.js";
188
188
  import "./chunk-ZNFJWEN4.js";
189
- import "./chunk-VKSBVRGP.js";
189
+ import "./chunk-CVT7L2WZ.js";
190
190
  import "./chunk-T27IEBNQ.js";
191
191
  import "./chunk-N7J63Q6C.js";
192
192
  import {
@@ -194,11 +194,11 @@ import {
194
194
  buildIdentityBlock,
195
195
  buildRuntimeGuidanceBlocks,
196
196
  resolveToolGuidedSections
197
- } from "./chunk-HMMOAG2I.js";
197
+ } from "./chunk-NN3AMBY3.js";
198
198
  import "./chunk-6BYAXNH5.js";
199
199
  import {
200
200
  resolvePlatformAuthToken
201
- } from "./chunk-JBL24PK6.js";
201
+ } from "./chunk-SP3DPVBH.js";
202
202
  import "./chunk-TNPCQNGQ.js";
203
203
  import {
204
204
  isQuotaExhaustedError
@@ -207,7 +207,7 @@ import "./chunk-2MBTWINN.js";
207
207
  import {
208
208
  DEFAULT_CONTEXT_WINDOW,
209
209
  getModelContextWindow
210
- } from "./chunk-F22JQTSX.js";
210
+ } from "./chunk-SW7RCUGA.js";
211
211
  import {
212
212
  buildCompactionMetricsFromPlan,
213
213
  buildCompactionUserContent,
@@ -219,10 +219,10 @@ import {
219
219
  planCompression,
220
220
  serializeMessageContent
221
221
  } from "./chunk-HR5XDXYM.js";
222
- import "./chunk-AV4Z57LV.js";
222
+ import "./chunk-VRJUIUIY.js";
223
223
  import "./chunk-NQ4N4IGO.js";
224
224
  import "./chunk-FD36SCCD.js";
225
- import "./chunk-BO3YFOZR.js";
225
+ import "./chunk-QDHZCAH3.js";
226
226
  import {
227
227
  compactWhitespace
228
228
  } from "./chunk-DWLEOOGR.js";
@@ -268,8 +268,8 @@ import {
268
268
  import {
269
269
  DEFAULT_NOLO_SERVER_URL
270
270
  } from "./chunk-OLZBQWZU.js";
271
- import "./chunk-Y7TGWSUN.js";
272
- import "./chunk-VFN256RI.js";
271
+ import "./chunk-56W233KG.js";
272
+ import "./chunk-WL3UOGYO.js";
273
273
  import "./chunk-SQTVMYMU.js";
274
274
  import "./chunk-X7S7OFUX.js";
275
275
  import "./chunk-Y5GCAMGP.js";
@@ -1166,6 +1166,7 @@ function createTurnHistory() {
1166
1166
  turns: [],
1167
1167
  currentRole: null,
1168
1168
  currentContent: "",
1169
+ currentBlocks: [],
1169
1170
  scrollTop: 0,
1170
1171
  followBottom: true
1171
1172
  };
@@ -1176,19 +1177,40 @@ function startTurn(history, role) {
1176
1177
  }
1177
1178
  history.currentRole = role;
1178
1179
  history.currentContent = "";
1180
+ history.currentBlocks = [];
1179
1181
  resetStreamingTurnCache();
1180
1182
  }
1181
1183
  function appendToCurrentTurn(history, chunk) {
1182
1184
  history.currentContent += chunk;
1185
+ appendCurrentBlock(history, "assistant", chunk);
1186
+ }
1187
+ function appendCurrentBlock(history, kind, chunk) {
1188
+ if (!chunk) return;
1189
+ const last = history.currentBlocks.at(-1);
1190
+ if (last?.kind === kind) {
1191
+ last.content = applyTerminalOutputToText(last.content, chunk);
1192
+ } else {
1193
+ history.currentBlocks.push({
1194
+ kind,
1195
+ content: applyTerminalOutputToText("", chunk)
1196
+ });
1197
+ }
1183
1198
  }
1184
1199
  function finalizeCurrentTurn(history) {
1185
1200
  if (history.currentRole !== null) {
1186
1201
  history.turns.push({
1187
1202
  role: history.currentRole,
1188
- content: compactTurnContent(history.currentContent)
1203
+ content: compactTurnContent(history.currentContent),
1204
+ ...history.currentRole === "assistant" && history.currentBlocks.length > 0 ? {
1205
+ blocks: history.currentBlocks.map((block) => ({
1206
+ ...block,
1207
+ content: compactTurnContent(block.content)
1208
+ })).filter((block) => block.content.length > 0)
1209
+ } : {}
1189
1210
  });
1190
1211
  history.currentRole = null;
1191
1212
  history.currentContent = "";
1213
+ history.currentBlocks = [];
1192
1214
  resetStreamingTurnCache();
1193
1215
  trimHistoryToBudget(history);
1194
1216
  }
@@ -1203,17 +1225,20 @@ function appendLocalTurn(history, command, output) {
1203
1225
  trimHistoryToBudget(history);
1204
1226
  resetStreamingTurnCache();
1205
1227
  }
1206
- function applyOutputChunkToCurrentTurn(history, chunk) {
1228
+ function applyOutputChunkToCurrentTurn(history, chunk, kind = "assistant") {
1207
1229
  const next = applyTerminalOutputToText(history.currentContent, chunk);
1208
1230
  if (next === history.currentContent) return false;
1209
1231
  history.currentContent = next;
1232
+ appendCurrentBlock(history, kind, chunk);
1210
1233
  return true;
1211
1234
  }
1212
1235
  function styleAssistantTurn(content, colorEnabled) {
1213
1236
  const highlighted = colorEnabled ? formatAssistantDisplay(content, { trimEdges: false }) : stripAnsi(formatAssistantDisplay(content, { trimEdges: false }));
1214
1237
  const rawLines = highlighted.split("\n");
1215
- const styledLines = rawLines.map((line, idx) => {
1216
- if (idx === 0 && !line.startsWith("[nolo]")) {
1238
+ let anchored = false;
1239
+ const styledLines = rawLines.map((line) => {
1240
+ if (!anchored && line.trim().length > 0 && !line.startsWith("[nolo]")) {
1241
+ anchored = true;
1217
1242
  const anchorPrefix = colorEnabled ? `${themeColorSequence("chrome")}\u25C8\x1B[39m ` : "\u25C8 ";
1218
1243
  return `${anchorPrefix}${line}`;
1219
1244
  }
@@ -1324,9 +1349,11 @@ function layoutTurnRows(role, content, contentWidth, colorEnabled, command) {
1324
1349
  let rawIdx = 0;
1325
1350
  let rawOffset = 0;
1326
1351
  const rows = [];
1352
+ let anchored = false;
1327
1353
  for (let i = 0; i < styledLines.length; i++) {
1328
1354
  const styledLine = styledLines[i];
1329
- const isFirstLine = i === 0 && !styledLine.startsWith("[nolo]");
1355
+ const isFirstLine = !anchored && styledLine.trim().length > 0 && !styledLine.startsWith("[nolo]");
1356
+ if (isFirstLine) anchored = true;
1330
1357
  const anchorPrefix = isFirstLine ? colorEnabled ? `${themeColorSequence("chrome")}\u25C8\x1B[39m ` : "\u25C8 " : "";
1331
1358
  const prefixWidth = isFirstLine ? 2 : 0;
1332
1359
  const prefixCharCount = anchorPrefix.length;
@@ -1387,15 +1414,7 @@ function renderPrefixTurnBlock(role, content, contentWidth, colorEnabled) {
1387
1414
  if (role === "user") {
1388
1415
  return renderTurnBlock(role, content, contentWidth, colorEnabled);
1389
1416
  }
1390
- const highlighted = colorEnabled ? formatAssistantDisplay(content, { trimEdges: false }) : stripAnsi(formatAssistantDisplay(content, { trimEdges: false }));
1391
- const rawLines = highlighted.split("\n");
1392
- const styledLines = rawLines.map((line, idx) => {
1393
- if (idx === 0 && !line.startsWith("[nolo]")) {
1394
- const anchorPrefix = colorEnabled ? `${themeColorSequence("chrome")}\u25C8\x1B[39m ` : "\u25C8 ";
1395
- return `${anchorPrefix}${line}`;
1396
- }
1397
- return line.startsWith("[nolo]") && colorEnabled ? themeText(line, "chrome", true) : line;
1398
- });
1417
+ const styledLines = styleAssistantTurn(content, colorEnabled).split("\n");
1399
1418
  const lines = [];
1400
1419
  for (const logicalLine of styledLines) {
1401
1420
  lines.push(...wrapTranscriptLine(logicalLine, contentWidth));
@@ -1728,16 +1747,23 @@ function renderHistory(output, history, inputLines, selection) {
1728
1747
  }
1729
1748
  }
1730
1749
  function createHistoryOutputStream(history, onUpdate) {
1731
- return {
1750
+ const stream = {
1732
1751
  isTTY: true,
1752
+ assistantLabelManaged: true,
1733
1753
  write(chunk) {
1734
1754
  const text = typeof chunk === "string" ? chunk : chunk.toString();
1735
1755
  if (applyOutputChunkToCurrentTurn(history, text)) {
1736
1756
  onUpdate();
1737
1757
  }
1738
1758
  return true;
1759
+ },
1760
+ writeToolBlock(chunk) {
1761
+ if (applyOutputChunkToCurrentTurn(history, chunk, "tool")) {
1762
+ onUpdate();
1763
+ }
1739
1764
  }
1740
1765
  };
1766
+ return stream;
1741
1767
  }
1742
1768
  function applyScrollAction(history, action, output, inputLines) {
1743
1769
  const tty = output;
@@ -1830,9 +1856,25 @@ function activeInFlight(snapshot) {
1830
1856
  if (isAgentRunTerminalStatus(snapshot.status)) return null;
1831
1857
  return snapshot.inFlight ?? null;
1832
1858
  }
1859
+ function formatTerminalRunAge(snapshot, now) {
1860
+ if (!isAgentRunTerminalStatus(snapshot.status)) return null;
1861
+ return formatRunAge(snapshot, now);
1862
+ }
1833
1863
  function formatUnassignedFact(snapshot) {
1834
1864
  return snapshot.unassigned ? "parent: ?" : null;
1835
1865
  }
1866
+ function sanitizeRunSnapshotForNormal(snapshot) {
1867
+ const clean = (value) => stripAnsi(value).replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
1868
+ return {
1869
+ ...snapshot,
1870
+ agentName: snapshot.agentName ? clean(snapshot.agentName) : snapshot.agentName,
1871
+ taskPreview: snapshot.taskPreview ? clean(snapshot.taskPreview) : snapshot.taskPreview,
1872
+ lastAssistantText: snapshot.lastAssistantText ? clean(snapshot.lastAssistantText) : snapshot.lastAssistantText,
1873
+ lastToolNames: snapshot.lastToolNames?.map(clean).filter(Boolean),
1874
+ errorMessage: void 0,
1875
+ logLines: void 0
1876
+ };
1877
+ }
1836
1878
 
1837
1879
  // packages/cli/tui/agentRunPanelLines.ts
1838
1880
  function formatPanelProgress(snapshot, now) {
@@ -1868,7 +1910,7 @@ function formatAgentRunPanelLines(snapshot, colorEnabled, now = Date.now()) {
1868
1910
  const unassignedFact = formatUnassignedFact(snapshot);
1869
1911
  const unassignedPart = unassignedFact ? ` \xB7 ${unassignedFact}` : "";
1870
1912
  const progressPart = formatPanelProgress(snapshot, now);
1871
- const age = formatRunAge(snapshot, now);
1913
+ const age = formatTerminalRunAge(snapshot, now);
1872
1914
  const agePart = age ? ` \xB7 ${age}` : "";
1873
1915
  if (!colorEnabled) {
1874
1916
  lines.push(
@@ -2007,11 +2049,13 @@ function createRunDock(deps) {
2007
2049
  const ordered = orderedEntries();
2008
2050
  if (ordered.length === 0) return [];
2009
2051
  const at = now();
2010
- if (ordered.length === 1) {
2011
- return formatAgentRunPanelLines(ordered[0].snapshot, colorEnabled, at);
2052
+ const mode = typeof deps.displayMode === "function" ? deps.displayMode() : deps.displayMode;
2053
+ const displaySnapshots = mode === "normal" || mode === "hide" ? ordered.map((entry) => sanitizeRunSnapshotForNormal(entry.snapshot)) : ordered.map((entry) => entry.snapshot);
2054
+ if (displaySnapshots.length === 1) {
2055
+ return formatAgentRunPanelLines(displaySnapshots[0], colorEnabled, at);
2012
2056
  }
2013
2057
  return formatRunDockLines(
2014
- ordered.map((entry) => entry.snapshot),
2058
+ displaySnapshots,
2015
2059
  colorEnabled,
2016
2060
  at,
2017
2061
  maxRows
@@ -2070,7 +2114,7 @@ function formatRunDockRow(snapshot, colorEnabled, now) {
2070
2114
  const terminal = isAgentRunTerminalStatus(snapshot.status);
2071
2115
  const statusColor = runStatusTone(snapshot.status);
2072
2116
  const facts = [];
2073
- const age = formatRunAge(snapshot, now);
2117
+ const age = formatTerminalRunAge(snapshot, now);
2074
2118
  if (terminal) facts.push(age ? `${snapshot.status} ${age}` : snapshot.status);
2075
2119
  else if (age) facts.push(age);
2076
2120
  const unassigned = formatUnassignedFact(snapshot);
@@ -2180,7 +2224,8 @@ function createActivityIndicator(deps) {
2180
2224
  onRepaint: deps.onRepaint,
2181
2225
  now,
2182
2226
  setIntervalFn,
2183
- clearIntervalFn
2227
+ clearIntervalFn,
2228
+ displayMode: deps.displayMode
2184
2229
  });
2185
2230
  const updateAgentRun = (snapshot) => {
2186
2231
  runDock.update(snapshot);
@@ -2241,25 +2286,6 @@ var RUN_POLL_INTERVAL_MS = 1e3;
2241
2286
  var DISCOVERY_EVERY_TICKS = 5;
2242
2287
  var DISCOVERY_TERMINAL_LINGER_MS = 6e4;
2243
2288
  var RUN_RECONCILE_SILENCE_MS = 15e3;
2244
- var RUNNING_AGENT_COUNT_CACHE_TTL_MS = 1e3;
2245
- var cachedRunningAgentCount = 0;
2246
- var lastRunningAgentCountScannedAt = 0;
2247
- function getCachedRunningAgentCount(options) {
2248
- const now = options?.now ?? Date.now();
2249
- if (!options?.force && lastRunningAgentCountScannedAt > 0 && now - lastRunningAgentCountScannedAt < RUNNING_AGENT_COUNT_CACHE_TTL_MS) {
2250
- return cachedRunningAgentCount;
2251
- }
2252
- const readFn = options?.reader ?? listRunRecords;
2253
- try {
2254
- const records = readFn();
2255
- cachedRunningAgentCount = records.filter(
2256
- (r) => !isAgentRunTerminalStatus(r.status)
2257
- ).length;
2258
- lastRunningAgentCountScannedAt = now;
2259
- } catch {
2260
- }
2261
- return cachedRunningAgentCount;
2262
- }
2263
2289
  function snapshotFromRunRecord(record, now) {
2264
2290
  const label = resolveRunLabel(record);
2265
2291
  const startedAt = readTimestamp(record.startedAt);
@@ -2343,18 +2369,18 @@ function createRunRegistryPoller(deps) {
2343
2369
  }
2344
2370
  const discovered = discoveredRecords;
2345
2371
  const currentDialogId = deps.getCurrentDialogId?.();
2372
+ const belongsToCurrentDialog = (record) => !deps.getCurrentDialogId || currentDialogId !== null && record.parentDialogId === currentDialogId;
2346
2373
  const discoveredActive = discovered.filter(
2347
- (record) => record.runId && !dockedIds.has(record.runId) && !retiredRunIds.has(record.runId) && !isAgentRunTerminalStatus(record.status) && (!deps.getCurrentDialogId || currentDialogId !== void 0 && (record.parentDialogId === currentDialogId || !record.parentDialogId))
2374
+ (record) => record.runId && !dockedIds.has(record.runId) && !retiredRunIds.has(record.runId) && !isAgentRunTerminalStatus(record.status) && belongsToCurrentDialog(record)
2348
2375
  );
2349
2376
  const discoveredTerminal = discovered.filter((record) => {
2350
2377
  if (!record.runId || dockedIds.has(record.runId) || retiredRunIds.has(record.runId)) return false;
2351
- if (!isAgentRunTerminalStatus(record.status)) return false;
2352
- if (deps.getCurrentDialogId && (currentDialogId === void 0 || !(record.parentDialogId === currentDialogId || !record.parentDialogId))) return false;
2378
+ if (!isAgentRunTerminalStatus(record.status) || !belongsToCurrentDialog(record)) return false;
2353
2379
  const endedAt = readTimestamp(record.endedAt);
2354
2380
  return endedAt !== void 0 && at - endedAt <= DISCOVERY_TERMINAL_LINGER_MS;
2355
2381
  });
2356
2382
  for (const record of discovered) {
2357
- if (record.runId && isAgentRunTerminalStatus(record.status) && !discoveredTerminal.includes(record)) {
2383
+ if (record.runId && isAgentRunTerminalStatus(record.status) && belongsToCurrentDialog(record) && !discoveredTerminal.includes(record)) {
2358
2384
  retiredRunIds.add(record.runId);
2359
2385
  }
2360
2386
  }
@@ -2378,6 +2404,7 @@ function createRunRegistryPoller(deps) {
2378
2404
  continue;
2379
2405
  }
2380
2406
  if (!record) continue;
2407
+ if (deps.getCurrentDialogId && !belongsToCurrentDialog(record)) continue;
2381
2408
  polled.push(record);
2382
2409
  const snapshot = snapshotFromRunRecord(record, at);
2383
2410
  const mark = fingerprint(snapshot);
@@ -3623,7 +3650,7 @@ function renderComposerTokenChip(tokens, fallbackContextWindow, estimatedContext
3623
3650
  const pctText = pct > 0 && pct < 10 ? pct.toFixed(1) : Math.round(pct).toString();
3624
3651
  return `context: ${pctText}% (${formatTokenCount(used)}/${formatTokenCount(cw)})`;
3625
3652
  }
3626
- function renderStatusLine(state) {
3653
+ function renderStatusLine(state, maxWidth) {
3627
3654
  const colorEnabled = resolveCliColorEnabled();
3628
3655
  const sep = themeText(" \xB7 ", "chrome", colorEnabled);
3629
3656
  const agentDisplayName = state.agentName;
@@ -3652,25 +3679,65 @@ function renderStatusLine(state) {
3652
3679
  );
3653
3680
  parts.push(tokenSegment);
3654
3681
  const runningTaskCount = getProcessRegistry().listBackground().filter((p) => p.status === "running").length;
3655
- const runningAgentCount = getCachedRunningAgentCount();
3656
- const runningParts = [];
3657
3682
  if (runningTaskCount > 0) {
3658
- runningParts.push(`${runningTaskCount} running`);
3659
- }
3660
- if (runningAgentCount > 0) {
3661
- runningParts.push(`${runningAgentCount} ${runningAgentCount === 1 ? "agent" : "agents"}`);
3662
- }
3663
- if (runningParts.length > 0) {
3664
- parts.push(themeText(`\u2699 ${runningParts.join(" \xB7 ")}`, "info", colorEnabled));
3683
+ parts.push(themeText(`\u2699 ${runningTaskCount} running`, "info", colorEnabled));
3665
3684
  }
3666
3685
  if (state.autoConfirm === true) {
3667
3686
  parts.push(themeText("\u23F5 auto", "warning", colorEnabled));
3668
3687
  }
3669
- const body = parts.join(sep);
3688
+ let visibleParts = parts;
3689
+ if (maxWidth && maxWidth > 0) {
3690
+ const widthOf = (segments) => displayWidth(stripAnsi(segments.join(" \xB7 "))) + 2;
3691
+ for (const optional of [tokenSegment, cwdSegment, agentSegment]) {
3692
+ if (widthOf(visibleParts) <= maxWidth) break;
3693
+ visibleParts = visibleParts.filter((part) => part !== optional);
3694
+ }
3695
+ if (widthOf(visibleParts) > maxWidth && state.gitStatus) {
3696
+ const gitIndex = visibleParts.findIndex((part) => stripAnsi(part).startsWith("\u2442 "));
3697
+ if (gitIndex >= 0) {
3698
+ const { modified, untracked } = state.gitStatus;
3699
+ const compactDirty = themeText(
3700
+ `\u2442${modified > 0 ? ` *${modified}` : ""}${untracked > 0 ? ` ?${untracked}` : ""}`,
3701
+ "warning",
3702
+ colorEnabled
3703
+ );
3704
+ visibleParts = visibleParts.with(gitIndex, compactDirty);
3705
+ }
3706
+ }
3707
+ if (widthOf(visibleParts) > maxWidth) {
3708
+ const emergency = [];
3709
+ if (state.autoConfirm === true) {
3710
+ emergency.push(themeText("\u23F5", "warning", colorEnabled));
3711
+ }
3712
+ const runningTotal = runningTaskCount;
3713
+ if (runningTotal > 0) {
3714
+ emergency.push(themeText(`\u2699${runningTotal}`, "info", colorEnabled));
3715
+ }
3716
+ if (state.gitStatus) {
3717
+ const { modified, untracked } = state.gitStatus;
3718
+ emergency.push(themeText(
3719
+ `\u2442${modified > 0 ? `*${modified}` : ""}${untracked > 0 ? `?${untracked}` : ""}`,
3720
+ "warning",
3721
+ colorEnabled
3722
+ ));
3723
+ }
3724
+ visibleParts = [emergency.join(" ")];
3725
+ }
3726
+ }
3727
+ const body = visibleParts.join(sep);
3670
3728
  const surface = colorEnabled ? surfaceBackgroundSequence() : "";
3671
3729
  if (!surface) return body;
3672
3730
  return `${surface} ${body} \x1B[49m`;
3673
3731
  }
3732
+ function composeStatusLineWithQueue(state, queueSuffix, maxWidth) {
3733
+ const hasBudget = typeof maxWidth === "number" && maxWidth > 0;
3734
+ const queueWidth = queueSuffix ? visibleWidth(queueSuffix) : 0;
3735
+ const budget = hasBudget ? Math.max(1, maxWidth - queueWidth) : void 0;
3736
+ const base = renderStatusLine(state, budget);
3737
+ if (!queueSuffix) return base;
3738
+ if (!hasBudget) return base + queueSuffix;
3739
+ return visibleWidth(base) + queueWidth <= maxWidth ? base + queueSuffix : base;
3740
+ }
3674
3741
  function buildPlainScene(isDark, frame = 0, maxFrames = 0) {
3675
3742
  let skyLine = ` ${isDark ? "\u{1F319}" : "\u2600"}`;
3676
3743
  if (isDark) {
@@ -4328,7 +4395,7 @@ function createInitialTuiState(env = process.env) {
4328
4395
  modeLabel: asOptionalTrimmedString(env.NOLO_CLI_STATUS_MODE) ?? runtimeMode,
4329
4396
  userLanguage: asOptionalTrimmedString(env.NOLO_LANG),
4330
4397
  gitStatus: void 0,
4331
- toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact"),
4398
+ toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "normal"),
4332
4399
  thinkingDisplay: "show",
4333
4400
  contextWindow: resolveAgentContextWindow({ agentKey, agentName }),
4334
4401
  estimatedContextTokens: estimateDefaultCliContextTokens({
@@ -4498,7 +4565,7 @@ function handleTuiInput(input, state) {
4498
4565
  };
4499
4566
  }
4500
4567
  const normalizedArg = asTrimmedLowercaseString(argText);
4501
- if (!["hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
4568
+ if (!["normal", "pro", "hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
4502
4569
  return {
4503
4570
  nextState: state,
4504
4571
  output: t("toolsUsage")
@@ -5945,8 +6012,13 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
5945
6012
  cachedMemoryOverlay: memoryPromptBlock
5946
6013
  };
5947
6014
  }
6015
+ function isApprovedConfirmationInput(answer) {
6016
+ const normalized = answer.trim().toLowerCase();
6017
+ return normalized === "" || normalized === "y" || normalized === "yes" || normalized === "\u786E\u8BA4";
6018
+ }
5948
6019
  function waitForActionGate(rl, input, output, gate, spawnRunner) {
5949
6020
  const commandPayload = gate.kind === "handoff" ? readCommandActionGatePayload(gate.payload) : null;
6021
+ const isConfirmation = gate.kind === "confirm";
5950
6022
  const displayCommand = commandPayload?.displayCommand ?? commandPayload?.command.join(" ") ?? gate.title;
5951
6023
  const isInteractiveHandoff = gate.kind === "handoff" && gate.title === "This command requires an interactive terminal.";
5952
6024
  const title = isInteractiveHandoff ? t("actionGateInteractiveTitle") : gate.title;
@@ -5960,7 +6032,7 @@ function waitForActionGate(rl, input, output, gate, spawnRunner) {
5960
6032
  `);
5961
6033
  output.write(` ${displayCommand}
5962
6034
  `);
5963
- output.write(`[nolo] ${t("actionGateEnterHint")}
6035
+ output.write(`[nolo] ${isConfirmation ? t("actionGateConfirmHint") : t("actionGateEnterHint")}
5964
6036
  `);
5965
6037
  return new Promise((resolve2) => {
5966
6038
  let settled = false;
@@ -5989,8 +6061,12 @@ function waitForActionGate(rl, input, output, gate, spawnRunner) {
5989
6061
  const onSigint = () => finish(cancelResult("interrupted"));
5990
6062
  rl.once("close", onClose);
5991
6063
  rl.once("SIGINT", onSigint);
5992
- rl.question("", async () => {
6064
+ rl.question("", async (answer) => {
5993
6065
  if (settled) return;
6066
+ if (isConfirmation) {
6067
+ finish(isApprovedConfirmationInput(answer) ? { content: `action gate completed: ${gate.title}`, metadata: { actionGateResult: { gateId: gate.id, status: "completed", output: "confirmed" } } } : cancelResult("confirmation declined"));
6068
+ return;
6069
+ }
5994
6070
  if (!commandPayload) {
5995
6071
  finish(failResult("unsupported gate payload"));
5996
6072
  return;
@@ -6037,6 +6113,7 @@ function isInteractiveInput(input) {
6037
6113
  }
6038
6114
  function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
6039
6115
  const commandPayload = gate.kind === "handoff" ? readCommandActionGatePayload(gate.payload) : null;
6116
+ const isConfirmation = gate.kind === "confirm";
6040
6117
  const displayCommand = commandPayload?.displayCommand ?? commandPayload?.command.join(" ") ?? gate.title;
6041
6118
  const isInteractiveHandoff = gate.kind === "handoff" && gate.title === "This command requires an interactive terminal.";
6042
6119
  const title = isInteractiveHandoff ? t("actionGateInteractiveTitle") : gate.title;
@@ -6050,12 +6127,13 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
6050
6127
  `);
6051
6128
  output.write(` ${displayCommand}
6052
6129
  `);
6053
- output.write(`[nolo] ${t("actionGateEnterHint")}
6130
+ output.write(`[nolo] ${isConfirmation ? t("actionGateConfirmHint") : t("actionGateEnterHint")}
6054
6131
  `);
6055
6132
  return new Promise((resolve2) => {
6056
6133
  const rawInput = input;
6057
6134
  let settled = false;
6058
6135
  let commandRunning = false;
6136
+ let confirmationLine = "";
6059
6137
  const finish = (result) => {
6060
6138
  if (settled) return;
6061
6139
  settled = true;
@@ -6119,12 +6197,38 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
6119
6197
  };
6120
6198
  const handleToken = (text) => {
6121
6199
  if (settled || commandRunning) return;
6122
- if (text.includes("")) {
6200
+ if (text.includes("") || isConfirmation && text.includes("\x1B")) {
6123
6201
  cancel("interrupted");
6124
6202
  return;
6125
6203
  }
6204
+ if (isConfirmation) {
6205
+ const newline = text.search(/[\r\n]/);
6206
+ confirmationLine += newline >= 0 ? text.slice(0, newline) : text;
6207
+ if (newline >= 0) {
6208
+ const normalized = confirmationLine.trim().toLowerCase();
6209
+ confirmationLine = "";
6210
+ if (!isApprovedConfirmationInput(confirmationLine)) {
6211
+ cancel("confirmation declined");
6212
+ return;
6213
+ }
6214
+ finish({
6215
+ content: `action gate completed: ${gate.title}`,
6216
+ metadata: { actionGateResult: { gateId: gate.id, status: "completed", output: "confirmed" } }
6217
+ });
6218
+ }
6219
+ return;
6220
+ }
6126
6221
  if (text.includes("\r") || text.includes("\n")) {
6127
- void runCommand();
6222
+ if (isConfirmation) {
6223
+ finish({
6224
+ content: `action gate completed: ${gate.title}`,
6225
+ metadata: {
6226
+ actionGateResult: { gateId: gate.id, status: "completed", output: "confirmed" }
6227
+ }
6228
+ });
6229
+ } else {
6230
+ void runCommand();
6231
+ }
6128
6232
  }
6129
6233
  };
6130
6234
  const onData = (chunk) => {
@@ -6942,7 +7046,7 @@ function createFixedInput(output, config) {
6942
7046
  if (titleLine) {
6943
7047
  sections.push(fitAnsiLine(titleLine.replace(/\r?\n/g, " "), cols));
6944
7048
  }
6945
- sections.push(fitAnsiLine(config.getStatusLine(), cols));
7049
+ sections.push(fitAnsiLine(config.getStatusLine(cols), cols));
6946
7050
  const queueLines = config.getQueueLines?.() ?? [];
6947
7051
  for (const line of queueLines) {
6948
7052
  sections.push(fitAnsiLine(line.replace(/\r?\n/g, " "), cols));
@@ -8010,6 +8114,7 @@ async function runTuiWorkspace(options) {
8010
8114
  isTurnActive: () => activeTurnAbort !== null,
8011
8115
  fallbackLabel: () => `${state.agentName} -> working`,
8012
8116
  stoppingLabel: () => t("turnStopping"),
8117
+ displayMode: () => state.toolDisplay,
8013
8118
  onRepaint: () => {
8014
8119
  if (fixedInput.active && !fixedInput.isPaused()) {
8015
8120
  output.write("\x1B[?2026h\x1B[?25l");
@@ -8036,7 +8141,7 @@ async function runTuiWorkspace(options) {
8036
8141
  // 与 reconcile 的调用点也是同样写法。
8037
8142
  readRecord: (runId) => readRunRecord(runId, { env: effectiveEnv }),
8038
8143
  discoverRuns: () => listRunRecords({ env: effectiveEnv }),
8039
- getCurrentDialogId: () => state.dialogId,
8144
+ getCurrentDialogId: () => state.dialogId ?? null,
8040
8145
  reconcile: (runId) => checkStaleRun(runId, { env: effectiveEnv }),
8041
8146
  onRecordsPolled: (records) => runCompletionWatcher.observe(records)
8042
8147
  });
@@ -8303,15 +8408,12 @@ async function runTuiWorkspace(options) {
8303
8408
  let done = false;
8304
8409
  let resolveDone = null;
8305
8410
  const baseFixedInput = createFixedInput(output, {
8306
- getStatusLine: () => {
8307
- let base = renderStatusLine(state);
8308
- if (chatQueueBinding && chatQueueBinding.queueLength() > 0) {
8309
- base += dimCliText(
8310
- ` \xB7 ${chatQueueBinding.queueLength()} ${t("queuedHint")}`,
8311
- resolveCliColorEnabled()
8312
- );
8313
- }
8314
- return base;
8411
+ getStatusLine: (maxWidth) => {
8412
+ const queueSuffix = chatQueueBinding && chatQueueBinding.queueLength() > 0 ? dimCliText(
8413
+ ` \xB7 ${chatQueueBinding.queueLength()} ${t("queuedHint")}`,
8414
+ resolveCliColorEnabled()
8415
+ ) : "";
8416
+ return composeStatusLineWithQueue(state, queueSuffix, maxWidth);
8315
8417
  },
8316
8418
  getActivityLines: () => activityIndicator.getActivityLines(resolveCliColorEnabled()),
8317
8419
  getQueueLines: () => {