@meistrari/remy-cli 1.2.0 → 1.3.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 +1 -0
- package/dist/remy.js +67 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ Drag to select visible text in any Remy view; Remy copies it to the local clipbo
|
|
|
50
50
|
| --- | --- |
|
|
51
51
|
| `Esc` | Interrupt the active turn; the session stays open. |
|
|
52
52
|
| `/complete` | Complete an open session after its active turn stops. |
|
|
53
|
+
| `/cancel` | Cancel the current session, including an active turn. |
|
|
53
54
|
| `/sessions` | Return to the dashboard. |
|
|
54
55
|
| `/new` | Start another new-session flow. |
|
|
55
56
|
| `/logout` | Sign out of Remy after confirmation. |
|
package/dist/remy.js
CHANGED
|
@@ -32820,6 +32820,13 @@ async function completeSession({ client, sessionId }) {
|
|
|
32820
32820
|
throw new CodingAgentProtocolError("Session completion response did not match the public API contract.", { cause: parsed.error });
|
|
32821
32821
|
return parsed.data;
|
|
32822
32822
|
}
|
|
32823
|
+
async function cancelSession({ client, sessionId }) {
|
|
32824
|
+
const response = await client.request(`/v1/sessions/${encodeURIComponent(sessionId)}/cancel`, { method: "PUT" });
|
|
32825
|
+
const parsed = sessionLifecycleResponseSchema.safeParse(await parseJson2(response, "Session cancellation response was not valid JSON."));
|
|
32826
|
+
if (!parsed.success)
|
|
32827
|
+
throw new CodingAgentProtocolError("Session cancellation response did not match the public API contract.", { cause: parsed.error });
|
|
32828
|
+
return parsed.data;
|
|
32829
|
+
}
|
|
32823
32830
|
async function listSessions({
|
|
32824
32831
|
client,
|
|
32825
32832
|
limit,
|
|
@@ -36061,6 +36068,7 @@ import { CliRenderEvents as CliRenderEvents4, BoxRenderable as BoxRenderable4, b
|
|
|
36061
36068
|
var composerSlashCommands = [
|
|
36062
36069
|
{ value: "/sessions", description: "Back to the session list" },
|
|
36063
36070
|
{ value: "/complete", description: "Finish this session" },
|
|
36071
|
+
{ value: "/cancel", description: "Cancel this session" },
|
|
36064
36072
|
{ value: "/new", description: "Start a new session" },
|
|
36065
36073
|
{ value: "/logout", description: "Sign out of Remy" },
|
|
36066
36074
|
{ value: "/help", description: "Show what you can do here" },
|
|
@@ -36073,6 +36081,7 @@ async function createSessionTui({
|
|
|
36073
36081
|
submitMessage,
|
|
36074
36082
|
requestInterrupt,
|
|
36075
36083
|
requestComplete,
|
|
36084
|
+
requestCancel,
|
|
36076
36085
|
repositoryLabel,
|
|
36077
36086
|
readClipboardImage,
|
|
36078
36087
|
savePastedImage,
|
|
@@ -36153,8 +36162,8 @@ async function createSessionTui({
|
|
|
36153
36162
|
const working = isRemyWorking(latestState);
|
|
36154
36163
|
const startedAt = workingTurnStartedAt(latestState);
|
|
36155
36164
|
const elapsedMs = startedAt === undefined ? 0 : Math.max(0, now3() - Date.parse(startedAt));
|
|
36156
|
-
statusBand.content = renderStatusBand({ state: latestState, working, elapsedMs, stopState,
|
|
36157
|
-
const liveIndicator =
|
|
36165
|
+
statusBand.content = renderStatusBand({ state: latestState, working, elapsedMs, stopState, lifecycleRequestState, repositoryLabel });
|
|
36166
|
+
const liveIndicator = lifecycleRequestState.kind === "pending" ? renderWorkingIndicator({ frame: workingSpinnerFrames[spinnerFrameIndex], elapsedMs: 0, mode: lifecycleRequestState.operation }) : working ? renderWorkingIndicator({
|
|
36158
36167
|
frame: workingSpinnerFrames[spinnerFrameIndex],
|
|
36159
36168
|
elapsedMs,
|
|
36160
36169
|
mode: stopState.kind === "stopping" ? "stopping" : "working"
|
|
@@ -36165,8 +36174,8 @@ async function createSessionTui({
|
|
|
36165
36174
|
`), joinStyled(liveContent, `
|
|
36166
36175
|
|
|
36167
36176
|
`)], "");
|
|
36168
|
-
if (
|
|
36169
|
-
composer.placeholder =
|
|
36177
|
+
if (lifecycleRequestState.kind === "pending")
|
|
36178
|
+
composer.placeholder = `${lifecycleOperationPresentParticiple(lifecycleRequestState.operation)} the session \u2014 messages are paused.`;
|
|
36170
36179
|
if (latestState.aggregateStatus === "open")
|
|
36171
36180
|
composerLayout.render();
|
|
36172
36181
|
const submissionStatus = renderComposerStatus({ admittedSubmissions });
|
|
@@ -36183,7 +36192,7 @@ async function createSessionTui({
|
|
|
36183
36192
|
|
|
36184
36193
|
`) : "";
|
|
36185
36194
|
hints.visible = renderer.height >= 10;
|
|
36186
|
-
hints.content = hints.visible ? renderActionBar({ state: latestState, working, stopState,
|
|
36195
|
+
hints.content = hints.visible ? renderActionBar({ state: latestState, working, stopState, lifecycleRequestState }) : "";
|
|
36187
36196
|
renderer.requestRender();
|
|
36188
36197
|
}, syncTerminalSessionControls = function() {
|
|
36189
36198
|
const terminal = latestState.aggregateStatus !== "open";
|
|
@@ -36215,7 +36224,7 @@ async function createSessionTui({
|
|
|
36215
36224
|
renderedAdmittedSubmissions = admittedSubmissions;
|
|
36216
36225
|
renderedWorking = working;
|
|
36217
36226
|
}, spinnerActive = function() {
|
|
36218
|
-
return isRemyWorking(latestState) ||
|
|
36227
|
+
return isRemyWorking(latestState) || lifecycleRequestState.kind === "pending";
|
|
36219
36228
|
}, syncWorkingIndicator = function() {
|
|
36220
36229
|
if (!spinnerActive()) {
|
|
36221
36230
|
if (workingSpinnerTimer) {
|
|
@@ -36244,7 +36253,7 @@ async function createSessionTui({
|
|
|
36244
36253
|
slashCompletions = [];
|
|
36245
36254
|
return;
|
|
36246
36255
|
}
|
|
36247
|
-
slashCompletions = composerSlashCommands.filter((command) => command.value.startsWith(value) && command.value !== value && (
|
|
36256
|
+
slashCompletions = composerSlashCommands.filter((command) => command.value.startsWith(value) && command.value !== value && (!["/complete", "/cancel"].includes(command.value) || latestState.aggregateStatus === "open"));
|
|
36248
36257
|
slashCompletionIndex = 0;
|
|
36249
36258
|
}, finish = function(result, error93) {
|
|
36250
36259
|
if (settled)
|
|
@@ -36286,7 +36295,7 @@ async function createSessionTui({
|
|
|
36286
36295
|
let pendingPastedImageWrites = 0;
|
|
36287
36296
|
let admittedSubmissions = [];
|
|
36288
36297
|
let stopState = { kind: "idle" };
|
|
36289
|
-
let
|
|
36298
|
+
let lifecycleRequestState = { kind: "idle" };
|
|
36290
36299
|
let helpVisible = false;
|
|
36291
36300
|
let logoutConfirmationOpen = false;
|
|
36292
36301
|
let latestState = controller.getState();
|
|
@@ -36524,8 +36533,8 @@ async function createSessionTui({
|
|
|
36524
36533
|
return;
|
|
36525
36534
|
if (await handleComposerCommand(value))
|
|
36526
36535
|
return;
|
|
36527
|
-
if (
|
|
36528
|
-
composerFeedback =
|
|
36536
|
+
if (lifecycleRequestState.kind === "pending") {
|
|
36537
|
+
composerFeedback = `${lifecycleOperationPresentParticiple(lifecycleRequestState.operation)} the session \u2014 messages are paused.`;
|
|
36529
36538
|
render();
|
|
36530
36539
|
return;
|
|
36531
36540
|
}
|
|
@@ -36585,7 +36594,13 @@ async function createSessionTui({
|
|
|
36585
36594
|
if (command === "/complete") {
|
|
36586
36595
|
composer.setText("");
|
|
36587
36596
|
composerDraft = { ...composerDraft, text: "" };
|
|
36588
|
-
await
|
|
36597
|
+
await handleLifecycleRequest("complete");
|
|
36598
|
+
return true;
|
|
36599
|
+
}
|
|
36600
|
+
if (command === "/cancel") {
|
|
36601
|
+
composer.setText("");
|
|
36602
|
+
composerDraft = { ...composerDraft, text: "" };
|
|
36603
|
+
await handleLifecycleRequest("cancel");
|
|
36589
36604
|
return true;
|
|
36590
36605
|
}
|
|
36591
36606
|
if (command === "/logout") {
|
|
@@ -36669,39 +36684,39 @@ async function createSessionTui({
|
|
|
36669
36684
|
}
|
|
36670
36685
|
render();
|
|
36671
36686
|
}
|
|
36672
|
-
async function
|
|
36673
|
-
if (
|
|
36687
|
+
async function handleLifecycleRequest(operation) {
|
|
36688
|
+
if (lifecycleRequestState.kind === "pending")
|
|
36674
36689
|
return;
|
|
36675
36690
|
if (latestState.aggregateStatus !== "open") {
|
|
36676
|
-
|
|
36691
|
+
lifecycleRequestState = { kind: "idle" };
|
|
36677
36692
|
composerFeedback = "This session is already terminal.";
|
|
36678
36693
|
render();
|
|
36679
36694
|
return;
|
|
36680
36695
|
}
|
|
36681
|
-
if (isRemyWorking(latestState)) {
|
|
36696
|
+
if (operation === "complete" && isRemyWorking(latestState)) {
|
|
36682
36697
|
composerFeedback = "Stop Remy\u2019s turn before completing the session.";
|
|
36683
36698
|
render();
|
|
36684
36699
|
return;
|
|
36685
36700
|
}
|
|
36686
|
-
|
|
36687
|
-
composerFeedback =
|
|
36701
|
+
lifecycleRequestState = { kind: "pending", operation };
|
|
36702
|
+
composerFeedback = `${lifecycleOperationPresentParticiple(operation)} the session\u2026`;
|
|
36688
36703
|
render();
|
|
36689
36704
|
try {
|
|
36690
|
-
await requestComplete();
|
|
36705
|
+
await (operation === "complete" ? requestComplete() : requestCancel());
|
|
36691
36706
|
if (destroyed)
|
|
36692
36707
|
return;
|
|
36693
|
-
if (
|
|
36708
|
+
if (lifecycleRequestState.kind !== "pending" || lifecycleRequestState.operation !== operation)
|
|
36694
36709
|
return;
|
|
36695
|
-
composerFeedback =
|
|
36710
|
+
composerFeedback = lifecycleOperationSuccessFeedback(operation);
|
|
36696
36711
|
if (latestState.aggregateStatus !== "open")
|
|
36697
|
-
|
|
36712
|
+
lifecycleRequestState = { kind: "idle" };
|
|
36698
36713
|
} catch (error93) {
|
|
36699
36714
|
if (destroyed)
|
|
36700
36715
|
return;
|
|
36701
|
-
if (
|
|
36716
|
+
if (lifecycleRequestState.kind === "pending" && lifecycleRequestState.operation === operation) {
|
|
36702
36717
|
const message = error93 instanceof Error ? error93.message : String(error93);
|
|
36703
|
-
|
|
36704
|
-
composerFeedback = `Could not
|
|
36718
|
+
lifecycleRequestState = { kind: "failed", operation, message };
|
|
36719
|
+
composerFeedback = `Could not ${operation} the session: ${message}`;
|
|
36705
36720
|
}
|
|
36706
36721
|
}
|
|
36707
36722
|
render();
|
|
@@ -36713,9 +36728,10 @@ async function createSessionTui({
|
|
|
36713
36728
|
if (composerFeedback === "Stop requested.")
|
|
36714
36729
|
composerFeedback = undefined;
|
|
36715
36730
|
}
|
|
36716
|
-
if (
|
|
36717
|
-
|
|
36718
|
-
|
|
36731
|
+
if (lifecycleRequestState.kind === "pending" && latestState.aggregateStatus !== "open") {
|
|
36732
|
+
const operation = lifecycleRequestState.operation;
|
|
36733
|
+
lifecycleRequestState = { kind: "idle" };
|
|
36734
|
+
composerFeedback = lifecycleOperationSuccessFeedback(operation);
|
|
36719
36735
|
}
|
|
36720
36736
|
render();
|
|
36721
36737
|
});
|
|
@@ -36792,6 +36808,7 @@ var helpEntries = [
|
|
|
36792
36808
|
{ group: "command", token: "/new", description: "start a new session" },
|
|
36793
36809
|
{ group: "command", token: "/sessions", description: "back to the session list" },
|
|
36794
36810
|
{ group: "command", token: "/complete", description: "finish this session" },
|
|
36811
|
+
{ group: "command", token: "/cancel", description: "cancel this session" },
|
|
36795
36812
|
{ group: "command", token: "/logout", description: "sign out of Remy" },
|
|
36796
36813
|
{ group: "command", token: "/exit", description: "leave Remy" },
|
|
36797
36814
|
{ group: "key", token: "esc", description: "stop Remy\u2019s current turn" },
|
|
@@ -36817,10 +36834,10 @@ function renderHelpPanel() {
|
|
|
36817
36834
|
function hasRunningTurn(state) {
|
|
36818
36835
|
return state.aggregateStatus === "open" && Object.values(state.messageTurns).some((turn) => turn.outcome === undefined);
|
|
36819
36836
|
}
|
|
36820
|
-
function renderStatusBand({ state, working, elapsedMs, stopState,
|
|
36837
|
+
function renderStatusBand({ state, working, elapsedMs, stopState, lifecycleRequestState, repositoryLabel }) {
|
|
36821
36838
|
const stopping = stopState?.kind === "stopping";
|
|
36822
|
-
const
|
|
36823
|
-
const presentation =
|
|
36839
|
+
const pendingOperation = lifecycleRequestState?.kind === "pending" ? lifecycleRequestState.operation : undefined;
|
|
36840
|
+
const presentation = pendingOperation ? { label: lifecycleOperationPresentParticiple(pendingOperation), color: PALETTE.approvalQuestion } : stopping ? { label: "Stopping", color: PALETTE.approvalQuestion } : sessionViewStatePresentation({ aggregateStatus: state.aggregateStatus, isWorking: working });
|
|
36824
36841
|
const elapsed = (working || stopping) && elapsedMs !== undefined && elapsedMs > 0 ? ` ${formatElapsed(elapsedMs)}` : "";
|
|
36825
36842
|
const connection = state.connectionStatus === "connected" ? dim4(fg6(PALETTE.dimText)("connected")) : fg6(PALETTE.approvalQuestion)("reconnecting\u2026");
|
|
36826
36843
|
const sessionLabel = state.sessionNumber !== undefined ? `Session #${state.sessionNumber}` : `Session ${state.sessionId}`;
|
|
@@ -36854,14 +36871,14 @@ function renderTerminalSessionBand({ aggregateStatus }) {
|
|
|
36854
36871
|
], `
|
|
36855
36872
|
`);
|
|
36856
36873
|
}
|
|
36857
|
-
function renderActionBar({ state, working, stopState,
|
|
36858
|
-
if (
|
|
36859
|
-
return new StyledText5([dim4(fg6(PALETTE.dimText)(
|
|
36874
|
+
function renderActionBar({ state, working, stopState, lifecycleRequestState }) {
|
|
36875
|
+
if (lifecycleRequestState.kind === "pending")
|
|
36876
|
+
return new StyledText5([dim4(fg6(PALETTE.dimText)(`${lifecycleOperationPresentParticiple(lifecycleRequestState.operation).toLowerCase()} the session\u2026`))]);
|
|
36860
36877
|
if (state.aggregateStatus !== "open")
|
|
36861
36878
|
return new StyledText5([]);
|
|
36862
36879
|
const stopToken = working && stopState.kind === "failed" ? ["esc retry stop"] : [];
|
|
36863
|
-
const idleGroup =
|
|
36864
|
-
const tokens = working ? ["/ commands",
|
|
36880
|
+
const idleGroup = lifecycleRequestState.kind === "failed" ? `/${lifecycleRequestState.operation} retries \xB7 /new \xB7 /sessions` : "/new \xB7 /sessions \xB7 /complete \xB7 /cancel";
|
|
36881
|
+
const tokens = working ? ["/ commands", ...stopToken, "ctrl+o activity"] : ["/ commands", idleGroup, "ctrl+o activity"];
|
|
36865
36882
|
return new StyledText5([dim4(fg6(PALETTE.dimText)(tokens.join(" \xB7 ")))]);
|
|
36866
36883
|
}
|
|
36867
36884
|
function isRemyWorking(state) {
|
|
@@ -37022,10 +37039,10 @@ function renderWorkingIndicator({ frame, elapsedMs, mode }) {
|
|
|
37022
37039
|
dim4(fg6(PALETTE.dimText)(` Stopping\u2026 ${formatElapsed(elapsedMs)}`))
|
|
37023
37040
|
]);
|
|
37024
37041
|
}
|
|
37025
|
-
if (mode === "
|
|
37042
|
+
if (mode === "complete" || mode === "cancel") {
|
|
37026
37043
|
return new StyledText5([
|
|
37027
37044
|
fg6(PALETTE.approvalQuestion)(frame),
|
|
37028
|
-
dim4(fg6(PALETTE.dimText)(
|
|
37045
|
+
dim4(fg6(PALETTE.dimText)(` ${lifecycleOperationPresentParticiple(mode)} the session\u2026`))
|
|
37029
37046
|
]);
|
|
37030
37047
|
}
|
|
37031
37048
|
return new StyledText5([
|
|
@@ -37033,6 +37050,12 @@ function renderWorkingIndicator({ frame, elapsedMs, mode }) {
|
|
|
37033
37050
|
dim4(fg6(PALETTE.dimText)(` Working ${formatElapsed(elapsedMs)}`))
|
|
37034
37051
|
]);
|
|
37035
37052
|
}
|
|
37053
|
+
function lifecycleOperationPresentParticiple(operation) {
|
|
37054
|
+
return operation === "complete" ? "Completing" : "Cancelling";
|
|
37055
|
+
}
|
|
37056
|
+
function lifecycleOperationSuccessFeedback(operation) {
|
|
37057
|
+
return operation === "complete" ? "Session completed." : "Session cancelled.";
|
|
37058
|
+
}
|
|
37036
37059
|
function formatElapsed(elapsedMs) {
|
|
37037
37060
|
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000));
|
|
37038
37061
|
if (totalSeconds < 60)
|
|
@@ -37174,7 +37197,7 @@ var compactMarkRows = 9;
|
|
|
37174
37197
|
var compactMinWidth = 48;
|
|
37175
37198
|
var compactMinHeight = 20;
|
|
37176
37199
|
var markBrightnessGain = 4.2;
|
|
37177
|
-
var remyCliVersion = "1.
|
|
37200
|
+
var remyCliVersion = "1.3.0";
|
|
37178
37201
|
async function showRemySplash({
|
|
37179
37202
|
createRenderer = createRemyRenderer,
|
|
37180
37203
|
durationMs = splashDurationMs,
|
|
@@ -38516,6 +38539,10 @@ async function runAttachedSession({
|
|
|
38516
38539
|
const detail = await operations.completeSession({ client: operations.client, sessionId });
|
|
38517
38540
|
controller.updateDetail(detail);
|
|
38518
38541
|
},
|
|
38542
|
+
requestCancel: async () => {
|
|
38543
|
+
const detail = await operations.cancelSession({ client: operations.client, sessionId });
|
|
38544
|
+
controller.updateDetail(detail);
|
|
38545
|
+
},
|
|
38519
38546
|
readClipboardImage,
|
|
38520
38547
|
savePastedImage: async (input) => await writePastedImage({ ...input, temporaryDirectory: tmpdir() }),
|
|
38521
38548
|
attachPromptPaths: async (input) => await uploadPromptPaths({ operations, ...input })
|
|
@@ -38630,6 +38657,7 @@ async function createSessionOperations(dependencies, { onAuthenticated } = {}) {
|
|
|
38630
38657
|
reserveAndUploadFile: dependencies.reserveAndUploadFile ?? reserveAndUploadFile,
|
|
38631
38658
|
createCodexSession: dependencies.createCodexSession ?? createCodexSession,
|
|
38632
38659
|
appendSessionMessage: dependencies.appendSessionMessage ?? appendSessionMessage,
|
|
38660
|
+
cancelSession: dependencies.cancelSession ?? cancelSession,
|
|
38633
38661
|
completeSession: dependencies.completeSession ?? completeSession,
|
|
38634
38662
|
interruptSession: dependencies.interruptSession ?? interruptSession,
|
|
38635
38663
|
getSession: dependencies.getSession ?? getSession,
|
|
@@ -38647,6 +38675,7 @@ async function createSessionOperations(dependencies, { onAuthenticated } = {}) {
|
|
|
38647
38675
|
reserveAndUploadFile: dependencies.reserveAndUploadFile ?? reserveAndUploadFile,
|
|
38648
38676
|
createCodexSession: dependencies.createCodexSession ?? createCodexSession,
|
|
38649
38677
|
appendSessionMessage: dependencies.appendSessionMessage ?? appendSessionMessage,
|
|
38678
|
+
cancelSession: dependencies.cancelSession ?? cancelSession,
|
|
38650
38679
|
completeSession: dependencies.completeSession ?? completeSession,
|
|
38651
38680
|
interruptSession: dependencies.interruptSession ?? interruptSession,
|
|
38652
38681
|
getSession: dependencies.getSession ?? getSession,
|