arp-tui 0.0.2 → 0.0.4

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.
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { parseArgs as nodeParseArgs } from "util";
5
5
  import { render } from "ink";
6
6
 
7
7
  // src/app.tsx
8
- import { Box as Box7, Text as Text9, useApp, useInput, useStdin } from "ink";
8
+ import { Box as Box8, Text as Text10, useApp, useInput, useStdin } from "ink";
9
9
  import { useEffect, useSyncExternalStore } from "react";
10
10
 
11
11
  // src/state/store.ts
@@ -968,6 +968,73 @@ var RelayRest = class {
968
968
  }
969
969
  };
970
970
 
971
+ // src/state/activityFold.ts
972
+ function eventTs(e) {
973
+ return typeof e.ts === "number" && Number.isFinite(e.ts) ? e.ts : 0;
974
+ }
975
+ function supersedes(nextTs, nextOrder, prevTs, prevOrder) {
976
+ if (nextTs !== prevTs) return nextTs > prevTs;
977
+ return nextOrder >= prevOrder;
978
+ }
979
+ function foldActivityEvents(events) {
980
+ const turns = /* @__PURE__ */ new Map();
981
+ events.forEach((e, idx) => {
982
+ if (!e.turnId || !e.toolCallId) return;
983
+ let turn = turns.get(e.turnId);
984
+ if (!turn) {
985
+ turn = { order: [], calls: /* @__PURE__ */ new Map() };
986
+ turns.set(e.turnId, turn);
987
+ }
988
+ const ts = eventTs(e);
989
+ const existing = turn.calls.get(e.toolCallId);
990
+ if (!existing) {
991
+ turn.order.push(e.toolCallId);
992
+ turn.calls.set(e.toolCallId, {
993
+ toolCallId: e.toolCallId,
994
+ turnId: e.turnId,
995
+ agentId: e.agentId,
996
+ kind: e.kind,
997
+ title: e.title,
998
+ status: e.status,
999
+ locations: e.locations,
1000
+ ts,
1001
+ _winTs: ts,
1002
+ _winOrder: idx
1003
+ });
1004
+ return;
1005
+ }
1006
+ if (supersedes(ts, idx, existing._winTs, existing._winOrder)) {
1007
+ if (e.kind !== void 0) existing.kind = e.kind;
1008
+ if (e.title !== void 0) existing.title = e.title;
1009
+ if (e.status !== void 0) existing.status = e.status;
1010
+ if (e.locations !== void 0) existing.locations = e.locations;
1011
+ if (e.agentId) existing.agentId = e.agentId;
1012
+ existing.ts = ts;
1013
+ existing._winTs = ts;
1014
+ existing._winOrder = idx;
1015
+ } else {
1016
+ if (existing.kind === void 0 && e.kind !== void 0) existing.kind = e.kind;
1017
+ if (existing.title === void 0 && e.title !== void 0) existing.title = e.title;
1018
+ if (existing.status === void 0 && e.status !== void 0) existing.status = e.status;
1019
+ if (existing.locations === void 0 && e.locations !== void 0) existing.locations = e.locations;
1020
+ }
1021
+ });
1022
+ const out = /* @__PURE__ */ new Map();
1023
+ for (const [turnId, turn] of turns) {
1024
+ out.set(
1025
+ turnId,
1026
+ turn.order.map((tcId) => {
1027
+ const c = turn.calls.get(tcId);
1028
+ const { _winTs, _winOrder, ...pub } = c;
1029
+ void _winTs;
1030
+ void _winOrder;
1031
+ return pub;
1032
+ })
1033
+ );
1034
+ }
1035
+ return out;
1036
+ }
1037
+
971
1038
  // src/state/priority.ts
972
1039
  function channelPriority(cid, p) {
973
1040
  const level = p.attention[cid]?.highestLevel;
@@ -1235,6 +1302,10 @@ var IDLE_CHECK_MS = 3e4;
1235
1302
  var TICK_MS = 1e4;
1236
1303
  var ACTIVITY_AUTOCLEAR_MS = 6e4;
1237
1304
  var RENDER_THROTTLE_MS = 250;
1305
+ var MAX_ACTIVITY_TURNS = 8;
1306
+ var MAX_TOOL_CALLS_PER_TURN = 50;
1307
+ var MAX_RAW_EVENTS_PER_TURN = 200;
1308
+ var ACTIVITY_SETTLE_MS = 4e3;
1238
1309
  function createStore(opts) {
1239
1310
  const instance2 = opts.instance;
1240
1311
  const relayUrl = instance2.relayUrl;
@@ -1272,7 +1343,11 @@ function createStore(opts) {
1272
1343
  unreadCapNotice: null,
1273
1344
  attention: {},
1274
1345
  notifications: [],
1275
- notifSelected: 0
1346
+ notifSelected: 0,
1347
+ activityByTurn: {},
1348
+ plansByTurn: {},
1349
+ activityPinned: false,
1350
+ activityIdleSince: null
1276
1351
  };
1277
1352
  let lastNotifyAt = 0;
1278
1353
  let notifyTimer = null;
@@ -1591,6 +1666,50 @@ function createStore(opts) {
1591
1666
  scheduleActivitySweep();
1592
1667
  }
1593
1668
  }
1669
+ let rawActivityByTurn = /* @__PURE__ */ new Map();
1670
+ let activitySettleTimer = null;
1671
+ function activityIsLive() {
1672
+ const aKeys = Object.keys(state.activityByTurn);
1673
+ const lastA = aKeys[aKeys.length - 1];
1674
+ const rows = lastA !== void 0 ? state.activityByTurn[lastA] : void 0;
1675
+ if (rows) {
1676
+ for (const r of rows) if (r.status === "pending" || r.status === "in_progress") return true;
1677
+ }
1678
+ const pKeys = Object.keys(state.plansByTurn);
1679
+ const lastP = pKeys[pKeys.length - 1];
1680
+ const entries = lastP !== void 0 ? state.plansByTurn[lastP] : void 0;
1681
+ if (entries) {
1682
+ for (const e of entries) if (e.status !== "completed") return true;
1683
+ }
1684
+ return false;
1685
+ }
1686
+ function evictOldestTurns(rec) {
1687
+ const keys = Object.keys(rec);
1688
+ if (keys.length <= MAX_ACTIVITY_TURNS) return rec;
1689
+ const drop = keys.slice(0, keys.length - MAX_ACTIVITY_TURNS);
1690
+ const next = { ...rec };
1691
+ for (const k of drop) delete next[k];
1692
+ return next;
1693
+ }
1694
+ function reconcileActivitySettle() {
1695
+ if (activityIsLive()) {
1696
+ if (activitySettleTimer) {
1697
+ clearTimeout(activitySettleTimer);
1698
+ activitySettleTimer = null;
1699
+ }
1700
+ if (state.activityIdleSince !== null) setThrottled({ activityIdleSince: null });
1701
+ return;
1702
+ }
1703
+ if (state.activityIdleSince === null) setThrottled({ activityIdleSince: Date.now() });
1704
+ if (activitySettleTimer) return;
1705
+ activitySettleTimer = setTimeout(() => {
1706
+ activitySettleTimer = null;
1707
+ setThrottled({});
1708
+ }, ACTIVITY_SETTLE_MS);
1709
+ }
1710
+ function togglePin() {
1711
+ set({ activityPinned: !state.activityPinned });
1712
+ }
1594
1713
  let countdownTimer = null;
1595
1714
  function syncCountdown(s) {
1596
1715
  if (s === "reconnecting" && !countdownTimer) {
@@ -1692,6 +1811,42 @@ function createStore(opts) {
1692
1811
  pushDivider("channel archived");
1693
1812
  return;
1694
1813
  }
1814
+ case "activity_event": {
1815
+ if (frame.channelId !== state.activeChannelId) return;
1816
+ if (!frame.turnId || !frame.toolCallId) return;
1817
+ const ev = {
1818
+ turnId: frame.turnId,
1819
+ toolCallId: frame.toolCallId,
1820
+ agentId: frame.agentId,
1821
+ kind: frame.kind,
1822
+ title: frame.title,
1823
+ status: frame.status,
1824
+ locations: frame.locations,
1825
+ ts: frame.ts
1826
+ };
1827
+ const list = [...rawActivityByTurn.get(frame.turnId) ?? [], ev];
1828
+ if (list.length > MAX_RAW_EVENTS_PER_TURN) list.splice(0, list.length - MAX_RAW_EVENTS_PER_TURN);
1829
+ rawActivityByTurn.set(frame.turnId, list);
1830
+ while (rawActivityByTurn.size > MAX_ACTIVITY_TURNS) {
1831
+ const oldest = rawActivityByTurn.keys().next().value;
1832
+ rawActivityByTurn.delete(oldest);
1833
+ }
1834
+ const foldedMap = foldActivityEvents(Array.from(rawActivityByTurn.values()).flat());
1835
+ let activityByTurn = {};
1836
+ for (const [tid, rows] of foldedMap) activityByTurn[tid] = rows.slice(0, MAX_TOOL_CALLS_PER_TURN);
1837
+ activityByTurn = evictOldestTurns(activityByTurn);
1838
+ setThrottled({ activityByTurn });
1839
+ reconcileActivitySettle();
1840
+ return;
1841
+ }
1842
+ case "plan_update": {
1843
+ if (frame.channelId !== state.activeChannelId) return;
1844
+ if (!frame.turnId) return;
1845
+ const plansByTurn = evictOldestTurns({ ...state.plansByTurn, [frame.turnId]: frame.entries ?? [] });
1846
+ setThrottled({ plansByTurn });
1847
+ reconcileActivitySettle();
1848
+ return;
1849
+ }
1695
1850
  default:
1696
1851
  return;
1697
1852
  }
@@ -1853,8 +2008,16 @@ function createStore(opts) {
1853
2008
  mode: "normal",
1854
2009
  switcherFilter: "",
1855
2010
  lastSeq: config.lastSeq?.[channelId] ?? null,
1856
- error: null
2011
+ error: null,
2012
+ activityByTurn: {},
2013
+ plansByTurn: {},
2014
+ activityIdleSince: null
1857
2015
  });
2016
+ rawActivityByTurn = /* @__PURE__ */ new Map();
2017
+ if (activitySettleTimer) {
2018
+ clearTimeout(activitySettleTimer);
2019
+ activitySettleTimer = null;
2020
+ }
1858
2021
  clearUnread(channelId);
1859
2022
  ws.subscribe(channelId);
1860
2023
  config = { ...config, lastChannelId: channelId };
@@ -1890,6 +2053,10 @@ function createStore(opts) {
1890
2053
  if (idleTimer) clearInterval(idleTimer);
1891
2054
  if (tickTimer) clearInterval(tickTimer);
1892
2055
  if (activitySweep) clearTimeout(activitySweep);
2056
+ if (activitySettleTimer) {
2057
+ clearTimeout(activitySettleTimer);
2058
+ activitySettleTimer = null;
2059
+ }
1893
2060
  if (countdownTimer) clearInterval(countdownTimer);
1894
2061
  if (attentionTimer) {
1895
2062
  clearInterval(attentionTimer);
@@ -1931,6 +2098,7 @@ function createStore(opts) {
1931
2098
  const target = nextActiveChannel(s.channels, s.activeChannelId, { attention: s.attention, unread: s.unread });
1932
2099
  if (target) openChannel(target.id);
1933
2100
  },
2101
+ toggleActivityPin: () => togglePin(),
1934
2102
  quit
1935
2103
  };
1936
2104
  }
@@ -1968,9 +2136,95 @@ function ActivityLine({ activities }) {
1968
2136
  ] });
1969
2137
  }
1970
2138
 
1971
- // src/ui/ChannelSwitcher.tsx
2139
+ // src/ui/ActivitySurface.tsx
1972
2140
  import { Box, Text as Text2 } from "ink";
1973
2141
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
2142
+ function statusGlyph(status) {
2143
+ switch (status) {
2144
+ case "completed":
2145
+ return "\u2713";
2146
+ case "failed":
2147
+ return "\u2717";
2148
+ case "in_progress":
2149
+ return "\u22EF";
2150
+ case "pending":
2151
+ return "\u25CB";
2152
+ default:
2153
+ return "\xB7";
2154
+ }
2155
+ }
2156
+ function kindGlyph(kind) {
2157
+ switch (kind) {
2158
+ case "read":
2159
+ return "r";
2160
+ case "edit":
2161
+ return "e";
2162
+ case "write":
2163
+ return "w";
2164
+ case "run":
2165
+ return "\u25B6";
2166
+ case "search":
2167
+ return "s";
2168
+ case "fetch":
2169
+ return "f";
2170
+ case "task":
2171
+ return "t";
2172
+ default:
2173
+ return "\xB7";
2174
+ }
2175
+ }
2176
+ function planGlyph(status) {
2177
+ switch (status) {
2178
+ case "completed":
2179
+ return "[x]";
2180
+ case "in_progress":
2181
+ return "[~]";
2182
+ default:
2183
+ return "[ ]";
2184
+ }
2185
+ }
2186
+ function fallbackTitle(call) {
2187
+ if (call.title) return call.title;
2188
+ if (call.kind) return call.kind.charAt(0).toUpperCase() + call.kind.slice(1);
2189
+ return "Tool call";
2190
+ }
2191
+ function ActivitySurface(props) {
2192
+ const { toolCalls, plan, visible, pinned } = props;
2193
+ if (!visible) return null;
2194
+ if (toolCalls.length === 0 && plan.length === 0) {
2195
+ return /* @__PURE__ */ jsx2(Box, { paddingLeft: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "no activity yet" }) });
2196
+ }
2197
+ return /* @__PURE__ */ jsxs2(Box, { flexDirection: "column", paddingLeft: 1, children: [
2198
+ toolCalls.length > 0 && /* @__PURE__ */ jsxs2(Box, { flexDirection: "column", children: [
2199
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "tool calls \xB7 only you can see this" }),
2200
+ toolCalls.map((call) => /* @__PURE__ */ jsxs2(Box, { flexDirection: "column", children: [
2201
+ /* @__PURE__ */ jsxs2(Text2, { children: [
2202
+ statusGlyph(call.status),
2203
+ " ",
2204
+ kindGlyph(call.kind),
2205
+ " ",
2206
+ sanitizeLabel(fallbackTitle(call), 48)
2207
+ ] }),
2208
+ pinned && call.locations && call.locations.length > 0 && /* @__PURE__ */ jsx2(Box, { flexDirection: "column", paddingLeft: 2, children: call.locations.map((loc, i) => /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2209
+ sanitizeLabel(loc.path, 60),
2210
+ loc.line != null ? `:${loc.line}` : ""
2211
+ ] }, i)) })
2212
+ ] }, call.toolCallId))
2213
+ ] }),
2214
+ plan.length > 0 && /* @__PURE__ */ jsxs2(Box, { flexDirection: "column", children: [
2215
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "plan \xB7 shared with the channel" }),
2216
+ plan.map((entry, i) => /* @__PURE__ */ jsxs2(Text2, { dimColor: entry.status === "completed", children: [
2217
+ planGlyph(entry.status),
2218
+ " ",
2219
+ sanitizeForTty(entry.content)
2220
+ ] }, i))
2221
+ ] })
2222
+ ] });
2223
+ }
2224
+
2225
+ // src/ui/ChannelSwitcher.tsx
2226
+ import { Box as Box2, Text as Text3 } from "ink";
2227
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1974
2228
  function channelLabel(ch) {
1975
2229
  return `${channelSigil(ch.kind)}${sanitizeLabel(ch.name)}`;
1976
2230
  }
@@ -1985,7 +2239,7 @@ function ChannelBadge({
1985
2239
  if (att) {
1986
2240
  const color = att.highestLevel === "critical" ? "red" : att.highestLevel === "action_required" ? "yellow" : "cyan";
1987
2241
  const sigil = att.highestLevel === "critical" ? "!" : att.highestLevel === "action_required" ? "\u25B2" : "\u2022";
1988
- return /* @__PURE__ */ jsxs2(Text2, { color, children: [
2242
+ return /* @__PURE__ */ jsxs3(Text3, { color, children: [
1989
2243
  " ",
1990
2244
  "[",
1991
2245
  sigil,
@@ -1995,7 +2249,7 @@ function ChannelBadge({
1995
2249
  }
1996
2250
  const count = unread[channelId] ?? 0;
1997
2251
  if (count > 0) {
1998
- return /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2252
+ return /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1999
2253
  " (",
2000
2254
  count,
2001
2255
  ")"
@@ -2014,11 +2268,11 @@ function ChannelSwitcher({
2014
2268
  const sorted = sortChannelsByPriority(filtered, { attention, unread });
2015
2269
  const visible = sorted.slice(0, 9);
2016
2270
  const hidden = sorted.length - visible.length;
2017
- return /* @__PURE__ */ jsxs2(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
2018
- /* @__PURE__ */ jsxs2(Text2, { bold: true, children: [
2271
+ return /* @__PURE__ */ jsxs3(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
2272
+ /* @__PURE__ */ jsxs3(Text3, { bold: true, children: [
2019
2273
  "channels",
2020
2274
  " ",
2021
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2275
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
2022
2276
  "(",
2023
2277
  sorted.length,
2024
2278
  "/",
@@ -2026,23 +2280,23 @@ function ChannelSwitcher({
2026
2280
  ")"
2027
2281
  ] })
2028
2282
  ] }),
2029
- /* @__PURE__ */ jsxs2(Text2, { children: [
2030
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "filter: " }),
2031
- /* @__PURE__ */ jsx2(Text2, { children: sanitizeLabel(filter, 40) }),
2032
- /* @__PURE__ */ jsx2(Text2, { inverse: true, children: " " })
2283
+ /* @__PURE__ */ jsxs3(Text3, { children: [
2284
+ /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "filter: " }),
2285
+ /* @__PURE__ */ jsx3(Text3, { children: sanitizeLabel(filter, 40) }),
2286
+ /* @__PURE__ */ jsx3(Text3, { inverse: true, children: " " })
2033
2287
  ] }),
2034
- visible.map((ch, i) => /* @__PURE__ */ jsxs2(Text2, { children: [
2035
- /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
2288
+ visible.map((ch, i) => /* @__PURE__ */ jsxs3(Text3, { children: [
2289
+ /* @__PURE__ */ jsxs3(Text3, { color: "cyan", children: [
2036
2290
  i + 1,
2037
2291
  " "
2038
2292
  ] }),
2039
- /* @__PURE__ */ jsx2(Text2, { bold: ch.id === activeChannelId, children: channelLabel(ch) }),
2040
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2293
+ /* @__PURE__ */ jsx3(Text3, { bold: ch.id === activeChannelId, children: channelLabel(ch) }),
2294
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
2041
2295
  " \xB7 ",
2042
2296
  ch.members.length,
2043
2297
  " members"
2044
2298
  ] }),
2045
- /* @__PURE__ */ jsx2(
2299
+ /* @__PURE__ */ jsx3(
2046
2300
  ChannelBadge,
2047
2301
  {
2048
2302
  channelId: ch.id,
@@ -2052,36 +2306,36 @@ function ChannelSwitcher({
2052
2306
  }
2053
2307
  )
2054
2308
  ] }, ch.id)),
2055
- hidden > 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2309
+ hidden > 0 ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
2056
2310
  "\u2026",
2057
2311
  hidden,
2058
2312
  " more \u2014 keep typing to narrow"
2059
2313
  ] }) : null,
2060
- sorted.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
2314
+ sorted.length === 0 ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
2061
2315
  'no channels match "',
2062
2316
  sanitizeLabel(filter, 20),
2063
2317
  '"'
2064
2318
  ] }) : null,
2065
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: filter.length === 0 ? "type to filter \xB7 1\u20139 quick-select \xB7 n jump \xB7 Esc cancel" : "keep typing to narrow \xB7 Enter opens top match \xB7 Esc cancel" })
2319
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: filter.length === 0 ? "type to filter \xB7 1\u20139 quick-select \xB7 n jump \xB7 Esc cancel" : "keep typing to narrow \xB7 Enter opens top match \xB7 Esc cancel" })
2066
2320
  ] });
2067
2321
  }
2068
2322
 
2069
2323
  // src/ui/Composer.tsx
2070
- import { Box as Box2, Text as Text3 } from "ink";
2071
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
2324
+ import { Box as Box3, Text as Text4 } from "ink";
2325
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2072
2326
  function Composer({ draft, focused }) {
2073
2327
  const width = Math.max((process.stdout.columns ?? 80) - 8, 20);
2074
2328
  const visible = draft.length > width ? "\u2026" + draft.slice(-(width - 1)) : draft;
2075
- return /* @__PURE__ */ jsx3(Box2, { borderStyle: "round", borderColor: focused ? "cyan" : "gray", paddingX: 1, width: "100%", children: /* @__PURE__ */ jsxs3(Text3, { wrap: "truncate", children: [
2076
- /* @__PURE__ */ jsx3(Text3, { color: focused ? "cyan" : "gray", children: "> " }),
2077
- draft.length === 0 && !focused ? /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "i to compose" }) : /* @__PURE__ */ jsx3(Text3, { children: visible }),
2078
- focused ? /* @__PURE__ */ jsx3(Text3, { inverse: true, children: " " }) : null
2329
+ return /* @__PURE__ */ jsx4(Box3, { borderStyle: "round", borderColor: focused ? "cyan" : "gray", paddingX: 1, width: "100%", children: /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate", children: [
2330
+ /* @__PURE__ */ jsx4(Text4, { color: focused ? "cyan" : "gray", children: "> " }),
2331
+ draft.length === 0 && !focused ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "i to compose" }) : /* @__PURE__ */ jsx4(Text4, { children: visible }),
2332
+ focused ? /* @__PURE__ */ jsx4(Text4, { inverse: true, children: " " }) : null
2079
2333
  ] }) });
2080
2334
  }
2081
2335
 
2082
2336
  // src/ui/Header.tsx
2083
- import { Box as Box3, Text as Text4 } from "ink";
2084
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2337
+ import { Box as Box4, Text as Text5 } from "ink";
2338
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2085
2339
  var STATUS_DOT = {
2086
2340
  online: { glyph: "\u25CF", color: "green" },
2087
2341
  away: { glyph: "\u25D0", color: "yellow" },
@@ -2098,32 +2352,32 @@ function Header({
2098
2352
  members,
2099
2353
  presence
2100
2354
  }) {
2101
- return /* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", children: [
2102
- /* @__PURE__ */ jsxs4(Box3, { justifyContent: "space-between", children: [
2103
- /* @__PURE__ */ jsxs4(Text4, { children: [
2104
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", bold: true, children: "arp-tui" }),
2105
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " \u25B8 " }),
2106
- /* @__PURE__ */ jsxs4(Text4, { bold: true, children: [
2355
+ return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", children: [
2356
+ /* @__PURE__ */ jsxs5(Box4, { justifyContent: "space-between", children: [
2357
+ /* @__PURE__ */ jsxs5(Text5, { children: [
2358
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", bold: true, children: "arp-tui" }),
2359
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: " \u25B8 " }),
2360
+ /* @__PURE__ */ jsxs5(Text5, { bold: true, children: [
2107
2361
  channelSigil(channelKind),
2108
2362
  sanitizeLabel(channelName)
2109
2363
  ] })
2110
2364
  ] }),
2111
- /* @__PURE__ */ jsx4(Text4, { children: members.map((m) => {
2365
+ /* @__PURE__ */ jsx5(Text5, { children: members.map((m) => {
2112
2366
  const dot = STATUS_DOT[effectiveStatus(m, presence)];
2113
- return /* @__PURE__ */ jsxs4(Text4, { children: [
2114
- /* @__PURE__ */ jsxs4(Text4, { color: dot.color, children: [
2367
+ return /* @__PURE__ */ jsxs5(Text5, { children: [
2368
+ /* @__PURE__ */ jsxs5(Text5, { color: dot.color, children: [
2115
2369
  dot.glyph,
2116
2370
  " "
2117
2371
  ] }),
2118
- /* @__PURE__ */ jsxs4(Text4, { dimColor: effectiveStatus(m, presence) === "offline", children: [
2372
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: effectiveStatus(m, presence) === "offline", children: [
2119
2373
  m.type === "bot" ? "\u2699" : "",
2120
2374
  sanitizeLabel(m.name, 20)
2121
2375
  ] }),
2122
- /* @__PURE__ */ jsx4(Text4, { children: " " })
2376
+ /* @__PURE__ */ jsx5(Text5, { children: " " })
2123
2377
  ] }, m.id);
2124
2378
  }) })
2125
2379
  ] }),
2126
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "\u2500".repeat(Math.min(process.stdout.columns ?? 80, 100)) })
2380
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2500".repeat(Math.min(process.stdout.columns ?? 80, 100)) })
2127
2381
  ] });
2128
2382
  }
2129
2383
 
@@ -2131,8 +2385,8 @@ function Header({
2131
2385
  import { Static } from "ink";
2132
2386
 
2133
2387
  // src/ui/MessageRow.tsx
2134
- import { Box as Box4, Text as Text5 } from "ink";
2135
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2388
+ import { Box as Box5, Text as Text6 } from "ink";
2389
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2136
2390
  function hhmm(rfc3339) {
2137
2391
  const d = new Date(rfc3339);
2138
2392
  return isNaN(d.getTime()) ? "--:--" : `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
@@ -2145,7 +2399,7 @@ function TokenChip({ message }) {
2145
2399
  if (message.messageType !== "agent" || !message.tokensUsed) return null;
2146
2400
  const parts = [`${formatTokens(message.tokensUsed)} tok`];
2147
2401
  if (message.model) parts.push(sanitizeLabel(message.model, 16));
2148
- return /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
2402
+ return /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
2149
2403
  message.verified ? "\u2713 " : "",
2150
2404
  parts.join(" \xB7 ")
2151
2405
  ] });
@@ -2155,41 +2409,41 @@ function MessageRow({ message }) {
2155
2409
  const isSystem = message.messageType === "system";
2156
2410
  const name = sanitizeLabel(message.agentName, 20);
2157
2411
  if (isSystem) {
2158
- return /* @__PURE__ */ jsx5(Box4, { children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, italic: true, children: [
2412
+ return /* @__PURE__ */ jsx6(Box5, { children: /* @__PURE__ */ jsxs6(Text6, { dimColor: true, italic: true, children: [
2159
2413
  " ",
2160
2414
  "\u2500\u2500 ",
2161
2415
  sanitizeForTty(message.content),
2162
2416
  " \u2500\u2500"
2163
2417
  ] }) });
2164
2418
  }
2165
- return /* @__PURE__ */ jsxs5(Box4, { justifyContent: "space-between", gap: 2, children: [
2166
- /* @__PURE__ */ jsx5(Box4, { flexShrink: 1, children: /* @__PURE__ */ jsxs5(Text5, { children: [
2167
- /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
2419
+ return /* @__PURE__ */ jsxs6(Box5, { justifyContent: "space-between", gap: 2, children: [
2420
+ /* @__PURE__ */ jsx6(Box5, { flexShrink: 1, children: /* @__PURE__ */ jsxs6(Text6, { children: [
2421
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
2168
2422
  hhmm(message.createdAt),
2169
2423
  " "
2170
2424
  ] }),
2171
- /* @__PURE__ */ jsxs5(Text5, { color: isBot ? "magenta" : "cyan", bold: !isBot, children: [
2425
+ /* @__PURE__ */ jsxs6(Text6, { color: isBot ? "magenta" : "cyan", bold: !isBot, children: [
2172
2426
  isBot ? "\u2699" : "",
2173
2427
  name.padEnd(12)
2174
2428
  ] }),
2175
- /* @__PURE__ */ jsxs5(Text5, { children: [
2429
+ /* @__PURE__ */ jsxs6(Text6, { children: [
2176
2430
  " ",
2177
2431
  sanitizeForTty(message.content)
2178
2432
  ] })
2179
2433
  ] }) }),
2180
- /* @__PURE__ */ jsx5(Box4, { flexShrink: 0, children: /* @__PURE__ */ jsx5(TokenChip, { message }) })
2434
+ /* @__PURE__ */ jsx6(Box5, { flexShrink: 0, children: /* @__PURE__ */ jsx6(TokenChip, { message }) })
2181
2435
  ] });
2182
2436
  }
2183
2437
 
2184
2438
  // src/ui/MessageList.tsx
2185
- import { jsx as jsx6 } from "react/jsx-runtime";
2439
+ import { jsx as jsx7 } from "react/jsx-runtime";
2186
2440
  function MessageList({ messages }) {
2187
- return /* @__PURE__ */ jsx6(Static, { items: messages, children: (m) => /* @__PURE__ */ jsx6(MessageRow, { message: m }, m.id) });
2441
+ return /* @__PURE__ */ jsx7(Static, { items: messages, children: (m) => /* @__PURE__ */ jsx7(MessageRow, { message: m }, m.id) });
2188
2442
  }
2189
2443
 
2190
2444
  // src/ui/NotificationsPanel.tsx
2191
- import { Box as Box5, Text as Text6 } from "ink";
2192
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2445
+ import { Box as Box6, Text as Text7 } from "ink";
2446
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2193
2447
  function relativeAge(createdAt) {
2194
2448
  const ms = Date.now() - new Date(createdAt).getTime();
2195
2449
  if (!Number.isFinite(ms) || ms < 0) return "\u2014";
@@ -2207,11 +2461,11 @@ function NotificationsPanel({
2207
2461
  notifSelected
2208
2462
  }) {
2209
2463
  const unreadCount = notifications.filter((n) => !n.readAt).length;
2210
- return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2211
- /* @__PURE__ */ jsxs6(Text6, { bold: true, children: [
2464
+ return /* @__PURE__ */ jsxs7(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2465
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
2212
2466
  "alerts",
2213
2467
  " ",
2214
- /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
2468
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2215
2469
  "(",
2216
2470
  unreadCount,
2217
2471
  " unread \xB7 ",
@@ -2219,32 +2473,32 @@ function NotificationsPanel({
2219
2473
  " total)"
2220
2474
  ] })
2221
2475
  ] }),
2222
- notifications.length === 0 ? /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "no notifications" }) : notifications.map((n, i) => {
2476
+ notifications.length === 0 ? /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "no notifications" }) : notifications.map((n, i) => {
2223
2477
  const isSelected = i === notifSelected;
2224
2478
  const isUnread = n.readAt === null;
2225
2479
  const type = sanitizeLabel(n.type, 20);
2226
2480
  const ref = shortRef(sanitizeForTty(n.entityRef));
2227
2481
  const age = relativeAge(n.createdAt);
2228
- return /* @__PURE__ */ jsxs6(Text6, { inverse: isSelected, children: [
2229
- isUnread ? /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "\u2022 " }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " " }),
2230
- /* @__PURE__ */ jsx7(Text6, { bold: isSelected, children: type }),
2231
- /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
2482
+ return /* @__PURE__ */ jsxs7(Text7, { inverse: isSelected, children: [
2483
+ isUnread ? /* @__PURE__ */ jsx8(Text7, { color: "yellow", children: "\u2022 " }) : /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " " }),
2484
+ /* @__PURE__ */ jsx8(Text7, { bold: isSelected, children: type }),
2485
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2232
2486
  " ",
2233
2487
  ref
2234
2488
  ] }),
2235
- /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
2489
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2236
2490
  " ",
2237
2491
  age
2238
2492
  ] })
2239
2493
  ] }, n.id);
2240
2494
  }),
2241
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "J/K move \xB7 d dismiss \xB7 a mark all read \xB7 Esc close" })
2495
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "J/K move \xB7 d dismiss \xB7 a mark all read \xB7 Esc close" })
2242
2496
  ] });
2243
2497
  }
2244
2498
 
2245
2499
  // src/ui/StatusBar.tsx
2246
- import { Text as Text7 } from "ink";
2247
- import { Fragment, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2500
+ import { Text as Text8 } from "ink";
2501
+ import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2248
2502
  var MODE_LABEL = {
2249
2503
  normal: "NORMAL",
2250
2504
  insert: "INSERT",
@@ -2301,41 +2555,41 @@ function StatusBar({
2301
2555
  color: stale ? "yellow" : "green"
2302
2556
  };
2303
2557
  }
2304
- return /* @__PURE__ */ jsxs7(Text7, { children: [
2305
- /* @__PURE__ */ jsxs7(Text7, { bold: true, color: mode === "insert" ? "cyan" : mode === "token" ? "yellow" : "white", children: [
2558
+ return /* @__PURE__ */ jsxs8(Text8, { children: [
2559
+ /* @__PURE__ */ jsxs8(Text8, { bold: true, color: mode === "insert" ? "cyan" : mode === "token" ? "yellow" : "white", children: [
2306
2560
  " ",
2307
2561
  MODE_LABEL[mode],
2308
2562
  " "
2309
2563
  ] }),
2310
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "\u2502 " }),
2311
- /* @__PURE__ */ jsx8(Text7, { color: connColor, children: connectionLabel(connection, reconnectAt, reconnectAttempt) }),
2312
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " \u2502 " }),
2313
- /* @__PURE__ */ jsx8(Text7, { color: tokenSeg.color, children: tokenSeg.text }),
2314
- /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2564
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "\u2502 " }),
2565
+ /* @__PURE__ */ jsx9(Text8, { color: connColor, children: connectionLabel(connection, reconnectAt, reconnectAttempt) }),
2566
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " \u2502 " }),
2567
+ /* @__PURE__ */ jsx9(Text8, { color: tokenSeg.color, children: tokenSeg.text }),
2568
+ /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2315
2569
  " \u2502 seq ",
2316
2570
  lastSeq ?? "\u2014"
2317
2571
  ] }),
2318
- notifCount > 0 ? /* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
2572
+ notifCount > 0 ? /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
2319
2573
  " \u2502 alerts:",
2320
2574
  notifCount
2321
2575
  ] }) : null,
2322
2576
  error ? (
2323
2577
  // BL-222: an error replaces the full hint line but must never strand
2324
2578
  // the user — keep the exit hint visible alongside it
2325
- /* @__PURE__ */ jsxs7(Fragment, { children: [
2326
- /* @__PURE__ */ jsxs7(Text7, { color: "red", children: [
2579
+ /* @__PURE__ */ jsxs8(Fragment, { children: [
2580
+ /* @__PURE__ */ jsxs8(Text8, { color: "red", children: [
2327
2581
  " \u2502 ",
2328
2582
  sanitizeForTty(error)
2329
2583
  ] }),
2330
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " \u2502 q quit" })
2584
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " \u2502 q quit" })
2331
2585
  ] })
2332
- ) : /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " \u2502 c channels \xB7 a alerts \xB7 n next \xB7 i compose \xB7 r reconnect \xB7 Esc normal \xB7 q quit" })
2586
+ ) : /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " \u2502 c channels \xB7 a alerts \xB7 n next \xB7 v watch \xB7 i compose \xB7 r reconnect \xB7 Esc normal \xB7 q quit" })
2333
2587
  ] });
2334
2588
  }
2335
2589
 
2336
2590
  // src/ui/TokenPrompt.tsx
2337
- import { Box as Box6, Text as Text8 } from "ink";
2338
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2591
+ import { Box as Box7, Text as Text9 } from "ink";
2592
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2339
2593
  function TokenPrompt({
2340
2594
  value,
2341
2595
  reason,
@@ -2343,26 +2597,27 @@ function TokenPrompt({
2343
2597
  jwtTemplate
2344
2598
  }) {
2345
2599
  const masked = value.length === 0 ? "" : value.length <= 16 ? value : `${value.slice(0, 12)}\u2026 (${value.length} chars)`;
2346
- return /* @__PURE__ */ jsxs8(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2347
- /* @__PURE__ */ jsx9(Text8, { bold: true, color: "yellow", children: "token needed" }),
2348
- reason ? /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: sanitizeForTty(reason) }) : null,
2349
- /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2600
+ return /* @__PURE__ */ jsxs9(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2601
+ /* @__PURE__ */ jsx10(Text9, { bold: true, color: "yellow", children: "token needed" }),
2602
+ reason ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: sanitizeForTty(reason) }) : null,
2603
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2350
2604
  "mint one: open ",
2351
2605
  webUrl,
2352
2606
  " logged in, browser console:"
2353
2607
  ] }),
2354
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: ` await window.Clerk.session.getToken({template:'${jwtTemplate}'})` }),
2355
- /* @__PURE__ */ jsxs8(Text8, { children: [
2356
- /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "> " }),
2357
- /* @__PURE__ */ jsx9(Text8, { children: masked }),
2358
- /* @__PURE__ */ jsx9(Text8, { inverse: true, children: " " })
2608
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: ` await window.Clerk.session.getToken({template:'${jwtTemplate}'})` }),
2609
+ /* @__PURE__ */ jsxs9(Text9, { children: [
2610
+ /* @__PURE__ */ jsx10(Text9, { color: "yellow", children: "> " }),
2611
+ /* @__PURE__ */ jsx10(Text9, { children: masked }),
2612
+ /* @__PURE__ */ jsx10(Text9, { inverse: true, children: " " })
2359
2613
  ] }),
2360
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "paste, then Enter \xB7 Ctrl+C quits" })
2614
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "paste, then Enter \xB7 Ctrl+C quits" })
2361
2615
  ] });
2362
2616
  }
2363
2617
 
2364
2618
  // src/app.tsx
2365
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2619
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2620
+ var ACTIVITY_SETTLE_MS2 = 4e3;
2366
2621
  function cleanInput(input) {
2367
2622
  return input.replace(/\r\n|[\r\n]/g, " ").replace(/[\x00-\x1f\x7f]/g, "");
2368
2623
  }
@@ -2434,12 +2689,22 @@ function App({ store: store2 }) {
2434
2689
  else if (input === "i" || key.return) store2.setMode("insert");
2435
2690
  else if (input === "r") store2.reconnectNow();
2436
2691
  else if (input === "n") store2.jumpNextActive();
2692
+ else if (input === "v") store2.toggleActivityPin();
2437
2693
  },
2438
2694
  { isActive: interactive }
2439
2695
  );
2440
2696
  const activeChannel = state.channels.find((c) => c.id === state.activeChannelId);
2441
- return /* @__PURE__ */ jsxs9(Box7, { flexDirection: "column", children: [
2442
- /* @__PURE__ */ jsx10(
2697
+ const lastKey = (r) => {
2698
+ const ks = Object.keys(r);
2699
+ return ks[ks.length - 1];
2700
+ };
2701
+ const activityRows = state.activityByTurn[lastKey(state.activityByTurn) ?? ""] ?? [];
2702
+ const activityPlan = state.plansByTurn[lastKey(state.plansByTurn) ?? ""] ?? [];
2703
+ const activityLive = activityRows.some((r) => r.status === "pending" || r.status === "in_progress") || activityPlan.some((e) => e.status !== "completed");
2704
+ const activityWithinSettle = state.activityIdleSince !== null && Date.now() - state.activityIdleSince < ACTIVITY_SETTLE_MS2;
2705
+ const activityVisible = state.activityPinned || activityLive || activityWithinSettle;
2706
+ return /* @__PURE__ */ jsxs10(Box8, { flexDirection: "column", children: [
2707
+ /* @__PURE__ */ jsx11(
2443
2708
  Header,
2444
2709
  {
2445
2710
  channelName: activeChannel?.name ?? "(connecting\u2026)",
@@ -2448,8 +2713,9 @@ function App({ store: store2 }) {
2448
2713
  presence: state.presence
2449
2714
  }
2450
2715
  ),
2451
- /* @__PURE__ */ jsx10(MessageList, { messages: state.messages }),
2452
- state.mode === "switcher" ? /* @__PURE__ */ jsx10(
2716
+ /* @__PURE__ */ jsx11(MessageList, { messages: state.messages }),
2717
+ /* @__PURE__ */ jsx11(ActivitySurface, { toolCalls: activityRows, plan: activityPlan, visible: activityVisible, pinned: state.activityPinned }),
2718
+ state.mode === "switcher" ? /* @__PURE__ */ jsx11(
2453
2719
  ChannelSwitcher,
2454
2720
  {
2455
2721
  channels: state.channels,
@@ -2459,14 +2725,14 @@ function App({ store: store2 }) {
2459
2725
  unread: state.unread
2460
2726
  }
2461
2727
  ) : null,
2462
- state.mode === "notifications" ? /* @__PURE__ */ jsx10(
2728
+ state.mode === "notifications" ? /* @__PURE__ */ jsx11(
2463
2729
  NotificationsPanel,
2464
2730
  {
2465
2731
  notifications: state.notifications,
2466
2732
  notifSelected: state.notifSelected
2467
2733
  }
2468
2734
  ) : null,
2469
- state.mode === "token" ? /* @__PURE__ */ jsx10(
2735
+ state.mode === "token" ? /* @__PURE__ */ jsx11(
2470
2736
  TokenPrompt,
2471
2737
  {
2472
2738
  value: state.tokenPrompt,
@@ -2475,9 +2741,9 @@ function App({ store: store2 }) {
2475
2741
  jwtTemplate: store2.instance.clerkJwtTemplate
2476
2742
  }
2477
2743
  ) : null,
2478
- /* @__PURE__ */ jsx10(ActivityLine, { activities: state.activities }),
2479
- /* @__PURE__ */ jsx10(Composer, { draft: state.draft, focused: state.mode === "insert" }),
2480
- /* @__PURE__ */ jsx10(
2744
+ /* @__PURE__ */ jsx11(ActivityLine, { activities: state.activities }),
2745
+ /* @__PURE__ */ jsx11(Composer, { draft: state.draft, focused: state.mode === "insert" }),
2746
+ /* @__PURE__ */ jsx11(
2481
2747
  StatusBar,
2482
2748
  {
2483
2749
  mode: state.mode,
@@ -2493,7 +2759,7 @@ function App({ store: store2 }) {
2493
2759
  error: state.error
2494
2760
  }
2495
2761
  ),
2496
- !interactive ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "(non-interactive terminal: keys disabled \u2014 tail is read-only here)" }) : null
2762
+ !interactive ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "(non-interactive terminal: keys disabled \u2014 tail is read-only here)" }) : null
2497
2763
  ] });
2498
2764
  }
2499
2765
 
@@ -2577,7 +2843,7 @@ unknown profile command "${args2.sub}".`);
2577
2843
  }
2578
2844
 
2579
2845
  // src/index.tsx
2580
- import { jsx as jsx11 } from "react/jsx-runtime";
2846
+ import { jsx as jsx12 } from "react/jsx-runtime";
2581
2847
  function helpText(profileName2, base2, effective) {
2582
2848
  const relayOverridden = effective.relayUrl !== base2.relayUrl;
2583
2849
  const overrideNote = relayOverridden ? `
@@ -2772,4 +3038,4 @@ if (credentials?.tokenType === "dev-jwt" && credentials.token && !credentials.cl
2772
3038
  );
2773
3039
  }
2774
3040
  var store = createStore({ instance, credentials });
2775
- render(/* @__PURE__ */ jsx11(App, { store }));
3041
+ render(/* @__PURE__ */ jsx12(App, { store }));
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "arp-tui",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "arp-tui",
9
- "version": "0.0.2",
9
+ "version": "0.0.4",
10
10
  "license": "SEE LICENSE IN LICENSE.md",
11
11
  "dependencies": {
12
12
  "ink": "^5.2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arp-tui",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Human-facing terminal client for Agent Relay Protocol. Tail channels and post messages from your terminal.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "SnowyRoad",