Merge PR #8074: fix(coding-agent): display subagent registration time locally (@anatoli-tsinovoy)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
- Fixed `/vibe` mode losing the pre-vibe toolset when a session already in vibe mode switches into another session that is also in vibe mode, which left `bash`, `edit`, `write`, `grep`, `glob`, `task`, and `hub` silently unavailable after exiting the mode; the pre-vibe toolset is now recorded on the `mode_change` entry and restored from there.
|
||||
- Preserved extension-filtered pasted image payloads and source links when `/goal`, `/plan`, or `/vibe` submits the composer draft.
|
||||
- Fixed Agent Hub lineage registration timestamps displaying in UTC instead of the user's local timezone.
|
||||
|
||||
## [17.2.12] - 2026-08-08
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import { type AgentRef, AgentRegistry, type AgentStatus, MAIN_AGENT_ID } from ".
|
||||
import { registerPersistedSubagents } from "../../registry/persisted-agents";
|
||||
import { USER_INTERRUPT_LABEL } from "../../session/messages";
|
||||
import { shortenPath, truncateToWidth } from "../../tools/render-utils";
|
||||
import { formatLocalDateTimeWithOffset } from "../../utils/local-date";
|
||||
import type { ObservableSession, SessionObserverRegistry } from "../session-observer-registry";
|
||||
import { theme } from "../theme/theme";
|
||||
import { matchesSelectDown, matchesSelectUp } from "../utils/keybinding-matchers";
|
||||
@@ -829,7 +830,7 @@ export class AgentHubOverlayComponent extends Container implements SelectListMou
|
||||
`Spawned by ${sanitizeDisplayText(ref.parentId ?? MAIN_AGENT_ID)}${children.length > 0 ? ` · ${children.length} children` : ""}`,
|
||||
);
|
||||
if (children.length > 0) add(theme.fg("dim", formatChildIds(children, width)));
|
||||
add(theme.fg("dim", `Registered ${new Date(ref.createdAt).toISOString().slice(0, 16).replace("T", " ")}Z`));
|
||||
add(theme.fg("dim", `Registered ${formatLocalDateTimeWithOffset(new Date(ref.createdAt))}`));
|
||||
|
||||
section("Changes");
|
||||
add(
|
||||
|
||||
@@ -5,3 +5,16 @@ export function formatLocalCalendarDate(date: Date = new Date()): string {
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
|
||||
/** Format a local date and minute with a compact numeric UTC offset. */
|
||||
export function formatLocalDateTimeWithOffset(date: Date): string {
|
||||
const offsetMinutes = date.getTimezoneOffset();
|
||||
const offsetSign = offsetMinutes <= 0 ? "+" : "-";
|
||||
const absoluteOffset = Math.abs(offsetMinutes);
|
||||
const offsetHours = Math.floor(absoluteOffset / 60);
|
||||
const offsetRemainderMinutes = absoluteOffset % 60;
|
||||
const pad2 = (value: number): string => String(value).padStart(2, "0");
|
||||
return `${formatLocalCalendarDate(date)} ${pad2(date.getHours())}:${pad2(date.getMinutes())} ${offsetSign}${pad2(
|
||||
offsetHours,
|
||||
)}:${pad2(offsetRemainderMinutes)}`;
|
||||
}
|
||||
|
||||
@@ -579,6 +579,7 @@ describe("Agent hub row ordering", () => {
|
||||
it("renders aggregate usage and a selected-agent inspector without inventing change attribution", () => {
|
||||
geometry = stubStdoutGeometry(140);
|
||||
geometry.setRows(28);
|
||||
const createdAt = Date.parse("2026-08-09T20:15:00Z");
|
||||
const agents = new AgentRegistry();
|
||||
agents.register({
|
||||
id: "Reviewer",
|
||||
@@ -591,6 +592,7 @@ describe("Agent hub row ordering", () => {
|
||||
patchPath: "/tmp/Reviewer.patch",
|
||||
branchName: "omp/task/Reviewer",
|
||||
},
|
||||
createdAt,
|
||||
});
|
||||
const observers = new SessionObserverRegistry();
|
||||
vi.spyOn(observers, "getSessions").mockReturnValue([
|
||||
@@ -634,7 +636,24 @@ describe("Agent hub row ordering", () => {
|
||||
expect(rendered).toContain("Security Reviewer");
|
||||
expect(rendered).toContain("read · src/session/agent-session.ts");
|
||||
expect(rendered).toContain("31K/128K 24%");
|
||||
expect(rendered).toContain("Registered ");
|
||||
const createdDate = new Date(createdAt);
|
||||
const localDateTime = createdDate.toLocaleString("sv-SE", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
const offsetMinutes = -createdDate.getTimezoneOffset();
|
||||
const offsetSign = offsetMinutes >= 0 ? "+" : "-";
|
||||
const absoluteOffset = Math.abs(offsetMinutes);
|
||||
const offset = `${offsetSign}${String(Math.floor(absoluteOffset / 60)).padStart(2, "0")}:${String(
|
||||
absoluteOffset % 60,
|
||||
).padStart(2, "0")}`;
|
||||
const registeredLine = `Registered ${localDateTime} ${offset}`;
|
||||
expect(rendered).toContain(registeredLine);
|
||||
expect(rendered).not.toMatch(/Registered \d{4}-\d{2}-\d{2} \d{2}:\d{2}Z/u);
|
||||
expect(Bun.stripANSI(hub.render(96).join("\n"))).toContain(registeredLine);
|
||||
expect(rendered).toContain("Shared workspace · per-agent LoC not attributable");
|
||||
expect(rendered).toContain("Output /tmp/Reviewer.md");
|
||||
expect(rendered).toContain("Patch /tmp/Reviewer.patch");
|
||||
|
||||
Reference in New Issue
Block a user