nolo-cli 0.16.0-alpha.19 → 0.16.0-alpha.20

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 (63) hide show
  1. package/{_executeModel-YY6LVJXJ.js → _executeModel-GRCQXT5R.js} +13 -13
  2. package/{agentDeleteCommand-TJ2EAYDA.js → agentDeleteCommand-WNL3CNQX.js} +6 -6
  3. package/{agentEmailCommands-UKEGNW25.js → agentEmailCommands-MPEUMRAS.js} +16 -16
  4. package/{agentListCommands-WD5XYVGK.js → agentListCommands-YO4AOQMS.js} +8 -8
  5. package/{agentMachineCommands-OHZ3HKOV.js → agentMachineCommands-WYM6YRYJ.js} +6 -6
  6. package/{agentRecordCommands-N2JQMKS4.js → agentRecordCommands-BVWSHMIY.js} +16 -16
  7. package/{agentRunCommand-P2ECE6UJ.js → agentRunCommand-E3ZI6RSF.js} +16 -16
  8. package/{agentRunControl-P75VPTGS.js → agentRunControl-Y5AFH5PQ.js} +2 -2
  9. package/{agentRuntimeLocal-K2J7IS6O.js → agentRuntimeLocal-P4VGX6H6.js} +3 -3
  10. package/{agentSlice-OOLSXBHE.js → agentSlice-D33GU3JL.js} +1 -1
  11. package/{appDeleteCommands-X7YGULGZ.js → appDeleteCommands-VA4R2SWX.js} +7 -7
  12. package/{appDeployCommands-IMNPBUN7.js → appDeployCommands-JWMWQNG6.js} +7 -7
  13. package/{appDeployStatusCommands-2KFZUEET.js → appDeployStatusCommands-KYXGLZSQ.js} +7 -7
  14. package/{appGetCommands-AYG44S7G.js → appGetCommands-ELOO3JG6.js} +7 -7
  15. package/{appListCommands-Z7CLYPLH.js → appListCommands-SJUW4RLW.js} +7 -7
  16. package/{chunk-IOOMJJ4Z.js → chunk-34WPV75U.js} +21 -0
  17. package/{chunk-RYFZ55YC.js → chunk-5PGGCJGV.js} +3 -3
  18. package/{chunk-5ICZUVFN.js → chunk-AKVLLMOU.js} +3 -3
  19. package/{chunk-B26VDWID.js → chunk-BE2GNT5E.js} +1 -1
  20. package/{chunk-IRQJSVET.js → chunk-E5KQTMMJ.js} +39 -12
  21. package/{chunk-X3AHTP6B.js → chunk-ENP2ELIL.js} +2 -2
  22. package/{chunk-SQNQOXQ6.js → chunk-EXAEHRLI.js} +24 -33
  23. package/{chunk-FKXFCYVO.js → chunk-FQZZLA3C.js} +2 -0
  24. package/{chunk-JIDA7LBE.js → chunk-GMZZ5EKJ.js} +3 -3
  25. package/{chunk-BLQ3U7UK.js → chunk-HQNPCMWL.js} +1 -1
  26. package/{chunk-A7QNCVO5.js → chunk-IQZ6TGVW.js} +1 -1
  27. package/{chunk-2M54XJFV.js → chunk-J67FKTTY.js} +22 -20
  28. package/{chunk-CGSHUOC7.js → chunk-JFE7XW4D.js} +1 -1
  29. package/{chunk-XJITGCTM.js → chunk-JP7REMYP.js} +9 -0
  30. package/{chunk-KO4PXGVN.js → chunk-KKWJ5VPZ.js} +1 -1
  31. package/{chunk-OZPVJZBX.js → chunk-L2RRMXNJ.js} +11 -2
  32. package/{chunk-QSLNKTUG.js → chunk-MUIT5AAM.js} +84 -15
  33. package/{chunk-3PGT7DEK.js → chunk-N2HYIBLH.js} +2 -2
  34. package/{chunk-YEFSRF54.js → chunk-PUSK7HXJ.js} +25 -9
  35. package/{chunk-XYXJ4JRT.js → chunk-RIDWN7AP.js} +1 -1
  36. package/{chunk-JBWVSKBS.js → chunk-RUTSBLDM.js} +38 -9
  37. package/{chunk-BDSHV5HO.js → chunk-UIOYWBU7.js} +9 -13
  38. package/{chunk-TSIYZBTH.js → chunk-VNAEBGDK.js} +1 -1
  39. package/{chunk-XU6XCPWB.js → chunk-VST53WEL.js} +1 -1
  40. package/{chunk-QCJITMYO.js → chunk-VVKQFITN.js} +5 -2
  41. package/{chunk-OOKISU7J.js → chunk-XFYDGBXL.js} +1 -1
  42. package/{createAgentAutomationAction-EL5ORU35.js → createAgentAutomationAction-ONKZ46XE.js} +2 -2
  43. package/{createDialogAction-DKED4DHE.js → createDialogAction-7QWJEBKU.js} +3 -3
  44. package/{createPageAction-BYW4YP54.js → createPageAction-PB3KXZIA.js} +2 -2
  45. package/{dialogCommands-J7C6MB3Q.js → dialogCommands-YZFU4Q26.js} +7 -7
  46. package/{dialogSlice-RJCHTUIG.js → dialogSlice-53B5ISGQ.js} +2 -2
  47. package/{docCreateCommands-Y7OSXNB6.js → docCreateCommands-LOUC5PFB.js} +6 -6
  48. package/{docDeleteCommands-ALZGQRCE.js → docDeleteCommands-HHPGT4BR.js} +7 -7
  49. package/{docReadCommands-4BDDESGT.js → docReadCommands-YPSN4HEF.js} +6 -6
  50. package/{docStore-QWYVY7SV.js → docStore-LJXXRB5W.js} +3 -3
  51. package/{docUpdateCommands-LU2ZM2VE.js → docUpdateCommands-CJCZO54M.js} +6 -6
  52. package/{handleSendMessageAction-CUZL72WD.js → handleSendMessageAction-ICGX4QCM.js} +2 -2
  53. package/index.js +45 -45
  54. package/{machineCommands-QMODXRTA.js → machineCommands-YLDZXK4D.js} +15 -15
  55. package/{machineWsRunDispatch-UPWS4PZD.js → machineWsRunDispatch-LTQL3DRE.js} +15 -15
  56. package/package.json +1 -1
  57. package/{readlineWorkspace-ZDN3CREA.js → readlineWorkspace-OSPVWNAT.js} +493 -88
  58. package/{runAgentClientLoop-XKFPXIZC.js → runAgentClientLoop-76SUKKPX.js} +10 -10
  59. package/{spaceCommands-UG4QHSHD.js → spaceCommands-GIF7MKVD.js} +6 -6
  60. package/{spaceSlice-LR2XC33A.js → spaceSlice-M4PVN5PO.js} +2 -2
  61. package/{streamAgentChatTurn-5UOO7W6S.js → streamAgentChatTurn-GCKTFSHQ.js} +12 -12
  62. package/{tools-VHE5VME5.js → tools-RJVFXOLR.js} +7 -7
  63. package/{updateDialogTitleAction-OZZQ7SB2.js → updateDialogTitleAction-PSR67DLV.js} +2 -2
@@ -3,17 +3,17 @@ import {
3
3
  normalizeDialogRecord,
4
4
  readDialogSnapshot,
5
5
  sortDialogs
6
- } from "./chunk-BLQ3U7UK.js";
6
+ } from "./chunk-HQNPCMWL.js";
7
7
  import {
8
8
  listFavoriteAgentIdsAcrossServers,
9
9
  listLocalCachedAgents,
10
10
  listRemoteAgents,
11
11
  listRemoteAgentsAcrossServers
12
- } from "./chunk-5ICZUVFN.js";
12
+ } from "./chunk-AKVLLMOU.js";
13
13
  import "./chunk-ID4G2MAR.js";
14
14
  import {
15
15
  listUserRecordsFromServers
16
- } from "./chunk-XU6XCPWB.js";
16
+ } from "./chunk-VST53WEL.js";
17
17
  import {
18
18
  buildOverlayPresentation
19
19
  } from "./chunk-V5R4NZP2.js";
@@ -32,6 +32,7 @@ import {
32
32
  clearCollapsedPasteStore,
33
33
  countPhysicalLines,
34
34
  createCollapsedPasteStore,
35
+ detectSystemBrightnessFromEnv,
35
36
  dimCliText,
36
37
  displayWidth,
37
38
  expandRangeToCollapsedPasteChips,
@@ -69,7 +70,7 @@ import {
69
70
  visibleWidth,
70
71
  wrapTextToLines,
71
72
  wrapTranscriptLine
72
- } from "./chunk-IRQJSVET.js";
73
+ } from "./chunk-E5KQTMMJ.js";
73
74
  import "./chunk-DZ3XJVET.js";
74
75
  import {
75
76
  getReadableCliDb
@@ -78,17 +79,18 @@ import {
78
79
  deleteDbRecord,
79
80
  queryUserRecords,
80
81
  readDbRecord
81
- } from "./chunk-A7QNCVO5.js";
82
+ } from "./chunk-IQZ6TGVW.js";
82
83
  import {
83
84
  createCliLocalRuntimeAdapter,
84
85
  initCliLocale,
85
86
  isQuotaExhaustedError,
86
87
  parseCliLocale,
88
+ readTimestamp,
87
89
  setCliLocale,
88
90
  t
89
- } from "./chunk-JBWVSKBS.js";
91
+ } from "./chunk-RUTSBLDM.js";
90
92
  import "./chunk-UB4RYYNQ.js";
91
- import "./chunk-B26VDWID.js";
93
+ import "./chunk-BE2GNT5E.js";
92
94
  import {
93
95
  resolveCliAgentKeyInput
94
96
  } from "./chunk-VHBWHNVT.js";
@@ -98,18 +100,18 @@ import "./chunk-6HYVJV7B.js";
98
100
  import "./chunk-JEXVIMYZ.js";
99
101
  import {
100
102
  prepareTools
101
- } from "./chunk-OZPVJZBX.js";
103
+ } from "./chunk-L2RRMXNJ.js";
102
104
  import "./chunk-L6NVTGI7.js";
103
105
  import {
104
106
  expandEnabledPacks
105
- } from "./chunk-2M54XJFV.js";
107
+ } from "./chunk-J67FKTTY.js";
106
108
  import "./chunk-RQSOAMPJ.js";
107
- import "./chunk-XJITGCTM.js";
109
+ import "./chunk-JP7REMYP.js";
108
110
  import "./chunk-KQHGZWSV.js";
109
111
  import "./chunk-4T5F7YZQ.js";
110
112
  import "./chunk-3LY4F7SV.js";
111
113
  import "./chunk-VF4K2QE6.js";
112
- import "./chunk-3PGT7DEK.js";
114
+ import "./chunk-N2HYIBLH.js";
113
115
  import {
114
116
  initialRunOverlayState,
115
117
  reduceRunOverlay
@@ -120,16 +122,16 @@ import "./chunk-VP4WJWKW.js";
120
122
  import "./chunk-63W5N6P3.js";
121
123
  import "./chunk-WJRJDX2W.js";
122
124
  import "./chunk-LM6IYQ3F.js";
123
- import "./chunk-XYXJ4JRT.js";
125
+ import "./chunk-RIDWN7AP.js";
124
126
  import {
125
127
  extractReferenceKeysFromMessage
126
- } from "./chunk-BDSHV5HO.js";
128
+ } from "./chunk-UIOYWBU7.js";
127
129
  import {
128
130
  buildBuiltinSummaryContent
129
131
  } from "./chunk-XOIF2TNF.js";
130
132
  import "./chunk-B5TOXZAK.js";
131
133
  import "./chunk-MRC4Q34M.js";
132
- import "./chunk-RYFZ55YC.js";
134
+ import "./chunk-5PGGCJGV.js";
133
135
  import "./chunk-CWMSB67P.js";
134
136
  import "./chunk-XHG22OEX.js";
135
137
  import "./chunk-Z4NR32XR.js";
@@ -145,20 +147,20 @@ import {
145
147
  buildLocalWorkspaceOpenAiTools,
146
148
  buildLocalWorkspaceToolset,
147
149
  getProcessRegistry
148
- } from "./chunk-YEFSRF54.js";
150
+ } from "./chunk-PUSK7HXJ.js";
149
151
  import "./chunk-ZNFJWEN4.js";
150
152
  import "./chunk-AAODAAUQ.js";
151
153
  import "./chunk-OIQPORYI.js";
152
154
  import {
153
155
  readCommandActionGatePayload,
154
156
  resolveAgentImageInputSupport
155
- } from "./chunk-QCJITMYO.js";
157
+ } from "./chunk-VVKQFITN.js";
156
158
  import "./chunk-LSFAWXKC.js";
157
159
  import {
158
160
  buildCurrentTimeBlock,
159
161
  buildIdentityBlock,
160
162
  buildRuntimeGuidanceBlocks
161
- } from "./chunk-IOOMJJ4Z.js";
163
+ } from "./chunk-34WPV75U.js";
162
164
  import "./chunk-KFEVY3ST.js";
163
165
  import {
164
166
  resolvePlatformAuthToken
@@ -196,15 +198,21 @@ import {
196
198
  compactWhitespace
197
199
  } from "./chunk-DWLEOOGR.js";
198
200
  import {
199
- queryRunRecords
200
- } from "./chunk-TSIYZBTH.js";
201
+ checkStaleRun,
202
+ queryRunRecords,
203
+ readRunRecord
204
+ } from "./chunk-VNAEBGDK.js";
201
205
  import {
206
+ clipText,
207
+ formatDuration,
202
208
  formatRunAge,
203
209
  getAgentRunStatusIcon,
210
+ isAgentNameFallback,
204
211
  isAgentRunTerminalStatus,
212
+ resolveRunLabel,
205
213
  runShowsLogTail,
206
214
  shortRunId
207
- } from "./chunk-FKXFCYVO.js";
215
+ } from "./chunk-FQZZLA3C.js";
208
216
  import "./chunk-X7W4TNB4.js";
209
217
  import "./chunk-ATNTHIZI.js";
210
218
  import "./chunk-JBTJAPUF.js";
@@ -1667,6 +1675,274 @@ function createDialogHost(args) {
1667
1675
  };
1668
1676
  }
1669
1677
 
1678
+ // packages/cli/tui/runSnapshotDisplay.ts
1679
+ function runStatusTone(status) {
1680
+ if (!isAgentRunTerminalStatus(status)) return "warning";
1681
+ return status === "done" ? "success" : "danger";
1682
+ }
1683
+ function formatInFlightFact(inFlight, now, maxNameLength = 20) {
1684
+ const label = inFlight.kind === "llm" ? "thinking" : clipText(inFlight.name, maxNameLength);
1685
+ return `${label} ${formatDuration(Math.max(0, now - inFlight.startedAt))}`;
1686
+ }
1687
+ function activeInFlight(snapshot) {
1688
+ if (isAgentRunTerminalStatus(snapshot.status)) return null;
1689
+ return snapshot.inFlight ?? null;
1690
+ }
1691
+
1692
+ // packages/cli/tui/agentRunPanelLines.ts
1693
+ function formatPanelProgress(snapshot, now) {
1694
+ const parts = [];
1695
+ if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1696
+ parts.push(`${snapshot.toolCallCount} tools`);
1697
+ }
1698
+ const inFlight = activeInFlight(snapshot);
1699
+ if (inFlight) {
1700
+ parts.push(formatInFlightFact(inFlight, now));
1701
+ } else if (snapshot.lastToolNames && snapshot.lastToolNames.length > 0) {
1702
+ parts.push(snapshot.lastToolNames.join(", "));
1703
+ }
1704
+ return parts.length > 0 ? ` \xB7 ${parts.join(" \xB7 ")}` : "";
1705
+ }
1706
+ function formatPanelDetail(snapshot) {
1707
+ const note = snapshot.lastAssistantText?.trim();
1708
+ if (note) return note;
1709
+ if (!runShowsLogTail(snapshot.status)) return "";
1710
+ const lines = snapshot.logLines;
1711
+ if (!lines || lines.length === 0) return "";
1712
+ return lines[lines.length - 1]?.trim() ?? "";
1713
+ }
1714
+ function formatAgentRunPanelLines(snapshot, colorEnabled, now = Date.now()) {
1715
+ const lines = [];
1716
+ const name = snapshot.agentName || "sub-agent";
1717
+ const short = shortRunId(snapshot.runId);
1718
+ const runId = short ? ` (${short})` : "";
1719
+ const status = snapshot.status || "running";
1720
+ const statusSymbol = getAgentRunStatusIcon(status);
1721
+ const statusColor = runStatusTone(status);
1722
+ const errPart = snapshot.errorMessage ? ` \xB7 ${snapshot.errorMessage}` : "";
1723
+ const progressPart = formatPanelProgress(snapshot, now);
1724
+ const age = formatRunAge(snapshot, now);
1725
+ const agePart = age ? ` \xB7 ${age}` : "";
1726
+ if (!colorEnabled) {
1727
+ lines.push(
1728
+ `\u{1F916} Sub-Agent: ${name}${runId} \xB7 ${statusSymbol} ${status}${agePart}${progressPart}${errPart}`
1729
+ );
1730
+ } else {
1731
+ const botIcon = themeText("\u{1F916}", "accent", true);
1732
+ const labelText = themeText(" Sub-Agent: ", "muted", true);
1733
+ const nameText = themeText(`${name}${runId}`, "chrome", true);
1734
+ const statusText = themeText(` \xB7 ${statusSymbol} ${status}`, statusColor, true);
1735
+ const ageText = agePart ? themeText(agePart, "chrome") : "";
1736
+ const progressText = progressPart ? themeText(progressPart, "chrome") : "";
1737
+ const errorText = errPart ? themeText(errPart, "danger") : "";
1738
+ lines.push(`${botIcon}${labelText}${nameText}${statusText}${ageText}${progressText}${errorText}`);
1739
+ }
1740
+ const detail = formatPanelDetail(snapshot);
1741
+ if (detail) {
1742
+ if (!colorEnabled) {
1743
+ lines.push(` \u2514 ${detail}`);
1744
+ } else {
1745
+ lines.push(`${themeText(" \u2514 ", "muted")}${themeText(detail, "chrome")}`);
1746
+ }
1747
+ }
1748
+ return lines;
1749
+ }
1750
+
1751
+ // packages/cli/tui/runDock.ts
1752
+ var RUN_DOCK_TICK_INTERVAL_MS = 1e3;
1753
+ var RUN_DOCK_LINGER_MS = 8e3;
1754
+ var RUN_DOCK_STALE_MS = 5 * 6e4;
1755
+ var RUN_DOCK_MAX_ROWS = 3;
1756
+ var RETIRED_MEMORY = 64;
1757
+ function mergeSnapshot(prev, next) {
1758
+ const merged = { ...prev, ...next };
1759
+ if (merged.errorMessage && next.errorMessage === void 0 && !isAgentRunTerminalStatus(merged.status)) {
1760
+ delete merged.errorMessage;
1761
+ }
1762
+ if (next.inFlight === void 0) {
1763
+ if (prev.inFlight !== void 0) merged.inFlight = prev.inFlight;
1764
+ }
1765
+ return merged;
1766
+ }
1767
+ function createRunDock(deps) {
1768
+ const now = deps.now ?? (() => Date.now());
1769
+ const tickIntervalMs = deps.tickIntervalMs ?? RUN_DOCK_TICK_INTERVAL_MS;
1770
+ const lingerMs = deps.lingerMs ?? RUN_DOCK_LINGER_MS;
1771
+ const staleMs = deps.staleMs ?? RUN_DOCK_STALE_MS;
1772
+ const maxRows = deps.maxRows ?? RUN_DOCK_MAX_ROWS;
1773
+ const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
1774
+ const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
1775
+ const entries = /* @__PURE__ */ new Map();
1776
+ const retired = /* @__PURE__ */ new Set();
1777
+ let seqCounter = 0;
1778
+ let timer = null;
1779
+ let disposed = false;
1780
+ const stopTimer = () => {
1781
+ if (timer !== null) {
1782
+ clearIntervalFn(timer);
1783
+ timer = null;
1784
+ }
1785
+ };
1786
+ const prune = () => {
1787
+ const at = now();
1788
+ let changed = false;
1789
+ for (const [runId, entry] of entries) {
1790
+ const expiredTerminal = entry.terminalAt !== null && at - entry.terminalAt >= lingerMs;
1791
+ const stale = at - entry.updatedAt >= staleMs;
1792
+ if (!expiredTerminal && !stale) continue;
1793
+ entries.delete(runId);
1794
+ changed = true;
1795
+ if (expiredTerminal) {
1796
+ retired.add(runId);
1797
+ if (retired.size > RETIRED_MEMORY) {
1798
+ const oldest = retired.values().next().value;
1799
+ if (oldest !== void 0) retired.delete(oldest);
1800
+ }
1801
+ }
1802
+ }
1803
+ if (entries.size === 0) stopTimer();
1804
+ return changed;
1805
+ };
1806
+ const tick = () => {
1807
+ prune();
1808
+ deps.onRepaint();
1809
+ };
1810
+ const ensureTimer = () => {
1811
+ if (timer === null && entries.size > 0) {
1812
+ timer = setIntervalFn(tick, tickIntervalMs);
1813
+ }
1814
+ };
1815
+ const update = (snapshot) => {
1816
+ if (disposed) return;
1817
+ const runId = snapshot.runId;
1818
+ if (!runId) return;
1819
+ if (snapshot.status === "not_found") {
1820
+ remove(runId);
1821
+ return;
1822
+ }
1823
+ if (retired.has(runId)) return;
1824
+ const at = now();
1825
+ const prev = entries.get(runId);
1826
+ const merged = prev ? mergeSnapshot(prev.snapshot, snapshot) : snapshot;
1827
+ const terminal = isAgentRunTerminalStatus(merged.status);
1828
+ entries.set(runId, {
1829
+ snapshot: merged,
1830
+ seq: prev ? prev.seq : seqCounter++,
1831
+ updatedAt: at,
1832
+ // terminalAt 只在首次进入终态时记一次:终态 run 后续还会被轮询到,
1833
+ // 每次都刷新的话 linger 永远走不完,面板会一直挂着已完成的 run。
1834
+ terminalAt: terminal ? prev?.terminalAt ?? at : null
1835
+ });
1836
+ ensureTimer();
1837
+ deps.onRepaint();
1838
+ };
1839
+ const remove = (runId) => {
1840
+ if (!entries.delete(runId)) return;
1841
+ if (entries.size === 0) stopTimer();
1842
+ deps.onRepaint();
1843
+ };
1844
+ const clear = () => {
1845
+ if (entries.size === 0) return;
1846
+ entries.clear();
1847
+ stopTimer();
1848
+ deps.onRepaint();
1849
+ };
1850
+ const orderedEntries = () => [...entries.values()].sort((a, b) => {
1851
+ const aTerminal = a.terminalAt !== null ? 1 : 0;
1852
+ const bTerminal = b.terminalAt !== null ? 1 : 0;
1853
+ if (aTerminal !== bTerminal) return aTerminal - bTerminal;
1854
+ return a.seq - b.seq;
1855
+ });
1856
+ const getRuns = () => orderedEntries().map((entry) => entry.snapshot);
1857
+ const getLines = (colorEnabled) => {
1858
+ prune();
1859
+ const ordered = orderedEntries();
1860
+ if (ordered.length === 0) return [];
1861
+ const at = now();
1862
+ if (ordered.length === 1) {
1863
+ return formatAgentRunPanelLines(ordered[0].snapshot, colorEnabled, at);
1864
+ }
1865
+ return formatRunDockLines(
1866
+ ordered.map((entry) => entry.snapshot),
1867
+ colorEnabled,
1868
+ at,
1869
+ maxRows
1870
+ );
1871
+ };
1872
+ return {
1873
+ update,
1874
+ remove,
1875
+ clear,
1876
+ getRuns,
1877
+ getLines,
1878
+ dispose() {
1879
+ disposed = true;
1880
+ entries.clear();
1881
+ retired.clear();
1882
+ stopTimer();
1883
+ }
1884
+ };
1885
+ }
1886
+ function summarize(snapshots) {
1887
+ let running = 0;
1888
+ const terminal = /* @__PURE__ */ new Map();
1889
+ for (const snapshot of snapshots) {
1890
+ if (!isAgentRunTerminalStatus(snapshot.status)) {
1891
+ running += 1;
1892
+ continue;
1893
+ }
1894
+ terminal.set(snapshot.status, (terminal.get(snapshot.status) ?? 0) + 1);
1895
+ }
1896
+ const parts = [];
1897
+ if (running > 0) parts.push(`${running} running`);
1898
+ for (const [status, count] of terminal) parts.push(`${count} ${status}`);
1899
+ return parts.join(" \xB7 ");
1900
+ }
1901
+ function formatRunDockLines(snapshots, colorEnabled, now = Date.now(), maxRows = RUN_DOCK_MAX_ROWS) {
1902
+ if (snapshots.length === 0) return [];
1903
+ const lines = [];
1904
+ const summary = summarize(snapshots);
1905
+ const header = `\u{1F916} runs \xB7 ${summary}`;
1906
+ lines.push(colorEnabled ? themeText(header, "muted", true) : header);
1907
+ const shown = snapshots.slice(0, Math.max(1, maxRows));
1908
+ for (const snapshot of shown) {
1909
+ lines.push(formatRunDockRow(snapshot, colorEnabled, now));
1910
+ }
1911
+ const hidden = snapshots.length - shown.length;
1912
+ if (hidden > 0) {
1913
+ const more = ` +${hidden} more`;
1914
+ lines.push(colorEnabled ? themeText(more, "chrome") : more);
1915
+ }
1916
+ return lines;
1917
+ }
1918
+ function formatRunDockRow(snapshot, colorEnabled, now) {
1919
+ const name = snapshot.agentName || "sub-agent";
1920
+ const short = shortRunId(snapshot.runId);
1921
+ const icon = getAgentRunStatusIcon(snapshot.status);
1922
+ const terminal = isAgentRunTerminalStatus(snapshot.status);
1923
+ const statusColor = runStatusTone(snapshot.status);
1924
+ const facts = [];
1925
+ const age = formatRunAge(snapshot, now);
1926
+ if (terminal) facts.push(age ? `${snapshot.status} ${age}` : snapshot.status);
1927
+ else if (age) facts.push(age);
1928
+ if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1929
+ facts.push(`${snapshot.toolCallCount} tools`);
1930
+ }
1931
+ const inFlight = activeInFlight(snapshot);
1932
+ if (inFlight) {
1933
+ facts.push(formatInFlightFact(inFlight, now));
1934
+ } else {
1935
+ const lastTool = snapshot.lastToolNames?.[snapshot.lastToolNames.length - 1];
1936
+ if (lastTool) facts.push(clipText(lastTool, 20));
1937
+ }
1938
+ if (snapshot.errorMessage) facts.push(clipText(snapshot.errorMessage, 40));
1939
+ const label = `${name}${short ? ` #${short}` : ""}`;
1940
+ const factsPart = facts.length > 0 ? ` \xB7 ${facts.join(" \xB7 ")}` : "";
1941
+ if (!colorEnabled) return ` ${icon} ${label}${factsPart}`;
1942
+ const errorTail = snapshot.errorMessage;
1943
+ return themeText(" ", "chrome") + themeText(icon, statusColor, true) + " " + themeText(label, "chrome", true) + themeText(factsPart, errorTail ? "danger" : "chrome");
1944
+ }
1945
+
1670
1946
  // packages/cli/tui/activityIndicator.ts
1671
1947
  var ACTIVITY_FRAMES = ["\xB7", "~", "\u2248", "\u223F", "\u2248", "~"];
1672
1948
  var ACTIVITY_FRAME_INTERVAL_MS = 150;
@@ -1750,16 +2026,19 @@ function createActivityIndicator(deps) {
1750
2026
  }
1751
2027
  return null;
1752
2028
  };
1753
- let agentRunSnapshot = null;
2029
+ const runDock = deps.runDock ?? createRunDock({
2030
+ onRepaint: deps.onRepaint,
2031
+ now,
2032
+ setIntervalFn,
2033
+ clearIntervalFn
2034
+ });
1754
2035
  const updateAgentRun = (snapshot) => {
1755
- agentRunSnapshot = snapshot;
1756
- deps.onRepaint();
2036
+ runDock.update(snapshot);
1757
2037
  };
1758
2038
  const clearAgentRun = () => {
1759
- agentRunSnapshot = null;
1760
- deps.onRepaint();
2039
+ runDock.clear();
1761
2040
  };
1762
- const getAgentRun = () => agentRunSnapshot;
2041
+ const getAgentRuns = () => runDock.getRuns();
1763
2042
  const getActivityLines = (colorEnabled = resolveCliColorEnabled()) => {
1764
2043
  const lines = [];
1765
2044
  const baseView = getView();
@@ -1775,9 +2054,7 @@ function createActivityIndicator(deps) {
1775
2054
  );
1776
2055
  }
1777
2056
  }
1778
- if (agentRunSnapshot) {
1779
- lines.push(...formatAgentRunPanelLines(agentRunSnapshot, colorEnabled, now()));
1780
- }
2057
+ lines.push(...runDock.getLines(colorEnabled));
1781
2058
  return lines.length > 0 ? lines : null;
1782
2059
  };
1783
2060
  const stop = () => {
@@ -1791,73 +2068,134 @@ function createActivityIndicator(deps) {
1791
2068
  fallbackStartedAt = 0;
1792
2069
  lastActivityAt = 0;
1793
2070
  stopping = false;
1794
- agentRunSnapshot = null;
1795
2071
  };
1796
2072
  return {
1797
2073
  report,
1798
2074
  updateAgentRun,
1799
2075
  clearAgentRun,
1800
- getAgentRun,
2076
+ getAgentRuns,
1801
2077
  getView,
1802
2078
  getActivityLines,
1803
2079
  markStopping,
1804
2080
  isStopping,
1805
- stop
2081
+ stop,
2082
+ dispose() {
2083
+ stop();
2084
+ runDock.dispose();
2085
+ }
1806
2086
  };
1807
2087
  }
1808
- function formatPanelProgress(snapshot) {
1809
- const parts = [];
1810
- if (typeof snapshot.toolCallCount === "number" && Number.isFinite(snapshot.toolCallCount)) {
1811
- parts.push(`${snapshot.toolCallCount} tools`);
1812
- }
1813
- if (snapshot.lastToolNames && snapshot.lastToolNames.length > 0) {
1814
- parts.push(snapshot.lastToolNames.join(", "));
2088
+
2089
+ // packages/cli/tui/runRegistryPoller.ts
2090
+ var RUN_POLL_INTERVAL_MS = 1e3;
2091
+ var RUN_RECONCILE_SILENCE_MS = 15e3;
2092
+ function snapshotFromRunRecord(record, now) {
2093
+ const label = resolveRunLabel(record);
2094
+ const startedAt = readTimestamp(record.startedAt);
2095
+ const endedAt = readTimestamp(record.endedAt);
2096
+ const activity = record.activity;
2097
+ const counters = activity?.counters;
2098
+ let inFlight = null;
2099
+ const raw = activity?.inFlight;
2100
+ if (raw && !isAgentRunTerminalStatus(record.status)) {
2101
+ const updatedAt = activity?.updatedAt ? Date.parse(activity.updatedAt) : NaN;
2102
+ const base = Number.isFinite(updatedAt) ? updatedAt : now;
2103
+ const startedFrom = base - (Number.isFinite(raw.sinceMs) ? raw.sinceMs : 0);
2104
+ const usable = Number.isFinite(startedFrom) && startedFrom > 0 ? Math.min(startedFrom, now) : now;
2105
+ inFlight = { kind: raw.kind, name: raw.name, startedAt: usable };
1815
2106
  }
1816
- return parts.length > 0 ? ` \xB7 ${parts.join(" \xB7 ")}` : "";
2107
+ return {
2108
+ runId: record.runId,
2109
+ status: record.status,
2110
+ ...isAgentNameFallback(label) ? {} : { agentName: label },
2111
+ ...startedAt !== void 0 ? { startedAt } : {},
2112
+ ...endedAt !== void 0 ? { finishedAt: endedAt } : {},
2113
+ ...typeof counters?.toolCalls === "number" ? { toolCallCount: counters.toolCalls } : {},
2114
+ // note 在终态时是死因("orphaned: process gone…"),非终态时只是备注。
2115
+ ...record.note && isAgentRunTerminalStatus(record.status) ? { errorMessage: record.note } : {},
2116
+ inFlight,
2117
+ logKey: ""
2118
+ };
1817
2119
  }
1818
- function formatPanelDetail(snapshot) {
1819
- const note = snapshot.lastAssistantText?.trim();
1820
- if (note) return note;
1821
- if (!runShowsLogTail(snapshot.status)) return "";
1822
- const lines = snapshot.logLines;
1823
- if (!lines || lines.length === 0) return "";
1824
- return lines[lines.length - 1]?.trim() ?? "";
2120
+ function fingerprint(snapshot) {
2121
+ return JSON.stringify([
2122
+ snapshot.status,
2123
+ snapshot.agentName ?? "",
2124
+ snapshot.toolCallCount ?? -1,
2125
+ snapshot.errorMessage ?? "",
2126
+ snapshot.finishedAt ?? 0,
2127
+ snapshot.inFlight ? [snapshot.inFlight.kind, snapshot.inFlight.name, snapshot.inFlight.startedAt] : null
2128
+ ]);
1825
2129
  }
1826
- function formatAgentRunPanelLines(snapshot, colorEnabled, now = Date.now()) {
1827
- const lines = [];
1828
- const name = snapshot.agentName || "sub-agent";
1829
- const short = shortRunId(snapshot.runId);
1830
- const runId = short ? ` (${short})` : "";
1831
- const status = snapshot.status || "running";
1832
- const statusSymbol = getAgentRunStatusIcon(status);
1833
- const statusColor = !isAgentRunTerminalStatus(status) ? "warning" : status === "done" ? "success" : "danger";
1834
- const errPart = snapshot.errorMessage ? ` \xB7 ${snapshot.errorMessage}` : "";
1835
- const progressPart = formatPanelProgress(snapshot);
1836
- const age = formatRunAge(snapshot, now);
1837
- const agePart = age ? ` \xB7 ${age}` : "";
1838
- if (!colorEnabled) {
1839
- lines.push(
1840
- `\u{1F916} Sub-Agent: ${name}${runId} \xB7 ${statusSymbol} ${status}${agePart}${progressPart}${errPart}`
2130
+ function createRunRegistryPoller(deps) {
2131
+ const now = deps.now ?? (() => Date.now());
2132
+ const intervalMs = deps.intervalMs ?? RUN_POLL_INTERVAL_MS;
2133
+ const reconcileSilenceMs = deps.reconcileSilenceMs ?? RUN_RECONCILE_SILENCE_MS;
2134
+ const setIntervalFn = deps.setIntervalFn ?? ((cb, ms) => setInterval(cb, ms));
2135
+ const clearIntervalFn = deps.clearIntervalFn ?? ((handle) => clearInterval(handle));
2136
+ let timer = null;
2137
+ let disposed = false;
2138
+ const lastEmitted = /* @__PURE__ */ new Map();
2139
+ const lastReconciledAt = /* @__PURE__ */ new Map();
2140
+ const stop = () => {
2141
+ if (timer !== null) {
2142
+ clearIntervalFn(timer);
2143
+ timer = null;
2144
+ }
2145
+ lastEmitted.clear();
2146
+ lastReconciledAt.clear();
2147
+ };
2148
+ const freshnessOf = (record) => {
2149
+ return readTimestamp(record.activity?.updatedAt) ?? readTimestamp(record.startedAt) ?? 0;
2150
+ };
2151
+ const poll = () => {
2152
+ const at = now();
2153
+ const active = deps.getDockedRuns().filter(
2154
+ (run) => run.runId && !isAgentRunTerminalStatus(run.status)
1841
2155
  );
1842
- } else {
1843
- const botIcon = themeText("\u{1F916}", "accent", true);
1844
- const labelText = themeText(" Sub-Agent: ", "muted", true);
1845
- const nameText = themeText(`${name}${runId}`, "chrome", true);
1846
- const statusText = themeText(` \xB7 ${statusSymbol} ${status}`, statusColor, true);
1847
- const ageText = agePart ? themeText(agePart, "chrome") : "";
1848
- const progressText = progressPart ? themeText(progressPart, "chrome") : "";
1849
- const errorText = errPart ? themeText(errPart, "danger") : "";
1850
- lines.push(`${botIcon}${labelText}${nameText}${statusText}${ageText}${progressText}${errorText}`);
1851
- }
1852
- const detail = formatPanelDetail(snapshot);
1853
- if (detail) {
1854
- if (!colorEnabled) {
1855
- lines.push(` \u2514 ${detail}`);
1856
- } else {
1857
- lines.push(`${themeText(" \u2514 ", "muted")}${themeText(detail, "chrome")}`);
2156
+ if (active.length === 0) {
2157
+ stop();
2158
+ return;
1858
2159
  }
1859
- }
1860
- return lines;
2160
+ const alive = /* @__PURE__ */ new Set();
2161
+ for (const run of active) {
2162
+ alive.add(run.runId);
2163
+ let record;
2164
+ try {
2165
+ record = deps.readRecord(run.runId);
2166
+ if (deps.reconcile && record && !isAgentRunTerminalStatus(record.status) && at - freshnessOf(record) >= reconcileSilenceMs && at - (lastReconciledAt.get(run.runId) ?? 0) >= reconcileSilenceMs) {
2167
+ lastReconciledAt.set(run.runId, at);
2168
+ record = deps.reconcile(run.runId) ?? record;
2169
+ }
2170
+ } catch {
2171
+ continue;
2172
+ }
2173
+ if (!record) continue;
2174
+ const snapshot = snapshotFromRunRecord(record, at);
2175
+ const mark = fingerprint(snapshot);
2176
+ if (lastEmitted.get(run.runId) === mark) continue;
2177
+ lastEmitted.set(run.runId, mark);
2178
+ deps.update(snapshot);
2179
+ }
2180
+ for (const runId of [...lastEmitted.keys()]) {
2181
+ if (!alive.has(runId)) lastEmitted.delete(runId);
2182
+ }
2183
+ for (const runId of [...lastReconciledAt.keys()]) {
2184
+ if (!alive.has(runId)) lastReconciledAt.delete(runId);
2185
+ }
2186
+ };
2187
+ return {
2188
+ ensureRunning() {
2189
+ if (disposed || timer !== null) return;
2190
+ timer = setIntervalFn(poll, intervalMs);
2191
+ },
2192
+ poll,
2193
+ stop,
2194
+ dispose() {
2195
+ disposed = true;
2196
+ stop();
2197
+ }
2198
+ };
1861
2199
  }
1862
2200
 
1863
2201
  // packages/ai/agent/utils/sortUtils.ts
@@ -3388,7 +3726,7 @@ function handleTuiInput(input, state) {
3388
3726
  }
3389
3727
  if (argText === "all") {
3390
3728
  const before = registry.list().filter((p) => p.status === "running").length;
3391
- registry.stopAll();
3729
+ registry.stopAll(void 0, { includePersist: true });
3392
3730
  return { nextState: state, output: t("stopAllDone", String(before)) };
3393
3731
  }
3394
3732
  if (/^\d+$/.test(argText)) {
@@ -3663,6 +4001,7 @@ function handleTuiInput(input, state) {
3663
4001
  }
3664
4002
 
3665
4003
  // packages/cli/tui/detectBackground.ts
4004
+ import { execFileSync } from "node:child_process";
3666
4005
  import { ReadStream } from "node:tty";
3667
4006
  var OSC11_QUERY = "\x1B]11;?\x07";
3668
4007
  var OSC11_REPLY_RE = /\x1b\]11;rgb:([0-9a-f]+)\/([0-9a-f]+)\/([0-9a-f]+)/i;
@@ -3691,7 +4030,7 @@ function parseOsc11Background(reply) {
3691
4030
  function isTerminalDevice(stream) {
3692
4031
  return stream instanceof ReadStream;
3693
4032
  }
3694
- async function detectTerminalBackground(args = {}) {
4033
+ async function probeTerminalBackground(args = {}) {
3695
4034
  const stdin = args.stdin ?? process.stdin;
3696
4035
  const stdout = args.stdout ?? process.stdout;
3697
4036
  const timeoutMs = args.timeoutMs ?? 100;
@@ -3734,6 +4073,48 @@ async function detectTerminalBackground(args = {}) {
3734
4073
  timer = setTimeout(() => finish(null), timeoutMs);
3735
4074
  });
3736
4075
  }
4076
+ async function detectTerminalBackground(args = {}) {
4077
+ const r = await probeTerminalBackground(args);
4078
+ if (r || !args.allowSystemFallback) return r;
4079
+ const brightness = detectSystemBrightness(process.env, { allowSubprocess: true });
4080
+ return brightness ? { brightness, hex: "" } : null;
4081
+ }
4082
+ function detectSystemBrightness(env = process.env, options = {}) {
4083
+ const envResult = detectSystemBrightnessFromEnv(env);
4084
+ if (envResult) return envResult;
4085
+ const allowSubprocess = options.allowSubprocess ?? false;
4086
+ if (!allowSubprocess) {
4087
+ return null;
4088
+ }
4089
+ if (process.platform === "darwin") {
4090
+ try {
4091
+ const out = execFileSync("defaults", ["read", "-g", "AppleInterfaceStyle"], {
4092
+ encoding: "utf8",
4093
+ stdio: ["ignore", "pipe", "ignore"],
4094
+ timeout: 200
4095
+ }).trim();
4096
+ if (out.toLowerCase() === "dark") return "dark";
4097
+ } catch {
4098
+ }
4099
+ } else if (process.platform === "linux") {
4100
+ try {
4101
+ const out = execFileSync(
4102
+ "gsettings",
4103
+ ["get", "org.gnome.desktop.interface", "color-scheme"],
4104
+ {
4105
+ encoding: "utf8",
4106
+ stdio: ["ignore", "pipe", "ignore"],
4107
+ timeout: 200
4108
+ }
4109
+ ).trim();
4110
+ const val = out.toLowerCase();
4111
+ if (/(?:^|[\s\-_:])dark(?:$|[\s\-_:])/i.test(val)) return "dark";
4112
+ if (/(?:^|[\s\-_:])light(?:$|[\s\-_:])/i.test(val)) return "light";
4113
+ } catch {
4114
+ }
4115
+ }
4116
+ return null;
4117
+ }
3737
4118
 
3738
4119
  // packages/core/chat/chatQueueMachine.ts
3739
4120
  var initialChatQueueState = {
@@ -4845,7 +5226,7 @@ function toOverlayStatus(status) {
4845
5226
  return "running";
4846
5227
  }
4847
5228
  }
4848
- function buildTuiRunOverlay(parentDialogId) {
5229
+ function buildTuiRunOverlay(parentDialogId, reported) {
4849
5230
  if (!parentDialogId) return null;
4850
5231
  let runs;
4851
5232
  try {
@@ -4854,6 +5235,11 @@ function buildTuiRunOverlay(parentDialogId) {
4854
5235
  return null;
4855
5236
  }
4856
5237
  if (runs.length === 0) return null;
5238
+ if (reported) {
5239
+ runs = runs.filter((run) => reported.get(run.runId) !== run.status);
5240
+ for (const run of runs) reported.set(run.runId, run.status);
5241
+ if (runs.length === 0) return null;
5242
+ }
4857
5243
  let overlay = initialRunOverlayState;
4858
5244
  for (const run of runs) {
4859
5245
  overlay = reduceRunOverlay(overlay, {
@@ -5263,7 +5649,8 @@ async function startTuiWorkspace(options) {
5263
5649
  }
5264
5650
  const detected = await detectTerminalBackground({
5265
5651
  stdin: input,
5266
- stdout: output
5652
+ stdout: output,
5653
+ allowSystemFallback: true
5267
5654
  });
5268
5655
  if (detected) {
5269
5656
  setActiveBrightness(detected.brightness);
@@ -5296,6 +5683,13 @@ async function startTuiWorkspace(options) {
5296
5683
  }
5297
5684
  });
5298
5685
  const activityReporter = (label) => activityIndicator.report(label);
5686
+ const reportedRunStatuses = /* @__PURE__ */ new Map();
5687
+ const runRegistryPoller = createRunRegistryPoller({
5688
+ getDockedRuns: () => activityIndicator.getAgentRuns(),
5689
+ update: (snapshot) => activityIndicator.updateAgentRun(snapshot),
5690
+ readRecord: (runId) => readRunRecord(runId),
5691
+ reconcile: (runId) => checkStaleRun(runId)
5692
+ });
5299
5693
  let explicitAgentSwitch = false;
5300
5694
  let copyViewExitResolver = null;
5301
5695
  let copyViewRender = null;
@@ -5429,7 +5823,8 @@ async function startTuiWorkspace(options) {
5429
5823
  if (!isInteractiveInput(input)) return;
5430
5824
  const detected2 = await detectTerminalBackground({
5431
5825
  stdin: input,
5432
- stdout: output
5826
+ stdout: output,
5827
+ allowSystemFallback: true
5433
5828
  });
5434
5829
  if (sessionEnded) return;
5435
5830
  if (!detected2) {
@@ -5510,6 +5905,7 @@ async function startTuiWorkspace(options) {
5510
5905
  onAgentRunStatus: (snapshot) => {
5511
5906
  if (snapshot) {
5512
5907
  activityIndicator.updateAgentRun(snapshot);
5908
+ runRegistryPoller.ensureRunning();
5513
5909
  } else {
5514
5910
  activityIndicator.clearAgentRun();
5515
5911
  }
@@ -5577,7 +5973,7 @@ async function startTuiWorkspace(options) {
5577
5973
  }
5578
5974
  }
5579
5975
  if (!wasAborted) {
5580
- const overlayText = buildTuiRunOverlay(turnParentDialogId);
5976
+ const overlayText = buildTuiRunOverlay(turnParentDialogId, reportedRunStatuses);
5581
5977
  if (overlayText) {
5582
5978
  emitCommandOutput(`
5583
5979
  \u4F60\u7684 run \u8FDB\u5C55\uFF1A
@@ -5734,7 +6130,8 @@ ${overlayText}`);
5734
6130
  if (result.action?.type === "theme-refresh") {
5735
6131
  const detected2 = await detectTerminalBackground({
5736
6132
  stdin: input,
5737
- stdout: output
6133
+ stdout: output,
6134
+ allowSystemFallback: true
5738
6135
  });
5739
6136
  if (detected2 && applyDetectedBackground(detected2)) {
5740
6137
  emitCommandOutput(t("themeRefreshed", detected2.brightness));
@@ -6062,6 +6459,8 @@ ${err.message}` : ""}`
6062
6459
  clearInterval(autoThemeTimer);
6063
6460
  autoThemeTimer = null;
6064
6461
  }
6462
+ runRegistryPoller.dispose();
6463
+ activityIndicator.dispose();
6065
6464
  resolveDone?.();
6066
6465
  clearCollapsedPasteStore(pasteStore);
6067
6466
  resizeTarget.off?.("resize", onResize);
@@ -6440,7 +6839,13 @@ ${renderStatusLine(state)}
6440
6839
  rl.prompt();
6441
6840
  }
6442
6841
  } finally {
6443
- getProcessRegistry().stopAll();
6842
+ const registry = getProcessRegistry();
6843
+ const persistentCount = registry.list().filter((p) => p.persist && p.status === "running").length;
6844
+ registry.stopAll();
6845
+ if (persistentCount > 0) {
6846
+ output.write(`[nolo] ${t("persistentProcessesLeft", String(persistentCount))}
6847
+ `);
6848
+ }
6444
6849
  rl.close();
6445
6850
  }
6446
6851
  }