import { classifyTaskAgentKind, EventId, MessageId, ThreadId, TurnId, type OrchestrationThreadActivity,} from "@t3tools/contracts";import { describe, expect, it } from "vite-plus/test";import { resolveWorkEntryToolPresentation } from "@t3tools/client-runtime/work-log/presentation"; import { deriveActiveWorkStartedAt, deriveActivePlanState, derivePendingApprovals, derivePendingUserInputs, deriveTimelineEntries, deriveWorkLogEntries, findLatestProposedPlan, hasActionableProposedPlan, isLatestTurnSettled, workEntryIndicatesToolFailure, workEntryIndicatesToolNeutralStatus, workEntryIndicatesToolSuccess,} from "./session-logic"; let nextActivityId = 0; function makeActivity(overrides: { id?: string; createdAt?: string; kind?: string; summary?: string; tone?: OrchestrationThreadActivity["tone"]; payload?: Record<string, unknown>; turnId?: string; sequence?: number;}): OrchestrationThreadActivity { // Fixtures model post-ingestion rows: ingestion stamps agentKind on every // task.* payload. Pass an explicit agentKind to model legacy rows. const rawPayload = overrides.payload ?? {}; const payload = overrides.kind?.startsWith("task.") && !("agentKind" in rawPayload) ? { ...rawPayload, agentKind: classifyTaskAgentKind({ taskType: typeof rawPayload.taskType === "string" ? rawPayload.taskType : undefined, agentId: typeof rawPayload.agentId === "string" ? rawPayload.agentId : undefined, }), } : rawPayload; return { id: EventId.make(overrides.id ?? `activity-${nextActivityId++}`), createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z", kind: overrides.kind ?? "tool.started", summary: overrides.summary ?? "Tool call", tone: overrides.tone ?? "tool", payload, turnId: overrides.turnId ? TurnId.make(overrides.turnId) : null, ...(overrides.sequence !== undefined ? { sequence: overrides.sequence } : {}), };} describe("derivePendingApprovals", () => { it("tracks open approvals and removes resolved ones", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-1", requestKind: "command", detail: "bun run lint", }, }), makeActivity({ id: "approval-close", createdAt: "2026-02-23T00:00:02.000Z", kind: "approval.resolved", summary: "Approval resolved", tone: "info", payload: { requestId: "req-2" }, }), makeActivity({ id: "approval-closed-request", createdAt: "2026-02-23T00:00:01.500Z", kind: "approval.requested", summary: "File-change approval requested", tone: "approval", payload: { requestId: "req-2", requestKind: "file-change" }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-1", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "bun run lint", }, ]); }); it("maps canonical requestType payloads into pending approvals", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-request-type", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-request-type", requestType: "command_execution_approval", detail: "pwd", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-request-type", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "pwd", }, ]); }); it("keeps app access approvals and persistence choices from remote activities", () => { const options = [ { decision: "decline", label: "Decline" }, { decision: "acceptAlways", label: "Always allow Safari" }, { decision: "accept", label: "Approve" }, ]; const activities = [ makeActivity({ kind: "approval.requested", summary: "App access approval requested", tone: "approval", payload: { requestId: "req-safari", requestType: "mcp_elicitation_approval", detail: "Allow ChatGPT to use Safari?", appName: "Safari", options, }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-safari", requestKind: "mcp-elicitation", createdAt: "2026-02-23T00:00:00.000Z", detail: "Allow ChatGPT to use Safari?", appName: "Safari", options, }, ]); }); it("derives dynamic tool requests as actionable generic approvals", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-dynamic-tool", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Approval requested", tone: "approval", payload: { requestId: "req-dynamic-tool", requestType: "dynamic_tool_call", detail: "Search the web", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-dynamic-tool", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "Search the web", }, ]); }); it("clears stale pending approvals when provider reports unknown pending request", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-stale", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-stale-1", requestKind: "command", }, }), makeActivity({ id: "approval-failed-stale", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.approval.respond.failed", summary: "Provider approval response failed", tone: "error", payload: { requestId: "req-stale-1", detail: "Unknown pending permission request: req-stale-1", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([]); }); it("clears stale pending approvals when the backend marks them stale after restart", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-stale-restart", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-stale-restart-1", requestKind: "command", }, }), makeActivity({ id: "approval-failed-stale-restart", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.approval.respond.failed", summary: "Provider approval response failed", tone: "error", payload: { requestId: "req-stale-restart-1", detail: "Stale pending approval request: req-stale-restart-1. Provider callback state does not survive app restarts or recovered sessions. Restart the turn to continue.", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([]); });}); describe("derivePendingUserInputs", () => { it("tracks open structured prompts and removes resolved ones", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "user-input-open", createdAt: "2026-02-23T00:00:01.000Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-1", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: true, }, ], }, }), makeActivity({ id: "user-input-resolved", createdAt: "2026-02-23T00:00:02.000Z", kind: "user-input.resolved", summary: "User input submitted", tone: "info", payload: { requestId: "req-user-input-2", answers: { sandbox_mode: "workspace-write", }, }, }), makeActivity({ id: "user-input-open-2", createdAt: "2026-02-23T00:00:01.500Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-2", questions: [ { id: "approval", header: "Approval", question: "Continue?", options: [ { label: "yes", description: "Continue execution", }, ], multiSelect: false, }, ], }, }), ]; expect(derivePendingUserInputs(activities)).toEqual([ { requestId: "req-user-input-1", createdAt: "2026-02-23T00:00:01.000Z", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: true, }, ], }, ]); }); it("clears stale pending user-input prompts when the provider reports an orphaned request", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "user-input-open-stale", createdAt: "2026-02-23T00:00:01.000Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-stale-1", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: false, }, ], }, }), makeActivity({ id: "user-input-failed-stale", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.user-input.respond.failed", summary: "Provider user input response failed", tone: "error", payload: { requestId: "req-user-input-stale-1", detail: "Provider adapter request failed (codex) for item/tool/requestUserInput: Unknown pending Codex user input request: req-user-input-stale-1", }, }), ]; expect(derivePendingUserInputs(activities)).toEqual([]); });}); describe("deriveActivePlanState", () => { it("returns the latest plan update for the active turn", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-old", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { explanation: "Initial plan", plan: [{ step: "Inspect code", status: "pending" }], }, }), makeActivity({ id: "plan-latest", createdAt: "2026-02-23T00:00:02.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { explanation: "Refined plan", plan: [{ step: "Implement Codex user input", status: "inProgress" }], }, }), ]; expect(deriveActivePlanState(activities, TurnId.make("turn-1"))).toEqual({ createdAt: "2026-02-23T00:00:02.000Z", turnId: "turn-1", explanation: "Refined plan", steps: [{ step: "Implement Codex user input", status: "inProgress" }], }); }); it("falls back to the most recent plan from a previous turn", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-from-turn-1", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Write tests", status: "completed" }], }, }), ]; // Current turn is turn-2, which has no plan activity — should fall back to turn-1's plan const result = deriveActivePlanState(activities, TurnId.make("turn-2")); expect(result).toEqual({ createdAt: "2026-02-23T00:00:01.000Z", turnId: "turn-1", steps: [{ step: "Write tests", status: "completed" }], }); }); it("starts timing again after a plan is cleared and recreated", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-old-start", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "inProgress" }] }, }), makeActivity({ id: "plan-old-complete", createdAt: "2026-02-23T00:00:05.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "completed" }] }, }), makeActivity({ id: "plan-clear", createdAt: "2026-02-23T00:00:06.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [] }, }), makeActivity({ id: "plan-new-start", createdAt: "2026-02-23T00:00:10.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "inProgress" }] }, }), makeActivity({ id: "plan-new-complete", createdAt: "2026-02-23T00:00:13.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "completed" }] }, }), ]; expect(deriveActivePlanState(activities, TurnId.make("turn-1"))?.steps).toEqual([ { durationMs: 3_000, step: "Check", status: "completed" }, ]); }); it("tracks repeated step labels independently", () => { const activities: OrchestrationThreadActivity[] = [Lines 1–500 of 2467. Load more
import { classifyTaskAgentKind, EventId, MessageId, ThreadId, TurnId, type OrchestrationThreadActivity, } from "@t3tools/contracts"; import { describe, expect, it } from "vite-plus/test"; import { resolveWorkEntryToolPresentation } from "@t3tools/client-runtime/work-log/presentation"; import { deriveActiveWorkStartedAt, deriveActivePlanState, derivePendingApprovals, derivePendingUserInputs, deriveTimelineEntries, deriveWorkLogEntries, findLatestProposedPlan, hasActionableProposedPlan, isLatestTurnSettled, workEntryIndicatesToolFailure, workEntryIndicatesToolNeutralStatus, workEntryIndicatesToolSuccess, } from "./session-logic"; let nextActivityId = 0; function makeActivity(overrides: { id?: string; createdAt?: string; kind?: string; summary?: string; tone?: OrchestrationThreadActivity["tone"]; payload?: Record<string, unknown>; turnId?: string; sequence?: number; }): OrchestrationThreadActivity { // Fixtures model post-ingestion rows: ingestion stamps agentKind on every // task.* payload. Pass an explicit agentKind to model legacy rows. const rawPayload = overrides.payload ?? {}; const payload = overrides.kind?.startsWith("task.") && !("agentKind" in rawPayload) ? { ...rawPayload, agentKind: classifyTaskAgentKind({ taskType: typeof rawPayload.taskType === "string" ? rawPayload.taskType : undefined, agentId: typeof rawPayload.agentId === "string" ? rawPayload.agentId : undefined, }), } : rawPayload; return { id: EventId.make(overrides.id ?? `activity-${nextActivityId++}`), createdAt: overrides.createdAt ?? "2026-02-23T00:00:00.000Z", kind: overrides.kind ?? "tool.started", summary: overrides.summary ?? "Tool call", tone: overrides.tone ?? "tool", payload, turnId: overrides.turnId ? TurnId.make(overrides.turnId) : null, ...(overrides.sequence !== undefined ? { sequence: overrides.sequence } : {}), }; } describe("derivePendingApprovals", () => { it("tracks open approvals and removes resolved ones", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-1", requestKind: "command", detail: "bun run lint", }, }), makeActivity({ id: "approval-close", createdAt: "2026-02-23T00:00:02.000Z", kind: "approval.resolved", summary: "Approval resolved", tone: "info", payload: { requestId: "req-2" }, }), makeActivity({ id: "approval-closed-request", createdAt: "2026-02-23T00:00:01.500Z", kind: "approval.requested", summary: "File-change approval requested", tone: "approval", payload: { requestId: "req-2", requestKind: "file-change" }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-1", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "bun run lint", }, ]); }); it("maps canonical requestType payloads into pending approvals", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-request-type", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-request-type", requestType: "command_execution_approval", detail: "pwd", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-request-type", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "pwd", }, ]); }); it("keeps app access approvals and persistence choices from remote activities", () => { const options = [ { decision: "decline", label: "Decline" }, { decision: "acceptAlways", label: "Always allow Safari" }, { decision: "accept", label: "Approve" }, ]; const activities = [ makeActivity({ kind: "approval.requested", summary: "App access approval requested", tone: "approval", payload: { requestId: "req-safari", requestType: "mcp_elicitation_approval", detail: "Allow ChatGPT to use Safari?", appName: "Safari", options, }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-safari", requestKind: "mcp-elicitation", createdAt: "2026-02-23T00:00:00.000Z", detail: "Allow ChatGPT to use Safari?", appName: "Safari", options, }, ]); }); it("derives dynamic tool requests as actionable generic approvals", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-dynamic-tool", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Approval requested", tone: "approval", payload: { requestId: "req-dynamic-tool", requestType: "dynamic_tool_call", detail: "Search the web", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([ { requestId: "req-dynamic-tool", requestKind: "command", createdAt: "2026-02-23T00:00:01.000Z", detail: "Search the web", }, ]); }); it("clears stale pending approvals when provider reports unknown pending request", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-stale", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-stale-1", requestKind: "command", }, }), makeActivity({ id: "approval-failed-stale", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.approval.respond.failed", summary: "Provider approval response failed", tone: "error", payload: { requestId: "req-stale-1", detail: "Unknown pending permission request: req-stale-1", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([]); }); it("clears stale pending approvals when the backend marks them stale after restart", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "approval-open-stale-restart", createdAt: "2026-02-23T00:00:01.000Z", kind: "approval.requested", summary: "Command approval requested", tone: "approval", payload: { requestId: "req-stale-restart-1", requestKind: "command", }, }), makeActivity({ id: "approval-failed-stale-restart", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.approval.respond.failed", summary: "Provider approval response failed", tone: "error", payload: { requestId: "req-stale-restart-1", detail: "Stale pending approval request: req-stale-restart-1. Provider callback state does not survive app restarts or recovered sessions. Restart the turn to continue.", }, }), ]; expect(derivePendingApprovals(activities)).toEqual([]); }); }); describe("derivePendingUserInputs", () => { it("tracks open structured prompts and removes resolved ones", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "user-input-open", createdAt: "2026-02-23T00:00:01.000Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-1", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: true, }, ], }, }), makeActivity({ id: "user-input-resolved", createdAt: "2026-02-23T00:00:02.000Z", kind: "user-input.resolved", summary: "User input submitted", tone: "info", payload: { requestId: "req-user-input-2", answers: { sandbox_mode: "workspace-write", }, }, }), makeActivity({ id: "user-input-open-2", createdAt: "2026-02-23T00:00:01.500Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-2", questions: [ { id: "approval", header: "Approval", question: "Continue?", options: [ { label: "yes", description: "Continue execution", }, ], multiSelect: false, }, ], }, }), ]; expect(derivePendingUserInputs(activities)).toEqual([ { requestId: "req-user-input-1", createdAt: "2026-02-23T00:00:01.000Z", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: true, }, ], }, ]); }); it("clears stale pending user-input prompts when the provider reports an orphaned request", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "user-input-open-stale", createdAt: "2026-02-23T00:00:01.000Z", kind: "user-input.requested", summary: "User input requested", tone: "info", payload: { requestId: "req-user-input-stale-1", questions: [ { id: "sandbox_mode", header: "Sandbox", question: "Which mode should be used?", options: [ { label: "workspace-write", description: "Allow workspace writes only", }, ], multiSelect: false, }, ], }, }), makeActivity({ id: "user-input-failed-stale", createdAt: "2026-02-23T00:00:02.000Z", kind: "provider.user-input.respond.failed", summary: "Provider user input response failed", tone: "error", payload: { requestId: "req-user-input-stale-1", detail: "Provider adapter request failed (codex) for item/tool/requestUserInput: Unknown pending Codex user input request: req-user-input-stale-1", }, }), ]; expect(derivePendingUserInputs(activities)).toEqual([]); }); }); describe("deriveActivePlanState", () => { it("returns the latest plan update for the active turn", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-old", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { explanation: "Initial plan", plan: [{ step: "Inspect code", status: "pending" }], }, }), makeActivity({ id: "plan-latest", createdAt: "2026-02-23T00:00:02.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { explanation: "Refined plan", plan: [{ step: "Implement Codex user input", status: "inProgress" }], }, }), ]; expect(deriveActivePlanState(activities, TurnId.make("turn-1"))).toEqual({ createdAt: "2026-02-23T00:00:02.000Z", turnId: "turn-1", explanation: "Refined plan", steps: [{ step: "Implement Codex user input", status: "inProgress" }], }); }); it("falls back to the most recent plan from a previous turn", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-from-turn-1", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Write tests", status: "completed" }], }, }), ]; // Current turn is turn-2, which has no plan activity — should fall back to turn-1's plan const result = deriveActivePlanState(activities, TurnId.make("turn-2")); expect(result).toEqual({ createdAt: "2026-02-23T00:00:01.000Z", turnId: "turn-1", steps: [{ step: "Write tests", status: "completed" }], }); }); it("starts timing again after a plan is cleared and recreated", () => { const activities: OrchestrationThreadActivity[] = [ makeActivity({ id: "plan-old-start", createdAt: "2026-02-23T00:00:01.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "inProgress" }] }, }), makeActivity({ id: "plan-old-complete", createdAt: "2026-02-23T00:00:05.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "completed" }] }, }), makeActivity({ id: "plan-clear", createdAt: "2026-02-23T00:00:06.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [] }, }), makeActivity({ id: "plan-new-start", createdAt: "2026-02-23T00:00:10.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "inProgress" }] }, }), makeActivity({ id: "plan-new-complete", createdAt: "2026-02-23T00:00:13.000Z", kind: "turn.plan.updated", summary: "Plan updated", tone: "info", turnId: "turn-1", payload: { plan: [{ step: "Check", status: "completed" }] }, }), ]; expect(deriveActivePlanState(activities, TurnId.make("turn-1"))?.steps).toEqual([ { durationMs: 3_000, step: "Check", status: "completed" }, ]); }); it("tracks repeated step labels independently", () => { const activities: OrchestrationThreadActivity[] = [