import { EMPTY_V2_ITEM_SUPPORT } from "@t3tools/client-runtime/state/item-support";import { CheckpointId, CheckpointScopeId, NodeId, ProviderDriverKind, ProviderInstanceId, RunId, ThreadId, TurnItemId, type OrchestrationV2ProjectedTurnItem, type OrchestrationV2TurnItem,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime";import { describe, expect, it } from "vite-plus/test"; import { buildThreadFeed, type ThreadFeedActivity } from "./threadActivity";import { buildThreadActivityInspector } from "./threadActivityInspector"; const threadId = ThreadId.make("thread-1");const sourceThreadId = ThreadId.make("thread-source");const runId = RunId.make("run-1");const nodeId = NodeId.make("node-1");const startedAt = DateTime.makeUnsafe("2026-06-20T00:00:00.000Z");const completedAt = DateTime.makeUnsafe("2026-06-20T00:00:02.000Z"); function itemBase(id: string) { return { id: TurnItemId.make(id), threadId, runId, nodeId, providerThreadId: null, providerTurnId: null, nativeItemRef: null, parentItemId: null, ordinal: 0, status: "completed" as const, title: null, startedAt, completedAt, updatedAt: completedAt, };} function activityFor(item: OrchestrationV2TurnItem): ThreadFeedActivity { const row: OrchestrationV2ProjectedTurnItem = { position: 0, visibility: "inherited", sourceThreadId, sourceItemId: item.id, item, }; const group = buildThreadFeed([row])[0]; if (group?.type !== "activity-group" || !group.activities[0]) { throw new Error("Expected an activity group"); } return group.activities[0];} describe("buildThreadActivityInspector", () => { it("presents command lifecycle, execution support, output, and exit state", () => { const item: OrchestrationV2TurnItem = { ...itemBase("command"), type: "command_execution", input: "vp check", output: "all checks passed", exitCode: 0, }; const support = { ...EMPTY_V2_ITEM_SUPPORT, item, run: { status: "completed" } as never, attempts: [ { id: "attempt-1", attemptOrdinal: 1, status: "superseded", reason: "initial", }, { id: "attempt-2", attemptOrdinal: 2, status: "completed", reason: "steering_restart", }, ] as never, node: { kind: "tool_call", status: "completed" } as never, providerSession: { status: "ready", model: "gpt-5.4", cwd: "/workspace/project", } as never, }; const model = buildThreadActivityInspector(activityFor(item), support, sourceThreadId); expect(model.fields).toEqual( expect.arrayContaining([ { label: "Duration", value: "2.0s" }, { label: "Run", value: "completed" }, { label: "Working directory", value: "/workspace/project" }, { label: "Visibility", value: "inherited" }, ]), ); expect(model.blocks).toEqual( expect.arrayContaining([ expect.objectContaining({ label: "Command", value: "vp check" }), expect.objectContaining({ label: "Output", value: "all checks passed" }), expect.objectContaining({ label: "Exit", value: "Process exited with code 0" }), expect.objectContaining({ label: "Attempt history" }), ]), ); }); it("exposes file and web result provenance plus dynamic structured data", () => { const fileSearch: OrchestrationV2TurnItem = { ...itemBase("file-search"), type: "file_search", pattern: "resolveSession", results: [{ fileName: "src/session.ts", line: 42, preview: "function resolveSession()" }], }; const fileModel = buildThreadActivityInspector( activityFor(fileSearch), EMPTY_V2_ITEM_SUPPORT, sourceThreadId, ); expect(fileModel.fileLinks).toEqual([ { label: "src/session.ts — function resolveSession()", path: "src/session.ts", line: 42, }, ]); const webSearch: OrchestrationV2TurnItem = { ...itemBase("web-search"), type: "web_search", patterns: ["Effect Schema docs"], results: [ { title: "Schema", url: "https://effect.website/docs/schema", snippet: "Typed schemas" }, ], }; const webModel = buildThreadActivityInspector( activityFor(webSearch), EMPTY_V2_ITEM_SUPPORT, sourceThreadId, ); expect(webModel.webLinks).toEqual([ { label: "Schema", url: "https://effect.website/docs/schema" }, ]); expect(webModel.blocks).toEqual( expect.arrayContaining([ expect.objectContaining({ label: "Schema", value: "Typed schemas" }), ]), ); const dynamicTool: OrchestrationV2TurnItem = { ...itemBase("dynamic"), type: "dynamic_tool", toolName: "custom", input: { nested: { value: 1 } }, output: { ok: true }, }; const dynamicModel = buildThreadActivityInspector( activityFor(dynamicTool), EMPTY_V2_ITEM_SUPPORT, sourceThreadId, ); expect(dynamicModel.blocks).toEqual( expect.arrayContaining([ expect.objectContaining({ label: "Input", value: expect.stringContaining('"nested"') }), expect.objectContaining({ label: "Output", value: expect.stringContaining('"ok"') }), ]), ); expect(dynamicModel.structuredDetails).toContain('"type": "dynamic_tool"'); }); it("enables rollback only for the matching ready checkpoint", () => { const checkpointId = CheckpointId.make("checkpoint-1"); const scopeId = CheckpointScopeId.make("scope-1"); const item: OrchestrationV2TurnItem = { ...itemBase("checkpoint"), type: "checkpoint", checkpointId, scopeId, files: [{ path: "src/main.ts", kind: "modified", additions: 2, deletions: 1 }], }; const checkpoint = { id: checkpointId, scopeId, status: "ready" } as never; const model = buildThreadActivityInspector( activityFor(item), { ...EMPTY_V2_ITEM_SUPPORT, item, checkpoint, }, sourceThreadId, ); expect(model.canRollback).toBe(true); expect(model.rollbackTarget).toEqual({ threadId: sourceThreadId, checkpointId, scopeId, }); const inheritedModel = buildThreadActivityInspector( activityFor(item), { ...EMPTY_V2_ITEM_SUPPORT, item, checkpoint, }, ThreadId.make("child-thread"), ); expect(inheritedModel.canRollback).toBe(false); expect(inheritedModel.rollbackTarget).toBeNull(); }); it("prefers live subagent progress from supporting state", () => { const item: OrchestrationV2TurnItem = { ...itemBase("subagent"), type: "subagent", subagentId: nodeId, origin: "provider_native", driver: ProviderDriverKind.make("claude"), providerInstanceId: ProviderInstanceId.make("claude"), childThreadId: null, prompt: "Audit the reducer", progress: "Starting", result: null, }; const model = buildThreadActivityInspector( activityFor(item), { ...EMPTY_V2_ITEM_SUPPORT, item, subagent: { origin: "provider_native", status: "running", progress: "Reading projection tests", result: null, } as never, }, sourceThreadId, ); expect(model.fields).toContainEqual({ label: "Delegated task", value: "provider native · running", }); expect(model.blocks).toContainEqual({ label: "Progress", value: "Reading projection tests", monospaced: false, }); });});
import { EMPTY_V2_ITEM_SUPPORT } from "@t3tools/client-runtime/state/item-support";
import {
CheckpointId,
CheckpointScopeId,
NodeId,
ProviderDriverKind,
ProviderInstanceId,
RunId,
ThreadId,
TurnItemId,
type OrchestrationV2ProjectedTurnItem,
type OrchestrationV2TurnItem,
} from "@t3tools/contracts";
import * as DateTime from "effect/DateTime";
import { describe, expect, it } from "vite-plus/test";
import { buildThreadFeed, type ThreadFeedActivity } from "./threadActivity";
import { buildThreadActivityInspector } from "./threadActivityInspector";
const threadId = ThreadId.make("thread-1");
const sourceThreadId = ThreadId.make("thread-source");
const runId = RunId.make("run-1");
const nodeId = NodeId.make("node-1");
const startedAt = DateTime.makeUnsafe("2026-06-20T00:00:00.000Z");
const completedAt = DateTime.makeUnsafe("2026-06-20T00:00:02.000Z");
function itemBase(id: string) {
return {
id: TurnItemId.make(id),
threadId,
runId,
nodeId,
providerThreadId: null,
providerTurnId: null,
nativeItemRef: null,
parentItemId: null,
ordinal: 0,
status: "completed" as const,
title: null,
startedAt,
completedAt,
updatedAt: completedAt,
};
}
function activityFor(item: OrchestrationV2TurnItem): ThreadFeedActivity {
const row: OrchestrationV2ProjectedTurnItem = {
position: 0,
visibility: "inherited",
sourceThreadId,
sourceItemId: item.id,
item,
};
const group = buildThreadFeed([row])[0];
if (group?.type !== "activity-group" || !group.activities[0]) {
throw new Error("Expected an activity group");
}
return group.activities[0];
}
describe("buildThreadActivityInspector", () => {
it("presents command lifecycle, execution support, output, and exit state", () => {
const item: OrchestrationV2TurnItem = {
...itemBase("command"),
type: "command_execution",
input: "vp check",
output: "all checks passed",
exitCode: 0,
};
const support = {
...EMPTY_V2_ITEM_SUPPORT,
item,
run: { status: "completed" } as never,
attempts: [
{
id: "attempt-1",
attemptOrdinal: 1,
status: "superseded",
reason: "initial",
},
{
id: "attempt-2",
attemptOrdinal: 2,
status: "completed",
reason: "steering_restart",
},
] as never,
node: { kind: "tool_call", status: "completed" } as never,
providerSession: {
status: "ready",
model: "gpt-5.4",
cwd: "/workspace/project",
} as never,
};
const model = buildThreadActivityInspector(activityFor(item), support, sourceThreadId);
expect(model.fields).toEqual(
expect.arrayContaining([
{ label: "Duration", value: "2.0s" },
{ label: "Run", value: "completed" },
{ label: "Working directory", value: "/workspace/project" },
{ label: "Visibility", value: "inherited" },
]),
);
expect(model.blocks).toEqual(
expect.arrayContaining([
expect.objectContaining({ label: "Command", value: "vp check" }),
expect.objectContaining({ label: "Output", value: "all checks passed" }),
expect.objectContaining({ label: "Exit", value: "Process exited with code 0" }),
expect.objectContaining({ label: "Attempt history" }),
]),
);
});
it("exposes file and web result provenance plus dynamic structured data", () => {
const fileSearch: OrchestrationV2TurnItem = {
...itemBase("file-search"),
type: "file_search",
pattern: "resolveSession",
results: [{ fileName: "src/session.ts", line: 42, preview: "function resolveSession()" }],
};
const fileModel = buildThreadActivityInspector(
activityFor(fileSearch),
EMPTY_V2_ITEM_SUPPORT,
sourceThreadId,
);
expect(fileModel.fileLinks).toEqual([
{
label: "src/session.ts — function resolveSession()",
path: "src/session.ts",
line: 42,
},
]);
const webSearch: OrchestrationV2TurnItem = {
...itemBase("web-search"),
type: "web_search",
patterns: ["Effect Schema docs"],
results: [
{ title: "Schema", url: "https://effect.website/docs/schema", snippet: "Typed schemas" },
],
};
const webModel = buildThreadActivityInspector(
activityFor(webSearch),
EMPTY_V2_ITEM_SUPPORT,
sourceThreadId,
);
expect(webModel.webLinks).toEqual([
{ label: "Schema", url: "https://effect.website/docs/schema" },
]);
expect(webModel.blocks).toEqual(
expect.arrayContaining([
expect.objectContaining({ label: "Schema", value: "Typed schemas" }),
]),
);
const dynamicTool: OrchestrationV2TurnItem = {
...itemBase("dynamic"),
type: "dynamic_tool",
toolName: "custom",
input: { nested: { value: 1 } },
output: { ok: true },
};
const dynamicModel = buildThreadActivityInspector(
activityFor(dynamicTool),
EMPTY_V2_ITEM_SUPPORT,
sourceThreadId,
);
expect(dynamicModel.blocks).toEqual(
expect.arrayContaining([
expect.objectContaining({ label: "Input", value: expect.stringContaining('"nested"') }),
expect.objectContaining({ label: "Output", value: expect.stringContaining('"ok"') }),
]),
);
expect(dynamicModel.structuredDetails).toContain('"type": "dynamic_tool"');
});
it("enables rollback only for the matching ready checkpoint", () => {
const checkpointId = CheckpointId.make("checkpoint-1");
const scopeId = CheckpointScopeId.make("scope-1");
const item: OrchestrationV2TurnItem = {
...itemBase("checkpoint"),
type: "checkpoint",
checkpointId,
scopeId,
files: [{ path: "src/main.ts", kind: "modified", additions: 2, deletions: 1 }],
};
const checkpoint = { id: checkpointId, scopeId, status: "ready" } as never;
const model = buildThreadActivityInspector(
activityFor(item),
{
...EMPTY_V2_ITEM_SUPPORT,
item,
checkpoint,
},
sourceThreadId,
);
expect(model.canRollback).toBe(true);
expect(model.rollbackTarget).toEqual({
threadId: sourceThreadId,
checkpointId,
scopeId,
});
const inheritedModel = buildThreadActivityInspector(
activityFor(item),
{
...EMPTY_V2_ITEM_SUPPORT,
item,
checkpoint,
},
ThreadId.make("child-thread"),
);
expect(inheritedModel.canRollback).toBe(false);
expect(inheritedModel.rollbackTarget).toBeNull();
});
it("prefers live subagent progress from supporting state", () => {
const item: OrchestrationV2TurnItem = {
...itemBase("subagent"),
type: "subagent",
subagentId: nodeId,
origin: "provider_native",
driver: ProviderDriverKind.make("claude"),
providerInstanceId: ProviderInstanceId.make("claude"),
childThreadId: null,
prompt: "Audit the reducer",
progress: "Starting",
result: null,
};
const model = buildThreadActivityInspector(
activityFor(item),
{
...EMPTY_V2_ITEM_SUPPORT,
item,
subagent: {
origin: "provider_native",
status: "running",
progress: "Reading projection tests",
result: null,
} as never,
},
sourceThreadId,
);
expect(model.fields).toContainEqual({
label: "Delegated task",
value: "provider native · running",
});
expect(model.blocks).toContainEqual({
label: "Progress",
value: "Reading projection tests",
monospaced: false,
});
});
});