import { describe, expect, it } from "@effect/vitest"; import type { EnvironmentId, OrchestrationProjectShell, OrchestrationThreadShell, ThreadId, TurnId,} from "@t3tools/contracts";import { ProviderInstanceId } from "@t3tools/contracts"; import { projectThreadAwareness } from "./agentAwareness.ts"; const NOW = "2026-05-22T12:00:00.000Z"; const project = { title: "t3code",} satisfies Pick<OrchestrationProjectShell, "title">; function thread( overrides: Partial<OrchestrationThreadShell> = {},): Pick< OrchestrationThreadShell, | "id" | "title" | "modelSelection" | "session" | "latestTurn" | "updatedAt" | "hasPendingApprovals" | "hasPendingUserInput"> { return { id: "thread-1" as ThreadId, title: "Fix failing CI", modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.4" }, session: null, latestTurn: null, updatedAt: NOW, hasPendingApprovals: false, hasPendingUserInput: false, ...overrides, };} describe("projectThreadAwareness", () => { it("returns null for idle threads without an active awareness state", () => { expect( projectThreadAwareness({ environmentId: "env-1" as EnvironmentId, project, thread: thread(), }), ).toBeNull(); }); it("prioritizes approval requests over running state", () => { const state = projectThreadAwareness({ environmentId: "env-1" as EnvironmentId, project, thread: thread({ hasPendingApprovals: true, session: { threadId: "thread-1" as ThreadId, status: "running", providerName: "Codex", runtimeMode: "full-access", activeTurnId: "turn-1" as TurnId, lastError: null, updatedAt: NOW, }, }), }); expect(state?.phase).toBe("waiting_for_approval"); expect(state?.headline).toBe("Approval needed"); }); it("projects running provider sessions", () => { const state = projectThreadAwareness({ environmentId: "env-1" as EnvironmentId, project, thread: thread({ session: { threadId: "thread-1" as ThreadId, status: "running", providerName: "Codex", runtimeMode: "full-access", activeTurnId: "turn-1" as TurnId, lastError: null, updatedAt: NOW, }, }), }); expect(state).toMatchObject({ phase: "running", headline: "Agent is working", detail: "Codex is active.", modelTitle: "gpt-5.4", deepLink: "/threads/env-1/thread-1", }); }); it("projects failures with the session error detail", () => { const state = projectThreadAwareness({ environmentId: "env-1" as EnvironmentId, project, thread: thread({ session: { threadId: "thread-1" as ThreadId, status: "error", providerName: "Codex", runtimeMode: "full-access", activeTurnId: null, lastError: "Provider process exited.", updatedAt: NOW, }, }), }); expect(state).toMatchObject({ phase: "failed", headline: "Agent failed", detail: "Provider process exited.", }); });});
import { describe, expect, it } from "@effect/vitest";
import type {
EnvironmentId,
OrchestrationProjectShell,
OrchestrationThreadShell,
ThreadId,
TurnId,
} from "@t3tools/contracts";
import { ProviderInstanceId } from "@t3tools/contracts";
import { projectThreadAwareness } from "./agentAwareness.ts";
const NOW = "2026-05-22T12:00:00.000Z";
const project = {
title: "t3code",
} satisfies Pick<OrchestrationProjectShell, "title">;
function thread(
overrides: Partial<OrchestrationThreadShell> = {},
): Pick<
OrchestrationThreadShell,
| "id"
| "title"
| "modelSelection"
| "session"
| "latestTurn"
| "updatedAt"
| "hasPendingApprovals"
| "hasPendingUserInput"
> {
return {
id: "thread-1" as ThreadId,
title: "Fix failing CI",
modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.4" },
session: null,
latestTurn: null,
updatedAt: NOW,
hasPendingApprovals: false,
hasPendingUserInput: false,
...overrides,
};
}
describe("projectThreadAwareness", () => {
it("returns null for idle threads without an active awareness state", () => {
expect(
projectThreadAwareness({
environmentId: "env-1" as EnvironmentId,
project,
thread: thread(),
}),
).toBeNull();
});
it("prioritizes approval requests over running state", () => {
const state = projectThreadAwareness({
environmentId: "env-1" as EnvironmentId,
project,
thread: thread({
hasPendingApprovals: true,
session: {
threadId: "thread-1" as ThreadId,
status: "running",
providerName: "Codex",
runtimeMode: "full-access",
activeTurnId: "turn-1" as TurnId,
lastError: null,
updatedAt: NOW,
},
}),
});
expect(state?.phase).toBe("waiting_for_approval");
expect(state?.headline).toBe("Approval needed");
});
it("projects running provider sessions", () => {
const state = projectThreadAwareness({
environmentId: "env-1" as EnvironmentId,
project,
thread: thread({
session: {
threadId: "thread-1" as ThreadId,
status: "running",
providerName: "Codex",
runtimeMode: "full-access",
activeTurnId: "turn-1" as TurnId,
lastError: null,
updatedAt: NOW,
},
}),
});
expect(state).toMatchObject({
phase: "running",
headline: "Agent is working",
detail: "Codex is active.",
modelTitle: "gpt-5.4",
deepLink: "/threads/env-1/thread-1",
});
});
it("projects failures with the session error detail", () => {
const state = projectThreadAwareness({
environmentId: "env-1" as EnvironmentId,
project,
thread: thread({
session: {
threadId: "thread-1" as ThreadId,
status: "error",
providerName: "Codex",
runtimeMode: "full-access",
activeTurnId: null,
lastError: "Provider process exited.",
updatedAt: NOW,
},
}),
});
expect(state).toMatchObject({
phase: "failed",
headline: "Agent failed",
detail: "Provider process exited.",
});
});
});