@meistrari/remy-cli 1.11.0 → 1.13.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 +2 -0
  2. package/dist/remy.js +652 -48
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -46,6 +46,8 @@ Use Up/Down to select a session in the dashboard, Left/Right to load the adjacen
46
46
 
47
47
  The **Live reasoning preview** shows the newest main-agent summary as it arrives. It is a short, best-effort preview—not private chain-of-thought. Long previews show **Preview shortened.** Opening or reconnecting partway through a summary may show no preview; the final summary still appears in activity history. Disconnecting or finishing the item clears the live preview.
48
48
 
49
+ Subagent work appears as named **Subagent · <name>** activity rather than messages from Remy. Resolved descendants stay grouped under their actual parent as a compact `Parent › Child` path; missing or contradictory ancestry remains explicitly **Unattributed subagent** instead of being assigned to the active main turn. Press `Ctrl+O` to read retained child messages, complete tool results, reasoning summaries, and child IDs. Child input does not enter your prompt history, child output does not replace Remy's main live preview, and parent or main completion does not end a still-running descendant. Child-specific Stop controls are not available.
50
+
49
51
  Published files and Tela Pages appear in the timeline. A Tela Page row includes its title and canonical URL so you can open it directly from the terminal.
50
52
 
51
53
  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.
package/dist/remy.js CHANGED
@@ -32478,6 +32478,32 @@ var usageAgentEventSchema = agentTurnEventBaseSchema.extend({
32478
32478
  usage: agentUsageSchema
32479
32479
  }).strict()
32480
32480
  }).strict();
32481
+ var agentContextWindowSchema = zod_default2.discriminatedUnion("status", [
32482
+ zod_default2.object({
32483
+ status: zod_default2.literal("unknown")
32484
+ }).strict(),
32485
+ zod_default2.object({
32486
+ status: zod_default2.literal("known"),
32487
+ capacityTokens: zod_default2.number().int().positive().max(Number.MAX_SAFE_INTEGER),
32488
+ remainingPercent: zod_default2.number().int().min(0).max(100)
32489
+ }).strict()
32490
+ ]);
32491
+ var agentContextSnapshotSchema = zod_default2.discriminatedUnion("status", [
32492
+ zod_default2.object({
32493
+ status: zod_default2.literal("unknown")
32494
+ }).strict(),
32495
+ zod_default2.object({
32496
+ status: zod_default2.literal("observed"),
32497
+ usedTokens: zod_default2.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
32498
+ window: agentContextWindowSchema
32499
+ }).strict()
32500
+ ]);
32501
+ var contextUpdatedAgentEventSchema = agentTurnEventBaseSchema.extend({
32502
+ type: zod_default2.literal("context.updated"),
32503
+ payload: zod_default2.object({
32504
+ snapshot: agentContextSnapshotSchema
32505
+ }).strict()
32506
+ }).strict();
32481
32507
  var contextCompactionStartedAgentEventSchema = agentTurnEventBaseSchema.extend({
32482
32508
  type: zod_default2.literal("context.compaction.started"),
32483
32509
  payload: zod_default2.object({
@@ -32546,6 +32572,7 @@ var agentEventSchema = zod_default2.discriminatedUnion("type", [
32546
32572
  subagentProgressAgentEventSchema,
32547
32573
  subagentEndedAgentEventSchema,
32548
32574
  usageAgentEventSchema,
32575
+ contextUpdatedAgentEventSchema,
32549
32576
  contextCompactionStartedAgentEventSchema,
32550
32577
  contextCompactionCompletedAgentEventSchema,
32551
32578
  userInputRequestedAgentEventSchema,
@@ -32982,7 +33009,10 @@ var retainedSessionEventSchema = exports_external2.object({
32982
33009
  occurred_at: exports_external2.iso.datetime(),
32983
33010
  recorded_at: exports_external2.iso.datetime(),
32984
33011
  event: retainedEventBodySchema,
32985
- artifact: sessionArtifactEventSchema.optional()
33012
+ artifact: sessionArtifactEventSchema.optional(),
33013
+ context: exports_external2.object({
33014
+ main: agentContextSnapshotSchema
33015
+ }).strict().optional()
32986
33016
  }).strict();
32987
33017
  var ephemeralSessionEventSchema = exports_external2.object({
32988
33018
  occurred_at: exports_external2.iso.datetime(),
@@ -33810,6 +33840,9 @@ var wrappedSubagentEndedAgentEventSchema = subagentEndedAgentEventSchema.extend(
33810
33840
  var wrappedUsageAgentEventSchema = usageAgentEventSchema.extend({
33811
33841
  type: zod_default2.literal("agent.usage")
33812
33842
  }).strict();
33843
+ var wrappedContextUpdatedAgentEventSchema = contextUpdatedAgentEventSchema.extend({
33844
+ type: zod_default2.literal("agent.context.updated")
33845
+ }).strict();
33813
33846
  var wrappedContextCompactionStartedAgentEventSchema = contextCompactionStartedAgentEventSchema.extend({
33814
33847
  type: zod_default2.literal("agent.context.compaction.started")
33815
33848
  }).strict();
@@ -33847,6 +33880,7 @@ var wrappedAgentEventSchema = zod_default2.discriminatedUnion("type", [
33847
33880
  wrappedSubagentProgressAgentEventSchema,
33848
33881
  wrappedSubagentEndedAgentEventSchema,
33849
33882
  wrappedUsageAgentEventSchema,
33883
+ wrappedContextUpdatedAgentEventSchema,
33850
33884
  wrappedContextCompactionStartedAgentEventSchema,
33851
33885
  wrappedContextCompactionCompletedAgentEventSchema,
33852
33886
  wrappedUserInputRequestedAgentEventSchema,
@@ -33891,15 +33925,16 @@ var sessionWorkspaceGitRevisionEventSchema = exports_external2.object({
33891
33925
  trigger: exports_external2.enum(["turn-ended", "boot-reconcile"])
33892
33926
  }).passthrough()
33893
33927
  }).passthrough();
33894
- var agentTurnEndedEventSchema = exports_external2.object({
33895
- type: exports_external2.literal("agent.turn.ended"),
33896
- turnId: exports_external2.string().min(1),
33897
- actor: exports_external2.object({ type: exports_external2.enum(["main", "subagent"]) }).passthrough(),
33898
- payload: exports_external2.object({ status: exports_external2.enum(["completed", "failed", "cancelled", "interrupted"]) }).passthrough()
33928
+ var agentTurnEndedEventSchema = wrappedTurnEndedAgentEventSchema.pick({
33929
+ type: true,
33930
+ turnId: true,
33931
+ actor: true,
33932
+ payload: true
33899
33933
  }).passthrough();
33900
- var agentMessageDeltaEventSchema = exports_external2.object({
33901
- type: exports_external2.literal("agent.message.delta"),
33902
- payload: exports_external2.object({ role: exports_external2.string(), delta: exports_external2.string() }).passthrough()
33934
+ var agentMessageDeltaEventSchema = wrappedMessageDeltaAgentEventSchema.pick({
33935
+ type: true,
33936
+ actor: true,
33937
+ payload: true
33903
33938
  }).passthrough();
33904
33939
  var publicMessageContentSegmentSchema = exports_external2.discriminatedUnion("type", [
33905
33940
  exports_external2.strictObject({ type: exports_external2.literal("text"), text: exports_external2.string() }),
@@ -33950,7 +33985,18 @@ function createSessionViewState({ detail, activeMessageId }) {
33950
33985
  workTurnBaselines: {},
33951
33986
  messageTurns: {},
33952
33987
  retainedTurnStarts: {},
33953
- retainedTurnEnds: {}
33988
+ retainedTurnEnds: {},
33989
+ childLineage: {
33990
+ nextOrder: 0,
33991
+ runtimeEpochs: {},
33992
+ seenRuntimeBoundaryEventIds: {},
33993
+ facts: [],
33994
+ owners: []
33995
+ },
33996
+ context: {
33997
+ snapshot: { status: "unknown" },
33998
+ through: 0
33999
+ }
33954
34000
  };
33955
34001
  }
33956
34002
  function updateSessionDetail({ state, detail }) {
@@ -33981,8 +34027,11 @@ function projectRemoteSessionEvent({ state, frame }) {
33981
34027
  retainedEventId: frame.id,
33982
34028
  artifact: frame.data.artifact
33983
34029
  });
34030
+ const annotation = frame.data.context;
34031
+ const context = annotation && frame.data.history_sequence > projected.context.through ? { snapshot: annotation.main, through: frame.data.history_sequence } : projected.context;
33984
34032
  return {
33985
34033
  ...projected,
34034
+ context,
33986
34035
  lastRetainedEventId: frame.id,
33987
34036
  seenRetainedEventIds: { ...projected.seenRetainedEventIds, [frame.id]: true }
33988
34037
  };
@@ -33997,7 +34046,7 @@ function sessionTurnOutcome({ state, sessionMessageId }) {
33997
34046
  }
33998
34047
  function projectEphemeralEvent({ state, event }) {
33999
34048
  const messageDelta = agentMessageDeltaEventSchema.safeParse(event);
34000
- if (messageDelta.success && messageDelta.data.payload.role === "assistant") {
34049
+ if (messageDelta.success && messageDelta.data.actor.type === "main" && messageDelta.data.payload.role === "assistant") {
34001
34050
  return {
34002
34051
  ...state,
34003
34052
  previews: { ...state.previews, assistantText: state.previews.assistantText + messageDelta.data.payload.delta }
@@ -34018,6 +34067,7 @@ function projectRetainedEvent({
34018
34067
  const workspaceGitRevision = sessionWorkspaceGitRevisionEventSchema.safeParse(event);
34019
34068
  const turnEnded = agentTurnEndedEventSchema.safeParse(event);
34020
34069
  let projected = messageCreated.success ? projectSessionMessageCreated({ state, event: messageCreated.data, occurredAt }) : turnAssociated.success ? projectSessionMessageTurnAssociated({ state, event: turnAssociated.data }) : workspaceGitInitialized.success ? projectSessionWorkspaceGitInitialized({ state, event: workspaceGitInitialized.data, occurredAt, retainedEventId }) : workspaceGitRevision.success ? projectSessionWorkspaceGitRevision({ state, event: workspaceGitRevision.data, occurredAt, retainedEventId }) : turnEnded.success ? projectAgentTurnEnded({ state, event: turnEnded.data, occurredAt, retainedEventId }) : projectDurableAgentEvent({ state, event, occurredAt, retainedEventId });
34070
+ projected = recordAgentLineageEvent({ state: projected, event, retainedEventId });
34021
34071
  if (artifact) {
34022
34072
  const publication = artifact.kind === "file" ? { artifactId: artifact.artifact_id, kind: artifact.kind, title: artifact.filename } : { artifactId: artifact.artifact_id, kind: artifact.kind, title: artifact.title, url: artifact.url };
34023
34073
  const timelineArtifact = artifact.kind === "file" ? {
@@ -34130,19 +34180,24 @@ function projectSessionWorkspaceGitRevision({ state, event, occurredAt, retained
34130
34180
  });
34131
34181
  }
34132
34182
  function projectAgentTurnEnded({ state, event, occurredAt, retainedEventId }) {
34133
- const retainedTurnEnds = { ...state.retainedTurnEnds, [event.turnId]: { actorType: event.actor.type, outcome: event.payload.status } };
34134
- const messageTurns = event.actor.type === "main" ? Object.fromEntries(Object.entries(state.messageTurns).map(([messageId, turn]) => [messageId, turn.turnId === event.turnId ? { ...turn, outcome: event.payload.status } : turn])) : state.messageTurns;
34135
- return appendActivity({
34136
- state: { ...state, retainedTurnEnds, messageTurns },
34137
- retainedEventId,
34138
- occurredAt,
34139
- card: 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}.` }
34183
+ const stateWithTurnOutcome = event.actor.type === "main" ? {
34184
+ ...state,
34185
+ retainedTurnEnds: { ...state.retainedTurnEnds, [event.turnId]: { actorType: event.actor.type, outcome: event.payload.status } },
34186
+ messageTurns: Object.fromEntries(Object.entries(state.messageTurns).map(([messageId, turn]) => [messageId, turn.turnId === event.turnId ? { ...turn, outcome: event.payload.status } : turn]))
34187
+ } : state;
34188
+ const card = event.actor.type === "main" ? 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}.` } : createChildActivityCard({
34189
+ identity: event.actor,
34190
+ activityTitle: event.payload.status === "failed" ? "Turn failed" : "Turn ended",
34191
+ 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}.` }
34140
34192
  });
34193
+ return appendActivity({ state: stateWithTurnOutcome, retainedEventId, occurredAt, card });
34141
34194
  }
34142
34195
  function projectDurableAgentEvent({ state, event, occurredAt, retainedEventId }) {
34143
34196
  const agentEvent = parseDurableAgentEvent(event);
34144
34197
  if (agentEvent.type === "agent.message.ended")
34145
- return projectAgentMessageEnded({ state, event: agentEvent, occurredAt });
34198
+ return projectAgentMessageEnded({ state, event: agentEvent, occurredAt, retainedEventId });
34199
+ if (agentEvent.type === "agent.context.updated")
34200
+ return state;
34146
34201
  if (agentEvent.type === "agent.work.observed" && agentEvent.actor.type === "main")
34147
34202
  return projectAgentWorkObserved({ state, event: agentEvent, occurredAt });
34148
34203
  const stateWithTurnStart = agentEvent.type === "agent.turn.started" && agentEvent.actor.type === "main" ? {
@@ -34152,6 +34207,9 @@ function projectDurableAgentEvent({ state, event, occurredAt, retainedEventId })
34152
34207
  } : state;
34153
34208
  return appendActivity({ state: stateWithTurnStart, retainedEventId, occurredAt, card: toAgentActivityCard(agentEvent) });
34154
34209
  }
34210
+ function hasOwnContextIdentity(identities, identity) {
34211
+ return Object.prototype.hasOwnProperty.call(identities, identity);
34212
+ }
34155
34213
  function projectAgentWorkObserved({
34156
34214
  state,
34157
34215
  event,
@@ -34223,23 +34281,45 @@ function patchedWorkItemId(observation) {
34223
34281
  return observation.itemId;
34224
34282
  return null;
34225
34283
  }
34226
- function projectAgentMessageEnded({ state, event, occurredAt }) {
34284
+ function projectAgentMessageEnded({ state, event, occurredAt, retainedEventId }) {
34227
34285
  const messageId = event.payload.messageId;
34286
+ const text = event.payload.content.map(publicMessageContentSegmentText).join("");
34287
+ if (event.actor.type === "subagent") {
34288
+ const childId = terminalSafeSingleLine(event.actor.subagentId);
34289
+ const card = createChildActivityCard({
34290
+ identity: event.actor,
34291
+ activityTitle: event.payload.role === "assistant" ? "Message completed" : `${capitalize(event.payload.role)} message`,
34292
+ titleIncludesActivity: false,
34293
+ card: {
34294
+ kind: event.payload.role === "assistant" ? "command-output" : "progress",
34295
+ weight: "signal",
34296
+ summary: `${event.payload.role === "assistant" ? "Message completed." : `${capitalize(event.payload.role)} message retained.`} \xB7 ${childId}`,
34297
+ detail: stripAnsi(text) || "[Empty message]"
34298
+ }
34299
+ });
34300
+ return appendActivity({ state, retainedEventId, occurredAt, card });
34301
+ }
34228
34302
  if (state.transcript.some((item) => item.kind === "message" && item.messageId === messageId))
34229
34303
  return state;
34230
34304
  const role2 = event.payload.role;
34231
34305
  const author = role2 === "assistant" ? { label: "Remy", role: "remy" } : role2 === "system" ? { label: "System", role: "system" } : { label: event.payload.commandId ? state.commandAuthorLabels[event.payload.commandId] ?? "Human" : "Human", role: "human" };
34232
- const text = event.payload.content.map(publicMessageContentSegmentText).join("") || (author.role === "remy" ? "[Remy sent an empty message]" : "[Empty message]");
34306
+ const displayedText = text || (author.role === "remy" ? "[Remy sent an empty message]" : "[Empty message]");
34233
34307
  return {
34234
34308
  ...state,
34235
34309
  ...author.role === "remy" ? { previews: { ...state.previews, assistantText: "" } } : {},
34236
- transcript: [...state.transcript, { kind: "message", messageId, occurredAt, author, text, attachments: [] }]
34310
+ transcript: [...state.transcript, { kind: "message", messageId, occurredAt, author, text: displayedText, attachments: [] }]
34237
34311
  };
34238
34312
  }
34239
34313
  function appendActivity({ state, retainedEventId, occurredAt, card }) {
34240
34314
  return { ...state, transcript: [...state.transcript, { kind: "activity", activityId: `activity:${retainedEventId}`, occurredAt, card }] };
34241
34315
  }
34242
34316
  function toAgentActivityCard(event) {
34317
+ const identity = childActivityIdentity(event);
34318
+ if (identity)
34319
+ return toChildAgentActivityCard({ event, identity });
34320
+ return toMainAgentActivityCard(event);
34321
+ }
34322
+ function toMainAgentActivityCard(event) {
34243
34323
  switch (event.type) {
34244
34324
  case "agent.session.started":
34245
34325
  return { kind: "lifecycle", weight: "noise", title: "Remy session started", summary: "Session is ready." };
@@ -34304,6 +34384,444 @@ function toAgentActivityCard(event) {
34304
34384
  throw new SessionProjectionProtocolError("Cannot project an unknown retained agent event.");
34305
34385
  }
34306
34386
  }
34387
+ function toChildAgentActivityCard({ event, identity }) {
34388
+ switch (event.type) {
34389
+ case "agent.turn.started":
34390
+ return createChildActivityCard({ identity, activityTitle: "Turn started", card: { kind: "lifecycle", weight: "noise", summary: "Turn started." } });
34391
+ case "agent.turn.ended":
34392
+ return createChildActivityCard({
34393
+ identity,
34394
+ activityTitle: event.payload.status === "failed" ? "Turn failed" : "Turn ended",
34395
+ 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}.` }
34396
+ });
34397
+ case "agent.work.observed":
34398
+ return createChildActivityCard({ identity, activityTitle: "Work progress", card: { kind: "progress", weight: "noise", summary: "Subagent updated its work plan.", detail: jsonDetail(event.payload.observations) } });
34399
+ case "agent.message.started":
34400
+ return createChildActivityCard({ identity, activityTitle: "Message started", card: { kind: "lifecycle", weight: "noise", summary: "Subagent is composing a message." } });
34401
+ case "agent.reasoning.started":
34402
+ return createChildActivityCard({ identity, activityTitle: "Reasoning", card: { kind: "reasoning", weight: "noise", summary: "Subagent started a reasoning summary." } });
34403
+ case "agent.reasoning.ended": {
34404
+ const summary = stripAnsi(event.payload.summary ?? "").trim();
34405
+ return createChildActivityCard({
34406
+ identity,
34407
+ activityTitle: "Reasoning",
34408
+ card: summary.length > 0 ? { kind: "reasoning", weight: "signal", summary } : { kind: "reasoning", weight: "noise", summary: "Subagent completed a reasoning summary." }
34409
+ });
34410
+ }
34411
+ case "agent.tool.call.started":
34412
+ return createChildActivityCard({
34413
+ identity,
34414
+ activityTitle: terminalSafeSingleLine(event.payload.toolName),
34415
+ card: {
34416
+ kind: "tool",
34417
+ weight: "signal",
34418
+ summary: "Tool started.",
34419
+ ...event.payload.input === undefined ? {} : { detail: jsonDetail(event.payload.input), detailFormat: "code" }
34420
+ }
34421
+ });
34422
+ case "agent.tool.call.completed": {
34423
+ const failed = event.payload.status === "failed" || event.payload.status === "cancelled";
34424
+ const detail = event.payload.output === undefined ? undefined : toolOutputDetail(event.payload.output);
34425
+ return createChildActivityCard({
34426
+ identity,
34427
+ activityTitle: failed ? "Tool failed" : "Tool completed",
34428
+ card: failed ? { kind: "failure", weight: "signal", summary: providerText(event.payload.error?.message, `Tool ${event.payload.status}.`), ...detail === undefined ? {} : { detail, detailFormat: "code" } } : { kind: "command-output", weight: "signal", summary: "Tool completed.", ...detail === undefined ? {} : { detail, detailFormat: "code" } }
34429
+ });
34430
+ }
34431
+ case "agent.subagent.started":
34432
+ return createChildActivityCard({ identity, activityTitle: "Started", card: { kind: "progress", weight: "signal", summary: providerText(event.payload.name, event.payload.subagentId) } });
34433
+ case "agent.subagent.progress":
34434
+ return createChildActivityCard({ identity, activityTitle: "Progress", card: { kind: "progress", weight: "signal", summary: providerText(event.payload.summary, "Subagent is working.") } });
34435
+ case "agent.subagent.ended":
34436
+ return createChildActivityCard({
34437
+ identity,
34438
+ activityTitle: event.payload.status === "failed" ? "Failed" : "Ended",
34439
+ card: event.payload.status === "failed" ? { kind: "failure", weight: "signal", summary: providerText(event.payload.error?.message, "Subagent failed.") } : { kind: "progress", weight: "signal", summary: providerText(event.payload.summary, `Subagent ${event.payload.status}.`) }
34440
+ });
34441
+ case "agent.usage":
34442
+ return createChildActivityCard({ identity, activityTitle: "Usage updated", card: { kind: "progress", weight: "noise", summary: "Subagent reported usage.", detail: jsonDetail(event.payload.usage) } });
34443
+ case "agent.context.compaction.started":
34444
+ return createChildActivityCard({ identity, activityTitle: "Context compaction started", card: { kind: "reasoning", weight: "noise", summary: "Subagent is compacting context." } });
34445
+ case "agent.context.compaction.completed":
34446
+ return createChildActivityCard({
34447
+ identity,
34448
+ activityTitle: event.payload.status === "failed" ? "Context compaction failed" : "Context compaction completed",
34449
+ card: event.payload.status === "failed" ? { kind: "failure", weight: "signal", summary: providerText(event.payload.error?.message, "Context compaction failed.") } : { kind: "reasoning", weight: "noise", summary: "Subagent compacted context." }
34450
+ });
34451
+ case "agent.user-input.requested":
34452
+ return createChildActivityCard({ identity, activityTitle: "Needs input", card: { kind: "approval-question", weight: "signal", summary: providerText(event.payload.prompt, "Subagent needs input."), detail: jsonDetail(event.payload.questions) } });
34453
+ case "agent.session.started":
34454
+ case "agent.session.configured":
34455
+ case "agent.session.skills.updated":
34456
+ case "agent.session.state.changed":
34457
+ case "agent.session.ended":
34458
+ case "agent.user-input.resolved":
34459
+ case "agent.error":
34460
+ throw new SessionProjectionProtocolError(`Cannot attribute non-child session event type ${event.type} to a subagent.`);
34461
+ case "agent.message.delta":
34462
+ case "agent.reasoning.summary.delta":
34463
+ case "agent.tool.output.delta":
34464
+ throw new SessionProjectionProtocolError(`Cannot project ephemeral session event type ${event.type} as retained history.`);
34465
+ default:
34466
+ throw new SessionProjectionProtocolError("Cannot attribute an unknown retained event to a subagent.");
34467
+ }
34468
+ }
34469
+ function createChildActivityCard({
34470
+ identity,
34471
+ activityTitle,
34472
+ titleIncludesActivity = true,
34473
+ card
34474
+ }) {
34475
+ const subagentId = terminalSafeSingleLine(identity.subagentId);
34476
+ const actorId = terminalSafeSingleLine(identity.actorId);
34477
+ const displayName = terminalSafeSingleLine(identity.name ?? "") || subagentId;
34478
+ const identityDetail = [
34479
+ `Subagent ID: ${subagentId}`,
34480
+ ...actorId !== subagentId ? [`Actor ID: ${actorId}`] : []
34481
+ ].join(`
34482
+ `);
34483
+ const detail = card.detail === undefined ? identityDetail : `${identityDetail}
34484
+
34485
+ ${card.detail}`;
34486
+ return {
34487
+ ...card,
34488
+ title: `Subagent \xB7 ${displayName}${activityTitle === undefined || !titleIncludesActivity ? "" : ` \xB7 ${activityTitle}`}`,
34489
+ detail,
34490
+ attribution: {
34491
+ status: "unresolved",
34492
+ identity,
34493
+ ...activityTitle === undefined ? {} : { activityTitle }
34494
+ }
34495
+ };
34496
+ }
34497
+ function childActivityIdentity(event) {
34498
+ if (event.type === "agent.subagent.started" || event.type === "agent.subagent.progress" || event.type === "agent.subagent.ended") {
34499
+ if (event.actor.type === "subagent") {
34500
+ if (!subagentLifecycleIdentityMatches({ actor: event.actor, payload: event.payload }))
34501
+ throw new SessionProjectionProtocolError(`Retained session event type ${event.type} carried contradictory subagent actor and payload identity.`);
34502
+ return {
34503
+ ...event.actor,
34504
+ ...event.actor.name === undefined && event.payload.name !== undefined ? { name: event.payload.name } : {}
34505
+ };
34506
+ }
34507
+ return {
34508
+ type: "subagent",
34509
+ actorId: event.payload.actorId,
34510
+ subagentId: event.payload.subagentId,
34511
+ parentActorId: event.payload.parentActorId,
34512
+ origin: event.payload.origin,
34513
+ ...event.payload.parentToolCallId === undefined ? {} : { parentToolCallId: event.payload.parentToolCallId },
34514
+ ...event.payload.name === undefined ? {} : { name: event.payload.name }
34515
+ };
34516
+ }
34517
+ if ("actor" in event && event.actor.type === "subagent") {
34518
+ return event.actor;
34519
+ }
34520
+ return;
34521
+ }
34522
+ function subagentLifecycleIdentityMatches({ actor, payload }) {
34523
+ return actor.actorId === payload.actorId && actor.subagentId === payload.subagentId && actor.parentActorId === payload.parentActorId && actor.parentToolCallId === payload.parentToolCallId && subagentOriginsMatch(actor.origin, payload.origin);
34524
+ }
34525
+ function subagentOriginsMatch(left, right) {
34526
+ if (left.type === "tool_call")
34527
+ return right.type === "tool_call" && left.toolCallId === right.toolCallId;
34528
+ return right.type === "provider_task" && left.taskId === right.taskId;
34529
+ }
34530
+ function recordAgentLineageEvent({
34531
+ state,
34532
+ event,
34533
+ retainedEventId
34534
+ }) {
34535
+ if (!event.type.startsWith("agent."))
34536
+ return state;
34537
+ let parsed;
34538
+ try {
34539
+ parsed = parseDurableAgentEvent(event);
34540
+ } catch (error93) {
34541
+ if (error93 instanceof SessionProjectionProtocolError)
34542
+ return state;
34543
+ throw error93;
34544
+ }
34545
+ const runtimeBase = lineageRuntimeBase(parsed);
34546
+ let childLineage = state.childLineage;
34547
+ if (parsed.type === "agent.session.started" || parsed.type === "agent.session.ended") {
34548
+ const boundaryKey = `${runtimeBase}:${lengthPrefixed(parsed.eventId)}`;
34549
+ if (hasOwnContextIdentity(childLineage.seenRuntimeBoundaryEventIds, boundaryKey))
34550
+ return state;
34551
+ childLineage = {
34552
+ ...childLineage,
34553
+ runtimeEpochs: parsed.type === "agent.session.started" ? { ...childLineage.runtimeEpochs, [runtimeBase]: (childLineage.runtimeEpochs[runtimeBase] ?? 0) + 1 } : childLineage.runtimeEpochs,
34554
+ seenRuntimeBoundaryEventIds: {
34555
+ ...childLineage.seenRuntimeBoundaryEventIds,
34556
+ [boundaryKey]: true
34557
+ }
34558
+ };
34559
+ return { ...state, childLineage };
34560
+ }
34561
+ if (!("turnId" in parsed))
34562
+ return state;
34563
+ const runtimeScope = lineageRuntimeScope({
34564
+ runtimeBase,
34565
+ epoch: childLineage.runtimeEpochs[runtimeBase] ?? 0
34566
+ });
34567
+ const order = childLineage.nextOrder;
34568
+ const identity = childActivityIdentity(parsed);
34569
+ const fact = identity ? {
34570
+ retainedEventId,
34571
+ order,
34572
+ runtimeScope,
34573
+ turnId: parsed.turnId,
34574
+ eventType: parsed.type,
34575
+ identity
34576
+ } : parsed.type === "agent.tool.call.started" && parsed.actor.type === "main" ? {
34577
+ retainedEventId,
34578
+ order,
34579
+ runtimeScope,
34580
+ turnId: parsed.turnId,
34581
+ eventType: parsed.type,
34582
+ toolCallId: parsed.payload.toolCallId
34583
+ } : undefined;
34584
+ if (!fact)
34585
+ return state;
34586
+ const nextState = {
34587
+ ...state,
34588
+ childLineage: {
34589
+ ...childLineage,
34590
+ nextOrder: order + 1,
34591
+ facts: [...childLineage.facts, fact]
34592
+ }
34593
+ };
34594
+ if (!isChildLineageFact(fact) || isSubagentLifecycleType(fact.eventType))
34595
+ return reconcileChildLineage(nextState);
34596
+ const resolution = resolveBodyFactAgainstOwners(childLineage.owners, fact);
34597
+ if (resolution.status === "graph-change")
34598
+ return reconcileChildLineage(nextState);
34599
+ if (resolution.status === "unresolved")
34600
+ return nextState;
34601
+ return stampResolvedAttribution({ state: nextState, retainedEventId, fact, owner: resolution.owner });
34602
+ }
34603
+ function resolveBodyFactAgainstOwners(owners, fact) {
34604
+ const candidates = owners.filter((owner) => owner.runtimeScope === fact.runtimeScope && childIdentityMatches(owner.identity, fact.identity));
34605
+ const turnCandidates = candidates.filter((owner) => owner.childTurnIds.has(fact.turnId));
34606
+ if (turnCandidates.length === 1)
34607
+ return { status: "known", owner: turnCandidates[0] };
34608
+ if (candidates.length === 1)
34609
+ return { status: "graph-change" };
34610
+ return { status: "unresolved" };
34611
+ }
34612
+ function stampResolvedAttribution({ state, retainedEventId, fact, owner }) {
34613
+ const activityId = `activity:${retainedEventId}`;
34614
+ for (let index = state.transcript.length - 1;index >= 0; index -= 1) {
34615
+ const item = state.transcript[index];
34616
+ if (item.kind !== "activity" || item.activityId !== activityId)
34617
+ continue;
34618
+ if (!item.card.attribution)
34619
+ return state;
34620
+ const attribution = {
34621
+ status: "resolved",
34622
+ identity: fact.identity,
34623
+ ...item.card.attribution.activityTitle === undefined ? {} : { activityTitle: item.card.attribution.activityTitle },
34624
+ ownerKey: owner.key,
34625
+ owningMainTurnId: owner.owningMainTurnId,
34626
+ path: ownerPath(owner)
34627
+ };
34628
+ if (childAttributionEqual(item.card.attribution, attribution))
34629
+ return state;
34630
+ const transcript = [...state.transcript];
34631
+ transcript[index] = { ...item, card: { ...item.card, attribution } };
34632
+ return { ...state, transcript };
34633
+ }
34634
+ return state;
34635
+ }
34636
+ function lineageRuntimeBase(event) {
34637
+ return `${lengthPrefixed(event.sessionId)}:${lengthPrefixed(event.providerSessionId)}`;
34638
+ }
34639
+ function lineageRuntimeScope({ runtimeBase, epoch }) {
34640
+ return `${runtimeBase}:${epoch}`;
34641
+ }
34642
+ function lengthPrefixed(value) {
34643
+ return `${value.length}:${value}`;
34644
+ }
34645
+ function isChildLineageFact(fact) {
34646
+ return "identity" in fact;
34647
+ }
34648
+ function isSubagentLifecycleType(type) {
34649
+ return type === "agent.subagent.started" || type === "agent.subagent.progress" || type === "agent.subagent.ended";
34650
+ }
34651
+ function childIdentityMatches(left, right) {
34652
+ return left.actorId === right.actorId && left.subagentId === right.subagentId && left.parentActorId === right.parentActorId && left.parentToolCallId === right.parentToolCallId && subagentOriginsMatch(left.origin, right.origin);
34653
+ }
34654
+ function childIdentityCanAnchor(identity) {
34655
+ return identity.actorId !== identity.parentActorId && (identity.origin.type !== "tool_call" || identity.parentToolCallId === undefined || identity.parentToolCallId === identity.origin.toolCallId);
34656
+ }
34657
+ function reconcileChildLineage(state) {
34658
+ const facts = state.childLineage.facts;
34659
+ const childFacts = facts.filter(isChildLineageFact);
34660
+ const mainToolTurns = new Map;
34661
+ for (const fact of facts) {
34662
+ if (isChildLineageFact(fact))
34663
+ continue;
34664
+ const key = `${fact.runtimeScope}:${lengthPrefixed(fact.toolCallId)}`;
34665
+ const turns = mainToolTurns.get(key) ?? new Set;
34666
+ turns.add(fact.turnId);
34667
+ mainToolTurns.set(key, turns);
34668
+ }
34669
+ const owners = [];
34670
+ const ownerByFactOrder = new Map;
34671
+ const mainTurnForToolOrigin = (fact) => {
34672
+ if (fact.identity.origin.type !== "tool_call")
34673
+ return;
34674
+ const turns = mainToolTurns.get(`${fact.runtimeScope}:${lengthPrefixed(fact.identity.origin.toolCallId)}`);
34675
+ return turns?.size === 1 ? [...turns][0] : undefined;
34676
+ };
34677
+ const createOwner = ({
34678
+ fact,
34679
+ owningMainTurnId,
34680
+ parent
34681
+ }) => {
34682
+ if (!childIdentityCanAnchor(fact.identity))
34683
+ return;
34684
+ if (parent && ownerHasActorAncestor(parent, fact.identity.actorId))
34685
+ return;
34686
+ 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);
34687
+ if (samePlacement.some((owner2) => !childIdentityMatches(owner2.identity, fact.identity)))
34688
+ return;
34689
+ const existing = samePlacement.find((owner2) => childIdentityMatches(owner2.identity, fact.identity));
34690
+ if (existing)
34691
+ return existing;
34692
+ const owner = {
34693
+ key: `${fact.runtimeScope}:${lengthPrefixed(owningMainTurnId)}:${fact.order}`,
34694
+ identity: fact.identity,
34695
+ runtimeScope: fact.runtimeScope,
34696
+ owningMainTurnId,
34697
+ parent,
34698
+ childTurnIds: new Set
34699
+ };
34700
+ owners.push(owner);
34701
+ return owner;
34702
+ };
34703
+ for (const fact of childFacts) {
34704
+ if (fact.eventType !== "agent.subagent.started" || fact.identity.parentActorId !== "main")
34705
+ continue;
34706
+ const toolTurn = mainTurnForToolOrigin(fact);
34707
+ if (fact.identity.origin.type === "tool_call" && toolTurn === undefined) {
34708
+ const turns = mainToolTurns.get(`${fact.runtimeScope}:${lengthPrefixed(fact.identity.origin.toolCallId)}`);
34709
+ if (turns && turns.size > 1)
34710
+ continue;
34711
+ }
34712
+ if (toolTurn !== undefined && toolTurn !== fact.turnId)
34713
+ continue;
34714
+ const owner = createOwner({ fact, owningMainTurnId: fact.turnId, parent: null });
34715
+ if (owner)
34716
+ ownerByFactOrder.set(fact.order, owner);
34717
+ }
34718
+ for (const fact of childFacts) {
34719
+ if (isSubagentLifecycleType(fact.eventType) && fact.eventType !== "agent.subagent.started" && fact.identity.parentActorId === "main") {
34720
+ const toolTurn = mainTurnForToolOrigin(fact);
34721
+ if (toolTurn === undefined)
34722
+ continue;
34723
+ const owner = owners.find((candidate) => candidate.runtimeScope === fact.runtimeScope && candidate.parent === null && candidate.owningMainTurnId === toolTurn && childIdentityMatches(candidate.identity, fact.identity)) ?? createOwner({ fact, owningMainTurnId: toolTurn, parent: null });
34724
+ if (owner) {
34725
+ ownerByFactOrder.set(fact.order, owner);
34726
+ owner.childTurnIds.add(fact.turnId);
34727
+ }
34728
+ }
34729
+ }
34730
+ let changed = true;
34731
+ while (changed) {
34732
+ changed = false;
34733
+ for (const fact of childFacts) {
34734
+ if (ownerByFactOrder.has(fact.order))
34735
+ continue;
34736
+ const candidates = owners.filter((owner2) => owner2.runtimeScope === fact.runtimeScope && childIdentityMatches(owner2.identity, fact.identity));
34737
+ const turnCandidates = candidates.filter((owner2) => owner2.childTurnIds.has(fact.turnId));
34738
+ const owner = turnCandidates.length === 1 ? turnCandidates[0] : candidates.length === 1 ? candidates[0] : undefined;
34739
+ if (!owner || fact.eventType === "agent.subagent.started")
34740
+ continue;
34741
+ ownerByFactOrder.set(fact.order, owner);
34742
+ owner.childTurnIds.add(fact.turnId);
34743
+ changed = true;
34744
+ }
34745
+ for (const fact of childFacts) {
34746
+ if (ownerByFactOrder.has(fact.order) || fact.eventType !== "agent.subagent.started" || fact.identity.parentActorId === "main" || !childIdentityCanAnchor(fact.identity)) {
34747
+ continue;
34748
+ }
34749
+ const parentCandidates = owners.filter((owner2) => owner2.runtimeScope === fact.runtimeScope && owner2.identity.actorId === fact.identity.parentActorId);
34750
+ const turnParents = parentCandidates.filter((owner2) => owner2.childTurnIds.has(fact.turnId));
34751
+ const parent = turnParents.length === 1 ? turnParents[0] : parentCandidates.length === 1 ? parentCandidates[0] : undefined;
34752
+ if (!parent)
34753
+ continue;
34754
+ const owner = createOwner({ fact, owningMainTurnId: parent.owningMainTurnId, parent });
34755
+ if (!owner)
34756
+ continue;
34757
+ ownerByFactOrder.set(fact.order, owner);
34758
+ changed = true;
34759
+ }
34760
+ }
34761
+ const resolvedByRetainedEventId = new Map;
34762
+ for (const fact of childFacts) {
34763
+ const owner = ownerByFactOrder.get(fact.order);
34764
+ if (owner)
34765
+ resolvedByRetainedEventId.set(fact.retainedEventId, { fact, owner });
34766
+ }
34767
+ let transcriptChanged = false;
34768
+ const transcript = state.transcript.map((item) => {
34769
+ if (item.kind !== "activity" || !item.card.attribution)
34770
+ return item;
34771
+ const retainedEventId = item.activityId.slice("activity:".length);
34772
+ const resolved = resolvedByRetainedEventId.get(retainedEventId);
34773
+ const attribution = resolved ? {
34774
+ status: "resolved",
34775
+ identity: resolved.fact.identity,
34776
+ ...item.card.attribution.activityTitle === undefined ? {} : { activityTitle: item.card.attribution.activityTitle },
34777
+ ownerKey: resolved.owner.key,
34778
+ owningMainTurnId: resolved.owner.owningMainTurnId,
34779
+ path: ownerPath(resolved.owner)
34780
+ } : {
34781
+ status: "unresolved",
34782
+ identity: item.card.attribution.identity,
34783
+ ...item.card.attribution.activityTitle === undefined ? {} : { activityTitle: item.card.attribution.activityTitle }
34784
+ };
34785
+ if (childAttributionEqual(item.card.attribution, attribution))
34786
+ return item;
34787
+ transcriptChanged = true;
34788
+ return { ...item, card: { ...item.card, attribution } };
34789
+ });
34790
+ const nextState = { ...state, childLineage: { ...state.childLineage, owners } };
34791
+ return transcriptChanged ? { ...nextState, transcript } : nextState;
34792
+ }
34793
+ function ownerHasActorAncestor(parent, actorId) {
34794
+ let candidate = parent;
34795
+ while (candidate) {
34796
+ if (candidate.identity.actorId === actorId)
34797
+ return true;
34798
+ candidate = candidate.parent;
34799
+ }
34800
+ return false;
34801
+ }
34802
+ function ownerPath(owner) {
34803
+ const path = [];
34804
+ let candidate = owner;
34805
+ while (candidate) {
34806
+ path.unshift(candidate.identity);
34807
+ candidate = candidate.parent;
34808
+ }
34809
+ return path;
34810
+ }
34811
+ function childAttributionEqual(left, right) {
34812
+ if (left.status !== right.status || left.activityTitle !== right.activityTitle || !childIdentityMatches(left.identity, right.identity)) {
34813
+ return false;
34814
+ }
34815
+ if (left.status === "unresolved" || right.status === "unresolved")
34816
+ return true;
34817
+ return left.ownerKey === right.ownerKey && left.owningMainTurnId === right.owningMainTurnId && left.path.length === right.path.length && left.path.every((identity, index) => childIdentityMatches(identity, right.path[index]));
34818
+ }
34819
+ function terminalSafeSingleLine(value) {
34820
+ return stripAnsi(value).replace(/\s+/gu, " ").trim();
34821
+ }
34822
+ function capitalize(value) {
34823
+ return value.length === 0 ? value : `${value[0].toUpperCase()}${value.slice(1)}`;
34824
+ }
34307
34825
  function parseDurableAgentEvent(event) {
34308
34826
  if (!event.type.startsWith("agent."))
34309
34827
  throw new SessionProjectionProtocolError(`Cannot project retained session event type ${event.type}.`);
@@ -34340,6 +34858,9 @@ var terminalControlPattern = /[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/g;
34340
34858
  function stripAnsi(value) {
34341
34859
  return value.replace(ansiEscapePattern, "").replace(terminalControlPattern, "");
34342
34860
  }
34861
+ function terminalSafeText(value) {
34862
+ return stripAnsi(value);
34863
+ }
34343
34864
  function formatReasoningPreview(item) {
34344
34865
  if (item.status === "absent")
34345
34866
  return "";
@@ -37377,6 +37898,7 @@ function renderStatusBand({ state, working, elapsedMs, stopState, lifecycleReque
37377
37898
  const elapsed = (working || stopping) && elapsedMs !== undefined && elapsedMs > 0 ? ` ${formatElapsed(elapsedMs)}` : "";
37378
37899
  const connection = state.connectionStatus === "connected" ? dim4(fg6(PALETTE.dimText)("connected")) : fg6(PALETTE.approvalQuestion)("reconnecting\u2026");
37379
37900
  const sessionLabel = state.sessionNumber !== undefined ? `Session #${state.sessionNumber}` : `Session ${state.sessionId}`;
37901
+ const context = renderContextStatus(state.context.snapshot);
37380
37902
  const pullRequest = state.pullRequest;
37381
37903
  return new StyledText5([
37382
37904
  fg6(presentation.color)("\u25CF "),
@@ -37385,12 +37907,19 @@ function renderStatusBand({ state, working, elapsedMs, stopState, lifecycleReque
37385
37907
  bold4(fg6(presentation.color)(`${presentation.label}${elapsed}`)),
37386
37908
  dim4(fg6(PALETTE.dimText)(" \xB7 ")),
37387
37909
  connection,
37910
+ ...context ? [dim4(fg6(PALETTE.dimText)(` \xB7 ${context}`))] : [],
37388
37911
  ...pullRequest ? [
37389
37912
  dim4(fg6(PALETTE.dimText)(" \xB7 ")),
37390
37913
  bold4(fg6(statusColor(pullRequest.status))(`PR #${pullRequest.number} \xB7 ${pullRequest.draft ? "Draft" : sessionStatusLabel(pullRequest.status)}`))
37391
37914
  ] : []
37392
37915
  ]);
37393
37916
  }
37917
+ function renderContextStatus(snapshot) {
37918
+ if (snapshot.status === "unknown")
37919
+ return;
37920
+ const usedTokens = snapshot.usedTokens.toLocaleString("en-US");
37921
+ return snapshot.window.status === "known" ? `Context ${snapshot.window.remainingPercent}% left \xB7 ${usedTokens} used` : `Context ${usedTokens} used`;
37922
+ }
37394
37923
  function renderTerminalSessionBand({ aggregateStatus }) {
37395
37924
  const status = sessionStatusLabel(aggregateStatus).toLowerCase();
37396
37925
  return joinStyled([
@@ -37542,16 +38071,20 @@ function activityGlyph({ kind, inFlight }) {
37542
38071
  return { glyph: "\xB7", color: PALETTE.dimText };
37543
38072
  return { glyph: "\u2713", color: PALETTE.dimText };
37544
38073
  }
37545
- function dedupeActivitySteps(items) {
37546
- const runs = [];
37547
- for (const item of items) {
37548
- const last = runs[runs.length - 1];
37549
- if (last && last.item.card.kind === item.card.kind && last.item.card.title === item.card.title && last.item.card.summary === item.card.summary)
37550
- last.count += 1;
37551
- else
37552
- runs.push({ item, count: 1 });
38074
+ function activityCardsHaveEqualDisclosure(left, right) {
38075
+ return left.kind === right.kind && left.title === right.title && left.summary === right.summary && left.detail === right.detail && left.detailFormat === right.detailFormat && canonicalValuesEqual(left.attribution, right.attribution);
38076
+ }
38077
+ function canonicalValuesEqual(left, right) {
38078
+ if (Object.is(left, right))
38079
+ return true;
38080
+ if (Array.isArray(left) || Array.isArray(right)) {
38081
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => canonicalValuesEqual(value, right[index]));
37553
38082
  }
37554
- return runs;
38083
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null)
38084
+ return false;
38085
+ const leftEntries = Object.entries(left);
38086
+ const rightEntries = Object.entries(right);
38087
+ return leftEntries.length === rightEntries.length && leftEntries.every(([key, value], index) => rightEntries[index]?.[0] === key && canonicalValuesEqual(value, rightEntries[index]?.[1]));
37555
38088
  }
37556
38089
  function renderActivityGroup({ items, activityExpanded }) {
37557
38090
  if (items.length === 0)
@@ -37573,22 +38106,82 @@ function renderActivityGroup({ items, activityExpanded }) {
37573
38106
  ], `
37574
38107
  `);
37575
38108
  }
37576
- const steps = dedupeActivitySteps(items).map(({ item, count }) => {
37577
- const inFlight = item.card.kind === "tool" && items.indexOf(item) === lastInFlightIndex;
37578
- const { glyph, color } = activityGlyph({ kind: item.card.kind, inFlight });
37579
- const showSummary = item.card.summary.length > 0 && item.card.summary !== item.card.title && !boilerplateActivitySummaries.has(item.card.summary);
37580
- const detail = item.card.detail === undefined ? undefined : item.card.detailFormat === "code" ? renderCodeSnippet({ text: item.card.detail, indent: " " }) : new StyledText5([dim4(fg6(PALETTE.dimText)(` ${item.card.detail}`))]);
37581
- const step = new StyledText5([
37582
- fg6(color)(` ${glyph} `),
37583
- fg6(PALETTE.bodyText)(item.card.title),
37584
- ...count > 1 ? [dim4(fg6(PALETTE.dimText)(` \xD7${count}`))] : [],
37585
- ...showSummary ? [dim4(fg6(PALETTE.dimText)(`
37586
- ${item.card.summary}`))] : []
37587
- ]);
37588
- return detail ? joinStyled([step, detail], `
38109
+ return joinStyled([summary, ...renderExpandedActivityHierarchy({ items, lastInFlightIndex })], `
38110
+ `);
38111
+ }
38112
+ function renderExpandedActivityHierarchy({ items, lastInFlightIndex }) {
38113
+ const rendered = [];
38114
+ let activeOwnerKey;
38115
+ let index = 0;
38116
+ while (index < items.length) {
38117
+ const item = items[index];
38118
+ const attribution = item.card.attribution;
38119
+ if (attribution?.status === "resolved") {
38120
+ if (activeOwnerKey !== attribution.ownerKey) {
38121
+ rendered.push(new StyledText5([
38122
+ dim4(fg6(PALETTE.dimText)(" ")),
38123
+ fg6(PALETTE.bodyText)(`Subagent \xB7 ${lineagePathLabel(attribution.path)}`)
38124
+ ]));
38125
+ }
38126
+ activeOwnerKey = attribution.ownerKey;
38127
+ } else {
38128
+ activeOwnerKey = undefined;
38129
+ }
38130
+ let count = 1;
38131
+ while (items[index + count] && activityCardsHaveEqualDisclosure(item.card, items[index + count].card)) {
38132
+ count += 1;
38133
+ }
38134
+ rendered.push(renderExpandedActivityStep({
38135
+ item,
38136
+ count,
38137
+ inFlight: item.card.kind === "tool" && index === lastInFlightIndex,
38138
+ nested: attribution?.status === "resolved"
38139
+ }));
38140
+ index += count;
38141
+ }
38142
+ return rendered;
38143
+ }
38144
+ function renderExpandedActivityStep({ item, count, inFlight, nested }) {
38145
+ const { glyph, color } = activityGlyph({ kind: item.card.kind, inFlight });
38146
+ const showSummary = item.card.summary.length > 0 && item.card.summary !== item.card.title && !boilerplateActivitySummaries.has(item.card.summary);
38147
+ const disclosure = renderActivityDisclosure(item.card);
38148
+ const title = expandedActivityTitle(item.card);
38149
+ const indent = nested ? " " : " ";
38150
+ const step = new StyledText5([
38151
+ fg6(color)(`${indent}${glyph} `),
38152
+ fg6(PALETTE.bodyText)(title),
38153
+ ...count > 1 ? [dim4(fg6(PALETTE.dimText)(` \xD7${count}`))] : [],
38154
+ ...showSummary ? [dim4(fg6(PALETTE.dimText)(`
38155
+ ${indent} ${item.card.summary}`))] : []
38156
+ ]);
38157
+ return disclosure ? joinStyled([step, disclosure], `
37589
38158
  `) : step;
37590
- });
37591
- return joinStyled([summary, ...steps], `
38159
+ }
38160
+ function expandedActivityTitle(card) {
38161
+ if (!card.attribution)
38162
+ return card.title;
38163
+ if (card.attribution.status === "resolved")
38164
+ return card.attribution.activityTitle ?? "Activity";
38165
+ const name = childIdentityLabel(card.attribution.identity);
38166
+ return `Unattributed subagent \xB7 ${name}${card.attribution.activityTitle ? ` \xB7 ${card.attribution.activityTitle}` : ""}`;
38167
+ }
38168
+ function lineagePathLabel(path) {
38169
+ return path.map(childIdentityLabel).join(" \u203A ");
38170
+ }
38171
+ function childIdentityLabel(identity) {
38172
+ const safeName = terminalSafeText(identity.name ?? "").replace(/\s+/gu, " ").trim();
38173
+ if (safeName.length > 0)
38174
+ return safeName;
38175
+ return terminalSafeText(identity.subagentId).replace(/\s+/gu, " ").trim();
38176
+ }
38177
+ function renderActivityDisclosure(card) {
38178
+ const details = [];
38179
+ if (card.detail !== undefined) {
38180
+ const safeDetail = terminalSafeText(card.detail);
38181
+ details.push(card.detailFormat === "code" ? renderCodeSnippet({ text: safeDetail, indent: " " }) : new StyledText5([dim4(fg6(PALETTE.dimText)(` ${safeDetail}`))]));
38182
+ }
38183
+ return details.length === 0 ? undefined : joinStyled(details, `
38184
+
37592
38185
  `);
37593
38186
  }
37594
38187
  function renderActivitySummary({ items, includeTimestamp }) {
@@ -37601,9 +38194,20 @@ function renderCollapsedActivityStep({ item, inFlight }) {
37601
38194
  const { glyph, color } = activityGlyph({ kind: item.card.kind, inFlight });
37602
38195
  return new StyledText5([
37603
38196
  fg6(color)(` ${glyph} `),
37604
- dim4(fg6(PALETTE.dimText)(item.card.title))
38197
+ dim4(fg6(PALETTE.dimText)(collapsedActivityTitle(item.card)))
37605
38198
  ]);
37606
38199
  }
38200
+ function collapsedActivityTitle(card) {
38201
+ const attribution = card.attribution;
38202
+ if (!attribution)
38203
+ return card.title;
38204
+ if (attribution.status === "unresolved") {
38205
+ const name = childIdentityLabel(attribution.identity);
38206
+ return `Unattributed subagent \xB7 ${name}${attribution.activityTitle ? ` \xB7 ${attribution.activityTitle}` : ""}`;
38207
+ }
38208
+ const activityTitle = attribution.activityTitle ? ` \xB7 ${attribution.activityTitle}` : "";
38209
+ return `${lineagePathLabel(attribution.path)}${activityTitle}`;
38210
+ }
37607
38211
  function renderSubmittedTimeline({ state, admittedSubmissions }) {
37608
38212
  const submitted = admittedSubmissions.filter((submission) => submission.status === "submitted" && !state.transcript.some((item) => item.kind === "message" && item.messageId === submission.messageId));
37609
38213
  const messages = submitted.map((submission) => {
@@ -37793,7 +38397,7 @@ var compactMarkRows = 9;
37793
38397
  var compactMinWidth = 48;
37794
38398
  var compactMinHeight = 20;
37795
38399
  var markBrightnessGain = 4.2;
37796
- var remyCliVersion = "1.11.0";
38400
+ var remyCliVersion = "1.13.0";
37797
38401
  async function showRemySplash({
37798
38402
  createRenderer = createRemyRenderer,
37799
38403
  durationMs = splashDurationMs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/remy-cli",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "description": "Remy, the Coding Agent terminal client.",
5
5
  "type": "module",
6
6
  "bin": {