@meistrari/remy-cli 1.16.0 → 1.17.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 +12 -1
  2. package/dist/remy.js +79 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -102,6 +102,14 @@ The branch-suggestion flow belongs to the interactive new-session wizard (`remy`
102
102
  remy --session <session-id>
103
103
  ```
104
104
 
105
+ To submit a follow-up immediately, add one quoted positional `prompt`:
106
+
107
+ ```bash
108
+ remy --session <session-id> "Add regression coverage for that fix"
109
+ ```
110
+
111
+ Remy sends the prompt as **Steer**, then opens the conversation. Omitting the prompt only attaches. An explicitly empty prompt is rejected. Use `--` before a prompt beginning with `--` to treat it as text.
112
+
105
113
  ### Automate a session
106
114
 
107
115
  `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.
@@ -111,8 +119,11 @@ Opaque session and message metadata returned by the API is accepted for compatib
111
119
  ```bash
112
120
  remy new --no-tui --repository owner/repository "Add a health check endpoint"
113
121
  remy --session <session-id> --json
122
+ remy --session <session-id> --no-tui "Add regression coverage for that fix"
114
123
  ```
115
124
 
125
+ With a follow-up prompt, Remy submits it once and streams JSON Lines until that message reaches a terminal outcome, even if a previous message is cached locally. It exits with status `0` for a completed turn or `1` for another terminal outcome or an API failure. A follow-up does not emit a `created` record because the session already exists. If the local session cache becomes unavailable after admission, Remy warns once and continues observing the accepted follow-up in memory. Do not resubmit the prompt because of that warning; local resume metadata may remain stale. These commands require prior sign-in and can be used by scripts or other agents.
126
+
116
127
  For a newly created session, Remy writes a `created` record, event-name records as they arrive, then a `terminal` record when the submitted turn settles. A completed turn exits with status `0`; another terminal outcome exits with status `1`.
117
128
 
118
129
  ```json
@@ -154,7 +165,7 @@ remy logout [--api-url <url>]
154
165
  remy whoami
155
166
  remy dashboard
156
167
  remy new [--repository <owner/name> ... --installation <id> --model <name> --reasoning-effort <low|medium|high|xhigh> --attach <path> ... --no-tui --json] <prompt>
157
- remy --session <session-id> [--no-tui] [--json]
168
+ remy --session <session-id> [--no-tui] [--json] [prompt]
158
169
  ```
159
170
 
160
171
  Run `remy <command> --help` for flags and command-specific usage. `remy whoami` prints the saved signed-in identity and organization.
package/dist/remy.js CHANGED
@@ -35315,6 +35315,7 @@ function createRemoteSessionController(dependencies) {
35315
35315
  let stopped = false;
35316
35316
  let state;
35317
35317
  let cachedLastRetainedEventId;
35318
+ let cacheUnavailable = false;
35318
35319
  let reasoningPreviewState = initialReasoningPreviewState();
35319
35320
  let reasoningConnectionGeneration = 0;
35320
35321
  let reasoningHistorySequenceFloor = -1;
@@ -35323,7 +35324,10 @@ function createRemoteSessionController(dependencies) {
35323
35324
  ready = new Promise((resolve) => {
35324
35325
  resolveReady = resolve;
35325
35326
  });
35326
- const cache = await readSessionCache(cachePath);
35327
+ const cache = await readSessionCache(cachePath).catch((error93) => {
35328
+ handleCacheError(error93);
35329
+ return null;
35330
+ });
35327
35331
  cachedLastRetainedEventId = input.mode === "live" ? input.lastRetainedEventId ?? cache?.lastRetainedEventId : undefined;
35328
35332
  state = createSessionViewState({
35329
35333
  detail: input.detail,
@@ -35550,6 +35554,8 @@ function createRemoteSessionController(dependencies) {
35550
35554
  };
35551
35555
  }
35552
35556
  async function writeCache() {
35557
+ if (cacheUnavailable)
35558
+ return;
35553
35559
  const currentState = getState();
35554
35560
  const cache = {
35555
35561
  version: 1,
@@ -35559,7 +35565,13 @@ function createRemoteSessionController(dependencies) {
35559
35565
  ...currentState.activeMessageId ? { activeMessageId: currentState.activeMessageId } : {},
35560
35566
  updatedAt: new Date().toISOString()
35561
35567
  };
35562
- await writeSessionCache({ path: cachePath, cache });
35568
+ await writeSessionCache({ path: cachePath, cache }).catch(handleCacheError);
35569
+ }
35570
+ function handleCacheError(error93) {
35571
+ if (!dependencies.onCacheError)
35572
+ throw error93;
35573
+ cacheUnavailable = true;
35574
+ dependencies.onCacheError(error93);
35563
35575
  }
35564
35576
  function publishState(frame) {
35565
35577
  const update = { state: getState(), ...frame ? { frame } : {} };
@@ -39596,7 +39608,7 @@ var compactMarkRows = 9;
39596
39608
  var compactMinWidth = 48;
39597
39609
  var compactMinHeight = 20;
39598
39610
  var markBrightnessGain = 4.2;
39599
- var remyCliVersion = "1.16.0";
39611
+ var remyCliVersion = "1.17.0";
39600
39612
  async function showRemySplash({
39601
39613
  createRenderer = createRemyRenderer,
39602
39614
  durationMs = splashDurationMs,
@@ -39969,7 +39981,7 @@ async function dispatchCliCommandWithShutdown({
39969
39981
  });
39970
39982
  }
39971
39983
  if (command.name === "session")
39972
- return await attachSession({ dependencies, sessionId: command.sessionId, noTui: command.noTui, json: command.json });
39984
+ return await attachSession({ dependencies, sessionId: command.sessionId, noTui: command.noTui, json: command.json, prompt: command.prompt });
39973
39985
  return await createNewSession({ dependencies, command });
39974
39986
  }
39975
39987
  function createCliShutdown({ abortSignal }) {
@@ -40876,12 +40888,30 @@ async function attachSession({
40876
40888
  dependencies,
40877
40889
  sessionId,
40878
40890
  noTui,
40879
- json: json3
40891
+ json: json3,
40892
+ prompt
40880
40893
  }) {
40881
40894
  const operations = await createSessionOperations(dependencies);
40882
40895
  const detail = await operations.getSession({ client: operations.client, sessionId });
40883
40896
  const repositories = detail.repositories.map((repository) => ({ id: repository.id, fullName: repository.full_name }));
40884
40897
  const cache = await (dependencies.readSessionCache ?? readSessionCache)(resolveSessionCachePathForCommand({ dependencies, sessionId }));
40898
+ let activeMessageId = cache?.activeMessageId;
40899
+ let cacheWarningReported = false;
40900
+ const onCacheError = prompt === undefined ? undefined : () => {
40901
+ if (cacheWarningReported)
40902
+ return;
40903
+ cacheWarningReported = true;
40904
+ dependencies.output.writeStderr(`Local session cache is unavailable; continuing to observe the accepted follow-up. Do not resubmit the prompt.
40905
+ `);
40906
+ };
40907
+ if (prompt !== undefined) {
40908
+ throwIfAborted2(dependencies.abortSignal);
40909
+ const appended = await operations.appendSessionMessage({
40910
+ client: operations.client,
40911
+ input: { sessionId, text: prompt, fileIds: [], mode: "steer", idempotencyKey: randomUUID5() }
40912
+ });
40913
+ activeMessageId = appended.message.id;
40914
+ }
40885
40915
  await (dependencies.writeSessionCache ?? writeSessionCache)({
40886
40916
  path: resolveSessionCachePathForCommand({ dependencies, sessionId }),
40887
40917
  cache: {
@@ -40889,20 +40919,25 @@ async function attachSession({
40889
40919
  sessionId,
40890
40920
  repositories,
40891
40921
  ...cache?.lastRetainedEventId ? { lastRetainedEventId: cache.lastRetainedEventId } : {},
40892
- ...cache?.activeMessageId ? { activeMessageId: cache.activeMessageId } : {},
40922
+ ...activeMessageId ? { activeMessageId } : {},
40893
40923
  updatedAt: new Date().toISOString()
40894
40924
  }
40925
+ }).catch((error93) => {
40926
+ if (!onCacheError)
40927
+ throw error93;
40928
+ onCacheError();
40895
40929
  });
40896
40930
  return await runAttachedSession({
40897
40931
  dependencies,
40898
40932
  operations,
40899
40933
  sessionId,
40900
40934
  repositories,
40901
- activeMessageId: cache?.activeMessageId,
40935
+ activeMessageId,
40902
40936
  start: { mode: "cold-resume", detail },
40903
40937
  noTui,
40904
40938
  json: json3,
40905
- emitCreated: false
40939
+ emitCreated: false,
40940
+ onCacheError
40906
40941
  });
40907
40942
  }
40908
40943
  async function runAttachedSession({
@@ -40914,7 +40949,8 @@ async function runAttachedSession({
40914
40949
  start,
40915
40950
  noTui,
40916
40951
  json: json3,
40917
- emitCreated
40952
+ emitCreated,
40953
+ onCacheError
40918
40954
  }) {
40919
40955
  if (dependencies.abortSignal?.aborted)
40920
40956
  throw dependencies.abortSignal.reason ?? new Error("interrupted");
@@ -40924,6 +40960,7 @@ async function runAttachedSession({
40924
40960
  repositories,
40925
40961
  ...activeMessageId ? { activeMessageId } : {},
40926
40962
  environment: dependencies.environment,
40963
+ onCacheError,
40927
40964
  getSession: async ({ sessionId: id }) => await operations.getSession({ client: operations.client, sessionId: id }),
40928
40965
  listSessionEvents: async ({ sessionId: id, limit, after, signal }) => await operations.listSessionEvents({ client: operations.client, sessionId: id, limit, after, signal }),
40929
40966
  openEventStream: ({ sessionId: id, lastRetainedEventId, signal, onSynchronized }) => operations.streamSessionEvents({ client: operations.client, sessionId: id, lastRetainedEventId, signal, onSynchronized })
@@ -41306,10 +41343,15 @@ Options:
41306
41343
  `;
41307
41344
  }
41308
41345
  if (topic === "session") {
41309
- return `Usage: remy --session <session-id> [options]
41346
+ return `Usage: remy --session <session-id> [options] [prompt]
41310
41347
 
41311
41348
  Attach to an existing remote session. An interactive terminal opens the session view; --no-tui streams output instead.
41312
41349
 
41350
+ Arguments:
41351
+ prompt Submit a follow-up as Steer before attaching
41352
+
41353
+ With a prompt, JSON output waits for that message's turn result. Use -- before a prompt beginning with --.
41354
+
41313
41355
  Options:
41314
41356
  --no-tui Do not open the interactive terminal view
41315
41357
  --json Write session updates as JSON
@@ -41341,8 +41383,8 @@ Usage:
41341
41383
  Commands:
41342
41384
  remy Open interactive dashboard
41343
41385
  remy dashboard Open interactive dashboard
41344
- remy --session <session-id> [--no-tui] [--json]
41345
- Attach to a session
41386
+ remy --session <session-id> [--no-tui] [--json] [prompt]
41387
+ Attach to a session, optionally submitting a follow-up
41346
41388
  remy new [--repository <owner/name> ... --installation <id> --model <name> --reasoning-effort <low|medium|high|xhigh> --attach <path> ... --no-tui --json] <prompt>
41347
41389
  Create a session
41348
41390
  remy login [--env production|staging] [--api-url <url> --auth-api-url <url> --requester-application-id <uuid> --target-application-id <uuid>]
@@ -41374,14 +41416,32 @@ function parseSessionAttach(argv) {
41374
41416
  const sessionId = argv[0];
41375
41417
  if (!sessionId || sessionId.startsWith("--"))
41376
41418
  throw new Error("--session requires a session ID.");
41377
- const flags = parseFlags(argv.slice(1));
41378
- if (typeof flags["no-tui"] === "string" || typeof flags.json === "string")
41379
- throw new Error("--no-tui and --json do not accept values.");
41380
- for (const flag of Object.keys(flags)) {
41381
- if (flag !== "no-tui" && flag !== "json")
41382
- throw new Error(`Unknown --session flag --${flag}.`);
41419
+ let noTui = false;
41420
+ let json3 = false;
41421
+ let prompt;
41422
+ let positionalOnly = false;
41423
+ for (const token of argv.slice(1)) {
41424
+ if (!positionalOnly && token === "--") {
41425
+ positionalOnly = true;
41426
+ continue;
41427
+ }
41428
+ if (!positionalOnly && token === "--no-tui") {
41429
+ noTui = true;
41430
+ continue;
41431
+ }
41432
+ if (!positionalOnly && token === "--json") {
41433
+ json3 = true;
41434
+ continue;
41435
+ }
41436
+ if (!positionalOnly && token.startsWith("--"))
41437
+ throw new Error(`Unknown --session flag ${token}.`);
41438
+ if (prompt !== undefined)
41439
+ throw new Error("--session accepts one prompt. Quote the full prompt as a single argument.");
41440
+ if (!token.trim())
41441
+ throw new Error("A follow-up prompt must not be empty.");
41442
+ prompt = token;
41383
41443
  }
41384
- return { name: "session", sessionId, noTui: flags["no-tui"] === true, json: flags.json === true };
41444
+ return { name: "session", sessionId, noTui, json: json3, ...prompt === undefined ? {} : { prompt } };
41385
41445
  }
41386
41446
  function parseNewCommand(argv) {
41387
41447
  const repositories = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/remy-cli",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "Remy, the Coding Agent terminal client.",
5
5
  "type": "module",
6
6
  "bin": {