Gateway: T3 RPC client, host connection, awareness port, storage, API contract
This commit is contained in:
1 parent
0fd556e313
commit
972f6e4be5
13 files changed
+1332
-9
No files matched your search
@@ -0,0 +1,98 @@
|
||||
// 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();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user