@meistrari/remy-cli 1.4.2 → 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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/remy.js +82 -11
  3. package/package.json +1 -1
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
 
@@ -82,6 +82,8 @@ remy --session <session-id>
82
82
 
83
83
  `remy new` and `remy --session` use JSON Lines output automatically when standard input or output is not a terminal. Pass `--no-tui` to choose that mode explicitly; `--json` also selects it.
84
84
 
85
+ Opaque session and message metadata returned by the API is accepted for compatibility but is not displayed in the terminal view or emitted in JSON Lines output.
86
+
85
87
  ```bash
86
88
  remy new --no-tui --repository owner/repository "Add a health check endpoint"
87
89
  remy --session <session-id> --json
package/dist/remy.js CHANGED
@@ -32581,6 +32581,7 @@ var sessionMessageSchema = exports_external2.strictObject({
32581
32581
  sequence: exports_external2.number().int().positive(),
32582
32582
  text: exports_external2.string(),
32583
32583
  file_ids: exports_external2.array(exports_external2.string()),
32584
+ metadata: jsonObjectSchema,
32584
32585
  created_at: exports_external2.iso.datetime()
32585
32586
  });
32586
32587
  var sessionConnectionSchema = exports_external2.discriminatedUnion("status", [
@@ -32623,7 +32624,8 @@ var createCodexSessionInputSchema = exports_external2.strictObject({
32623
32624
  var createSessionResponseSchema = exports_external2.strictObject({
32624
32625
  session: exports_external2.strictObject({
32625
32626
  id: exports_external2.string(),
32626
- status: sessionStatusSchema
32627
+ status: sessionStatusSchema,
32628
+ metadata: jsonObjectSchema
32627
32629
  }),
32628
32630
  messages: exports_external2.tuple([sessionMessageSchema]),
32629
32631
  connections: exports_external2.array(sessionConnectionSchema).max(1)
@@ -33787,7 +33789,7 @@ var sessionWorkspaceGitRevisionEventSchema = exports_external2.object({
33787
33789
  repository: exports_external2.object({ full_name: exports_external2.string().min(1) }).passthrough(),
33788
33790
  branch: exports_external2.string().min(1),
33789
33791
  sha: exports_external2.string().min(1),
33790
- turnId: exports_external2.string().min(1),
33792
+ turn_id: exports_external2.string().min(1),
33791
33793
  trigger: exports_external2.enum(["turn-ended", "boot-reconcile"])
33792
33794
  }).passthrough()
33793
33795
  }).passthrough();
@@ -34738,6 +34740,7 @@ async function renderRemyView({
34738
34740
  }
34739
34741
 
34740
34742
  // src/tui/dashboard.ts
34743
+ var DASHBOARD_POLL_INTERVAL_MS = 1e4;
34741
34744
  async function createDashboardTui({
34742
34745
  initialPage,
34743
34746
  loadPage,
@@ -34747,9 +34750,17 @@ async function createDashboardTui({
34747
34750
  let inputHandler;
34748
34751
  let keyHandler;
34749
34752
  let resizeHandler;
34753
+ let refreshTimer;
34750
34754
  let rendererDestroyed2 = false;
34755
+ const loadPageAbortController = new AbortController;
34751
34756
  try {
34752
- let render = function() {
34757
+ let stopPageRefresh = function() {
34758
+ if (refreshTimer !== undefined) {
34759
+ clearInterval(refreshTimer);
34760
+ refreshTimer = undefined;
34761
+ }
34762
+ loadPageAbortController.abort();
34763
+ }, render = function() {
34753
34764
  const contentWidth = renderer.width - 4;
34754
34765
  const rowsBelow = rowsBelowVisibleWindow({ sessionCount: page.sessions.length, selectedIndex, height: renderer.height });
34755
34766
  const isNarrow = renderer.width < 72;
@@ -34778,11 +34789,13 @@ async function createDashboardTui({
34778
34789
  if (settled)
34779
34790
  return;
34780
34791
  settled = true;
34792
+ stopPageRefresh();
34781
34793
  resolveAction(value);
34782
34794
  }, fail = function(error93) {
34783
34795
  if (settled)
34784
34796
  return;
34785
34797
  settled = true;
34798
+ stopPageRefresh();
34786
34799
  rejectDraft(error93);
34787
34800
  }, moveSelectionTo = function(index) {
34788
34801
  if (page.sessions.length === 0)
@@ -34901,6 +34914,7 @@ async function createDashboardTui({
34901
34914
  let pageIndex = 1;
34902
34915
  let selectedIndex = 0;
34903
34916
  let loadingPage = false;
34917
+ let pageRequestInFlight = false;
34904
34918
  let pageError;
34905
34919
  let awaitingVimGoToTop = false;
34906
34920
  let logoutConfirmationOpen = false;
@@ -34918,23 +34932,53 @@ async function createDashboardTui({
34918
34932
  rejectDraft = reject;
34919
34933
  });
34920
34934
  async function loadAdjacentPage(direction) {
34921
- if (loadingPage)
34935
+ if (pageRequestInFlight)
34922
34936
  return;
34923
34937
  const canLoad = direction === "next" ? page.hasMore : page.canGoPrevious;
34924
34938
  if (!canLoad)
34925
34939
  return;
34940
+ pageRequestInFlight = true;
34926
34941
  loadingPage = true;
34927
34942
  pageError = undefined;
34928
34943
  render();
34929
34944
  try {
34930
- page = await loadPage({ direction });
34945
+ const loadedPage = await loadPage({ target: direction, signal: loadPageAbortController.signal });
34946
+ if (destroyed || settled)
34947
+ return;
34948
+ page = loadedPage;
34931
34949
  pageIndex = Math.max(1, pageIndex + (direction === "next" ? 1 : -1));
34932
34950
  selectedIndex = direction === "next" ? 0 : Math.max(0, page.sessions.length - 1);
34933
34951
  } catch (error93) {
34934
- pageError = error93 instanceof Error ? error93.message : String(error93);
34952
+ if (!destroyed && !settled)
34953
+ pageError = error93 instanceof Error ? error93.message : String(error93);
34935
34954
  } finally {
34955
+ pageRequestInFlight = false;
34936
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;
34937
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;
34938
34982
  }
34939
34983
  }
34940
34984
  async function moveSelection(direction) {
@@ -34966,6 +35010,9 @@ async function createDashboardTui({
34966
35010
  renderer.on(CliRenderEvents2.RESIZE, resizeHandler);
34967
35011
  render();
34968
35012
  listRegion.focus();
35013
+ refreshTimer = setInterval(() => {
35014
+ refreshCurrentPage();
35015
+ }, DASHBOARD_POLL_INTERVAL_MS);
34969
35016
  return {
34970
35017
  waitForAction: async () => await action,
34971
35018
  destroy() {
@@ -34978,6 +35025,7 @@ async function createDashboardTui({
34978
35025
  renderer.keyInput.off("keypress", keyHandler);
34979
35026
  if (resizeHandler)
34980
35027
  renderer.off(CliRenderEvents2.RESIZE, resizeHandler);
35028
+ stopPageRefresh();
34981
35029
  rendererDestroyed2 = true;
34982
35030
  renderer.destroy();
34983
35031
  },
@@ -34992,6 +35040,9 @@ async function createDashboardTui({
34992
35040
  renderer.keyInput.off("keypress", keyHandler);
34993
35041
  if (resizeHandler)
34994
35042
  renderer.off(CliRenderEvents2.RESIZE, resizeHandler);
35043
+ if (refreshTimer !== undefined)
35044
+ clearInterval(refreshTimer);
35045
+ loadPageAbortController.abort();
34995
35046
  if (!rendererDestroyed2) {
34996
35047
  rendererDestroyed2 = true;
34997
35048
  renderer.destroy();
@@ -37292,7 +37343,7 @@ var compactMarkRows = 9;
37292
37343
  var compactMinWidth = 48;
37293
37344
  var compactMinHeight = 20;
37294
37345
  var markBrightnessGain = 4.2;
37295
- var remyCliVersion = "1.4.2";
37346
+ var remyCliVersion = "1.5.0";
37296
37347
  async function showRemySplash({
37297
37348
  createRenderer = createRemyRenderer,
37298
37349
  durationMs = splashDurationMs,
@@ -38071,18 +38122,34 @@ async function dashboard({
38071
38122
  function holdTransitionScreen() {
38072
38123
  showRemyTransitionScreen({ write: (chunk) => dependencies.output.writeStdout(chunk) });
38073
38124
  }
38074
- async function loadDashboardPage({ direction }) {
38125
+ async function loadDashboardPage({ target, signal }) {
38075
38126
  if (loadingPage)
38076
38127
  return await loadingPage;
38077
38128
  loadingPage = (async () => {
38078
- 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") {
38079
38141
  pageIndex = Math.max(0, pageIndex - 1);
38080
38142
  return { ...pages[pageIndex], canGoPrevious: pageIndex > 0 };
38081
38143
  }
38082
38144
  const current = pages[pageIndex];
38083
38145
  if (!current.hasMore || !current.nextCursor)
38084
38146
  return { ...current, canGoPrevious: pageIndex > 0 };
38085
- 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
+ }));
38086
38153
  pages.splice(pageIndex + 1);
38087
38154
  pages.push(next);
38088
38155
  pageIndex += 1;
@@ -38098,7 +38165,11 @@ async function dashboard({
38098
38165
  holdTransitionScreen();
38099
38166
  while (true) {
38100
38167
  if (!firstOpen) {
38101
- 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
+ })));
38102
38173
  pageIndex = 0;
38103
38174
  }
38104
38175
  firstOpen = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/remy-cli",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Remy, the Coding Agent terminal client.",
5
5
  "type": "module",
6
6
  "bin": {