@atlasharness/atlascode 0.1.38 → 0.1.39

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 (2) hide show
  1. package/dist/cli.js +395 -89
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -135054,10 +135054,13 @@ function applyColor(text, color) {
135054
135054
  }
135055
135055
  return colorize(text, color, "foreground");
135056
135056
  }
135057
- var CHALK_BOOSTED_FOR_XTERMJS, CHALK_CLAMPED_FOR_TMUX, RGB_REGEX, ANSI_REGEX, colorize = (str, color, type) => {
135057
+ var CHALK_BOOSTED_FOR_XTERMJS, CHALK_CLAMPED_FOR_TMUX, RGB_REGEX, ANSI_REGEX, BARE_ANSI_COLOR_NAMES, colorize = (str, color, type) => {
135058
135058
  if (!color) {
135059
135059
  return str;
135060
135060
  }
135061
+ if (BARE_ANSI_COLOR_NAMES.has(color)) {
135062
+ return colorize(str, `ansi:${color}`, type);
135063
+ }
135061
135064
  if (color.startsWith("ansi:")) {
135062
135065
  const value = color.substring("ansi:".length);
135063
135066
  switch (value) {
@@ -135124,6 +135127,24 @@ var init_colorize = __esm(() => {
135124
135127
  CHALK_CLAMPED_FOR_TMUX = clampChalkLevelForTmux();
135125
135128
  RGB_REGEX = /^rgb\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/;
135126
135129
  ANSI_REGEX = /^ansi256\(\s?(\d+)\s?\)$/;
135130
+ BARE_ANSI_COLOR_NAMES = new Set([
135131
+ "black",
135132
+ "red",
135133
+ "green",
135134
+ "yellow",
135135
+ "blue",
135136
+ "magenta",
135137
+ "cyan",
135138
+ "white",
135139
+ "blackBright",
135140
+ "redBright",
135141
+ "greenBright",
135142
+ "yellowBright",
135143
+ "blueBright",
135144
+ "magentaBright",
135145
+ "cyanBright",
135146
+ "whiteBright"
135147
+ ]);
135127
135148
  });
135128
135149
 
135129
135150
  // src/tui/utils/earlyInput.ts
@@ -159664,7 +159685,14 @@ function resolveColor2(color, theme) {
159664
159685
  if (color.startsWith("rgb(") || color.startsWith("#") || color.startsWith("ansi256(") || color.startsWith("ansi:")) {
159665
159686
  return color;
159666
159687
  }
159667
- return theme[color];
159688
+ const themed = theme[color];
159689
+ if (themed !== undefined) {
159690
+ return themed;
159691
+ }
159692
+ if (BARE_ANSI_COLOR_NAMES.has(color)) {
159693
+ return color;
159694
+ }
159695
+ return;
159668
159696
  }
159669
159697
  function ThemedText(t0) {
159670
159698
  const $ = import_compiler_runtime7.c(10);
@@ -159723,6 +159751,7 @@ function ThemedText(t0) {
159723
159751
  var import_compiler_runtime7, import_react12, jsx_dev_runtime10, TextHoverColorContext;
159724
159752
  var init_ThemedText = __esm(() => {
159725
159753
  init_Text();
159754
+ init_colorize();
159726
159755
  init_theme();
159727
159756
  init_ThemeProvider();
159728
159757
  import_compiler_runtime7 = __toESM(require_compiler_runtime(), 1);
@@ -419856,6 +419885,7 @@ __export(exports_sessionStorage, {
419856
419885
  clearAgentTranscriptSubdir: () => clearAgentTranscriptSubdir2,
419857
419886
  clearSessionMessagesCache: () => clearSessionMessagesCache2,
419858
419887
  clearSessionMetadata: () => clearSessionMetadata2,
419888
+ countVisibleMessages: () => countVisibleMessages2,
419859
419889
  enrichLogs: () => enrichLogs,
419860
419890
  extractTeammateTranscriptsFromTasks: () => extractTeammateTranscriptsFromTasks,
419861
419891
  getAgentTranscript: () => getAgentTranscript,
@@ -473624,14 +473654,187 @@ function formatCreated(date) {
473624
473654
  const d = date.getDate();
473625
473655
  return `${m}/${d}/${date.getFullYear()}`;
473626
473656
  }
473627
- function SessionTreeScreen({ onBack, onResume }) {
473657
+ function computeColumnLayout(termCols) {
473658
+ const NAME_MIN = 16;
473659
+ const ACTIVE_SLOT = 12;
473660
+ const CREATED_SLOT = 12;
473661
+ const BRANCH_SLOT = 13;
473662
+ const MSG_SLOT = 6;
473663
+ const LEFT = 4;
473664
+ const PAD = 4;
473665
+ const budget = termCols - PAD - LEFT - ACTIVE_SLOT;
473666
+ let showCreated = true;
473667
+ let showBranch = true;
473668
+ let showMsg = true;
473669
+ if (budget < NAME_MIN + CREATED_SLOT + BRANCH_SLOT + MSG_SLOT) {
473670
+ showMsg = false;
473671
+ if (budget < NAME_MIN + CREATED_SLOT + BRANCH_SLOT) {
473672
+ showBranch = false;
473673
+ if (budget < NAME_MIN + CREATED_SLOT) {
473674
+ showCreated = false;
473675
+ }
473676
+ }
473677
+ }
473678
+ let optional = 0;
473679
+ if (showCreated)
473680
+ optional += CREATED_SLOT;
473681
+ if (showBranch)
473682
+ optional += BRANCH_SLOT;
473683
+ if (showMsg)
473684
+ optional += MSG_SLOT;
473685
+ const flagsSlot = Math.round(budget * 0.3);
473686
+ const nameW = Math.max(NAME_MIN, budget - optional - flagsSlot);
473687
+ return { nameW, showCreated, showBranch, showMsg };
473688
+ }
473689
+ function agentColorToThemeColor(agentColor, theme) {
473690
+ const field = agentColor ? AGENT_COLOR_THEME_FIELD[agentColor] : undefined;
473691
+ return field ? theme[field] : undefined;
473692
+ }
473693
+ function agentRowColors(log, isSelected, isFocused, isCurrent, theme) {
473694
+ const identity = agentColorToThemeColor(log.agentColor, theme);
473695
+ const rowColor = isSelected ? "magentaBright" : isFocused ? "cyan" : identity;
473696
+ const dotGlyph = identity || isSelected || isCurrent ? "● " : "○ ";
473697
+ const dotColor = isSelected ? "magentaBright" : identity !== undefined ? identity : isCurrent ? "cyan" : undefined;
473698
+ return { rowColor, dotColor, dotGlyph };
473699
+ }
473700
+ function buildActionRow(state, title) {
473701
+ switch (state.kind) {
473702
+ case "confirm":
473703
+ return { text: `✋ ${title} · [再按 f 确认 fork · 3s 自动取消]`, color: "yellow" };
473704
+ case "forking":
473705
+ return { text: `→ forking ${title}…`, color: "yellow" };
473706
+ case "done":
473707
+ return { text: `✓ 已创建分支 ${title}`, color: "green" };
473708
+ case "error":
473709
+ return { text: `✗ fork 失败 · ${state.message}`, color: "red" };
473710
+ case "idle":
473711
+ default:
473712
+ return { text: SESSION_ROW_HINT };
473713
+ }
473714
+ }
473715
+ function rowSlotCost(idx, expandedIdx) {
473716
+ return idx === expandedIdx ? 2 : 1;
473717
+ }
473718
+ function slotPrefix(idx, expandedIdx, count) {
473719
+ const n = Math.min(Math.max(idx, 0), count);
473720
+ let slots = n;
473721
+ if (expandedIdx !== null && expandedIdx < n)
473722
+ slots += 1;
473723
+ return slots;
473724
+ }
473725
+ function computeRenderWindow(count, offset, expandedIdx, visibleRows) {
473726
+ if (count <= 0)
473727
+ return { start: 0, end: 0 };
473728
+ const start = Math.max(0, Math.min(offset, count - 1));
473729
+ let end = start;
473730
+ let slots = 0;
473731
+ while (end < count) {
473732
+ const cost = rowSlotCost(end, expandedIdx);
473733
+ if (slots + cost > visibleRows)
473734
+ break;
473735
+ slots += cost;
473736
+ end += 1;
473737
+ }
473738
+ return { start, end };
473739
+ }
473740
+ function clampWindowToCursor(focusedIdx, offset, expandedIdx, visibleRows, count) {
473741
+ if (count <= 0 || visibleRows <= 0)
473742
+ return 0;
473743
+ const cursor = Math.max(0, Math.min(focusedIdx, count - 1));
473744
+ let off = Math.max(0, Math.min(offset, count - 1));
473745
+ for (let guard = 0;guard <= count + 1; guard++) {
473746
+ const cStart = slotPrefix(cursor, expandedIdx, count);
473747
+ if (cStart < slotPrefix(off, expandedIdx, count))
473748
+ return cursor;
473749
+ const win = computeRenderWindow(count, off, expandedIdx, visibleRows);
473750
+ const cEnd = cStart + rowSlotCost(cursor, expandedIdx);
473751
+ if (cEnd <= slotPrefix(win.end, expandedIdx, count))
473752
+ return off;
473753
+ off += 1;
473754
+ }
473755
+ return Math.max(0, count - 1);
473756
+ }
473757
+ function getSummaryLine(log) {
473758
+ const s = (log.summary ?? "").trim();
473759
+ if (s)
473760
+ return s;
473761
+ const fp = log.firstPrompt ? stripDisplayTagsAllowEmpty(log.firstPrompt) : "";
473762
+ if (fp)
473763
+ return fp;
473764
+ return "(无摘要)";
473765
+ }
473766
+ function nextSortKey(current) {
473767
+ const i = SESSION_SORT_KEYS.indexOf(current);
473768
+ return SESSION_SORT_KEYS[(i + 1) % SESSION_SORT_KEYS.length];
473769
+ }
473770
+ function sortLogsBy(logs, key) {
473771
+ const out = [...logs];
473772
+ switch (key) {
473773
+ case "modified":
473774
+ out.sort((a, b) => b.modified.getTime() - a.modified.getTime());
473775
+ break;
473776
+ case "created":
473777
+ out.sort((a, b) => b.created.getTime() - a.created.getTime());
473778
+ break;
473779
+ case "messages":
473780
+ out.sort((a, b) => (b.messageCount ?? 0) - (a.messageCount ?? 0));
473781
+ break;
473782
+ case "title":
473783
+ out.sort((a, b) => getLogDisplayTitle(a).localeCompare(getLogDisplayTitle(b)));
473784
+ break;
473785
+ }
473786
+ return out;
473787
+ }
473788
+ function filterLogs(logs, query) {
473789
+ const q = query.trim().toLowerCase();
473790
+ if (!q)
473791
+ return logs;
473792
+ return logs.filter((l) => [
473793
+ getLogDisplayTitle(l),
473794
+ l.summary ?? "",
473795
+ l.firstPrompt ?? "",
473796
+ l.gitBranch ?? "",
473797
+ l.tag ?? "",
473798
+ l.agentSetting ?? "",
473799
+ l.sessionId ?? ""
473800
+ ].join(" ").toLowerCase().includes(q));
473801
+ }
473802
+ function makeLru(max) {
473803
+ const m = new Map;
473804
+ return {
473805
+ get: (k) => m.get(k),
473806
+ set: (k, v) => {
473807
+ if (m.has(k))
473808
+ m.delete(k);
473809
+ m.set(k, v);
473810
+ if (m.size > max) {
473811
+ const oldest = m.keys().next().value;
473812
+ if (oldest !== undefined)
473813
+ m.delete(oldest);
473814
+ }
473815
+ },
473816
+ has: (k) => m.has(k)
473817
+ };
473818
+ }
473819
+ function SessionTreeScreen({
473820
+ onBack,
473821
+ onResume,
473822
+ onAgenticSearch
473823
+ }) {
473628
473824
  const [logs, setLogs] = React134.useState([]);
473629
473825
  const [loading, setLoading] = React134.useState(true);
473630
473826
  const [focusedIdx, setFocusedIdx] = React134.useState(0);
473631
473827
  const [selectedIdx, setSelectedIdx] = React134.useState(null);
473632
473828
  const [rowStates, setRowStates] = React134.useState(new Map);
473633
- const [bottomMessage, setBottomMessage] = React134.useState(null);
473634
473829
  const [scrollOffset, setScrollOffset] = React134.useState(0);
473830
+ const [expanded, setExpanded] = React134.useState(false);
473831
+ const expandedIdx = expanded ? focusedIdx : null;
473832
+ const [searchMode, setSearchMode] = React134.useState(false);
473833
+ const [query, setQuery] = React134.useState("");
473834
+ const [sortKey, setSortKey] = React134.useState("modified");
473835
+ const [agenticResults, setAgenticResults] = React134.useState(null);
473836
+ const exactCountCacheRef = React134.useRef(makeLru(64));
473837
+ const [, bumpExactCounts] = React134.useReducer((x) => x + 1, 0);
473635
473838
  const confirmTimerRef = React134.useRef(null);
473636
473839
  const forkInFlightRef = React134.useRef(false);
473637
473840
  const fileMetaCacheRef = React134.useRef(new Map);
@@ -473692,7 +473895,6 @@ function SessionTreeScreen({ onBack, onResume }) {
473692
473895
  } catch (err) {
473693
473896
  const message = err instanceof Error ? err.message : String(err);
473694
473897
  setRowState(target.sessionId, { kind: "error", message });
473695
- setBottomMessage(message);
473696
473898
  setTimeout(() => setRowState(target.sessionId, { kind: "idle" }), 2000);
473697
473899
  } finally {
473698
473900
  forkInFlightRef.current = false;
@@ -473702,41 +473904,90 @@ function SessionTreeScreen({ onBack, onResume }) {
473702
473904
  setFocusedIdx(idx);
473703
473905
  setSelectedIdx(null);
473704
473906
  }
473705
- function clampScrollToCursor(idx, offset, visible) {
473706
- if (visible <= 0)
473707
- return offset;
473708
- if (idx < offset)
473709
- return idx;
473710
- if (idx >= offset + visible)
473711
- return idx - visible + 1;
473712
- return offset;
473713
- }
473907
+ const computeViewLogs = React134.useCallback((base, q, sk, agentic) => {
473908
+ const local = q ? filterLogs(base, q) : base;
473909
+ const chosen = agentic && local.length === 0 ? agentic : local;
473910
+ return sortLogsBy(chosen, sk);
473911
+ }, []);
473912
+ const ensureExactCount = React134.useCallback(async (log) => {
473913
+ const sid = log.sessionId ?? "";
473914
+ if (!sid)
473915
+ return;
473916
+ if (exactCountCacheRef.current.has(sid))
473917
+ return;
473918
+ try {
473919
+ const full = isLiteLog(log) ? await loadFullLog(log) : log;
473920
+ exactCountCacheRef.current.set(sid, countVisibleMessages2(full.messages));
473921
+ bumpExactCounts();
473922
+ } catch {}
473923
+ }, [bumpExactCounts]);
473714
473924
  use_input_default((input, key, event) => {
473715
473925
  if (loading)
473716
473926
  return;
473717
- const current = logs[focusedIdx];
473927
+ const view = computeViewLogs(logs, query, sortKey, agenticResults);
473928
+ if (searchMode) {
473929
+ if (key.backspace) {
473930
+ setQuery((q) => q.slice(0, -1));
473931
+ setAgenticResults(null);
473932
+ setFocusedIdx(0);
473933
+ } else if (key.escape || input === "/") {
473934
+ setSearchMode(false);
473935
+ setQuery("");
473936
+ setAgenticResults(null);
473937
+ setFocusedIdx(0);
473938
+ } else if (key.return) {
473939
+ if (onAgenticSearch && query.trim()) {
473940
+ const localCount = filterLogs(logs, query).length;
473941
+ if (localCount === 0) {
473942
+ onAgenticSearch(query, logs).then((r) => setAgenticResults(r)).catch(() => {});
473943
+ }
473944
+ }
473945
+ } else if (input.length === 1 && !key.ctrl && !key.meta && !key.backspace && !key.return && !key.escape && input >= " ") {
473946
+ setQuery((q) => q + input);
473947
+ setAgenticResults(null);
473948
+ setFocusedIdx(0);
473949
+ }
473950
+ event.stopImmediatePropagation();
473951
+ return;
473952
+ }
473953
+ const current = view[focusedIdx];
473718
473954
  if (!current)
473719
473955
  return;
473720
473956
  const state = rowStates.get(current.sessionId ?? "")?.kind ?? "idle";
473721
473957
  if (state === "forking")
473722
473958
  return;
473959
+ if (input === "/") {
473960
+ setSearchMode(true);
473961
+ setQuery("");
473962
+ setAgenticResults(null);
473963
+ setFocusedIdx(0);
473964
+ event.stopImmediatePropagation();
473965
+ return;
473966
+ } else if (input === "s") {
473967
+ setSortKey((sk) => nextSortKey(sk));
473968
+ setFocusedIdx(0);
473969
+ setScrollOffset(0);
473970
+ event.stopImmediatePropagation();
473971
+ return;
473972
+ }
473723
473973
  const termRows = process.stdout.rows ?? 24;
473724
- const HEADER_ROWS = 3;
473725
- const FOOTER_ROWS = 2;
473726
473974
  const visibleRows = Math.max(1, termRows - HEADER_ROWS - FOOTER_ROWS);
473975
+ const clamp = (next, off) => clampWindowToCursor(next, off, expandedIdx, visibleRows, view.length);
473727
473976
  if (key.upArrow || key.wheelUp) {
473728
473977
  setSelectedIdx(null);
473729
473978
  setFocusedIdx((i) => {
473730
473979
  const next = Math.max(0, i - 1);
473731
- setScrollOffset((off) => clampScrollToCursor(next, off, visibleRows));
473980
+ setScrollOffset((off) => clamp(next, off));
473981
+ ensureExactCount(view[next]);
473732
473982
  return next;
473733
473983
  });
473734
473984
  event.stopImmediatePropagation();
473735
473985
  } else if (key.downArrow || key.wheelDown) {
473736
473986
  setSelectedIdx(null);
473737
473987
  setFocusedIdx((i) => {
473738
- const next = Math.min(logs.length - 1, i + 1);
473739
- setScrollOffset((off) => clampScrollToCursor(next, off, visibleRows));
473988
+ const next = Math.min(view.length - 1, i + 1);
473989
+ setScrollOffset((off) => clamp(next, off));
473990
+ ensureExactCount(view[next]);
473740
473991
  return next;
473741
473992
  });
473742
473993
  event.stopImmediatePropagation();
@@ -473744,18 +473995,23 @@ function SessionTreeScreen({ onBack, onResume }) {
473744
473995
  setSelectedIdx(null);
473745
473996
  setFocusedIdx((i) => {
473746
473997
  const next = Math.max(0, i - visibleRows);
473747
- setScrollOffset((off) => clampScrollToCursor(next, off, visibleRows));
473998
+ setScrollOffset((off) => clamp(next, off));
473999
+ ensureExactCount(view[next]);
473748
474000
  return next;
473749
474001
  });
473750
474002
  event.stopImmediatePropagation();
473751
474003
  } else if (key.pageDown) {
473752
474004
  setSelectedIdx(null);
473753
474005
  setFocusedIdx((i) => {
473754
- const next = Math.min(logs.length - 1, i + visibleRows);
473755
- setScrollOffset((off) => clampScrollToCursor(next, off, visibleRows));
474006
+ const next = Math.min(view.length - 1, i + visibleRows);
474007
+ setScrollOffset((off) => clamp(next, off));
474008
+ ensureExactCount(view[next]);
473756
474009
  return next;
473757
474010
  });
473758
474011
  event.stopImmediatePropagation();
474012
+ } else if (input === "x") {
474013
+ setExpanded((e) => e ? false : visibleRows >= 2);
474014
+ event.stopImmediatePropagation();
473759
474015
  } else if (key.escape || input === "q") {
473760
474016
  onBack();
473761
474017
  event.stopImmediatePropagation();
@@ -473805,26 +474061,26 @@ function SessionTreeScreen({ onBack, onResume }) {
473805
474061
  }, undefined, true, undefined, this);
473806
474062
  }
473807
474063
  const currentSessionId = getSessionId();
474064
+ const viewLogs = computeViewLogs(logs, query, sortKey, agenticResults);
473808
474065
  const termCols = process.stdout.columns ?? 100;
473809
474066
  const termRows = process.stdout.rows ?? 24;
473810
- const NARROW = termCols < 80;
474067
+ const layout = computeColumnLayout(termCols);
473811
474068
  const CURSOR_W = 2;
473812
474069
  const ICON_W = 2;
473813
- const NAME_W = NARROW ? 20 : 28;
474070
+ const NAME_W = layout.nameW;
473814
474071
  const CREATED_W = 11;
473815
474072
  const ACTIVE_W = 11;
473816
474073
  const BRANCH_W = 12;
473817
474074
  const MSG_W = 5;
473818
474075
  const GAP = 1;
473819
- const showCreated = !NARROW;
473820
- const showBranch = !NARROW;
473821
- const showMsg = !NARROW;
473822
- const HEADER_ROWS = NARROW ? 4 : 4;
473823
- const FOOTER_ROWS = 2;
474076
+ const showCreated = layout.showCreated;
474077
+ const showBranch = layout.showBranch;
474078
+ const showMsg = layout.showMsg;
473824
474079
  const visibleRows = Math.max(1, termRows - HEADER_ROWS - FOOTER_ROWS);
473825
- const effectiveOffset = Math.min(scrollOffset, Math.max(0, logs.length - visibleRows));
473826
- const startIdx = effectiveOffset;
473827
- const endIdx = Math.min(logs.length, startIdx + visibleRows);
474080
+ const effectiveOffset = Math.min(scrollOffset, Math.max(0, viewLogs.length - visibleRows));
474081
+ const win = computeRenderWindow(viewLogs.length, effectiveOffset, expandedIdx, visibleRows);
474082
+ const startIdx = win.start;
474083
+ const endIdx = win.end;
473828
474084
  let fixedW = CURSOR_W + ICON_W + NAME_W + ACTIVE_W;
473829
474085
  let gapCount = 3;
473830
474086
  if (showCreated) {
@@ -473840,8 +474096,31 @@ function SessionTreeScreen({ onBack, onResume }) {
473840
474096
  gapCount++;
473841
474097
  }
473842
474098
  fixedW += gapCount * GAP;
473843
- const headerLine = " " + " " + padToVisibleWidth("名称", NAME_W) + " " + (showCreated ? padToVisibleWidth("创建", CREATED_W) + " " : "") + padToVisibleWidth("最近活跃", ACTIVE_W) + (showBranch ? " " + padToVisibleWidth("分支", BRANCH_W) : "") + (showMsg ? " " + padLeftToVisibleWidth("消息", MSG_W) : "");
474099
+ const sortIndicator = ` · 排序:${SESSION_SORT_LABELS[sortKey]}`;
474100
+ const filterIndicator = query ? ` · 过滤:"${query}"` : "";
474101
+ const headerLine = truncateToVisibleWidth(" " + " " + padToVisibleWidth("名称", NAME_W) + " " + (showCreated ? padToVisibleWidth("创建", CREATED_W) + " " : "") + padToVisibleWidth("最近活跃", ACTIVE_W) + (showBranch ? " " + padToVisibleWidth("分支", BRANCH_W) : "") + (showMsg ? " " + padLeftToVisibleWidth("消息", MSG_W) : "") + sortIndicator + filterIndicator, Math.max(10, termCols - 4));
473844
474102
  const nowMs = Date.now();
474103
+ const theme = getTheme(resolveThemeSetting(getGlobalConfig().theme));
474104
+ const STATE_PRIORITY = {
474105
+ forking: 4,
474106
+ confirm: 3,
474107
+ done: 2,
474108
+ error: 1,
474109
+ idle: 0
474110
+ };
474111
+ let activeState = { kind: "idle" };
474112
+ let activeSid = "";
474113
+ for (const [sid, s] of rowStates) {
474114
+ if (STATE_PRIORITY[s.kind] > STATE_PRIORITY[activeState.kind]) {
474115
+ activeState = s;
474116
+ activeSid = sid;
474117
+ }
474118
+ }
474119
+ const actionLog = activeSid ? logs.find((l) => l.sessionId === activeSid) : undefined;
474120
+ const actionRow = buildActionRow(activeState, actionLog ? getLogDisplayTitle(actionLog) || "untitled" : "untitled");
474121
+ const searchActionText = searchMode ? `搜索:"${query}"${onAgenticSearch ? " · enter 触发语义搜索" : ""} · esc 退出` : undefined;
474122
+ const actionText = truncateToVisibleWidth(searchActionText ?? actionRow.text, Math.max(10, termCols - 4));
474123
+ const actionColor = searchMode ? "cyan" : actionRow.color;
473845
474124
  return /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
473846
474125
  flexDirection: "column",
473847
474126
  paddingX: 2,
@@ -473868,35 +474147,20 @@ function SessionTreeScreen({ onBack, onResume }) {
473868
474147
  const isCurrent = sid === currentSessionId;
473869
474148
  const cached = fileMetaCacheRef.current.get(sid);
473870
474149
  const isBranch = cached?.isBranch ?? false;
473871
- const rowState = rowStates.get(sid)?.kind ?? "idle";
473872
- const rowStateObj = rowStates.get(sid);
473873
474150
  const cursor = isSelected ? "» " : isFocused ? "> " : " ";
473874
- const statusIcon = isSelected || isCurrent ? "● " : "○ ";
474151
+ const { rowColor, dotColor, dotGlyph } = agentRowColors(log, isSelected, isFocused, isCurrent, theme);
473875
474152
  const title = truncateToVisibleWidth(getLogDisplayTitle(log) || "untitled", NAME_W);
473876
474153
  const created = formatCreated(log.created);
473877
474154
  const active = formatActive(log.modified, nowMs);
473878
474155
  const branch = log.gitBranch ? truncateToVisibleWidth(log.gitBranch, BRANCH_W) : "—";
473879
- const msgCount = String(cached?.messageCount ?? log.messageCount ?? 0);
473880
- let line = cursor + statusIcon + padToVisibleWidth(title, NAME_W) + " " + (showCreated ? padToVisibleWidth(created, CREATED_W) + " " : "") + padToVisibleWidth(active, ACTIVE_W);
474156
+ const exactCount = exactCountCacheRef.current.get(sid);
474157
+ const msgCount = String(exactCount ?? cached?.messageCount ?? log.messageCount ?? 0);
474158
+ let line = cursor + dotGlyph + padToVisibleWidth(title, NAME_W) + " " + (showCreated ? padToVisibleWidth(created, CREATED_W) + " " : "") + padToVisibleWidth(active, ACTIVE_W);
473881
474159
  if (showBranch)
473882
474160
  line += " " + padToVisibleWidth(branch, BRANCH_W);
473883
474161
  if (showMsg)
473884
474162
  line += " " + padLeftToVisibleWidth(msgCount, MSG_W);
473885
474163
  let flags = "";
473886
- let statusColor;
473887
- if (rowState === "confirm") {
473888
- flags += " [f 确认 fork]";
473889
- statusColor = "yellow";
473890
- } else if (rowState === "forking") {
473891
- flags += " → forking…";
473892
- statusColor = "yellow";
473893
- } else if (rowState === "done") {
473894
- flags += " ✓ 已创建分支";
473895
- statusColor = "green";
473896
- } else if (rowState === "error") {
473897
- flags += " ✗ fork 失败";
473898
- statusColor = "red";
473899
- }
473900
474164
  if (isBranch)
473901
474165
  flags += " (Branch)";
473902
474166
  if (isCurrent)
@@ -473907,70 +474171,112 @@ function SessionTreeScreen({ onBack, onResume }) {
473907
474171
  flags += ` @${log.agentSetting}`;
473908
474172
  if (log.mode === "coordinator")
473909
474173
  flags += " [C]";
474174
+ if (log.prNumber)
474175
+ flags += ` [PR #${log.prNumber}]`;
474176
+ if (log.fileSize)
474177
+ flags += ` (${formatFileSize3(log.fileSize)})`;
474178
+ if (log.worktreeSession?.worktreeName) {
474179
+ flags += ` [wt:${log.worktreeSession.worktreeName}]`;
474180
+ }
473910
474181
  const maxFlags = termCols - 2 - fixedW;
473911
474182
  if (visibleWidth(flags) > maxFlags) {
473912
474183
  flags = truncateToVisibleWidth(flags, maxFlags);
473913
474184
  }
473914
474185
  line += " " + flags;
473915
- const color = rowStateObj && rowStateObj.kind !== "idle" ? statusColor : isSelected ? "magentaBright" : isFocused ? "cyan" : AGENT_ROW_COLOR[log.agentColor ?? ""];
473916
- return /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
473917
- noSelect: true,
473918
- onClick: () => handleRowClick(i),
473919
- children: /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
473920
- color,
473921
- bold: isFocused || isSelected,
473922
- wrap: "truncate",
473923
- children: line
473924
- }, undefined, false, undefined, this)
473925
- }, sid || i, false, undefined, this);
474186
+ const summaryLine = " └ " + truncateToVisibleWidth(getSummaryLine(log), termCols - 4 - 6);
474187
+ return /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(React134.Fragment, {
474188
+ children: [
474189
+ /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
474190
+ noSelect: true,
474191
+ onClick: () => handleRowClick(i),
474192
+ children: /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
474193
+ flexDirection: "row",
474194
+ noSelect: true,
474195
+ children: [
474196
+ /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
474197
+ color: rowColor,
474198
+ bold: isFocused || isSelected,
474199
+ children: line.slice(0, 2)
474200
+ }, undefined, false, undefined, this),
474201
+ /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
474202
+ color: dotColor,
474203
+ bold: isFocused || isSelected,
474204
+ children: line.slice(2, 4)
474205
+ }, undefined, false, undefined, this),
474206
+ /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
474207
+ color: rowColor,
474208
+ bold: isFocused || isSelected,
474209
+ wrap: "truncate",
474210
+ children: line.slice(4)
474211
+ }, undefined, false, undefined, this)
474212
+ ]
474213
+ }, undefined, true, undefined, this)
474214
+ }, undefined, false, undefined, this),
474215
+ i === expandedIdx && /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
474216
+ noSelect: true,
474217
+ children: /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
474218
+ dimColor: true,
474219
+ wrap: "truncate",
474220
+ children: summaryLine
474221
+ }, undefined, false, undefined, this)
474222
+ }, undefined, false, undefined, this)
474223
+ ]
474224
+ }, sid || i, true, undefined, this);
473926
474225
  }),
473927
- logs.length === 0 && /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
474226
+ viewLogs.length === 0 && /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
473928
474227
  dimColor: true,
473929
- children: "No sessions found"
474228
+ children: query ? `No sessions match "${query}"` : "No sessions found"
473930
474229
  }, undefined, false, undefined, this)
473931
474230
  ]
473932
474231
  }, undefined, true, undefined, this),
473933
474232
  /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
473934
474233
  marginTop: 1,
473935
474234
  children: /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
473936
- dimColor: true,
473937
- children: "\uD83D\uDDB1 点击移动光标 · 滚轮/↑↓ 滚动 · enter 选中/进入 · f fork · q 返回"
473938
- }, undefined, false, undefined, this)
473939
- }, undefined, false, undefined, this),
473940
- bottomMessage && /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedBox_default, {
473941
- marginTop: 1,
473942
- children: /* @__PURE__ */ jsx_dev_runtime424.jsxDEV(ThemedText, {
473943
- color: "red",
474235
+ color: actionColor,
474236
+ dimColor: !actionColor,
473944
474237
  wrap: "truncate",
473945
- children: [
473946
- "✗ ",
473947
- bottomMessage
473948
- ]
473949
- }, undefined, true, undefined, this)
474238
+ children: actionText
474239
+ }, undefined, false, undefined, this)
473950
474240
  }, undefined, false, undefined, this)
473951
474241
  ]
473952
474242
  }, undefined, true, undefined, this);
473953
474243
  }
473954
- var React134, jsx_dev_runtime424, AGENT_ROW_COLOR;
474244
+ var React134, jsx_dev_runtime424, AGENT_COLOR_THEME_FIELD, SESSION_ROW_HINT = "\uD83D\uDDB1 点击移动光标 · 滚轮/↑↓ 滚动 · enter 选中/进入 · f fork · x 摘要 · q 返回", SESSION_SORT_KEYS, SESSION_SORT_LABELS, HEADER_ROWS = 4, FOOTER_ROWS = 2;
473955
474245
  var init_SessionTreeScreen = __esm(() => {
473956
474246
  init_ink2();
474247
+ init_config6();
474248
+ init_format2();
474249
+ init_theme();
473957
474250
  init_sessionStorage();
473958
474251
  init_worktree4();
473959
474252
  init_bootstrap();
473960
474253
  init_log5();
474254
+ init_displayTags();
473961
474255
  init_sessionStorage();
473962
474256
  init_branch();
473963
474257
  React134 = __toESM(require_react(), 1);
473964
474258
  jsx_dev_runtime424 = __toESM(require_jsx_dev_runtime(), 1);
473965
- AGENT_ROW_COLOR = {
473966
- red: "red",
473967
- blue: "blue",
473968
- green: "green",
473969
- yellow: "yellow",
473970
- purple: "magenta",
473971
- orange: "yellow",
473972
- pink: "magenta",
473973
- cyan: "cyan"
474259
+ AGENT_COLOR_THEME_FIELD = {
474260
+ red: "red_FOR_SUBAGENTS_ONLY",
474261
+ blue: "blue_FOR_SUBAGENTS_ONLY",
474262
+ green: "green_FOR_SUBAGENTS_ONLY",
474263
+ yellow: "yellow_FOR_SUBAGENTS_ONLY",
474264
+ purple: "purple_FOR_SUBAGENTS_ONLY",
474265
+ orange: "orange_FOR_SUBAGENTS_ONLY",
474266
+ pink: "pink_FOR_SUBAGENTS_ONLY",
474267
+ cyan: "cyan_FOR_SUBAGENTS_ONLY"
474268
+ };
474269
+ SESSION_SORT_KEYS = [
474270
+ "modified",
474271
+ "created",
474272
+ "messages",
474273
+ "title"
474274
+ ];
474275
+ SESSION_SORT_LABELS = {
474276
+ modified: "最近活跃",
474277
+ created: "创建",
474278
+ messages: "消息数",
474279
+ title: "名称"
473974
474280
  };
473975
474281
  });
473976
474282
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasharness/atlascode",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
4
4
  "description": "AtlasCode — Coding Agent for the domestic computing ecosystem (Ascend NPU + domestic LLM backends)",
5
5
  "bin": {
6
6
  "atlas": "dist/cli.js",