Skip to content

Commit 6e42231

Browse files
Extend Done display to 15 minutes and show up to 5 Live Activity banner rows (#3761)
1 parent bdf5aed commit 6e42231

4 files changed

Lines changed: 25 additions & 10 deletions

File tree

infra/relay/src/agentActivity/AgentActivityPublisher.test.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ describe("makeAggregateState", () => {
736736
...state,
737737
threadId: "thread-done" as RelayAgentActivityState["threadId"],
738738
phase: "completed",
739-
updatedAt: "1970-01-01T00:50:00.000Z",
739+
updatedAt: "1970-01-01T00:44:00.000Z",
740740
};
741741
const aggregate = AgentActivityPublisher.makeAggregateState({
742742
activeStates: [active, staleCompleted],
@@ -769,7 +769,7 @@ describe("makeAggregateState", () => {
769769
});
770770
expect(
771771
AgentActivityPublisher.makeAggregateState({
772-
activeStates: [{ ...lingeringCompleted, updatedAt: "1970-01-01T00:50:00.000Z" }],
772+
activeStates: [{ ...lingeringCompleted, updatedAt: "1970-01-01T00:44:00.000Z" }],
773773
terminalState: null,
774774
nowMs: hourMs,
775775
}),
@@ -789,16 +789,25 @@ describe("makeAggregateState", () => {
789789
updatedAt: "1970-01-01T00:59:00.000Z",
790790
};
791791
const aggregate = AgentActivityPublisher.makeAggregateState({
792-
activeStates: [mkActive("a-1"), mkActive("a-2"), mkActive("a-3"), justCompleted],
792+
activeStates: [
793+
mkActive("a-1"),
794+
mkActive("a-2"),
795+
mkActive("a-3"),
796+
mkActive("a-4"),
797+
mkActive("a-5"),
798+
justCompleted,
799+
],
793800
terminalState: null,
794801
nowMs: hourMs,
795802
});
796803

797-
expect(aggregate?.activeCount).toBe(3);
804+
expect(aggregate?.activeCount).toBe(5);
798805
expect(aggregate?.activities).toMatchObject([
799806
{ threadId: "a-1" },
800807
{ threadId: "a-2" },
801808
{ threadId: "a-3" },
809+
{ threadId: "a-4" },
810+
{ threadId: "a-5" },
802811
]);
803812
});
804813
});

infra/relay/src/agentActivity/AgentActivityPublisher.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import * as Option from "effect/Option";
1313
import {
1414
isExpiredAgentActivityState,
1515
isTerminalPhase,
16+
MAX_ACTIVITY_ROWS,
1617
sanitizeAgentActivityAggregateState,
1718
} from "./agentActivityPayloads.ts";
1819

@@ -228,7 +229,7 @@ function terminalAggregateState(state: RelayAgentActivityState): RelayAgentActiv
228229
// How long a finished thread keeps its Done/Failed row in the aggregate while
229230
// other agents are still active. Long enough to be seen on the lock screen,
230231
// short enough that the activity list stays about live work.
231-
export const TERMINAL_AGENT_ACTIVITY_DISPLAY_TTL_MS = 5 * 60 * 1_000;
232+
export const TERMINAL_AGENT_ACTIVITY_DISPLAY_TTL_MS = 15 * 60 * 1_000;
232233

233234
function isRecentTerminalState(state: RelayAgentActivityState, nowMs: number): boolean {
234235
if (!isTerminalPhase(state)) {
@@ -273,7 +274,7 @@ export function makeAggregateState(input: {
273274
subtitle: newest.phase === "failed" ? "Agent work failed" : "Agent work completed",
274275
activeCount: 0,
275276
updatedAt: newest.updatedAt,
276-
activities: recentTerminal.slice(0, 3).map(aggregateRowForState),
277+
activities: recentTerminal.slice(0, MAX_ACTIVITY_ROWS).map(aggregateRowForState),
277278
});
278279
}
279280
// Recently finished threads ride along after the active ones (display slots
@@ -282,7 +283,10 @@ export function makeAggregateState(input: {
282283
const recentTerminalStates = input.activeStates
283284
.filter((state) => isRecentTerminalState(state, input.nowMs))
284285
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
285-
const displayedStates = [...activeStates.slice(0, 3), ...recentTerminalStates].slice(0, 3);
286+
const displayedStates = [
287+
...activeStates.slice(0, MAX_ACTIVITY_ROWS),
288+
...recentTerminalStates,
289+
].slice(0, MAX_ACTIVITY_ROWS);
286290
const updatedAt = [...activeStates, ...recentTerminalStates].reduce((latest, state) =>
287291
state.updatedAt.localeCompare(latest.updatedAt) > 0 ? state : latest,
288292
).updatedAt;

infra/relay/src/agentActivity/ApnsDeliveries.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ describe("ApnsDeliveries", () => {
373373
...aggregate,
374374
title: longTitle,
375375
subtitle: longTitle,
376-
activities: [0, 1, 2, 3].map((index) =>
376+
activities: [0, 1, 2, 3, 4, 5].map((index) =>
377377
Object.assign({}, aggregate.activities[0]!, {
378378
projectTitle: longTitle,
379379
threadTitle: longTitle,
@@ -396,7 +396,7 @@ describe("ApnsDeliveries", () => {
396396
const payloadAggregate = queuedJobs[0]?.payload.aggregate;
397397
expect(payloadAggregate?.title.length).toBeLessThanOrEqual(120);
398398
expect(payloadAggregate?.subtitle.length).toBeLessThanOrEqual(120);
399-
expect(payloadAggregate?.activities).toHaveLength(3);
399+
expect(payloadAggregate?.activities).toHaveLength(5);
400400
expect(payloadAggregate?.activities[0]?.projectTitle.length).toBeLessThanOrEqual(120);
401401
expect(payloadAggregate?.activities[0]?.status.length).toBeLessThanOrEqual(40);
402402
expect(payloadAggregate?.activities[0]?.deepLink).toBe("/");

infra/relay/src/agentActivity/agentActivityPayloads.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ export function isExpiredAgentActivityState(
4343
const MAX_SUMMARY_TEXT_LENGTH = 120;
4444
const MAX_STATUS_TEXT_LENGTH = 40;
4545
const MAX_DEEP_LINK_LENGTH = 512;
46-
const MAX_ACTIVITY_ROWS = 3;
46+
// The Live Activity banner (lock screen / Notification Center) renders up to
47+
// five rows; the expanded Dynamic Island shows the top three of these.
48+
export const MAX_ACTIVITY_ROWS = 5;
4749

4850
function truncateText(value: string, maxLength: number): string {
4951
const trimmed = value.trim();

0 commit comments

Comments
 (0)