@meistrari/remy-cli 1.14.1 → 1.16.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 +6 -1
- package/dist/remy.js +245 -74
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ The dashboard is the starting point for all interactive work. It refreshes the v
|
|
|
36
36
|
|
|
37
37
|
### Start work
|
|
38
38
|
|
|
39
|
-
Press `n` in the dashboard. The new-session flow asks what you want done, selects a GitHub installation when needed, suggests repositories based on your request, and lets you review those suggestions.
|
|
39
|
+
Press `n` in the dashboard. The new-session flow asks what you want done, selects a GitHub installation when needed, suggests repositories based on your request, and lets you review those suggestions. Remy analyzes the request for existing work: a Remy session ID or number, a PR URL or number (`PR 267`, `#267`, or `owner/repo#267`), or an exact or approximate branch name. It verifies matches against the selected repositories and offers up to five branches per repository. In the branch step, use arrows to move, Space to select, and Enter to select the current option and review your choices. Each repository can continue one branch or start a new session branch. A lookup failure stays on a retry screen; press `r` to retry, `n` to explicitly choose new branches, or Esc to edit the request. Before creating the session, choose the agent model and reasoning effort. The wizard starts with `gpt-6-astra` and `medium` reasoning by default. Remy then opens the session and streams its activity.
|
|
40
40
|
|
|
41
41
|
Use `Tab` while writing the request to complete a local file or directory path. Remy attaches selected paths when you confirm the request. Each file may be at most 20 MiB. A directory may contain at most 20 MiB across its regular files before compression; Remy uploads it as a temporary `<directory>.tar.gz` archive with the selected directory preserved as its root, so the remote agent can extract and use its files. Remy rejects oversized attachments with guidance to choose a smaller file or directory, and rejects directory attachments that contain symbolic links or other non-regular entries. On macOS, `Ctrl+V` adds a PNG from the system clipboard to the request; Remy attaches it on confirmation. Remy uploads attachments before creating the session and shows their filenames beneath your message.
|
|
42
42
|
|
|
@@ -54,6 +54,8 @@ Published files and Tela Pages appear in the timeline. File artifacts include th
|
|
|
54
54
|
|
|
55
55
|
When Remy creates a plan, the session shows its checklist in the timeline and keeps `Plan <done>/<total>` with the current item pinned above the composer. Updates change the same checklist instead of producing repeated rows, and an unfinished plan remains visible after reconnecting or between turns. The collapsed timeline shows up to five plan items; press `Ctrl+O` for the complete checklist and activity detail.
|
|
56
56
|
|
|
57
|
+
Enter `/compact` to admit a durable main-thread context compaction control without sending a human message. Remy reports request admission immediately and shows the eventual completed, no-op, failed, or unknown provider result in retained activity. Compaction waits for a safe point and does not interrupt active work or jump ahead of an earlier Next message.
|
|
58
|
+
|
|
57
59
|
Drag to select visible text in any Remy view; Remy copies it to the local clipboard and emits OSC 52 for terminal or remote-session clipboard support, then clears the selection highlight. Published file artifacts show their filename and muted, full web preview URL; open the URL in a browser to select that artifact in its session. Tela Page rows retain their canonical Page URL. Remy does not fetch or print artifact bytes. When the conversation has focus, press `Tab` to return to the composer.
|
|
58
60
|
|
|
59
61
|
| Control | Result |
|
|
@@ -61,6 +63,7 @@ Drag to select visible text in any Remy view; Remy copies it to the local clipbo
|
|
|
61
63
|
| `Esc` | Interrupt the active turn; the session stays open. |
|
|
62
64
|
| `/complete` | Complete an open session after its active turn stops. |
|
|
63
65
|
| `/cancel` | Cancel the current session, including an active turn. |
|
|
66
|
+
| `/compact` | Admit a main-thread context compaction request without sending a message; the provider result appears in retained activity. |
|
|
64
67
|
| `/sessions` | Return to the dashboard. |
|
|
65
68
|
| `/new` | Start another new-session flow. |
|
|
66
69
|
| `/logout` | Sign out of Remy after confirmation. |
|
|
@@ -91,6 +94,8 @@ remy new --repository owner/repository "Add a health check endpoint"
|
|
|
91
94
|
|
|
92
95
|
Repeat `--repository` to select more repositories from the same GitHub installation. If you do not select a repository, supply `--installation <github-installation-id>`. Repeat `--attach <path>` to upload files or directories; the 20 MiB per-attachment limit is measured directly for a file and across all regular files before compressing a directory. Remy sends each accepted directory as a gzip-compressed tar archive. Direct creation uses `medium` reasoning unless `--reasoning-effort` overrides it; omit `--model` to use the server's `gpt-6-astra` default. `remy new` creates the session from the prompt and flags, then opens it when the terminal is interactive.
|
|
93
96
|
|
|
97
|
+
The branch-suggestion flow belongs to the interactive new-session wizard (`remy`, then `n`). Direct `remy new` creation does not analyze continuation references.
|
|
98
|
+
|
|
94
99
|
### Open a known session
|
|
95
100
|
|
|
96
101
|
```bash
|
package/dist/remy.js
CHANGED
|
@@ -31690,6 +31690,12 @@ var branchSuggestionsResponseSchema = exports_external2.strictObject({
|
|
|
31690
31690
|
url: exports_external2.url()
|
|
31691
31691
|
})
|
|
31692
31692
|
}),
|
|
31693
|
+
exports_external2.strictObject({
|
|
31694
|
+
repository_id: exports_external2.string().min(1),
|
|
31695
|
+
suggestion_kind: exports_external2.literal("continue_existing_branch"),
|
|
31696
|
+
branch_name: exports_external2.string().min(1),
|
|
31697
|
+
pull_request: exports_external2.null()
|
|
31698
|
+
}),
|
|
31693
31699
|
exports_external2.strictObject({
|
|
31694
31700
|
repository_id: exports_external2.string().min(1),
|
|
31695
31701
|
suggestion_kind: exports_external2.literal("create_session_branch"),
|
|
@@ -31791,6 +31797,7 @@ async function suggestRemoteBranches({
|
|
|
31791
31797
|
method: "POST",
|
|
31792
31798
|
headers: { "content-type": "application/json" },
|
|
31793
31799
|
body: JSON.stringify({
|
|
31800
|
+
suggestion_mode: "prompt",
|
|
31794
31801
|
github_installation_id: parsedInput.installationId,
|
|
31795
31802
|
prompt: parsedInput.prompt,
|
|
31796
31803
|
repository_ids: parsedInput.repositoryIds
|
|
@@ -31810,6 +31817,11 @@ async function suggestRemoteBranches({
|
|
|
31810
31817
|
repositoryId: repository.repository_id,
|
|
31811
31818
|
branchName: repository.branch_name,
|
|
31812
31819
|
pullRequest: repository.pull_request
|
|
31820
|
+
} : repository.suggestion_kind === "continue_existing_branch" ? {
|
|
31821
|
+
suggestionKind: "continueExistingBranch",
|
|
31822
|
+
repositoryId: repository.repository_id,
|
|
31823
|
+
branchName: repository.branch_name,
|
|
31824
|
+
pullRequest: null
|
|
31813
31825
|
} : {
|
|
31814
31826
|
suggestionKind: "createSessionBranch",
|
|
31815
31827
|
repositoryId: repository.repository_id,
|
|
@@ -32202,6 +32214,10 @@ var interruptAgentCommandSchema = runningCommandBaseSchema.extend({
|
|
|
32202
32214
|
turnId: zod_default2.string().min(1).optional(),
|
|
32203
32215
|
reason: zod_default2.string().min(1).optional()
|
|
32204
32216
|
}).strict();
|
|
32217
|
+
var compactContextAgentCommandSchema = runningCommandBaseSchema.extend({
|
|
32218
|
+
type: zod_default2.literal("agent.compact-context"),
|
|
32219
|
+
commandId: commandIdSchema
|
|
32220
|
+
}).strict();
|
|
32205
32221
|
var stopAgentCommandSchema = runningCommandBaseSchema.extend({
|
|
32206
32222
|
type: zod_default2.literal("agent.stop"),
|
|
32207
32223
|
reason: zod_default2.string().min(1).optional()
|
|
@@ -32215,6 +32231,7 @@ var respondUserInputAgentCommandSchema = runningCommandBaseSchema.extend({
|
|
|
32215
32231
|
var agentCommandSchema = zod_default2.union([
|
|
32216
32232
|
sendPromptCommandSchema,
|
|
32217
32233
|
interruptAgentCommandSchema,
|
|
32234
|
+
compactContextAgentCommandSchema,
|
|
32218
32235
|
stopAgentCommandSchema,
|
|
32219
32236
|
respondUserInputAgentCommandSchema
|
|
32220
32237
|
]);
|
|
@@ -32408,6 +32425,12 @@ var agentTurnEndStatusSchema = zod_default2.enum(["completed", "failed", "cancel
|
|
|
32408
32425
|
var agentSubagentStatusSchema = zod_default2.enum(["completed", "failed", "cancelled"]);
|
|
32409
32426
|
var agentContextCompactionTriggerSchema = zod_default2.enum(["manual", "auto", "unknown"]);
|
|
32410
32427
|
var agentContextCompactionStatusSchema = zod_default2.enum(["completed", "failed"]);
|
|
32428
|
+
var agentContextCompactionRequestResultSchema = zod_default2.discriminatedUnion("status", [
|
|
32429
|
+
zod_default2.object({ status: zod_default2.literal("completed") }).strict(),
|
|
32430
|
+
zod_default2.object({ status: zod_default2.literal("no_op"), reason: zod_default2.string() }).strict(),
|
|
32431
|
+
zod_default2.object({ status: zod_default2.literal("failed"), error: agentErrorSchema }).strict(),
|
|
32432
|
+
zod_default2.object({ status: zod_default2.literal("unknown") }).strict()
|
|
32433
|
+
]);
|
|
32411
32434
|
var agentErrorSourceSchema = zod_default2.enum(["provider", "runtime", "transport", "unknown"]);
|
|
32412
32435
|
var agentSkillScopeSchema = zod_default2.enum(["user", "repository", "system", "admin"]);
|
|
32413
32436
|
var agentSkillSchema = zod_default2.object({
|
|
@@ -32660,6 +32683,13 @@ var contextCompactionCompletedAgentEventSchema = agentTurnEventBaseSchema.extend
|
|
|
32660
32683
|
error: agentErrorSchema.optional()
|
|
32661
32684
|
}).strict()
|
|
32662
32685
|
}).strict();
|
|
32686
|
+
var contextCompactionRequestCompletedAgentEventSchema = agentEventBaseSchema.extend({
|
|
32687
|
+
type: zod_default2.literal("context.compaction.request.completed"),
|
|
32688
|
+
payload: zod_default2.object({
|
|
32689
|
+
commandId: zod_default2.string().min(1),
|
|
32690
|
+
result: agentContextCompactionRequestResultSchema
|
|
32691
|
+
}).strict()
|
|
32692
|
+
}).strict();
|
|
32663
32693
|
var userInputRequestedAgentEventSchema = agentTurnEventBaseSchema.extend({
|
|
32664
32694
|
type: zod_default2.literal("user-input.requested"),
|
|
32665
32695
|
payload: zod_default2.object({
|
|
@@ -32712,6 +32742,7 @@ var agentEventSchema = zod_default2.discriminatedUnion("type", [
|
|
|
32712
32742
|
contextUpdatedAgentEventSchema,
|
|
32713
32743
|
contextCompactionStartedAgentEventSchema,
|
|
32714
32744
|
contextCompactionCompletedAgentEventSchema,
|
|
32745
|
+
contextCompactionRequestCompletedAgentEventSchema,
|
|
32715
32746
|
userInputRequestedAgentEventSchema,
|
|
32716
32747
|
userInputResolvedAgentEventSchema,
|
|
32717
32748
|
errorAgentEventSchema
|
|
@@ -32900,6 +32931,13 @@ var interruptSessionResponseSchema = exports_external2.strictObject({
|
|
|
32900
32931
|
type: exports_external2.literal("agent.interrupt")
|
|
32901
32932
|
})
|
|
32902
32933
|
});
|
|
32934
|
+
var compactSessionContextResponseSchema = exports_external2.strictObject({
|
|
32935
|
+
command: exports_external2.strictObject({
|
|
32936
|
+
id: exports_external2.string(),
|
|
32937
|
+
sequence: exports_external2.number().int().positive(),
|
|
32938
|
+
type: exports_external2.literal("agent.compact-context")
|
|
32939
|
+
})
|
|
32940
|
+
});
|
|
32903
32941
|
var withdrawSessionMessageResponseSchema = exports_external2.strictObject({
|
|
32904
32942
|
command: exports_external2.strictObject({
|
|
32905
32943
|
id: exports_external2.string(),
|
|
@@ -33070,6 +33108,24 @@ async function interruptSession({
|
|
|
33070
33108
|
throw new CodingAgentProtocolError("Session interrupt response did not match the public API contract.", { cause: parsed.error });
|
|
33071
33109
|
return parsed.data.command;
|
|
33072
33110
|
}
|
|
33111
|
+
async function compactSessionContext({
|
|
33112
|
+
client,
|
|
33113
|
+
sessionId,
|
|
33114
|
+
idempotencyKey
|
|
33115
|
+
}) {
|
|
33116
|
+
const response = await client.request(`/v1/sessions/${encodeURIComponent(sessionId)}/compact`, {
|
|
33117
|
+
method: "POST",
|
|
33118
|
+
headers: {
|
|
33119
|
+
"content-type": "application/json",
|
|
33120
|
+
"Idempotency-Key": idempotencyKey
|
|
33121
|
+
},
|
|
33122
|
+
body: "{}"
|
|
33123
|
+
});
|
|
33124
|
+
const parsed = compactSessionContextResponseSchema.safeParse(await parseJson2(response, "Session context compaction response was not valid JSON."));
|
|
33125
|
+
if (!parsed.success)
|
|
33126
|
+
throw new CodingAgentProtocolError("Session context compaction response did not match the public API contract.", { cause: parsed.error });
|
|
33127
|
+
return parsed.data.command;
|
|
33128
|
+
}
|
|
33073
33129
|
async function completeSession({ client, sessionId }) {
|
|
33074
33130
|
const response = await client.request(`/v1/sessions/${encodeURIComponent(sessionId)}/complete`, { method: "PUT" });
|
|
33075
33131
|
const parsed = sessionDetailResponseSchema.safeParse(await parseJson2(response, "Session completion response was not valid JSON."));
|
|
@@ -34010,6 +34066,9 @@ var wrappedContextCompactionStartedAgentEventSchema = contextCompactionStartedAg
|
|
|
34010
34066
|
var wrappedContextCompactionCompletedAgentEventSchema = contextCompactionCompletedAgentEventSchema.extend({
|
|
34011
34067
|
type: zod_default2.literal("agent.context.compaction.completed")
|
|
34012
34068
|
}).strict();
|
|
34069
|
+
var wrappedContextCompactionRequestCompletedAgentEventSchema = contextCompactionRequestCompletedAgentEventSchema.extend({
|
|
34070
|
+
type: zod_default2.literal("agent.context.compaction.request.completed")
|
|
34071
|
+
}).strict();
|
|
34013
34072
|
var wrappedUserInputRequestedAgentEventSchema = userInputRequestedAgentEventSchema.extend({
|
|
34014
34073
|
type: zod_default2.literal("agent.user-input.requested")
|
|
34015
34074
|
}).strict();
|
|
@@ -34044,11 +34103,31 @@ var wrappedAgentEventSchema = zod_default2.discriminatedUnion("type", [
|
|
|
34044
34103
|
wrappedContextUpdatedAgentEventSchema,
|
|
34045
34104
|
wrappedContextCompactionStartedAgentEventSchema,
|
|
34046
34105
|
wrappedContextCompactionCompletedAgentEventSchema,
|
|
34106
|
+
wrappedContextCompactionRequestCompletedAgentEventSchema,
|
|
34047
34107
|
wrappedUserInputRequestedAgentEventSchema,
|
|
34048
34108
|
wrappedUserInputResolvedAgentEventSchema,
|
|
34049
34109
|
wrappedErrorAgentEventSchema
|
|
34050
34110
|
]);
|
|
34051
34111
|
|
|
34112
|
+
// ../../packages/agents-protocol/src/agent-identity.ts
|
|
34113
|
+
function normalizeAgentSubagentIdentity(identity) {
|
|
34114
|
+
return {
|
|
34115
|
+
actorId: identity.actorId,
|
|
34116
|
+
subagentId: identity.subagentId,
|
|
34117
|
+
parentActorId: identity.parentActorId,
|
|
34118
|
+
origin: identity.origin,
|
|
34119
|
+
parentToolCallId: identity.parentToolCallId ?? (identity.origin.type === "tool_call" ? identity.origin.toolCallId : undefined)
|
|
34120
|
+
};
|
|
34121
|
+
}
|
|
34122
|
+
function agentSubagentIdentitiesEqual(left, right) {
|
|
34123
|
+
const normalizedLeft = normalizeAgentSubagentIdentity(left);
|
|
34124
|
+
const normalizedRight = normalizeAgentSubagentIdentity(right);
|
|
34125
|
+
return normalizedLeft.actorId === normalizedRight.actorId && normalizedLeft.subagentId === normalizedRight.subagentId && normalizedLeft.parentActorId === normalizedRight.parentActorId && normalizedLeft.parentToolCallId === normalizedRight.parentToolCallId && (normalizedLeft.origin.type === "tool_call" ? normalizedRight.origin.type === "tool_call" && normalizedLeft.origin.toolCallId === normalizedRight.origin.toolCallId : normalizedRight.origin.type === "provider_task" && normalizedLeft.origin.taskId === normalizedRight.origin.taskId);
|
|
34126
|
+
}
|
|
34127
|
+
function agentRuntimeIdentityKey(event) {
|
|
34128
|
+
return `${event.sessionId.length}:${event.sessionId}:${event.providerSessionId.length}:${event.providerSessionId}`;
|
|
34129
|
+
}
|
|
34130
|
+
|
|
34052
34131
|
// src/sessions/projection.ts
|
|
34053
34132
|
var sessionMessageCreatedEventSchema = exports_external2.object({
|
|
34054
34133
|
type: exports_external2.literal("session.message.created"),
|
|
@@ -34377,11 +34456,7 @@ function projectAgentTurnEnded({ state, event, occurredAt, retainedEventId }) {
|
|
|
34377
34456
|
retainedTurnEnds: { ...state.retainedTurnEnds, [event.turnId]: { actorType: event.actor.type, outcome: event.payload.status } },
|
|
34378
34457
|
messageTurns: Object.fromEntries(Object.entries(state.messageTurns).map(([messageId, turn]) => [messageId, turn.turnId === event.turnId ? { ...turn, outcome: event.payload.status } : turn]))
|
|
34379
34458
|
} : state;
|
|
34380
|
-
const card = event
|
|
34381
|
-
identity: event.actor,
|
|
34382
|
-
activityTitle: event.payload.status === "failed" ? "Turn failed" : "Turn ended",
|
|
34383
|
-
card: event.payload.status === "failed" ? { kind: "failure", weight: "signal", summary: providerText(event.payload.error?.message, "Turn failed.") } : { kind: "lifecycle", weight: "noise", summary: `Turn ${event.payload.status}.` }
|
|
34384
|
-
});
|
|
34459
|
+
const card = toAgentActivityCard(event);
|
|
34385
34460
|
return appendActivity({ state: stateWithTurnOutcome, retainedEventId, occurredAt, card });
|
|
34386
34461
|
}
|
|
34387
34462
|
function projectDurableAgentEvent({ state, event, occurredAt, retainedEventId }) {
|
|
@@ -34526,7 +34601,7 @@ function toMainAgentActivityCard(event) {
|
|
|
34526
34601
|
case "agent.turn.started":
|
|
34527
34602
|
return { kind: "lifecycle", weight: "noise", title: "Remy turn started", summary: "Turn started." };
|
|
34528
34603
|
case "agent.turn.ended":
|
|
34529
|
-
return event.payload.status === "failed" ? { kind: "failure", weight: "signal", title: "Remy turn failed", summary:
|
|
34604
|
+
return event.payload.status === "failed" ? { kind: "failure", weight: "signal", title: "Remy turn failed", summary: "Turn failed." } : { kind: "lifecycle", weight: "noise", title: "Remy turn ended", summary: `Turn ${event.payload.status}.` };
|
|
34530
34605
|
case "agent.work.observed":
|
|
34531
34606
|
return { kind: "progress", weight: "noise", title: "Work progress", summary: "Remy updated its work plan.", detail: jsonDetail(event.payload.observations) };
|
|
34532
34607
|
case "agent.message.started":
|
|
@@ -34562,6 +34637,16 @@ function toMainAgentActivityCard(event) {
|
|
|
34562
34637
|
return { kind: "reasoning", weight: "noise", title: "Context compaction started", summary: "Remy is compacting context." };
|
|
34563
34638
|
case "agent.context.compaction.completed":
|
|
34564
34639
|
return event.payload.status === "failed" ? { kind: "failure", weight: "signal", title: "Context compaction failed", summary: providerText(event.payload.error?.message, "Context compaction failed.") } : { kind: "reasoning", weight: "noise", title: "Context compaction completed", summary: "Remy compacted context." };
|
|
34640
|
+
case "agent.context.compaction.request.completed": {
|
|
34641
|
+
const result = event.payload.result;
|
|
34642
|
+
if (result.status === "completed")
|
|
34643
|
+
return { kind: "progress", weight: "signal", title: "Context compaction completed", summary: "The provider completed manual context compaction." };
|
|
34644
|
+
if (result.status === "no_op")
|
|
34645
|
+
return { kind: "progress", weight: "signal", title: "Context not compacted", summary: providerText(result.reason, "The provider did not compact context.") };
|
|
34646
|
+
if (result.status === "failed")
|
|
34647
|
+
return { kind: "failure", weight: "signal", title: "Context compaction failed", summary: providerText(result.error.message, "Context compaction failed.") };
|
|
34648
|
+
return { kind: "progress", weight: "signal", title: "Context compaction result unknown", summary: "The provider result could not be correlated." };
|
|
34649
|
+
}
|
|
34565
34650
|
case "agent.user-input.requested":
|
|
34566
34651
|
return { kind: "approval-question", weight: "signal", title: "Remy needs input", summary: providerText(event.payload.prompt, "Remy needs input."), detail: jsonDetail(event.payload.questions) };
|
|
34567
34652
|
case "agent.user-input.resolved":
|
|
@@ -34647,6 +34732,7 @@ function toChildAgentActivityCard({ event, identity }) {
|
|
|
34647
34732
|
case "agent.session.skills.updated":
|
|
34648
34733
|
case "agent.session.state.changed":
|
|
34649
34734
|
case "agent.session.ended":
|
|
34735
|
+
case "agent.context.compaction.request.completed":
|
|
34650
34736
|
case "agent.user-input.resolved":
|
|
34651
34737
|
case "agent.error":
|
|
34652
34738
|
throw new SessionProjectionProtocolError(`Cannot attribute non-child session event type ${event.type} to a subagent.`);
|
|
@@ -34689,7 +34775,7 @@ ${card.detail}`;
|
|
|
34689
34775
|
function childActivityIdentity(event) {
|
|
34690
34776
|
if (event.type === "agent.subagent.started" || event.type === "agent.subagent.progress" || event.type === "agent.subagent.ended") {
|
|
34691
34777
|
if (event.actor.type === "subagent") {
|
|
34692
|
-
if (!
|
|
34778
|
+
if (!agentSubagentIdentitiesEqual(event.actor, event.payload))
|
|
34693
34779
|
throw new SessionProjectionProtocolError(`Retained session event type ${event.type} carried contradictory subagent actor and payload identity.`);
|
|
34694
34780
|
return {
|
|
34695
34781
|
...event.actor,
|
|
@@ -34711,14 +34797,6 @@ function childActivityIdentity(event) {
|
|
|
34711
34797
|
}
|
|
34712
34798
|
return;
|
|
34713
34799
|
}
|
|
34714
|
-
function subagentLifecycleIdentityMatches({ actor, payload }) {
|
|
34715
|
-
return actor.actorId === payload.actorId && actor.subagentId === payload.subagentId && actor.parentActorId === payload.parentActorId && actor.parentToolCallId === payload.parentToolCallId && subagentOriginsMatch(actor.origin, payload.origin);
|
|
34716
|
-
}
|
|
34717
|
-
function subagentOriginsMatch(left, right) {
|
|
34718
|
-
if (left.type === "tool_call")
|
|
34719
|
-
return right.type === "tool_call" && left.toolCallId === right.toolCallId;
|
|
34720
|
-
return right.type === "provider_task" && left.taskId === right.taskId;
|
|
34721
|
-
}
|
|
34722
34800
|
function recordAgentLineageEvent({
|
|
34723
34801
|
state,
|
|
34724
34802
|
event,
|
|
@@ -34734,7 +34812,7 @@ function recordAgentLineageEvent({
|
|
|
34734
34812
|
return state;
|
|
34735
34813
|
throw error93;
|
|
34736
34814
|
}
|
|
34737
|
-
const runtimeBase =
|
|
34815
|
+
const runtimeBase = agentRuntimeIdentityKey(parsed);
|
|
34738
34816
|
let childLineage = state.childLineage;
|
|
34739
34817
|
if (parsed.type === "agent.session.started" || parsed.type === "agent.session.ended") {
|
|
34740
34818
|
const boundaryKey = `${runtimeBase}:${lengthPrefixed(parsed.eventId)}`;
|
|
@@ -34793,7 +34871,7 @@ function recordAgentLineageEvent({
|
|
|
34793
34871
|
return stampResolvedAttribution({ state: nextState, retainedEventId, fact, owner: resolution.owner });
|
|
34794
34872
|
}
|
|
34795
34873
|
function resolveBodyFactAgainstOwners(owners, fact) {
|
|
34796
|
-
const candidates = owners.filter((owner) => owner.runtimeScope === fact.runtimeScope &&
|
|
34874
|
+
const candidates = owners.filter((owner) => owner.runtimeScope === fact.runtimeScope && agentSubagentIdentitiesEqual(owner.identity, fact.identity));
|
|
34797
34875
|
const turnCandidates = candidates.filter((owner) => owner.childTurnIds.has(fact.turnId));
|
|
34798
34876
|
if (turnCandidates.length === 1)
|
|
34799
34877
|
return { status: "known", owner: turnCandidates[0] };
|
|
@@ -34825,9 +34903,6 @@ function stampResolvedAttribution({ state, retainedEventId, fact, owner }) {
|
|
|
34825
34903
|
}
|
|
34826
34904
|
return state;
|
|
34827
34905
|
}
|
|
34828
|
-
function lineageRuntimeBase(event) {
|
|
34829
|
-
return `${lengthPrefixed(event.sessionId)}:${lengthPrefixed(event.providerSessionId)}`;
|
|
34830
|
-
}
|
|
34831
34906
|
function lineageRuntimeScope({ runtimeBase, epoch }) {
|
|
34832
34907
|
return `${runtimeBase}:${epoch}`;
|
|
34833
34908
|
}
|
|
@@ -34840,9 +34915,6 @@ function isChildLineageFact(fact) {
|
|
|
34840
34915
|
function isSubagentLifecycleType(type) {
|
|
34841
34916
|
return type === "agent.subagent.started" || type === "agent.subagent.progress" || type === "agent.subagent.ended";
|
|
34842
34917
|
}
|
|
34843
|
-
function childIdentityMatches(left, right) {
|
|
34844
|
-
return left.actorId === right.actorId && left.subagentId === right.subagentId && left.parentActorId === right.parentActorId && left.parentToolCallId === right.parentToolCallId && subagentOriginsMatch(left.origin, right.origin);
|
|
34845
|
-
}
|
|
34846
34918
|
function childIdentityCanAnchor(identity) {
|
|
34847
34919
|
return identity.actorId !== identity.parentActorId && (identity.origin.type !== "tool_call" || identity.parentToolCallId === undefined || identity.parentToolCallId === identity.origin.toolCallId);
|
|
34848
34920
|
}
|
|
@@ -34876,9 +34948,9 @@ function reconcileChildLineage(state) {
|
|
|
34876
34948
|
if (parent && ownerHasActorAncestor(parent, fact.identity.actorId))
|
|
34877
34949
|
return;
|
|
34878
34950
|
const samePlacement = owners.filter((owner2) => owner2.runtimeScope === fact.runtimeScope && owner2.owningMainTurnId === owningMainTurnId && owner2.parent === parent && owner2.identity.actorId === fact.identity.actorId && owner2.identity.subagentId === fact.identity.subagentId);
|
|
34879
|
-
if (samePlacement.some((owner2) => !
|
|
34951
|
+
if (samePlacement.some((owner2) => !agentSubagentIdentitiesEqual(owner2.identity, fact.identity)))
|
|
34880
34952
|
return;
|
|
34881
|
-
const existing = samePlacement.find((owner2) =>
|
|
34953
|
+
const existing = samePlacement.find((owner2) => agentSubagentIdentitiesEqual(owner2.identity, fact.identity));
|
|
34882
34954
|
if (existing)
|
|
34883
34955
|
return existing;
|
|
34884
34956
|
const owner = {
|
|
@@ -34912,7 +34984,7 @@ function reconcileChildLineage(state) {
|
|
|
34912
34984
|
const toolTurn = mainTurnForToolOrigin(fact);
|
|
34913
34985
|
if (toolTurn === undefined)
|
|
34914
34986
|
continue;
|
|
34915
|
-
const owner = owners.find((candidate) => candidate.runtimeScope === fact.runtimeScope && candidate.parent === null && candidate.owningMainTurnId === toolTurn &&
|
|
34987
|
+
const owner = owners.find((candidate) => candidate.runtimeScope === fact.runtimeScope && candidate.parent === null && candidate.owningMainTurnId === toolTurn && agentSubagentIdentitiesEqual(candidate.identity, fact.identity)) ?? createOwner({ fact, owningMainTurnId: toolTurn, parent: null });
|
|
34916
34988
|
if (owner) {
|
|
34917
34989
|
ownerByFactOrder.set(fact.order, owner);
|
|
34918
34990
|
owner.childTurnIds.add(fact.turnId);
|
|
@@ -34925,7 +34997,7 @@ function reconcileChildLineage(state) {
|
|
|
34925
34997
|
for (const fact of childFacts) {
|
|
34926
34998
|
if (ownerByFactOrder.has(fact.order))
|
|
34927
34999
|
continue;
|
|
34928
|
-
const candidates = owners.filter((owner2) => owner2.runtimeScope === fact.runtimeScope &&
|
|
35000
|
+
const candidates = owners.filter((owner2) => owner2.runtimeScope === fact.runtimeScope && agentSubagentIdentitiesEqual(owner2.identity, fact.identity));
|
|
34929
35001
|
const turnCandidates = candidates.filter((owner2) => owner2.childTurnIds.has(fact.turnId));
|
|
34930
35002
|
const owner = turnCandidates.length === 1 ? turnCandidates[0] : candidates.length === 1 ? candidates[0] : undefined;
|
|
34931
35003
|
if (!owner || fact.eventType === "agent.subagent.started")
|
|
@@ -35001,12 +35073,16 @@ function ownerPath(owner) {
|
|
|
35001
35073
|
return path;
|
|
35002
35074
|
}
|
|
35003
35075
|
function childAttributionEqual(left, right) {
|
|
35004
|
-
if (left
|
|
35076
|
+
if (left === right)
|
|
35077
|
+
return true;
|
|
35078
|
+
if (!left || !right)
|
|
35079
|
+
return false;
|
|
35080
|
+
if (left.status !== right.status || left.activityTitle !== right.activityTitle || left.identity.name !== right.identity.name || !agentSubagentIdentitiesEqual(left.identity, right.identity)) {
|
|
35005
35081
|
return false;
|
|
35006
35082
|
}
|
|
35007
35083
|
if (left.status === "unresolved" || right.status === "unresolved")
|
|
35008
35084
|
return true;
|
|
35009
|
-
return left.ownerKey === right.ownerKey && left.owningMainTurnId === right.owningMainTurnId && left.path.length === right.path.length && left.path.every((identity, index) =>
|
|
35085
|
+
return left.ownerKey === right.ownerKey && left.owningMainTurnId === right.owningMainTurnId && left.path.length === right.path.length && left.path.every((identity, index) => identity.name === right.path[index].name && agentSubagentIdentitiesEqual(identity, right.path[index]));
|
|
35010
35086
|
}
|
|
35011
35087
|
function terminalSafeSingleLine(value) {
|
|
35012
35088
|
return stripAnsi(value).replace(/\s+/gu, " ").trim();
|
|
@@ -36935,6 +37011,19 @@ async function createNewSessionWizard({
|
|
|
36935
37011
|
overrides.delete(repositoryId);
|
|
36936
37012
|
else
|
|
36937
37013
|
overrides.set(repositoryId, isSelected);
|
|
37014
|
+
}, branchOverridesForSelection = function() {
|
|
37015
|
+
return [...selectedBranches].map(([repositoryId, branchName]) => ({ repositoryId, branchName }));
|
|
37016
|
+
}, branchOptions = function() {
|
|
37017
|
+
return [...selectedRepositoryIds()].flatMap((repositoryId) => {
|
|
37018
|
+
const existing = branchSuggestions.filter((suggestion) => suggestion.repositoryId === repositoryId && suggestion.suggestionKind !== "createSessionBranch");
|
|
37019
|
+
return [...existing, { suggestionKind: "createSessionBranch", repositoryId, branchName: null, pullRequest: null }];
|
|
37020
|
+
});
|
|
37021
|
+
}, selectBranchOption = function() {
|
|
37022
|
+
const option = branchOptions()[branchOptionIndex];
|
|
37023
|
+
if (option.branchName === null)
|
|
37024
|
+
selectedBranches.delete(option.repositoryId);
|
|
37025
|
+
else
|
|
37026
|
+
selectedBranches.set(option.repositoryId, option.branchName);
|
|
36938
37027
|
}, renderRepositoryLoadingSkeleton = function() {
|
|
36939
37028
|
return new StyledText5([
|
|
36940
37029
|
dim4(fg6(PALETTE.dimText)(`\u283F \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
@@ -36947,7 +37036,7 @@ async function createNewSessionWizard({
|
|
|
36947
37036
|
const orient = (body) => joinStyled([renderStepIndicator({
|
|
36948
37037
|
step,
|
|
36949
37038
|
hasInstallationChoice: installationIds.length > 1,
|
|
36950
|
-
hasBranchChoice: step === "loadingBranches" || branchSuggestions.some((suggestion) => suggestion.suggestionKind !== "createSessionBranch")
|
|
37039
|
+
hasBranchChoice: step === "loadingBranches" || step === "branchError" || branchSuggestions.some((suggestion) => suggestion.suggestionKind !== "createSessionBranch")
|
|
36951
37040
|
}), body], `
|
|
36952
37041
|
`);
|
|
36953
37042
|
if (composerVisible && !composerMounted) {
|
|
@@ -37023,31 +37112,39 @@ async function createNewSessionWizard({
|
|
|
37023
37112
|
} else if (step === "loadingBranches") {
|
|
37024
37113
|
content.content = orient(joinStyled([
|
|
37025
37114
|
new StyledText5([stepHeader("Choose branches")]),
|
|
37026
|
-
new StyledText5([fg6(PALETTE.progress)(`${suggestionSpinnerFrames[suggestionSpinnerFrame]} Remy is
|
|
37115
|
+
new StyledText5([fg6(PALETTE.progress)(`${suggestionSpinnerFrames[suggestionSpinnerFrame]} Remy is analyzing session, PR, and branch references\u2026`)]),
|
|
37027
37116
|
new StyledText5([dim4(fg6(PALETTE.dimText)("This can take a few seconds."))]),
|
|
37028
37117
|
stringToStyledText4("esc back")
|
|
37029
37118
|
], `
|
|
37030
37119
|
|
|
37120
|
+
`));
|
|
37121
|
+
} else if (step === "branchError") {
|
|
37122
|
+
content.content = orient(joinStyled([
|
|
37123
|
+
new StyledText5([stepHeader("Branch lookup failed")]),
|
|
37124
|
+
stringToStyledText4(status),
|
|
37125
|
+
stringToStyledText4("r retry \xB7 n explicitly choose new branches \xB7 esc back")
|
|
37126
|
+
], `
|
|
37127
|
+
|
|
37031
37128
|
`));
|
|
37032
37129
|
} else if (step === "branches") {
|
|
37033
|
-
const
|
|
37034
|
-
const
|
|
37035
|
-
|
|
37036
|
-
|
|
37037
|
-
|
|
37038
|
-
|
|
37039
|
-
|
|
37040
|
-
|
|
37041
|
-
|
|
37042
|
-
|
|
37043
|
-
|
|
37044
|
-
|
|
37045
|
-
|
|
37046
|
-
|
|
37047
|
-
|
|
37130
|
+
const options = branchOptions();
|
|
37131
|
+
const visibleCount = Math.max(2, renderer.height - 12);
|
|
37132
|
+
const start = Math.max(0, Math.min(branchOptionIndex - Math.floor(visibleCount / 2), options.length - visibleCount));
|
|
37133
|
+
const parts = [
|
|
37134
|
+
new StyledText5([stepHeader("Choose branches")]),
|
|
37135
|
+
stringToStyledText4("Continue from the suggested branch, or choose new work for each repository:")
|
|
37136
|
+
];
|
|
37137
|
+
for (const [index, option] of options.slice(start, start + visibleCount).entries()) {
|
|
37138
|
+
const repository = installationRepositories().find((repository2) => repository2.id === option.repositoryId);
|
|
37139
|
+
const selected = (selectedBranches.get(option.repositoryId) ?? null) === option.branchName;
|
|
37140
|
+
const label = option.branchName === null ? "Create a new session branch" : `${option.branchName}${option.pullRequest ? ` (PR #${option.pullRequest.number}: ${option.pullRequest.title})` : ""}`;
|
|
37141
|
+
parts.push(new StyledText5(renderSelectableRow({
|
|
37142
|
+
label: `${selected ? "\u25CF" : "\u25CB"} ${repository?.fullName ?? option.repositoryId} \u2014 ${label}`,
|
|
37143
|
+
isCursor: start + index === branchOptionIndex
|
|
37144
|
+
})));
|
|
37048
37145
|
}
|
|
37146
|
+
parts.push(stringToStyledText4(`\u2191\u2193 move \xB7 space select \xB7 \u23CE select & review \xB7 esc back (${branchOptionIndex + 1}/${options.length})`));
|
|
37049
37147
|
content.content = orient(joinStyled(parts, `
|
|
37050
|
-
|
|
37051
37148
|
`));
|
|
37052
37149
|
} else if (repositoryListVisible) {
|
|
37053
37150
|
const selectionOverrides = searchSelections ?? manualSelections;
|
|
@@ -37092,13 +37189,13 @@ async function createNewSessionWizard({
|
|
|
37092
37189
|
editor.placeholder = "e.g. worker, migration, dashboard";
|
|
37093
37190
|
} else {
|
|
37094
37191
|
const selected = installationRepositories().filter((repository) => selectedRepositoryIds().has(repository.id));
|
|
37095
|
-
const branchOverrides =
|
|
37192
|
+
const branchOverrides = branchOverridesForSelection();
|
|
37096
37193
|
const meta5 = new StyledText5([
|
|
37097
37194
|
fg6(PALETTE.bodyText)(`Installation: ${selectedInstallationId() ?? "(missing)"}
|
|
37098
37195
|
`),
|
|
37099
37196
|
fg6(PALETTE.bodyText)(`Repositories: ${selected.map((repository) => repository.fullName).join(", ") || "(none)"}
|
|
37100
37197
|
`),
|
|
37101
|
-
fg6(PALETTE.bodyText)(`Branches: ${branchOverrides.length > 0 ?
|
|
37198
|
+
fg6(PALETTE.bodyText)(`Branches: ${branchOverrides.length > 0 ? selected.map((repository) => `${repository.fullName}: ${selectedBranches.get(repository.id) ?? "new session branch"}`).join(", ") : "new session branches"}
|
|
37102
37199
|
`),
|
|
37103
37200
|
fg6(PALETTE.bodyText)(`Model: ${newSessionModelLabel(model)} \xB7 ${newSessionReasoningEffortLabel(reasoningEffort)} reasoning`),
|
|
37104
37201
|
dim4(fg6(PALETTE.dimText)(" \u25B8 m model \xB7 \u2190\u2192 reasoning"))
|
|
@@ -37111,7 +37208,7 @@ async function createNewSessionWizard({
|
|
|
37111
37208
|
];
|
|
37112
37209
|
if (attachmentText.chunks.length > 0)
|
|
37113
37210
|
parts.push(attachmentText);
|
|
37114
|
-
parts.push(new StyledText5([dim4(fg6(PALETTE.dimText)(branchOverrides.length > 0 ? "Remy will continue on the selected
|
|
37211
|
+
parts.push(new StyledText5([dim4(fg6(PALETTE.dimText)(branchOverrides.length > 0 ? "Remy will continue on the selected branches and create new branches for other repositories; you land in the session view." : "Remy will clone the selected repositories, work on new session branches, and open a pull request for each repository; you land in the session view."))]));
|
|
37115
37212
|
parts.push(stringToStyledText4(branchSuggestions.some((suggestion) => suggestion.suggestionKind !== "createSessionBranch") ? "\u23CE create \xB7 e edit prompt \xB7 r repositories \xB7 b branches \xB7 esc back" : "\u23CE create \xB7 e edit prompt \xB7 r repositories \xB7 esc back"));
|
|
37116
37213
|
if (status)
|
|
37117
37214
|
parts.push(stringToStyledText4(status));
|
|
@@ -37244,7 +37341,7 @@ async function createNewSessionWizard({
|
|
|
37244
37341
|
returnToPromptFromRepositoryLoading();
|
|
37245
37342
|
return;
|
|
37246
37343
|
}
|
|
37247
|
-
if (step === "loadingBranches" || step === "branches") {
|
|
37344
|
+
if (step === "loadingBranches" || step === "branches" || step === "branchError") {
|
|
37248
37345
|
branchRequestGeneration += 1;
|
|
37249
37346
|
step = "repositories";
|
|
37250
37347
|
render();
|
|
@@ -37354,6 +37451,17 @@ async function createNewSessionWizard({
|
|
|
37354
37451
|
return;
|
|
37355
37452
|
}
|
|
37356
37453
|
}
|
|
37454
|
+
if (step === "branchError" && (key.name === "r" || key.name === "n")) {
|
|
37455
|
+
key.preventDefault();
|
|
37456
|
+
if (key.name === "r") {
|
|
37457
|
+
startBranchReview();
|
|
37458
|
+
} else {
|
|
37459
|
+
status = "";
|
|
37460
|
+
step = "confirmation";
|
|
37461
|
+
render();
|
|
37462
|
+
}
|
|
37463
|
+
return;
|
|
37464
|
+
}
|
|
37357
37465
|
if (step === "repositorySearch")
|
|
37358
37466
|
return;
|
|
37359
37467
|
if (step === "loadingSuggestions" && key.name === "s") {
|
|
@@ -37373,15 +37481,23 @@ async function createNewSessionWizard({
|
|
|
37373
37481
|
return;
|
|
37374
37482
|
}
|
|
37375
37483
|
}
|
|
37484
|
+
if (step === "branches" && key.name === "space") {
|
|
37485
|
+
key.preventDefault();
|
|
37486
|
+
selectBranchOption();
|
|
37487
|
+
render();
|
|
37488
|
+
return;
|
|
37489
|
+
}
|
|
37376
37490
|
if (step === "branches" && branchSuggestions.some((suggestion) => suggestion.suggestionKind !== "createSessionBranch") && (key.name === "up" || key.name === "down" || key.name === "left" || key.name === "right")) {
|
|
37377
37491
|
key.preventDefault();
|
|
37378
|
-
|
|
37492
|
+
const options = branchOptions();
|
|
37493
|
+
const direction = key.name === "up" || key.name === "left" ? -1 : 1;
|
|
37494
|
+
branchOptionIndex = (branchOptionIndex + direction + options.length) % options.length;
|
|
37379
37495
|
render();
|
|
37380
37496
|
return;
|
|
37381
37497
|
}
|
|
37382
37498
|
if (!composerMounted && (key.name === "return" || key.name === "enter")) {
|
|
37383
37499
|
key.preventDefault();
|
|
37384
|
-
if (step === "loadingBranches")
|
|
37500
|
+
if (step === "loadingBranches" || step === "branchError")
|
|
37385
37501
|
return;
|
|
37386
37502
|
submitEditor();
|
|
37387
37503
|
return;
|
|
@@ -37500,7 +37616,8 @@ async function createNewSessionWizard({
|
|
|
37500
37616
|
branchName: override.branchName,
|
|
37501
37617
|
pullRequest: null
|
|
37502
37618
|
})) ?? [];
|
|
37503
|
-
|
|
37619
|
+
const selectedBranches = new Map(initialDraft?.repositoryBranchOverrides?.map((override) => [override.repositoryId, override.branchName]));
|
|
37620
|
+
let branchOptionIndex = 0;
|
|
37504
37621
|
let status = initialError ?? "";
|
|
37505
37622
|
let attachmentFeedback;
|
|
37506
37623
|
let pendingPastedImageWrites = 0;
|
|
@@ -37575,9 +37692,16 @@ async function createNewSessionWizard({
|
|
|
37575
37692
|
if (!installationId)
|
|
37576
37693
|
return;
|
|
37577
37694
|
const repositoryIds = [...selectedRepositoryIds()];
|
|
37695
|
+
if (repositoryIds.length === 0) {
|
|
37696
|
+
branchSuggestions = [];
|
|
37697
|
+
selectedBranches.clear();
|
|
37698
|
+
step = "confirmation";
|
|
37699
|
+
render();
|
|
37700
|
+
return;
|
|
37701
|
+
}
|
|
37578
37702
|
const requestGeneration = ++branchRequestGeneration;
|
|
37579
37703
|
branchSuggestions = [];
|
|
37580
|
-
|
|
37704
|
+
selectedBranches.clear();
|
|
37581
37705
|
step = "loadingBranches";
|
|
37582
37706
|
status = "";
|
|
37583
37707
|
render();
|
|
@@ -37587,15 +37711,19 @@ async function createNewSessionWizard({
|
|
|
37587
37711
|
return;
|
|
37588
37712
|
branchSuggestions = suggestions;
|
|
37589
37713
|
const hasExistingBranch = branchSuggestions.some((suggestion) => suggestion.suggestionKind !== "createSessionBranch");
|
|
37590
|
-
|
|
37714
|
+
for (const suggestion of branchSuggestions) {
|
|
37715
|
+
if (suggestion.suggestionKind !== "createSessionBranch" && !selectedBranches.has(suggestion.repositoryId))
|
|
37716
|
+
selectedBranches.set(suggestion.repositoryId, suggestion.branchName);
|
|
37717
|
+
}
|
|
37718
|
+
branchOptionIndex = 0;
|
|
37591
37719
|
step = hasExistingBranch ? "branches" : "confirmation";
|
|
37592
37720
|
} catch (error93) {
|
|
37593
37721
|
if (destroyed || requestGeneration !== branchRequestGeneration || step !== "loadingBranches")
|
|
37594
37722
|
return;
|
|
37595
37723
|
branchSuggestions = [];
|
|
37596
|
-
|
|
37724
|
+
selectedBranches.clear();
|
|
37597
37725
|
status = error93 instanceof Error ? error93.message : String(error93);
|
|
37598
|
-
step = "
|
|
37726
|
+
step = "branchError";
|
|
37599
37727
|
}
|
|
37600
37728
|
render();
|
|
37601
37729
|
}
|
|
@@ -37668,7 +37796,7 @@ async function createNewSessionWizard({
|
|
|
37668
37796
|
fail(new Error("Selected repositories must belong to the chosen GitHub installation."));
|
|
37669
37797
|
return;
|
|
37670
37798
|
}
|
|
37671
|
-
const repositoryBranchOverrides =
|
|
37799
|
+
const repositoryBranchOverrides = branchOverridesForSelection();
|
|
37672
37800
|
const confirmation = Symbol("confirmation");
|
|
37673
37801
|
const confirmedAttachments = [...attachments];
|
|
37674
37802
|
const confirmedPrompt = prompt;
|
|
@@ -37755,6 +37883,7 @@ async function createNewSessionWizard({
|
|
|
37755
37883
|
return;
|
|
37756
37884
|
}
|
|
37757
37885
|
if (step === "branches") {
|
|
37886
|
+
selectBranchOption();
|
|
37758
37887
|
step = "confirmation";
|
|
37759
37888
|
render();
|
|
37760
37889
|
return;
|
|
@@ -37870,7 +37999,7 @@ function wizardStepKey(step) {
|
|
|
37870
37999
|
return "describe";
|
|
37871
38000
|
if (step === "installation")
|
|
37872
38001
|
return "installation";
|
|
37873
|
-
if (step === "loadingBranches" || step === "branches")
|
|
38002
|
+
if (step === "loadingBranches" || step === "branches" || step === "branchError")
|
|
37874
38003
|
return "branches";
|
|
37875
38004
|
if (step === "confirmation")
|
|
37876
38005
|
return "confirm";
|
|
@@ -37925,6 +38054,7 @@ var composerSlashCommands = [
|
|
|
37925
38054
|
{ value: "/sessions", description: "Back to the session list" },
|
|
37926
38055
|
{ value: "/complete", description: "Finish this session" },
|
|
37927
38056
|
{ value: "/cancel", description: "Cancel this session" },
|
|
38057
|
+
{ value: "/compact", description: "Compact main-thread context" },
|
|
37928
38058
|
{ value: "/new", description: "Start a new session" },
|
|
37929
38059
|
{ value: "/logout", description: "Sign out of Remy" },
|
|
37930
38060
|
{ value: "/help", description: "Show what you can do here" },
|
|
@@ -37936,6 +38066,7 @@ async function createSessionTui({
|
|
|
37936
38066
|
controller,
|
|
37937
38067
|
submitMessage,
|
|
37938
38068
|
requestInterrupt,
|
|
38069
|
+
requestCompact,
|
|
37939
38070
|
requestComplete,
|
|
37940
38071
|
requestCancel,
|
|
37941
38072
|
repositoryLabel,
|
|
@@ -38177,6 +38308,7 @@ async function createSessionTui({
|
|
|
38177
38308
|
let admittedSubmissions = [];
|
|
38178
38309
|
let stopState = { kind: "idle" };
|
|
38179
38310
|
let lifecycleRequestState = { kind: "idle" };
|
|
38311
|
+
let contextCompactionRequestState = { kind: "idle" };
|
|
38180
38312
|
let helpVisible = false;
|
|
38181
38313
|
let logoutConfirmationOpen = false;
|
|
38182
38314
|
let latestState = controller.getState();
|
|
@@ -38527,6 +38659,12 @@ async function createSessionTui({
|
|
|
38527
38659
|
handleLifecycleRequest("cancel");
|
|
38528
38660
|
return true;
|
|
38529
38661
|
}
|
|
38662
|
+
if (command === "/compact") {
|
|
38663
|
+
composer.setText("");
|
|
38664
|
+
composerDraft = { ...composerDraft, text: "" };
|
|
38665
|
+
await handleCompactionRequest();
|
|
38666
|
+
return true;
|
|
38667
|
+
}
|
|
38530
38668
|
if (command === "/logout") {
|
|
38531
38669
|
composer.setText("");
|
|
38532
38670
|
composerDraft = { ...composerDraft, text: "" };
|
|
@@ -38614,6 +38752,39 @@ async function createSessionTui({
|
|
|
38614
38752
|
}
|
|
38615
38753
|
render();
|
|
38616
38754
|
}
|
|
38755
|
+
async function handleCompactionRequest() {
|
|
38756
|
+
if (contextCompactionRequestState.kind === "requesting")
|
|
38757
|
+
return;
|
|
38758
|
+
if (latestState.aggregateStatus !== "open") {
|
|
38759
|
+
composerFeedback = "This session is already terminal.";
|
|
38760
|
+
render();
|
|
38761
|
+
return;
|
|
38762
|
+
}
|
|
38763
|
+
const idempotencyKey = contextCompactionRequestState.kind === "delivery-unknown" ? contextCompactionRequestState.idempotencyKey : crypto.randomUUID();
|
|
38764
|
+
contextCompactionRequestState = { kind: "requesting", idempotencyKey };
|
|
38765
|
+
composerFeedback = "Requesting context compaction\u2026";
|
|
38766
|
+
render();
|
|
38767
|
+
try {
|
|
38768
|
+
await requestCompact({ idempotencyKey });
|
|
38769
|
+
if (!destroyed) {
|
|
38770
|
+
contextCompactionRequestState = { kind: "admitted" };
|
|
38771
|
+
composerFeedback = "Context compaction request admitted. Result will appear in the timeline.";
|
|
38772
|
+
}
|
|
38773
|
+
} catch (error93) {
|
|
38774
|
+
if (!destroyed) {
|
|
38775
|
+
const message = error93 instanceof Error ? error93.message : String(error93);
|
|
38776
|
+
if (isKnownClientRejection(error93)) {
|
|
38777
|
+
contextCompactionRequestState = { kind: "idle" };
|
|
38778
|
+
composerFeedback = `Could not request context compaction: ${message}`;
|
|
38779
|
+
} else {
|
|
38780
|
+
contextCompactionRequestState = { kind: "delivery-unknown", idempotencyKey };
|
|
38781
|
+
composerFeedback = `Context compaction admission is unknown: ${message}. Run /compact again to retry the same request.`;
|
|
38782
|
+
}
|
|
38783
|
+
}
|
|
38784
|
+
}
|
|
38785
|
+
if (!destroyed)
|
|
38786
|
+
render();
|
|
38787
|
+
}
|
|
38617
38788
|
async function handleLifecycleRequest(operation) {
|
|
38618
38789
|
if (lifecycleRequestState.kind === "pending")
|
|
38619
38790
|
return;
|
|
@@ -38740,6 +38911,7 @@ var helpEntries = [
|
|
|
38740
38911
|
{ group: "command", token: "/sessions", description: "back to the session list" },
|
|
38741
38912
|
{ group: "command", token: "/complete", description: "finish this session" },
|
|
38742
38913
|
{ group: "command", token: "/cancel", description: "cancel this session" },
|
|
38914
|
+
{ group: "command", token: "/compact", description: "compact main-thread context" },
|
|
38743
38915
|
{ group: "command", token: "/logout", description: "sign out of Remy" },
|
|
38744
38916
|
{ group: "command", token: "/exit", description: "leave Remy" },
|
|
38745
38917
|
{ group: "key", token: "esc", description: "stop Remy\u2019s current turn" },
|
|
@@ -38957,19 +39129,7 @@ function activityGlyph({ kind, inFlight }) {
|
|
|
38957
39129
|
return { glyph: "\u2713", color: PALETTE.dimText };
|
|
38958
39130
|
}
|
|
38959
39131
|
function activityCardsHaveEqualDisclosure(left, right) {
|
|
38960
|
-
return left.kind === right.kind && left.title === right.title && left.summary === right.summary && left.detail === right.detail && left.detailFormat === right.detailFormat &&
|
|
38961
|
-
}
|
|
38962
|
-
function canonicalValuesEqual(left, right) {
|
|
38963
|
-
if (Object.is(left, right))
|
|
38964
|
-
return true;
|
|
38965
|
-
if (Array.isArray(left) || Array.isArray(right)) {
|
|
38966
|
-
return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => canonicalValuesEqual(value, right[index]));
|
|
38967
|
-
}
|
|
38968
|
-
if (typeof left !== "object" || left === null || typeof right !== "object" || right === null)
|
|
38969
|
-
return false;
|
|
38970
|
-
const leftEntries = Object.entries(left);
|
|
38971
|
-
const rightEntries = Object.entries(right);
|
|
38972
|
-
return leftEntries.length === rightEntries.length && leftEntries.every(([key, value], index) => rightEntries[index]?.[0] === key && canonicalValuesEqual(value, rightEntries[index]?.[1]));
|
|
39132
|
+
return left.kind === right.kind && left.title === right.title && left.summary === right.summary && left.detail === right.detail && left.detailFormat === right.detailFormat && childAttributionEqual(left.attribution, right.attribution);
|
|
38973
39133
|
}
|
|
38974
39134
|
function renderActivityGroup({ items, activityExpanded }) {
|
|
38975
39135
|
if (items.length === 0)
|
|
@@ -39170,6 +39330,12 @@ function renderComposerStatus({ admittedSubmissions }) {
|
|
|
39170
39330
|
|
|
39171
39331
|
`);
|
|
39172
39332
|
}
|
|
39333
|
+
function isKnownClientRejection(error93) {
|
|
39334
|
+
if (typeof error93 !== "object" || error93 === null || !("status" in error93))
|
|
39335
|
+
return false;
|
|
39336
|
+
const status = error93.status;
|
|
39337
|
+
return typeof status === "number" && status >= 400 && status < 500;
|
|
39338
|
+
}
|
|
39173
39339
|
async function createDefaultRenderer3() {
|
|
39174
39340
|
return await createRemyRenderer();
|
|
39175
39341
|
}
|
|
@@ -39430,7 +39596,7 @@ var compactMarkRows = 9;
|
|
|
39430
39596
|
var compactMinWidth = 48;
|
|
39431
39597
|
var compactMinHeight = 20;
|
|
39432
39598
|
var markBrightnessGain = 4.2;
|
|
39433
|
-
var remyCliVersion = "1.
|
|
39599
|
+
var remyCliVersion = "1.16.0";
|
|
39434
39600
|
async function showRemySplash({
|
|
39435
39601
|
createRenderer = createRemyRenderer,
|
|
39436
39602
|
durationMs = splashDurationMs,
|
|
@@ -40833,6 +40999,9 @@ async function runAttachedSession({
|
|
|
40833
40999
|
requestInterrupt: async ({ idempotencyKey }) => {
|
|
40834
41000
|
await operations.interruptSession({ client: operations.client, sessionId, idempotencyKey });
|
|
40835
41001
|
},
|
|
41002
|
+
requestCompact: async ({ idempotencyKey }) => {
|
|
41003
|
+
await operations.compactSessionContext({ client: operations.client, sessionId, idempotencyKey });
|
|
41004
|
+
},
|
|
40836
41005
|
requestComplete: async () => {
|
|
40837
41006
|
const detail = await operations.completeSession({ client: operations.client, sessionId });
|
|
40838
41007
|
controller.updateDetail(detail);
|
|
@@ -40959,6 +41128,7 @@ async function createSessionOperations(dependencies, { onAuthenticated } = {}) {
|
|
|
40959
41128
|
appendSessionMessage: dependencies.appendSessionMessage ?? appendSessionMessage,
|
|
40960
41129
|
cancelSession: dependencies.cancelSession ?? cancelSession,
|
|
40961
41130
|
completeSession: dependencies.completeSession ?? completeSession,
|
|
41131
|
+
compactSessionContext: dependencies.compactSessionContext ?? compactSessionContext,
|
|
40962
41132
|
interruptSession: dependencies.interruptSession ?? interruptSession,
|
|
40963
41133
|
getSession: dependencies.getSession ?? getSession,
|
|
40964
41134
|
listSessionEvents: dependencies.listSessionEvents ?? listSessionEvents,
|
|
@@ -40979,6 +41149,7 @@ async function createSessionOperations(dependencies, { onAuthenticated } = {}) {
|
|
|
40979
41149
|
appendSessionMessage: dependencies.appendSessionMessage ?? appendSessionMessage,
|
|
40980
41150
|
cancelSession: dependencies.cancelSession ?? cancelSession,
|
|
40981
41151
|
completeSession: dependencies.completeSession ?? completeSession,
|
|
41152
|
+
compactSessionContext: dependencies.compactSessionContext ?? compactSessionContext,
|
|
40982
41153
|
interruptSession: dependencies.interruptSession ?? interruptSession,
|
|
40983
41154
|
getSession: dependencies.getSession ?? getSession,
|
|
40984
41155
|
listSessionEvents: dependencies.listSessionEvents ?? listSessionEvents,
|