Files
wristcode/gateway/test/awareness.test.ts
T
gib 442036b22f
Gateway / check (push) Successful in 10s
Gateway / image (push) Successful in 22s
Gateway: hide delegated threads unless they wait on the user
2026-11-01 19:54:08 -05:00

107 lines
4.3 KiB
TypeScript

// Cases ported from T3 Code's agentAwareness.test.ts, so the gateway notifies when T3's own app would.
import { describe, expect, it } from "bun:test";
import { threadPhase } from "../src/awareness.ts";
import type { ThreadShell } from "../src/t3/types.ts";
const thread = (overrides: Partial<ThreadShell> = {}): ThreadShell => ({
id: "thread-2",
projectId: "project-1",
title: "Integrate orchestration",
createdAt: "2026-05-22T12:00:00.000Z",
updatedAt: "2026-05-22T12:00:00.000Z",
status: "running",
activeRunId: "run-1",
pendingRuntimeRequest: null,
modelSelection: { instanceId: "codex", model: "gpt-5.4" },
lineage: { relationshipToParent: null },
settledOverride: null,
...overrides,
});
const request = (kind: string, blocking?: boolean): ThreadShell["pendingRuntimeRequest"] => ({
id: `request-${kind}`,
kind,
createdAt: "2026-05-22T12:00:00.000Z",
...(blocking === undefined ? {} : { blocking }),
});
describe("threadPhase", () => {
it("does not announce completion after a manual stop", () => {
expect(threadPhase(thread({ status: "completed" }))).toBe("completed");
expect(threadPhase(thread({ status: "completed", latestRunStopRequested: true }))).toBeNull();
});
it.each(["running", "completed", "failed"])("hides %s subagent activity", (status) => {
expect(threadPhase(thread({ status, lineage: { relationshipToParent: "subagent" } }))).toBeNull();
});
it("keeps an older activity run visible over a newer cancelled run", () => {
expect(threadPhase(thread({ status: "cancelled", activityRunStatus: "running" }))).toBe("running");
});
it.each(["completed", "failed"])("hides settled %s work", (status) => {
expect(threadPhase(thread({ status, settledOverride: "settled" }))).toBeNull();
});
it.each([
["starting", "starting"],
["running", "running"],
["waiting", "running"],
] as const)("keeps settled %s work visible", (status, phase) => {
expect(threadPhase(thread({ status, settledOverride: "settled" }))).toBe(phase);
});
it.each([
["user_input", "waiting_for_input"],
["command", "waiting_for_approval"],
] as const)("keeps a settled terminal thread with a pending %s request", (kind, phase) => {
expect(
threadPhase(thread({ status: "completed", settledOverride: "settled", pendingRuntimeRequest: request(kind) })),
).toBe(phase);
});
it("keeps settled work held open by an awaited monitor", () => {
expect(
threadPhase(
thread({
status: "completed",
settledOverride: "settled",
pendingBackgroundTasks: [{ kind: "monitor", awaited: true }],
}),
),
).toBe("running");
});
it.each([
["only a dev server", "completed", [{ kind: "command" }]],
["a dev server's watchdog monitor", "completed", [{ kind: "monitor" }]],
["a command the agent waits on", "running", [{ kind: "command", awaited: true }]],
["a dev server and a subagent", "running", [{ kind: "command" }, { kind: "subagent" }]],
] as const)("reports a completed run waiting on %s as %s", (_case, phase, tasks) => {
expect(threadPhase(thread({ status: "completed", pendingBackgroundTasks: [...tasks] }))).toBe(phase);
});
it("reports an async question as input only after the working run completes", () => {
const asking = thread({ pendingRuntimeRequest: request("user_input", false) });
expect(threadPhase(asking)).toBe("running");
expect(threadPhase({ ...asking, status: "completed" })).toBe("waiting_for_input");
});
it("does not present authentication refreshes as approvals", () => {
expect(threadPhase(thread({ pendingRuntimeRequest: request("auth_refresh") }))).toBe("running");
});
it("hides threads that never ran", () => {
expect(threadPhase(thread({ status: "idle" }))).toBeNull();
});
// Not from upstream: delegate_task children carry no subagent lineage, only delegatedFrom.
it("shows delegated threads only while they wait on the user", () => {
const delegatedFrom = { environmentId: "env-desktop", threadId: "thread-1", title: "Parent" };
expect(threadPhase(thread({ delegatedFrom }))).toBeNull();
expect(threadPhase(thread({ delegatedFrom, status: "completed" }))).toBeNull();
expect(threadPhase(thread({ delegatedFrom, pendingRuntimeRequest: request("command") }))).toBe("waiting_for_approval");
});
});