233 lines · 6.9 KB · TypeScript
RawDownload
import {  EventId,  ProjectId,  ProviderInstanceId,  ThreadId,  TurnId,  type OrchestrationEvent,  type OrchestrationThread,  type OrchestrationThreadActivity,} from "@t3tools/contracts";import { describe, expect, it } from "vite-plus/test"; import { buildThreadFeed, type ThreadFeedActivity } from "../../mobile/src/lib/threadActivity.ts";import { deriveWorkLogEntries } from "../../web/src/session-logic.ts";import {  projectActivityEvent,  projectActivityPayload,  projectThreadDetailSnapshot,} from "../src/orchestration/ActivityPayloadProjection.ts"; function makeActivity(  id: string,  itemType: string,  data: Record<string, unknown>,): OrchestrationThreadActivity {  return {    id: EventId.make(id),    tone: "tool",    kind: "tool.completed",    summary: `Completed ${itemType}`,    payload: {      itemType,      title: itemType,      detail: `${itemType} detail`,      status: "completed",      requestKind: "command",      data,    },    turnId: TurnId.make(`turn-${id}`),    createdAt: "2026-07-27T00:00:00.000Z",  };} function makeThread(activities: ReadonlyArray<OrchestrationThreadActivity>): OrchestrationThread {  return {    id: ThreadId.make("thread-projection"),    projectId: ProjectId.make("project-projection"),    title: "Activity projection",    modelSelection: {      instanceId: ProviderInstanceId.make("codex"),      model: "gpt-5.4",    },    runtimeMode: "full-access",    interactionMode: "default",    branch: null,    worktreePath: null,    latestTurn: null,    createdAt: "2026-07-27T00:00:00.000Z",    updatedAt: "2026-07-27T00:00:00.000Z",    archivedAt: null,    settledOverride: null,    settledAt: null,    deletedAt: null,    messages: [],    proposedPlans: [],    activities,    checkpoints: [],    session: null,  };} const fixtures = [  makeActivity("command", "command_execution", {    item: {      command: ["bash", "-lc", "pnpm test"],      input: { command: "fallback input", ignored: "input bulk" },      result: { command: "fallback result", aggregatedOutput: "x".repeat(10_000) },      commandActions: [{ type: "unknown", output: "y".repeat(5_000) }],    },    command: "fallback data",    kind: "execute",    toolCallId: "tool-command",    rawOutput: {      content: "\n```\nfirst useful line\nsecond line",      stdout: "unused stdout",      ignored: "raw bulk",    },    ignored: "top-level bulk",  }),  makeActivity("file-change", "file_change", {    item: {      changes: [        { oldPath: "src/old.ts", newPath: "src/new.ts", patch: "large patch".repeat(1_000) },        { filePath: "src/second.ts" },      ],    },    ignored: "top-level bulk",  }),  makeActivity("dynamic", "dynamic_tool_call", {    toolCallId: "tool-dynamic",    rawOutput: {      stdout: "dynamic summary\nlong output".repeat(1_000),    },    ignored: "top-level bulk",  }),  makeActivity("collab", "collab_agent_tool_call", {    kind: "delegate",    rawOutput: {      content: "``` \n```",      stdout: "must not be used when content is present",    },    ignored: "top-level bulk",  }),  makeActivity("mcp", "mcp_tool_call", {    item: {      server: "repository",      tool: "search",      arguments: { query: "activity projection" },      aggregatedOutput: "mcp payload remains available",    },    ignored: "MCP data is rendered verbatim",  }),  makeActivity("search", "web_search", {    rawOutput: {      totalFiles: 42,      truncated: true,      content: "ignored because totalFiles wins",    },    ignored: "top-level bulk",  }),  makeActivity("image", "image_view", {    ignored: "top-level bulk",  }),] satisfies ReadonlyArray<OrchestrationThreadActivity>; describe("projectActivityPayload", () => {  function comparableActivity(activity: ThreadFeedActivity) {    return {      ...activity,      fullDetail: activity.getFullDetail(),      copyText: activity.getCopyText(),      getFullDetail: undefined,      getCopyText: undefined,    };  }   function comparableThreadFeed(activities: ReadonlyArray<OrchestrationThreadActivity>) {    return buildThreadFeed(makeThread(activities)).map((entry) =>      entry.type === "activity-group"        ? {            ...entry,            activities: entry.activities.map(comparableActivity),          }        : entry,    );  }   it("drops unread bulk while retaining command, file, tool, and summary inputs", () => {    const projected = projectActivityPayload(fixtures[0]!);    expect(projected.payload).toEqual({      itemType: "command_execution",      title: "command_execution",      detail: "command_execution detail",      status: "completed",      requestKind: "command",      data: {        item: {          command: ["bash", "-lc", "pnpm test"],          input: { command: "fallback input" },          result: { command: "fallback result" },        },        command: "fallback data",        toolCallId: "tool-command",        kind: "execute",        rawOutput: { content: "first useful line" },      },    });     expect(projectActivityPayload(fixtures[1]!).payload).toMatchObject({      data: {        files: [{ path: "src/new.ts" }, { path: "src/old.ts" }, { path: "src/second.ts" }],      },    });  });   it("passes MCP tool data through unchanged", () => {    expect(projectActivityPayload(fixtures[4]!)).toBe(fixtures[4]);  });   it("keeps current web and mobile derived output identical for every tool item type", () => {    for (const activity of fixtures) {      const projected = projectActivityPayload(activity);      expect(deriveWorkLogEntries([projected])).toEqual(deriveWorkLogEntries([activity]));      expect(comparableThreadFeed([projected])).toEqual(comparableThreadFeed([activity]));    }  });   it("projects snapshot and event transports without mutating their sources", () => {    const activity = fixtures[0]!;    const thread = makeThread([activity]);    const snapshot = { snapshotSequence: 7, thread };    const projectedSnapshot = projectThreadDetailSnapshot(snapshot);     expect(projectedSnapshot.thread.activities[0]).not.toBe(activity);    expect(snapshot.thread.activities[0]).toBe(activity);     const event = {      sequence: 8,      eventId: EventId.make("event-activity"),      aggregateKind: "thread",      aggregateId: thread.id,      occurredAt: "2026-07-27T00:00:01.000Z",      commandId: null,      causationEventId: null,      correlationId: null,      metadata: {},      type: "thread.activity-appended",      payload: {        threadId: thread.id,        activity,      },    } satisfies Extract<OrchestrationEvent, { type: "thread.activity-appended" }>;     const projectedEvent = projectActivityEvent(event);    expect(projectedEvent).not.toBe(event);    expect(      projectedEvent.type === "thread.activity-appended"        ? projectedEvent.payload.activity        : undefined,    ).toEqual(projectActivityPayload(activity));    expect(event.payload.activity).toBe(activity);  });});

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t