@meistrari/remy-cli 1.4.3 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,7 +32,7 @@ On first use, Remy opens browser-based device authorization, validates your Codi
32
32
 
33
33
  ## Your everyday workflow
34
34
 
35
- The dashboard is the starting point for all interactive work.
35
+ The dashboard is the starting point for all interactive work. It refreshes the visible session page every 10 seconds, so new sessions and status changes appear while you keep it open. If an update fails, Remy keeps showing the last successful list and retries on the next interval.
36
36
 
37
37
  ### Start work
38
38
 
package/dist/remy.js CHANGED
@@ -34740,6 +34740,7 @@ async function renderRemyView({
34740
34740
  }
34741
34741
 
34742
34742
  // src/tui/dashboard.ts
34743
+ var DASHBOARD_POLL_INTERVAL_MS = 1e4;
34743
34744
  async function createDashboardTui({
34744
34745
  initialPage,
34745
34746
  loadPage,
@@ -34749,9 +34750,17 @@ async function createDashboardTui({
34749
34750
  let inputHandler;
34750
34751
  let keyHandler;
34751
34752
  let resizeHandler;
34753
+ let refreshTimer;
34752
34754
  let rendererDestroyed2 = false;
34755
+ const loadPageAbortController = new AbortController;
34753
34756
  try {
34754
- let render = function() {
34757
+ let stopPageRefresh = function() {
34758
+ if (refreshTimer !== undefined) {
34759
+ clearInterval(refreshTimer);
34760
+ refreshTimer = undefined;
34761
+ }
34762
+ loadPageAbortController.abort();
34763
+ }, render = function() {
34755
34764
  const contentWidth = renderer.width - 4;
34756
34765
  const rowsBelow = rowsBelowVisibleWindow({ sessionCount: page.sessions.length, selectedIndex, height: renderer.height });
34757
34766
  const isNarrow = renderer.width < 72;
@@ -34780,11 +34789,13 @@ async function createDashboardTui({
34780
34789
  if (settled)
34781
34790
  return;
34782
34791
  settled = true;
34792
+ stopPageRefresh();
34783
34793
  resolveAction(value);
34784
34794
  }, fail = function(error93) {
34785
34795
  if (settled)
34786
34796
  return;
34787
34797
  settled = true;
34798
+ stopPageRefresh();
34788
34799
  rejectDraft(error93);
34789
34800
  }, moveSelectionTo = function(index) {
34790
34801
  if (page.sessions.length === 0)
@@ -34903,6 +34914,7 @@ async function createDashboardTui({
34903
34914
  let pageIndex = 1;
34904
34915
  let selectedIndex = 0;
34905
34916
  let loadingPage = false;
34917
+ let pageRequestInFlight = false;
34906
34918
  let pageError;
34907
34919
  let awaitingVimGoToTop = false;
34908
34920
  let logoutConfirmationOpen = false;
@@ -34920,23 +34932,53 @@ async function createDashboardTui({
34920
34932
  rejectDraft = reject;
34921
34933
  });
34922
34934
  async function loadAdjacentPage(direction) {
34923
- if (loadingPage)
34935
+ if (pageRequestInFlight)
34924
34936
  return;
34925
34937
  const canLoad = direction === "next" ? page.hasMore : page.canGoPrevious;
34926
34938
  if (!canLoad)
34927
34939
  return;
34940
+ pageRequestInFlight = true;
34928
34941
  loadingPage = true;
34929
34942
  pageError = undefined;
34930
34943
  render();
34931
34944
  try {
34932
- page = await loadPage({ direction });
34945
+ const loadedPage = await loadPage({ target: direction, signal: loadPageAbortController.signal });
34946
+ if (destroyed || settled)
34947
+ return;
34948
+ page = loadedPage;
34933
34949
  pageIndex = Math.max(1, pageIndex + (direction === "next" ? 1 : -1));
34934
34950
  selectedIndex = direction === "next" ? 0 : Math.max(0, page.sessions.length - 1);
34935
34951
  } catch (error93) {
34936
- pageError = error93 instanceof Error ? error93.message : String(error93);
34952
+ if (!destroyed && !settled)
34953
+ pageError = error93 instanceof Error ? error93.message : String(error93);
34937
34954
  } finally {
34955
+ pageRequestInFlight = false;
34938
34956
  loadingPage = false;
34957
+ if (!destroyed && !settled)
34958
+ render();
34959
+ }
34960
+ }
34961
+ async function refreshCurrentPage() {
34962
+ if (pageRequestInFlight || destroyed || settled)
34963
+ return;
34964
+ pageRequestInFlight = true;
34965
+ try {
34966
+ const refreshedPage = await loadPage({ target: "current", signal: loadPageAbortController.signal });
34967
+ if (destroyed || settled)
34968
+ return;
34969
+ const selectedSessionId = page.sessions[selectedIndex]?.id;
34970
+ page = refreshedPage;
34971
+ const refreshedSelectedIndex = selectedSessionId ? page.sessions.findIndex((session) => session.id === selectedSessionId) : -1;
34972
+ selectedIndex = refreshedSelectedIndex >= 0 ? refreshedSelectedIndex : Math.max(0, Math.min(selectedIndex, page.sessions.length - 1));
34973
+ pageError = undefined;
34939
34974
  render();
34975
+ } catch (error93) {
34976
+ if (!destroyed && !settled) {
34977
+ pageError = error93 instanceof Error ? error93.message : String(error93);
34978
+ render();
34979
+ }
34980
+ } finally {
34981
+ pageRequestInFlight = false;
34940
34982
  }
34941
34983
  }
34942
34984
  async function moveSelection(direction) {
@@ -34968,6 +35010,9 @@ async function createDashboardTui({
34968
35010
  renderer.on(CliRenderEvents2.RESIZE, resizeHandler);
34969
35011
  render();
34970
35012
  listRegion.focus();
35013
+ refreshTimer = setInterval(() => {
35014
+ refreshCurrentPage();
35015
+ }, DASHBOARD_POLL_INTERVAL_MS);
34971
35016
  return {
34972
35017
  waitForAction: async () => await action,
34973
35018
  destroy() {
@@ -34980,6 +35025,7 @@ async function createDashboardTui({
34980
35025
  renderer.keyInput.off("keypress", keyHandler);
34981
35026
  if (resizeHandler)
34982
35027
  renderer.off(CliRenderEvents2.RESIZE, resizeHandler);
35028
+ stopPageRefresh();
34983
35029
  rendererDestroyed2 = true;
34984
35030
  renderer.destroy();
34985
35031
  },
@@ -34994,6 +35040,9 @@ async function createDashboardTui({
34994
35040
  renderer.keyInput.off("keypress", keyHandler);
34995
35041
  if (resizeHandler)
34996
35042
  renderer.off(CliRenderEvents2.RESIZE, resizeHandler);
35043
+ if (refreshTimer !== undefined)
35044
+ clearInterval(refreshTimer);
35045
+ loadPageAbortController.abort();
34997
35046
  if (!rendererDestroyed2) {
34998
35047
  rendererDestroyed2 = true;
34999
35048
  renderer.destroy();
@@ -37294,7 +37343,7 @@ var compactMarkRows = 9;
37294
37343
  var compactMinWidth = 48;
37295
37344
  var compactMinHeight = 20;
37296
37345
  var markBrightnessGain = 4.2;
37297
- var remyCliVersion = "1.4.3";
37346
+ var remyCliVersion = "1.5.0";
37298
37347
  async function showRemySplash({
37299
37348
  createRenderer = createRemyRenderer,
37300
37349
  durationMs = splashDurationMs,
@@ -38073,18 +38122,34 @@ async function dashboard({
38073
38122
  function holdTransitionScreen() {
38074
38123
  showRemyTransitionScreen({ write: (chunk) => dependencies.output.writeStdout(chunk) });
38075
38124
  }
38076
- async function loadDashboardPage({ direction }) {
38125
+ async function loadDashboardPage({ target, signal }) {
38077
38126
  if (loadingPage)
38078
38127
  return await loadingPage;
38079
38128
  loadingPage = (async () => {
38080
- if (direction === "previous") {
38129
+ if (target === "current") {
38130
+ const after = pageIndex > 0 ? pages[pageIndex - 1]?.nextCursor ?? undefined : undefined;
38131
+ const refreshed = toDashboardPage(await operations.listSessions({
38132
+ client: operations.client,
38133
+ limit: 20,
38134
+ after,
38135
+ signal
38136
+ }));
38137
+ pages.splice(pageIndex, pages.length - pageIndex, refreshed);
38138
+ return { ...refreshed, canGoPrevious: pageIndex > 0 };
38139
+ }
38140
+ if (target === "previous") {
38081
38141
  pageIndex = Math.max(0, pageIndex - 1);
38082
38142
  return { ...pages[pageIndex], canGoPrevious: pageIndex > 0 };
38083
38143
  }
38084
38144
  const current = pages[pageIndex];
38085
38145
  if (!current.hasMore || !current.nextCursor)
38086
38146
  return { ...current, canGoPrevious: pageIndex > 0 };
38087
- const next = toDashboardPage(await operations.listSessions({ client: operations.client, after: current.nextCursor }));
38147
+ const next = toDashboardPage(await operations.listSessions({
38148
+ client: operations.client,
38149
+ limit: 20,
38150
+ after: current.nextCursor,
38151
+ signal
38152
+ }));
38088
38153
  pages.splice(pageIndex + 1);
38089
38154
  pages.push(next);
38090
38155
  pageIndex += 1;
@@ -38100,7 +38165,11 @@ async function dashboard({
38100
38165
  holdTransitionScreen();
38101
38166
  while (true) {
38102
38167
  if (!firstOpen) {
38103
- pages.splice(0, pages.length, toDashboardPage(await operations.listSessions({ client: operations.client, limit: 20 })));
38168
+ pages.splice(0, pages.length, toDashboardPage(await operations.listSessions({
38169
+ client: operations.client,
38170
+ limit: 20,
38171
+ signal: dependencies.abortSignal
38172
+ })));
38104
38173
  pageIndex = 0;
38105
38174
  }
38106
38175
  firstOpen = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/remy-cli",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "description": "Remy, the Coding Agent terminal client.",
5
5
  "type": "module",
6
6
  "bin": {