nolo-cli 0.17.0 → 0.19.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 (79) hide show
  1. package/{_executeModel-WPNX5DH4.js → _executeModel-X5PCIZN6.js} +19 -19
  2. package/{agentDeleteCommand-L3357EFL.js → agentDeleteCommand-2BZDQV36.js} +12 -12
  3. package/{agentEmailCommands-N65AVLEI.js → agentEmailCommands-2QJDGRMB.js} +25 -25
  4. package/{agentListCommands-CH27FTI2.js → agentListCommands-6VEPTKBI.js} +14 -14
  5. package/{agentMachineCommands-PPK5HJZB.js → agentMachineCommands-NVVHNWYI.js} +12 -12
  6. package/{agentRecordCommands-HTVXD4TT.js → agentRecordCommands-4GGRDMD4.js} +24 -24
  7. package/{agentRunCommand-MGLVJUA5.js → agentRunCommand-XOLQNKBZ.js} +24 -24
  8. package/{agentRunControl-P75VPTGS.js → agentRunControl-Y5AFH5PQ.js} +2 -2
  9. package/{agentRuntimeLocal-QUTBSY3I.js → agentRuntimeLocal-7WYWCGL4.js} +9 -9
  10. package/{agentSlice-DOGRCMWK.js → agentSlice-EAXPGEYV.js} +1 -1
  11. package/{appDeleteCommands-FEEVXUBG.js → appDeleteCommands-77KR2RJ4.js} +13 -13
  12. package/{appDeployCommands-C4HCGC4B.js → appDeployCommands-K7CAHGBI.js} +13 -13
  13. package/{appDeployStatusCommands-IR5ZUZBQ.js → appDeployStatusCommands-4OEKLTBT.js} +13 -13
  14. package/{appGetCommands-6RJGZ66Z.js → appGetCommands-VM2WDLAZ.js} +13 -13
  15. package/{appListCommands-VMTF5YZF.js → appListCommands-GX6BBA6U.js} +13 -13
  16. package/{authCommand-WJZPOLSS.js → authCommand-DY6UUL6O.js} +6 -6
  17. package/{chunk-UZY4BEBR.js → chunk-23FZYPLC.js} +43 -14
  18. package/{chunk-IOOMJJ4Z.js → chunk-34WPV75U.js} +21 -0
  19. package/{chunk-JP7REMYP.js → chunk-3ZX7PERL.js} +1 -1
  20. package/{chunk-HV2A3B4W.js → chunk-AHCY2S2I.js} +1 -1
  21. package/{chunk-BT6K76S7.js → chunk-BV4VEE3W.js} +41 -15
  22. package/{chunk-PZCBZO4J.js → chunk-CZ6NYQTV.js} +12 -3
  23. package/{chunk-FVIPEIVX.js → chunk-DFCFMCY6.js} +1 -1
  24. package/{chunk-NEKFSXOP.js → chunk-EDV7EBOI.js} +22 -20
  25. package/{chunk-FKXFCYVO.js → chunk-FQZZLA3C.js} +2 -0
  26. package/{chunk-L6NVTGI7.js → chunk-FXUSIQC2.js} +1 -1
  27. package/{chunk-VDNQF5VI.js → chunk-G5U6LDLG.js} +2 -2
  28. package/{chunk-ZVOZH2HW.js → chunk-HEGV7BH3.js} +1 -1
  29. package/{chunk-RRGVDPH3.js → chunk-HWW2M4SN.js} +3 -3
  30. package/{chunk-EGPCU42M.js → chunk-I2ZJKTG5.js} +2 -2
  31. package/{chunk-NYUXSXLY.js → chunk-IYEXFJPC.js} +2 -2
  32. package/{chunk-FPKLD4KB.js → chunk-L4F3I4SR.js} +1 -1
  33. package/{chunk-RK5NYQEL.js → chunk-LLWKHDG4.js} +1 -1
  34. package/{chunk-MUCU6ATG.js → chunk-MHSGJW4Z.js} +1 -1
  35. package/{chunk-O6W2O2DA.js → chunk-MKA6QE5E.js} +6 -2
  36. package/{chunk-YXTRNO5W.js → chunk-MPVYDS7I.js} +3 -3
  37. package/{chunk-AAODAAUQ.js → chunk-N54HIJVJ.js} +1 -1
  38. package/{chunk-UB4RYYNQ.js → chunk-OK6YSWLH.js} +1 -1
  39. package/{chunk-VGMJ6PDJ.js → chunk-PIZYJVHQ.js} +2 -2
  40. package/{chunk-D3HVJJIA.js → chunk-PJSV3IZ5.js} +1 -1
  41. package/{chunk-YLRTBX4Y.js → chunk-R35XMF6F.js} +25 -9
  42. package/{chunk-MD3V54DA.js → chunk-REA4JLBH.js} +3 -3
  43. package/{chunk-CEFXYF66.js → chunk-RQN4SEKL.js} +1 -1
  44. package/{chunk-NVB267BZ.js → chunk-SCTYAHYK.js} +87 -15
  45. package/{chunk-45BY7RLP.js → chunk-SWDPIPOY.js} +1 -1
  46. package/{chunk-HQPG2PIV.js → chunk-UAIVG4J6.js} +1 -1
  47. package/{chunk-SNZV4QCE.js → chunk-UBHAWFQ6.js} +86 -17
  48. package/{chunk-L2MLZQXU.js → chunk-V3ED5AWK.js} +2 -2
  49. package/{chunk-RG2U2MTJ.js → chunk-VDXCXCXH.js} +1 -1
  50. package/{chunk-TSIYZBTH.js → chunk-VNAEBGDK.js} +1 -1
  51. package/{chunk-ZJZCMKOR.js → chunk-VYHDJEQD.js} +17 -29
  52. package/{chunk-QCJITMYO.js → chunk-YGW4G5W5.js} +7 -4
  53. package/{createAgentAutomationAction-PMOLEPGJ.js → createAgentAutomationAction-GNFF524X.js} +6 -6
  54. package/{createDialogAction-DPRTYNAK.js → createDialogAction-RB55KCLO.js} +7 -7
  55. package/{createPageAction-JGZK3WAM.js → createPageAction-Y7343GLU.js} +6 -6
  56. package/{db-HCJ5PRB5.js → db-W3O47YGF.js} +38 -12
  57. package/{dialogCommands-XED6DKLV.js → dialogCommands-IAZK6YHQ.js} +13 -13
  58. package/{dialogSlice-KO4NRNKC.js → dialogSlice-UQAXF23P.js} +6 -6
  59. package/{docCreateCommands-P6DYWHH3.js → docCreateCommands-I2EWZGCI.js} +12 -12
  60. package/{docDeleteCommands-KUWXAMSN.js → docDeleteCommands-IZ45UZKG.js} +13 -13
  61. package/{docReadCommands-ECW55TKB.js → docReadCommands-R6Z4QJYU.js} +12 -12
  62. package/{docStore-6KMERNUY.js → docStore-5HOJ4D7D.js} +7 -7
  63. package/{docUpdateCommands-5J4BTJQN.js → docUpdateCommands-2LRBKQPY.js} +12 -12
  64. package/{getPricing-RYY6OBA4.js → getPricing-G7DLAST6.js} +3 -3
  65. package/{handleSendMessageAction-R3ZHTVU4.js → handleSendMessageAction-Q4HY35WX.js} +6 -6
  66. package/index.js +52 -52
  67. package/{localDialogRead-HQZPVIE3.js → localDialogRead-4H3QJFLW.js} +1 -1
  68. package/{machineCommands-JF2YL34J.js → machineCommands-PKBPQKTY.js} +23 -23
  69. package/{machineWsRunDispatch-ON4AEOJL.js → machineWsRunDispatch-UZAW4OXJ.js} +23 -23
  70. package/{models-5K5G2CZI.js → models-DJFSJ7SW.js} +2 -2
  71. package/package.json +1 -1
  72. package/{readlineWorkspace-SUCINTL7.js → readlineWorkspace-Y2RDOFZG.js} +472 -97
  73. package/{runAgentClientLoop-OBD2AVEL.js → runAgentClientLoop-NBPIKJ6J.js} +16 -16
  74. package/{spaceCommands-32NTNLHS.js → spaceCommands-DHCZ7J5I.js} +12 -12
  75. package/{spaceSlice-P7VOXLY6.js → spaceSlice-ZXLLG3CR.js} +6 -6
  76. package/{streamAgentChatTurn-UHEMNI3X.js → streamAgentChatTurn-L3YW6LSB.js} +19 -19
  77. package/{tools-BMXIXHMB.js → tools-ECGXR5QF.js} +11 -11
  78. package/{tuiSummaryLlmCaller-VUNVBRX3.js → tuiSummaryLlmCaller-OMSCNHXA.js} +4 -4
  79. package/{updateDialogTitleAction-LJBDYZLH.js → updateDialogTitleAction-HQ2EUDFT.js} +6 -6
@@ -3,17 +3,17 @@ import {
3
3
  normalizeDialogRecord,
4
4
  readDialogSnapshot,
5
5
  sortDialogs
6
- } from "./chunk-L2MLZQXU.js";
6
+ } from "./chunk-V3ED5AWK.js";
7
7
  import {
8
8
  listFavoriteAgentIdsAcrossServers,
9
9
  listLocalCachedAgents,
10
10
  listRemoteAgents,
11
11
  listRemoteAgentsAcrossServers
12
- } from "./chunk-RRGVDPH3.js";
12
+ } from "./chunk-HWW2M4SN.js";
13
13
  import "./chunk-ID4G2MAR.js";
14
14
  import {
15
15
  listUserRecordsFromServers
16
- } from "./chunk-ZVOZH2HW.js";
16
+ } from "./chunk-HEGV7BH3.js";
17
17
  import {
18
18
  buildOverlayPresentation
19
19
  } from "./chunk-V5R4NZP2.js";
@@ -28,6 +28,7 @@ import {
28
28
  applyDetectedBackground,
29
29
  applyTerminalOutputToText,
30
30
  buildSkillContextBlocks,
31
+ buildWindowTitle,
31
32
  classifyCliAutoRoute,
32
33
  clearCollapsedPasteStore,
33
34
  countPhysicalLines,
@@ -70,7 +71,7 @@ import {
70
71
  visibleWidth,
71
72
  wrapTextToLines,
72
73
  wrapTranscriptLine
73
- } from "./chunk-BT6K76S7.js";
74
+ } from "./chunk-BV4VEE3W.js";
74
75
  import "./chunk-DZ3XJVET.js";
75
76
  import {
76
77
  getReadableCliDb
@@ -79,17 +80,18 @@ import {
79
80
  deleteDbRecord,
80
81
  queryUserRecords,
81
82
  readDbRecord
82
- } from "./chunk-FVIPEIVX.js";
83
+ } from "./chunk-DFCFMCY6.js";
83
84
  import {
84
85
  createCliLocalRuntimeAdapter,
85
86
  initCliLocale,
86
87
  isQuotaExhaustedError,
87
88
  parseCliLocale,
89
+ readTimestamp,
88
90
  setCliLocale,
89
91
  t
90
- } from "./chunk-UZY4BEBR.js";
91
- import "./chunk-UB4RYYNQ.js";
92
- import "./chunk-45BY7RLP.js";
92
+ } from "./chunk-23FZYPLC.js";
93
+ import "./chunk-OK6YSWLH.js";
94
+ import "./chunk-SWDPIPOY.js";
93
95
  import {
94
96
  resolveCliAgentKeyInput
95
97
  } from "./chunk-VHBWHNVT.js";
@@ -99,18 +101,18 @@ import "./chunk-6HYVJV7B.js";
99
101
  import "./chunk-JEXVIMYZ.js";
100
102
  import {
101
103
  prepareTools
102
- } from "./chunk-PZCBZO4J.js";
103
- import "./chunk-L6NVTGI7.js";
104
+ } from "./chunk-CZ6NYQTV.js";
105
+ import "./chunk-FXUSIQC2.js";
104
106
  import {
105
107
  expandEnabledPacks
106
- } from "./chunk-NEKFSXOP.js";
108
+ } from "./chunk-EDV7EBOI.js";
107
109
  import "./chunk-RQSOAMPJ.js";
108
- import "./chunk-JP7REMYP.js";
110
+ import "./chunk-3ZX7PERL.js";
109
111
  import "./chunk-KQHGZWSV.js";
110
112
  import "./chunk-4T5F7YZQ.js";
111
113
  import "./chunk-3LY4F7SV.js";
112
114
  import "./chunk-VF4K2QE6.js";
113
- import "./chunk-VDNQF5VI.js";
115
+ import "./chunk-G5U6LDLG.js";
114
116
  import {
115
117
  initialRunOverlayState,
116
118
  reduceRunOverlay
@@ -121,16 +123,16 @@ import "./chunk-VP4WJWKW.js";
121
123
  import "./chunk-63W5N6P3.js";
122
124
  import "./chunk-WJRJDX2W.js";
123
125
  import "./chunk-LM6IYQ3F.js";
124
- import "./chunk-NYUXSXLY.js";
126
+ import "./chunk-IYEXFJPC.js";
125
127
  import {
126
128
  extractReferenceKeysFromMessage
127
- } from "./chunk-NVB267BZ.js";
129
+ } from "./chunk-SCTYAHYK.js";
128
130
  import {
129
131
  buildBuiltinSummaryContent
130
132
  } from "./chunk-XOIF2TNF.js";
131
133
  import "./chunk-B5TOXZAK.js";
132
134
  import "./chunk-MRC4Q34M.js";
133
- import "./chunk-MD3V54DA.js";
135
+ import "./chunk-REA4JLBH.js";
134
136
  import "./chunk-CWMSB67P.js";
135
137
  import "./chunk-XHG22OEX.js";
136
138
  import "./chunk-Z4NR32XR.js";
@@ -146,24 +148,24 @@ import {
146
148
  buildLocalWorkspaceOpenAiTools,
147
149
  buildLocalWorkspaceToolset,
148
150
  getProcessRegistry
149
- } from "./chunk-YLRTBX4Y.js";
151
+ } from "./chunk-R35XMF6F.js";
150
152
  import "./chunk-ZNFJWEN4.js";
151
- import "./chunk-AAODAAUQ.js";
153
+ import "./chunk-N54HIJVJ.js";
152
154
  import "./chunk-OIQPORYI.js";
153
155
  import {
154
156
  readCommandActionGatePayload,
155
157
  resolveAgentImageInputSupport
156
- } from "./chunk-QCJITMYO.js";
158
+ } from "./chunk-YGW4G5W5.js";
157
159
  import "./chunk-LSFAWXKC.js";
158
160
  import {
159
161
  buildCurrentTimeBlock,
160
162
  buildIdentityBlock,
161
163
  buildRuntimeGuidanceBlocks
162
- } from "./chunk-IOOMJJ4Z.js";
164
+ } from "./chunk-34WPV75U.js";
163
165
  import "./chunk-KFEVY3ST.js";
164
166
  import {
165
167
  resolvePlatformAuthToken
166
- } from "./chunk-MUCU6ATG.js";
168
+ } from "./chunk-MHSGJW4Z.js";
167
169
  import "./chunk-DKZFOK24.js";
168
170
  import {
169
171
  DEFAULT_CONTEXT_WINDOW,
@@ -171,13 +173,13 @@ import {
171
173
  getModelContextWindow,
172
174
  planCompression,
173
175
  serializeMessageContent
174
- } from "./chunk-EGPCU42M.js";
176
+ } from "./chunk-I2ZJKTG5.js";
175
177
  import {
176
178
  clipCompactText
177
179
  } from "./chunk-5MMAK75Q.js";
178
180
  import "./chunk-5CS33IBL.js";
179
181
  import "./chunk-JZPBVBIY.js";
180
- import "./chunk-HQPG2PIV.js";
182
+ import "./chunk-UAIVG4J6.js";
181
183
  import "./chunk-ZHXJ6M7T.js";
182
184
  import {
183
185
  toErrorMessage
@@ -197,15 +199,21 @@ import {
197
199
  compactWhitespace
198
200
  } from "./chunk-DWLEOOGR.js";
199
201
  import {
200
- queryRunRecords
201
- } from "./chunk-TSIYZBTH.js";
202
+ checkStaleRun,
203
+ queryRunRecords,
204
+ readRunRecord
205
+ } from "./chunk-VNAEBGDK.js";
202
206
  import {
207
+ clipText,
208
+ formatDuration,
203
209
  formatRunAge,
204
210
  getAgentRunStatusIcon,
211
+ isAgentNameFallback,
205
212
  isAgentRunTerminalStatus,
213
+ resolveRunLabel,
206
214
  runShowsLogTail,
207
215
  shortRunId
208
- } from "./chunk-FKXFCYVO.js";
216
+ } from "./chunk-FQZZLA3C.js";
209
217
  import "./chunk-X7W4TNB4.js";
210
218
  import "./chunk-ATNTHIZI.js";
211
219
  import "./chunk-JBTJAPUF.js";
@@ -229,8 +237,8 @@ import {
229
237
  import {
230
238
  DEFAULT_NOLO_SERVER_URL
231
239
  } from "./chunk-OLZBQWZU.js";
232
- import "./chunk-RK5NYQEL.js";
233
- import "./chunk-O6W2O2DA.js";
240
+ import "./chunk-LLWKHDG4.js";
241
+ import "./chunk-MKA6QE5E.js";
234
242
  import "./chunk-UGUW3FHG.js";
235
243
  import "./chunk-RVOUXDFU.js";
236
244
  import "./chunk-Y5GCAMGP.js";
@@ -1668,6 +1676,274 @@ function createDialogHost(args) {
1668
1676
  };
1669
1677
  }
1670
1678
 
1679
+ // packages/cli/tui/runSnapshotDisplay.ts
1680
+ function runStatusTone(status) {
1681
+ if (!isAgentRunTerminalStatus(status)) return "warning";
1682
+ return status === "done" ? "success" : "danger";
1683
+ }
1684
+ function formatInFlightFact(inFlight, now, maxNameLength = 20) {
1685
+ const label = inFlight.kind === "llm" ? "thinking" : clipText(inFlight.name, maxNameLength);
1686
+ return `${label} ${formatDuration(Math.max(0, now - inFlight.startedAt))}`;
1687
+ }
1688
+ function activeInFlight(snapshot) {
1689
+ if (isAgentRunTerminalStatus(snapshot.status)) return null;
1690
+ return snapshot.inFlight ?? null;
1691
+ }
1692
+
1693
+ // packages/cli/tui/agentRunPanelLines.ts
1694
+ function formatPanelProgress(snapshot, now) {
1695
+ const parts = [];
1696
+ if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1697
+ parts.push(`${snapshot.toolCallCount} tools`);
1698
+ }
1699
+ const inFlight = activeInFlight(snapshot);
1700
+ if (inFlight) {
1701
+ parts.push(formatInFlightFact(inFlight, now));
1702
+ } else if (snapshot.lastToolNames && snapshot.lastToolNames.length > 0) {
1703
+ parts.push(snapshot.lastToolNames.join(", "));
1704
+ }
1705
+ return parts.length > 0 ? ` \xB7 ${parts.join(" \xB7 ")}` : "";
1706
+ }
1707
+ function formatPanelDetail(snapshot) {
1708
+ const note = snapshot.lastAssistantText?.trim();
1709
+ if (note) return note;
1710
+ if (!runShowsLogTail(snapshot.status)) return "";
1711
+ const lines = snapshot.logLines;
1712
+ if (!lines || lines.length === 0) return "";
1713
+ return lines[lines.length - 1]?.trim() ?? "";
1714
+ }
1715
+ function formatAgentRunPanelLines(snapshot, colorEnabled, now = Date.now()) {
1716
+ const lines = [];
1717
+ const name = snapshot.agentName || "sub-agent";
1718
+ const short = shortRunId(snapshot.runId);
1719
+ const runId = short ? ` (${short})` : "";
1720
+ const status = snapshot.status || "running";
1721
+ const statusSymbol = getAgentRunStatusIcon(status);
1722
+ const statusColor = runStatusTone(status);
1723
+ const errPart = snapshot.errorMessage ? ` \xB7 ${snapshot.errorMessage}` : "";
1724
+ const progressPart = formatPanelProgress(snapshot, now);
1725
+ const age = formatRunAge(snapshot, now);
1726
+ const agePart = age ? ` \xB7 ${age}` : "";
1727
+ if (!colorEnabled) {
1728
+ lines.push(
1729
+ `\u{1F916} Sub-Agent: ${name}${runId} \xB7 ${statusSymbol} ${status}${agePart}${progressPart}${errPart}`
1730
+ );
1731
+ } else {
1732
+ const botIcon = themeText("\u{1F916}", "accent", true);
1733
+ const labelText = themeText(" Sub-Agent: ", "muted", true);
1734
+ const nameText = themeText(`${name}${runId}`, "chrome", true);
1735
+ const statusText = themeText(` \xB7 ${statusSymbol} ${status}`, statusColor, true);
1736
+ const ageText = agePart ? themeText(agePart, "chrome") : "";
1737
+ const progressText = progressPart ? themeText(progressPart, "chrome") : "";
1738
+ const errorText = errPart ? themeText(errPart, "danger") : "";
1739
+ lines.push(`${botIcon}${labelText}${nameText}${statusText}${ageText}${progressText}${errorText}`);
1740
+ }
1741
+ const detail = formatPanelDetail(snapshot);
1742
+ if (detail) {
1743
+ if (!colorEnabled) {
1744
+ lines.push(` \u2514 ${detail}`);
1745
+ } else {
1746
+ lines.push(`${themeText(" \u2514 ", "muted")}${themeText(detail, "chrome")}`);
1747
+ }
1748
+ }
1749
+ return lines;
1750
+ }
1751
+
1752
+ // packages/cli/tui/runDock.ts
1753
+ var RUN_DOCK_TICK_INTERVAL_MS = 1e3;
1754
+ var RUN_DOCK_LINGER_MS = 8e3;
1755
+ var RUN_DOCK_STALE_MS = 5 * 6e4;
1756
+ var RUN_DOCK_MAX_ROWS = 3;
1757
+ var RETIRED_MEMORY = 64;
1758
+ function mergeSnapshot(prev, next) {
1759
+ const merged = { ...prev, ...next };
1760
+ if (merged.errorMessage && next.errorMessage === void 0 && !isAgentRunTerminalStatus(merged.status)) {
1761
+ delete merged.errorMessage;
1762
+ }
1763
+ if (next.inFlight === void 0) {
1764
+ if (prev.inFlight !== void 0) merged.inFlight = prev.inFlight;
1765
+ }
1766
+ return merged;
1767
+ }
1768
+ function createRunDock(deps) {
1769
+ const now = deps.now ?? (() => Date.now());
1770
+ const tickIntervalMs = deps.tickIntervalMs ?? RUN_DOCK_TICK_INTERVAL_MS;
1771
+ const lingerMs = deps.lingerMs ?? RUN_DOCK_LINGER_MS;
1772
+ const staleMs = deps.staleMs ?? RUN_DOCK_STALE_MS;
1773
+ const maxRows = deps.maxRows ?? RUN_DOCK_MAX_ROWS;
1774
+ const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
1775
+ const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
1776
+ const entries = /* @__PURE__ */ new Map();
1777
+ const retired = /* @__PURE__ */ new Set();
1778
+ let seqCounter = 0;
1779
+ let timer = null;
1780
+ let disposed = false;
1781
+ const stopTimer = () => {
1782
+ if (timer !== null) {
1783
+ clearIntervalFn(timer);
1784
+ timer = null;
1785
+ }
1786
+ };
1787
+ const prune = () => {
1788
+ const at = now();
1789
+ let changed = false;
1790
+ for (const [runId, entry] of entries) {
1791
+ const expiredTerminal = entry.terminalAt !== null && at - entry.terminalAt >= lingerMs;
1792
+ const stale = at - entry.updatedAt >= staleMs;
1793
+ if (!expiredTerminal && !stale) continue;
1794
+ entries.delete(runId);
1795
+ changed = true;
1796
+ if (expiredTerminal) {
1797
+ retired.add(runId);
1798
+ if (retired.size > RETIRED_MEMORY) {
1799
+ const oldest = retired.values().next().value;
1800
+ if (oldest !== void 0) retired.delete(oldest);
1801
+ }
1802
+ }
1803
+ }
1804
+ if (entries.size === 0) stopTimer();
1805
+ return changed;
1806
+ };
1807
+ const tick = () => {
1808
+ prune();
1809
+ deps.onRepaint();
1810
+ };
1811
+ const ensureTimer = () => {
1812
+ if (timer === null && entries.size > 0) {
1813
+ timer = setIntervalFn(tick, tickIntervalMs);
1814
+ }
1815
+ };
1816
+ const update = (snapshot) => {
1817
+ if (disposed) return;
1818
+ const runId = snapshot.runId;
1819
+ if (!runId) return;
1820
+ if (snapshot.status === "not_found") {
1821
+ remove(runId);
1822
+ return;
1823
+ }
1824
+ if (retired.has(runId)) return;
1825
+ const at = now();
1826
+ const prev = entries.get(runId);
1827
+ const merged = prev ? mergeSnapshot(prev.snapshot, snapshot) : snapshot;
1828
+ const terminal = isAgentRunTerminalStatus(merged.status);
1829
+ entries.set(runId, {
1830
+ snapshot: merged,
1831
+ seq: prev ? prev.seq : seqCounter++,
1832
+ updatedAt: at,
1833
+ // terminalAt 只在首次进入终态时记一次:终态 run 后续还会被轮询到,
1834
+ // 每次都刷新的话 linger 永远走不完,面板会一直挂着已完成的 run。
1835
+ terminalAt: terminal ? prev?.terminalAt ?? at : null
1836
+ });
1837
+ ensureTimer();
1838
+ deps.onRepaint();
1839
+ };
1840
+ const remove = (runId) => {
1841
+ if (!entries.delete(runId)) return;
1842
+ if (entries.size === 0) stopTimer();
1843
+ deps.onRepaint();
1844
+ };
1845
+ const clear = () => {
1846
+ if (entries.size === 0) return;
1847
+ entries.clear();
1848
+ stopTimer();
1849
+ deps.onRepaint();
1850
+ };
1851
+ const orderedEntries = () => [...entries.values()].sort((a, b) => {
1852
+ const aTerminal = a.terminalAt !== null ? 1 : 0;
1853
+ const bTerminal = b.terminalAt !== null ? 1 : 0;
1854
+ if (aTerminal !== bTerminal) return aTerminal - bTerminal;
1855
+ return a.seq - b.seq;
1856
+ });
1857
+ const getRuns = () => orderedEntries().map((entry) => entry.snapshot);
1858
+ const getLines = (colorEnabled) => {
1859
+ prune();
1860
+ const ordered = orderedEntries();
1861
+ if (ordered.length === 0) return [];
1862
+ const at = now();
1863
+ if (ordered.length === 1) {
1864
+ return formatAgentRunPanelLines(ordered[0].snapshot, colorEnabled, at);
1865
+ }
1866
+ return formatRunDockLines(
1867
+ ordered.map((entry) => entry.snapshot),
1868
+ colorEnabled,
1869
+ at,
1870
+ maxRows
1871
+ );
1872
+ };
1873
+ return {
1874
+ update,
1875
+ remove,
1876
+ clear,
1877
+ getRuns,
1878
+ getLines,
1879
+ dispose() {
1880
+ disposed = true;
1881
+ entries.clear();
1882
+ retired.clear();
1883
+ stopTimer();
1884
+ }
1885
+ };
1886
+ }
1887
+ function summarize(snapshots) {
1888
+ let running = 0;
1889
+ const terminal = /* @__PURE__ */ new Map();
1890
+ for (const snapshot of snapshots) {
1891
+ if (!isAgentRunTerminalStatus(snapshot.status)) {
1892
+ running += 1;
1893
+ continue;
1894
+ }
1895
+ terminal.set(snapshot.status, (terminal.get(snapshot.status) ?? 0) + 1);
1896
+ }
1897
+ const parts = [];
1898
+ if (running > 0) parts.push(`${running} running`);
1899
+ for (const [status, count] of terminal) parts.push(`${count} ${status}`);
1900
+ return parts.join(" \xB7 ");
1901
+ }
1902
+ function formatRunDockLines(snapshots, colorEnabled, now = Date.now(), maxRows = RUN_DOCK_MAX_ROWS) {
1903
+ if (snapshots.length === 0) return [];
1904
+ const lines = [];
1905
+ const summary = summarize(snapshots);
1906
+ const header = `\u{1F916} runs \xB7 ${summary}`;
1907
+ lines.push(colorEnabled ? themeText(header, "muted", true) : header);
1908
+ const shown = snapshots.slice(0, Math.max(1, maxRows));
1909
+ for (const snapshot of shown) {
1910
+ lines.push(formatRunDockRow(snapshot, colorEnabled, now));
1911
+ }
1912
+ const hidden = snapshots.length - shown.length;
1913
+ if (hidden > 0) {
1914
+ const more = ` +${hidden} more`;
1915
+ lines.push(colorEnabled ? themeText(more, "chrome") : more);
1916
+ }
1917
+ return lines;
1918
+ }
1919
+ function formatRunDockRow(snapshot, colorEnabled, now) {
1920
+ const name = snapshot.agentName || "sub-agent";
1921
+ const short = shortRunId(snapshot.runId);
1922
+ const icon = getAgentRunStatusIcon(snapshot.status);
1923
+ const terminal = isAgentRunTerminalStatus(snapshot.status);
1924
+ const statusColor = runStatusTone(snapshot.status);
1925
+ const facts = [];
1926
+ const age = formatRunAge(snapshot, now);
1927
+ if (terminal) facts.push(age ? `${snapshot.status} ${age}` : snapshot.status);
1928
+ else if (age) facts.push(age);
1929
+ if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1930
+ facts.push(`${snapshot.toolCallCount} tools`);
1931
+ }
1932
+ const inFlight = activeInFlight(snapshot);
1933
+ if (inFlight) {
1934
+ facts.push(formatInFlightFact(inFlight, now));
1935
+ } else {
1936
+ const lastTool = snapshot.lastToolNames?.[snapshot.lastToolNames.length - 1];
1937
+ if (lastTool) facts.push(clipText(lastTool, 20));
1938
+ }
1939
+ if (snapshot.errorMessage) facts.push(clipText(snapshot.errorMessage, 40));
1940
+ const label = `${name}${short ? ` #${short}` : ""}`;
1941
+ const factsPart = facts.length > 0 ? ` \xB7 ${facts.join(" \xB7 ")}` : "";
1942
+ if (!colorEnabled) return ` ${icon} ${label}${factsPart}`;
1943
+ const errorTail = snapshot.errorMessage;
1944
+ return themeText(" ", "chrome") + themeText(icon, statusColor, true) + " " + themeText(label, "chrome", true) + themeText(factsPart, errorTail ? "danger" : "chrome");
1945
+ }
1946
+
1671
1947
  // packages/cli/tui/activityIndicator.ts
1672
1948
  var ACTIVITY_FRAMES = ["\xB7", "~", "\u2248", "\u223F", "\u2248", "~"];
1673
1949
  var ACTIVITY_FRAME_INTERVAL_MS = 150;
@@ -1751,16 +2027,19 @@ function createActivityIndicator(deps) {
1751
2027
  }
1752
2028
  return null;
1753
2029
  };
1754
- let agentRunSnapshot = null;
2030
+ const runDock = deps.runDock ?? createRunDock({
2031
+ onRepaint: deps.onRepaint,
2032
+ now,
2033
+ setIntervalFn,
2034
+ clearIntervalFn
2035
+ });
1755
2036
  const updateAgentRun = (snapshot) => {
1756
- agentRunSnapshot = snapshot;
1757
- deps.onRepaint();
2037
+ runDock.update(snapshot);
1758
2038
  };
1759
2039
  const clearAgentRun = () => {
1760
- agentRunSnapshot = null;
1761
- deps.onRepaint();
2040
+ runDock.clear();
1762
2041
  };
1763
- const getAgentRun = () => agentRunSnapshot;
2042
+ const getAgentRuns = () => runDock.getRuns();
1764
2043
  const getActivityLines = (colorEnabled = resolveCliColorEnabled()) => {
1765
2044
  const lines = [];
1766
2045
  const baseView = getView();
@@ -1776,9 +2055,7 @@ function createActivityIndicator(deps) {
1776
2055
  );
1777
2056
  }
1778
2057
  }
1779
- if (agentRunSnapshot) {
1780
- lines.push(...formatAgentRunPanelLines(agentRunSnapshot, colorEnabled, now()));
1781
- }
2058
+ lines.push(...runDock.getLines(colorEnabled));
1782
2059
  return lines.length > 0 ? lines : null;
1783
2060
  };
1784
2061
  const stop = () => {
@@ -1792,73 +2069,134 @@ function createActivityIndicator(deps) {
1792
2069
  fallbackStartedAt = 0;
1793
2070
  lastActivityAt = 0;
1794
2071
  stopping = false;
1795
- agentRunSnapshot = null;
1796
2072
  };
1797
2073
  return {
1798
2074
  report,
1799
2075
  updateAgentRun,
1800
2076
  clearAgentRun,
1801
- getAgentRun,
2077
+ getAgentRuns,
1802
2078
  getView,
1803
2079
  getActivityLines,
1804
2080
  markStopping,
1805
2081
  isStopping,
1806
- stop
2082
+ stop,
2083
+ dispose() {
2084
+ stop();
2085
+ runDock.dispose();
2086
+ }
1807
2087
  };
1808
2088
  }
1809
- function formatPanelProgress(snapshot) {
1810
- const parts = [];
1811
- if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1812
- parts.push(`${snapshot.toolCallCount} tools`);
1813
- }
1814
- if (snapshot.lastToolNames && snapshot.lastToolNames.length > 0) {
1815
- parts.push(snapshot.lastToolNames.join(", "));
2089
+
2090
+ // packages/cli/tui/runRegistryPoller.ts
2091
+ var RUN_POLL_INTERVAL_MS = 1e3;
2092
+ var RUN_RECONCILE_SILENCE_MS = 15e3;
2093
+ function snapshotFromRunRecord(record, now) {
2094
+ const label = resolveRunLabel(record);
2095
+ const startedAt = readTimestamp(record.startedAt);
2096
+ const endedAt = readTimestamp(record.endedAt);
2097
+ const activity = record.activity;
2098
+ const counters = activity?.counters;
2099
+ let inFlight = null;
2100
+ const raw = activity?.inFlight;
2101
+ if (raw && !isAgentRunTerminalStatus(record.status)) {
2102
+ const updatedAt = activity?.updatedAt ? Date.parse(activity.updatedAt) : NaN;
2103
+ const base = Number.isFinite(updatedAt) ? updatedAt : now;
2104
+ const startedFrom = base - (Number.isFinite(raw.sinceMs) ? raw.sinceMs : 0);
2105
+ const usable = Number.isFinite(startedFrom) && startedFrom > 0 ? Math.min(startedFrom, now) : now;
2106
+ inFlight = { kind: raw.kind, name: raw.name, startedAt: usable };
1816
2107
  }
1817
- return parts.length > 0 ? ` \xB7 ${parts.join(" \xB7 ")}` : "";
2108
+ return {
2109
+ runId: record.runId,
2110
+ status: record.status,
2111
+ ...isAgentNameFallback(label) ? {} : { agentName: label },
2112
+ ...startedAt !== void 0 ? { startedAt } : {},
2113
+ ...endedAt !== void 0 ? { finishedAt: endedAt } : {},
2114
+ ...typeof counters?.toolCalls === "number" ? { toolCallCount: counters.toolCalls } : {},
2115
+ // note 在终态时是死因("orphaned: process gone…"),非终态时只是备注。
2116
+ ...record.note && isAgentRunTerminalStatus(record.status) ? { errorMessage: record.note } : {},
2117
+ inFlight,
2118
+ logKey: ""
2119
+ };
1818
2120
  }
1819
- function formatPanelDetail(snapshot) {
1820
- const note = snapshot.lastAssistantText?.trim();
1821
- if (note) return note;
1822
- if (!runShowsLogTail(snapshot.status)) return "";
1823
- const lines = snapshot.logLines;
1824
- if (!lines || lines.length === 0) return "";
1825
- return lines[lines.length - 1]?.trim() ?? "";
2121
+ function fingerprint(snapshot) {
2122
+ return JSON.stringify([
2123
+ snapshot.status,
2124
+ snapshot.agentName ?? "",
2125
+ snapshot.toolCallCount ?? -1,
2126
+ snapshot.errorMessage ?? "",
2127
+ snapshot.finishedAt ?? 0,
2128
+ snapshot.inFlight ? [snapshot.inFlight.kind, snapshot.inFlight.name, snapshot.inFlight.startedAt] : null
2129
+ ]);
1826
2130
  }
1827
- function formatAgentRunPanelLines(snapshot, colorEnabled, now = Date.now()) {
1828
- const lines = [];
1829
- const name = snapshot.agentName || "sub-agent";
1830
- const short = shortRunId(snapshot.runId);
1831
- const runId = short ? ` (${short})` : "";
1832
- const status = snapshot.status || "running";
1833
- const statusSymbol = getAgentRunStatusIcon(status);
1834
- const statusColor = !isAgentRunTerminalStatus(status) ? "warning" : status === "done" ? "success" : "danger";
1835
- const errPart = snapshot.errorMessage ? ` \xB7 ${snapshot.errorMessage}` : "";
1836
- const progressPart = formatPanelProgress(snapshot);
1837
- const age = formatRunAge(snapshot, now);
1838
- const agePart = age ? ` \xB7 ${age}` : "";
1839
- if (!colorEnabled) {
1840
- lines.push(
1841
- `\u{1F916} Sub-Agent: ${name}${runId} \xB7 ${statusSymbol} ${status}${agePart}${progressPart}${errPart}`
2131
+ function createRunRegistryPoller(deps) {
2132
+ const now = deps.now ?? (() => Date.now());
2133
+ const intervalMs = deps.intervalMs ?? RUN_POLL_INTERVAL_MS;
2134
+ const reconcileSilenceMs = deps.reconcileSilenceMs ?? RUN_RECONCILE_SILENCE_MS;
2135
+ const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
2136
+ const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
2137
+ let timer = null;
2138
+ let disposed = false;
2139
+ const lastEmitted = /* @__PURE__ */ new Map();
2140
+ const lastReconciledAt = /* @__PURE__ */ new Map();
2141
+ const stop = () => {
2142
+ if (timer !== null) {
2143
+ clearIntervalFn(timer);
2144
+ timer = null;
2145
+ }
2146
+ lastEmitted.clear();
2147
+ lastReconciledAt.clear();
2148
+ };
2149
+ const freshnessOf = (record) => {
2150
+ return readTimestamp(record.activity?.updatedAt) ?? readTimestamp(record.startedAt) ?? 0;
2151
+ };
2152
+ const poll = () => {
2153
+ const at = now();
2154
+ const active = deps.getDockedRuns().filter(
2155
+ (run) => run.runId && !isAgentRunTerminalStatus(run.status)
1842
2156
  );
1843
- } else {
1844
- const botIcon = themeText("\u{1F916}", "accent", true);
1845
- const labelText = themeText(" Sub-Agent: ", "muted", true);
1846
- const nameText = themeText(`${name}${runId}`, "chrome", true);
1847
- const statusText = themeText(` \xB7 ${statusSymbol} ${status}`, statusColor, true);
1848
- const ageText = agePart ? themeText(agePart, "chrome") : "";
1849
- const progressText = progressPart ? themeText(progressPart, "chrome") : "";
1850
- const errorText = errPart ? themeText(errPart, "danger") : "";
1851
- lines.push(`${botIcon}${labelText}${nameText}${statusText}${ageText}${progressText}${errorText}`);
1852
- }
1853
- const detail = formatPanelDetail(snapshot);
1854
- if (detail) {
1855
- if (!colorEnabled) {
1856
- lines.push(` \u2514 ${detail}`);
1857
- } else {
1858
- lines.push(`${themeText(" \u2514 ", "muted")}${themeText(detail, "chrome")}`);
2157
+ if (active.length === 0) {
2158
+ stop();
2159
+ return;
1859
2160
  }
1860
- }
1861
- return lines;
2161
+ const alive = /* @__PURE__ */ new Set();
2162
+ for (const run of active) {
2163
+ alive.add(run.runId);
2164
+ let record;
2165
+ try {
2166
+ record = deps.readRecord(run.runId);
2167
+ if (deps.reconcile && record && !isAgentRunTerminalStatus(record.status) && at - freshnessOf(record) >= reconcileSilenceMs && at - (lastReconciledAt.get(run.runId) ?? 0) >= reconcileSilenceMs) {
2168
+ lastReconciledAt.set(run.runId, at);
2169
+ record = deps.reconcile(run.runId) ?? record;
2170
+ }
2171
+ } catch {
2172
+ continue;
2173
+ }
2174
+ if (!record) continue;
2175
+ const snapshot = snapshotFromRunRecord(record, at);
2176
+ const mark = fingerprint(snapshot);
2177
+ if (lastEmitted.get(run.runId) === mark) continue;
2178
+ lastEmitted.set(run.runId, mark);
2179
+ deps.update(snapshot);
2180
+ }
2181
+ for (const runId of [...lastEmitted.keys()]) {
2182
+ if (!alive.has(runId)) lastEmitted.delete(runId);
2183
+ }
2184
+ for (const runId of [...lastReconciledAt.keys()]) {
2185
+ if (!alive.has(runId)) lastReconciledAt.delete(runId);
2186
+ }
2187
+ };
2188
+ return {
2189
+ ensureRunning() {
2190
+ if (disposed || timer !== null) return;
2191
+ timer = setIntervalFn(poll, intervalMs);
2192
+ },
2193
+ poll,
2194
+ stop,
2195
+ dispose() {
2196
+ disposed = true;
2197
+ stop();
2198
+ }
2199
+ };
1862
2200
  }
1863
2201
 
1864
2202
  // packages/ai/agent/utils/sortUtils.ts
@@ -3389,7 +3727,7 @@ function handleTuiInput(input, state) {
3389
3727
  }
3390
3728
  if (argText === "all") {
3391
3729
  const before = registry.list().filter((p) => p.status === "running").length;
3392
- registry.stopAll();
3730
+ registry.stopAll(void 0, { includePersist: true });
3393
3731
  return { nextState: state, output: t("stopAllDone", String(before)) };
3394
3732
  }
3395
3733
  if (/^\d+$/.test(argText)) {
@@ -4889,7 +5227,7 @@ function toOverlayStatus(status) {
4889
5227
  return "running";
4890
5228
  }
4891
5229
  }
4892
- function buildTuiRunOverlay(parentDialogId) {
5230
+ function buildTuiRunOverlay(parentDialogId, reported) {
4893
5231
  if (!parentDialogId) return null;
4894
5232
  let runs;
4895
5233
  try {
@@ -4898,6 +5236,11 @@ function buildTuiRunOverlay(parentDialogId) {
4898
5236
  return null;
4899
5237
  }
4900
5238
  if (runs.length === 0) return null;
5239
+ if (reported) {
5240
+ runs = runs.filter((run) => reported.get(run.runId) !== run.status);
5241
+ for (const run of runs) reported.set(run.runId, run.status);
5242
+ if (runs.length === 0) return null;
5243
+ }
4901
5244
  let overlay = initialRunOverlayState;
4902
5245
  for (const run of runs) {
4903
5246
  overlay = reduceRunOverlay(overlay, {
@@ -5316,6 +5659,18 @@ async function startTuiWorkspace(options) {
5316
5659
  }
5317
5660
  const bannerColumns = output.columns;
5318
5661
  output.write(renderWelcome(state, 0, 0, bannerColumns));
5662
+ let lastSentTitle = null;
5663
+ const syncWindowTitle = () => {
5664
+ if (!output.isTTY) return;
5665
+ const env = options.env ?? process.env;
5666
+ const rawSetting = (env.NOLO_TUI_TITLE ?? "").trim().toLowerCase();
5667
+ if (rawSetting === "0" || rawSetting === "false") return;
5668
+ const currentTitle = state.dialogLabel?.trim() ?? "";
5669
+ if (currentTitle === lastSentTitle) return;
5670
+ lastSentTitle = currentTitle;
5671
+ output.write(buildWindowTitle(currentTitle));
5672
+ };
5673
+ syncWindowTitle();
5319
5674
  let fixedInput = createNoopFixedInput();
5320
5675
  let buffer = "";
5321
5676
  let cursorPos = 0;
@@ -5341,6 +5696,13 @@ async function startTuiWorkspace(options) {
5341
5696
  }
5342
5697
  });
5343
5698
  const activityReporter = (label) => activityIndicator.report(label);
5699
+ const reportedRunStatuses = /* @__PURE__ */ new Map();
5700
+ const runRegistryPoller = createRunRegistryPoller({
5701
+ getDockedRuns: () => activityIndicator.getAgentRuns(),
5702
+ update: (snapshot) => activityIndicator.updateAgentRun(snapshot),
5703
+ readRecord: (runId) => readRunRecord(runId),
5704
+ reconcile: (runId) => checkStaleRun(runId)
5705
+ });
5344
5706
  let explicitAgentSwitch = false;
5345
5707
  let copyViewExitResolver = null;
5346
5708
  let copyViewRender = null;
@@ -5556,6 +5918,7 @@ async function startTuiWorkspace(options) {
5556
5918
  onAgentRunStatus: (snapshot) => {
5557
5919
  if (snapshot) {
5558
5920
  activityIndicator.updateAgentRun(snapshot);
5921
+ runRegistryPoller.ensureRunning();
5559
5922
  } else {
5560
5923
  activityIndicator.clearAgentRun();
5561
5924
  }
@@ -5623,7 +5986,7 @@ async function startTuiWorkspace(options) {
5623
5986
  }
5624
5987
  }
5625
5988
  if (!wasAborted) {
5626
- const overlayText = buildTuiRunOverlay(turnParentDialogId);
5989
+ const overlayText = buildTuiRunOverlay(turnParentDialogId, reportedRunStatuses);
5627
5990
  if (overlayText) {
5628
5991
  emitCommandOutput(`
5629
5992
  \u4F60\u7684 run \u8FDB\u5C55\uFF1A
@@ -6046,11 +6409,7 @@ ${err.message}` : ""}`
6046
6409
  let busy = false;
6047
6410
  let done = false;
6048
6411
  let resolveDone = null;
6049
- fixedInput = createFixedInput(output, {
6050
- getTitleLine: () => {
6051
- const title = state.dialogLabel?.trim();
6052
- return title ? themeText(`\u{1F4AC} ${title}`, "accent", resolveCliColorEnabled()) : null;
6053
- },
6412
+ const baseFixedInput = createFixedInput(output, {
6054
6413
  getStatusLine: () => {
6055
6414
  let base = renderStatusLine(state);
6056
6415
  if (chatQueueBinding && chatQueueBinding.queueLength() > 0) {
@@ -6080,6 +6439,13 @@ ${err.message}` : ""}`
6080
6439
  renderHistoryToOutput();
6081
6440
  }
6082
6441
  });
6442
+ fixedInput = {
6443
+ ...baseFixedInput,
6444
+ repaint(draft, cursorPos2) {
6445
+ syncWindowTitle();
6446
+ return baseFixedInput.repaint(draft, cursorPos2);
6447
+ }
6448
+ };
6083
6449
  fixedInput.init();
6084
6450
  const paintFrame = (draft) => {
6085
6451
  renderHistoryToOutput();
@@ -6109,6 +6475,8 @@ ${err.message}` : ""}`
6109
6475
  clearInterval(autoThemeTimer);
6110
6476
  autoThemeTimer = null;
6111
6477
  }
6478
+ runRegistryPoller.dispose();
6479
+ activityIndicator.dispose();
6112
6480
  resolveDone?.();
6113
6481
  clearCollapsedPasteStore(pasteStore);
6114
6482
  resizeTarget.off?.("resize", onResize);
@@ -6487,7 +6855,13 @@ ${renderStatusLine(state)}
6487
6855
  rl.prompt();
6488
6856
  }
6489
6857
  } finally {
6490
- getProcessRegistry().stopAll();
6858
+ const registry = getProcessRegistry();
6859
+ const persistentCount = registry.list().filter((p) => p.persist && p.status === "running").length;
6860
+ registry.stopAll();
6861
+ if (persistentCount > 0) {
6862
+ output.write(`[nolo] ${t("persistentProcessesLeft", String(persistentCount))}
6863
+ `);
6864
+ }
6491
6865
  rl.close();
6492
6866
  }
6493
6867
  }
@@ -6498,6 +6872,7 @@ export {
6498
6872
  applyScrollAction,
6499
6873
  applyTerminalOutputToText,
6500
6874
  buildTuiRunOverlay,
6875
+ buildWindowTitle,
6501
6876
  countPhysicalLines,
6502
6877
  createFixedInput,
6503
6878
  createHistoryOutputStream,