671 lines · 20.9 KB · TypeScript
RawDownload
import { projectQuestionToolInput } from "@t3tools/shared/toolActivity";import type {  OrchestrationEvent,  OrchestrationThreadActivity,  OrchestrationThreadDetailSnapshot,} from "@t3tools/contracts";import { isWorkspaceImagePreviewPath } from "@t3tools/shared/filePreview";import { extractJsonObject } from "@t3tools/shared/schemaJson"; function asRecord(value: unknown): Record<string, unknown> | null {  return value !== null && typeof value === "object" && !Array.isArray(value)    ? (value as Record<string, unknown>)    : null;} function asTrimmedString(value: unknown): string | null {  if (typeof value !== "string") {    return null;  }  const trimmed = value.trim();  return trimmed.length > 0 ? trimmed : null;} function pushChangedFile(target: string[], seen: Set<string>, value: unknown): void {  const normalized = asTrimmedString(value);  if (!normalized || seen.has(normalized)) {    return;  }  seen.add(normalized);  target.push(normalized);} function collectChangedFiles(  value: unknown,  target: string[],  seen: Set<string>,  depth: number,): void {  if (depth > 4 || target.length >= 12) {    return;  }  if (Array.isArray(value)) {    for (const entry of value) {      collectChangedFiles(entry, target, seen, depth + 1);      if (target.length >= 12) {        return;      }    }    return;  }   const record = asRecord(value);  if (!record) {    return;  }   pushChangedFile(target, seen, record.path);  pushChangedFile(target, seen, record.filePath);  pushChangedFile(target, seen, record.relativePath);  pushChangedFile(target, seen, record.filename);  pushChangedFile(target, seen, record.newPath);  pushChangedFile(target, seen, record.oldPath);   for (const nestedKey of [    "item",    "result",    "input",    "data",    "changes",    "files",    "edits",    "patch",    "patches",    "operations",  ]) {    if (!(nestedKey in record)) {      continue;    }    collectChangedFiles(record[nestedKey], target, seen, depth + 1);    if (target.length >= 12) {      return;    }  }} function projectCommandData(data: Record<string, unknown>): Record<string, unknown> | undefined {  const item = asRecord(data.item);  if (!item) {    return undefined;  }   const projectedItem: Record<string, unknown> = {};  if ("command" in item) {    projectedItem.command = item.command;  }   const aggregatedOutput = asTrimmedString(item.aggregatedOutput);  if (aggregatedOutput) {    const summary = summarizeToolTextOutput(aggregatedOutput);    if (summary) {      projectedItem.aggregatedOutput = summary;    }  }   const input = asRecord(item.input);  if (input && "command" in input) {    projectedItem.input = { command: input.command };  }   const result = asRecord(item.result);  if (result) {    const projectedResult: Record<string, unknown> = {};    if ("command" in result) {      projectedResult.command = result.command;    }    const content = asTrimmedString(result.content);    if (content) {      const summary = summarizeToolTextOutput(content);      if (summary) {        projectedResult.content = summary;      }    }    if (Object.keys(projectedResult).length > 0) {      projectedItem.result = projectedResult;    }  }   return Object.keys(projectedItem).length > 0 ? projectedItem : undefined;} function projectCommandValue(data: Record<string, unknown>): unknown {  if (data.command !== undefined) {    return data.command;  }   const input = asRecord(data.input);  if (input?.command !== undefined) {    return input.command;  }   const stateInput = asRecord(asRecord(data.state)?.input);  if (stateInput?.command !== undefined) {    return stateInput.command;  }   return undefined;} function projectViewedImagePath(data: Record<string, unknown>): string | undefined {  const directPath = asTrimmedString(data.imagePath);  if (directPath && isWorkspaceImagePreviewPath(directPath)) {    return directPath;  }   const toolName = asTrimmedString(data.toolName)?.toLowerCase();  if (toolName !== "read" && toolName !== "read file") {    return undefined;  }  const input = asRecord(data.input);  const inputPath = asTrimmedString(input?.file_path) ?? asTrimmedString(input?.path);  return inputPath && isWorkspaceImagePreviewPath(inputPath) ? inputPath : undefined;} function summarizeToolTextOutput(value: string): string | null {  let meaningfulLineCount = 0;  let offset = 0;   while (offset <= value.length) {    const newlineIndex = value.indexOf("\n", offset);    const lineEnd = newlineIndex === -1 ? value.length : newlineIndex;    const line = value.slice(offset, lineEnd).replace(/\s+/g, " ").trim();    if (line.length > 0) {      meaningfulLineCount += 1;      if (line !== "```") {        const summary = line.length <= 84 ? line : `${line.slice(0, 83).trimEnd()}…`;        // V8 can retain the full tool output behind a short sliced string.        // Join a tiny character array so the returned preview owns its bytes.        return Array.from(summary).join("");      }    }    if (newlineIndex === -1) {      break;    }    offset = newlineIndex + 1;  }   return meaningfulLineCount > 1 ? `${meaningfulLineCount.toLocaleString()} lines` : null;} /** * Fields of an MCP tool-call item both clients render in the expanded * work-log row. Everything else — notably `result`, which carries the full * tool output and dominates wire size on MCP-heavy threads — is summarized * or dropped. Full payloads remain in persistence. */const MCP_ITEM_KEPT_FIELDS = [  "type",  "id",  "tool",  "server",  "status",  "arguments",  "appContext",  "error",  "durationMs",] as const; /** * Pulls renderable text out of an MCP tool result: either a Codex-style * `{content: [{type: "text", text}, ...]}` record or a raw Claude * `tool_result` block whose `content` is a string or block array. */function extractMcpResultText(result: unknown): string | null {  const record = asRecord(result);  if (!record) {    return typeof result === "string" ? result : null;  }  if (typeof record.content === "string") {    return record.content;  }  if (Array.isArray(record.content)) {    const texts: string[] = [];    for (const entry of record.content) {      const text = asRecord(entry)?.text;      if (typeof text === "string" && text.trim().length > 0) {        texts.push(text);      }    }    if (texts.length > 0) {      return texts.join("\n");    }  }  return null;} function summarizeMcpResult(result: unknown): Record<string, unknown> | undefined {  if (result === undefined || result === null) {    return undefined;  }  const text = extractMcpResultText(result);  const summary = text ? summarizeToolTextOutput(text) : null;  return summary ? { content: summary } : undefined;} /** Reuse the page URL already returned by preview tools before slimming their output. */function projectPreviewToolMetadata(data: Record<string, unknown>, status: unknown) {  const item = asRecord(data.item);  const name = item ? `mcp__${item.server}__${item.tool}` : (data.toolName ?? data.tool);  if (    typeof name !== "string" ||    !/^(?:mcp__)?(?:t3-code|t3_code|t3code)_{1,2}preview_(?:open|navigate|status|snapshot|click|type|press|scroll|resize|set_appearance|evaluate|wait_for|recording_start|recording_stop)$/.test(      name,    )  )    return {};  const state = asRecord(data.state);  const result = item?.result ?? data.result ?? state?.output;  const record = asRecord(result);  if (    status === "failed" ||    status === "declined" ||    state?.status === "error" ||    item?.error != null ||    record?.isError === true ||    record?.is_error === true  )    return {};   let page = record;  let output: unknown = result;  for (let depth = 0; depth < 3; depth += 1) {    if (page?.isError === true || page?.is_error === true) return {};    const structured = asRecord(page?.structuredContent);    if (structured) {      page = structured;      break;    }    const text = extractMcpResultText(output)?.slice(0, 2 * 1024 * 1024);    if (!text) break;    try {      page = asRecord(JSON.parse(extractJsonObject(text)));    } catch {      // A truncated MCP envelope can still contain a complete first text block.      const firstBlock = /^\s*\{\s*"content"\s*:\s*\[\s*/.exec(text);      if (!firstBlock) return {};      try {        const block = asRecord(JSON.parse(extractJsonObject(text.slice(firstBlock[0].length))));        page = block?.type === "text" ? { content: [block] } : null;      } catch {        return {};      }    }    output = page;  }  const rawUrl = asTrimmedString(    asRecord(page?.toolIcon)?.pageUrl ??      (/preview_(?:open|navigate|status|snapshot)$/.test(name) ? page?.url : undefined),  );  if (!rawUrl || rawUrl.length > 4096) return {};  try {    const url = new URL(rawUrl);    if (url.protocol !== "http:" && url.protocol !== "https:") return {};    return { toolIcon: { _tag: "website", pageUrl: url.href } };  } catch {    return {};  }} /** * MCP tool calls carry full tool results (`data.item.result` on Codex, * `data.result` on Claude/OpenCode) that used to bypass slimming entirely to * keep the expanded-row UI working. Keep the fields the UI actually renders * and summarize the result like regular tool output. */function projectMcpToolCallData(data: Record<string, unknown>): Record<string, unknown> {  const projectedData: Record<string, unknown> = {};   const item = asRecord(data.item);  if (item) {    const projectedItem: Record<string, unknown> = {};    for (const key of MCP_ITEM_KEPT_FIELDS) {      if (key in item) {        projectedItem[key] = item[key];      }    }    const result = summarizeMcpResult(item.result);    if (result) {      projectedItem.result = result;    }    projectedData.item = projectedItem;  }   if ("toolName" in data) {    projectedData.toolName = data.toolName;  }  if ("input" in data) {    projectedData.input = data.input;  }  if (!item) {    const result = summarizeMcpResult(data.result);    if (result) {      projectedData.result = result;    }  }   if ("toolCallId" in data) {    projectedData.toolCallId = data.toolCallId;  }  if ("kind" in data) {    projectedData.kind = data.kind;  }   const changedFiles: string[] = [];  collectChangedFiles(data, changedFiles, new Set<string>(), 0);  if (changedFiles.length > 0) {    projectedData.files = changedFiles.map((path) => ({ path }));  }   return projectedData;} function projectRawOutput(value: unknown): Record<string, unknown> | undefined {  const direct = asTrimmedString(value);  if (direct) {    const summary = summarizeToolTextOutput(direct);    return summary ? { content: summary } : undefined;  }   const rawOutput = asRecord(value);  if (!rawOutput) {    return undefined;  }   if (typeof rawOutput.totalFiles === "number" && Number.isFinite(rawOutput.totalFiles)) {    return {      totalFiles: rawOutput.totalFiles,      ...(rawOutput.truncated === true ? { truncated: true } : {}),    };  }   const content = asTrimmedString(rawOutput.content);  if (content) {    const summary = summarizeToolTextOutput(content);    return summary ? { content: summary } : undefined;  }   const stdout = asTrimmedString(rawOutput.stdout);  if (stdout) {    const summary = summarizeToolTextOutput(stdout);    return summary ? { content: summary } : undefined;  }   const stderr = asTrimmedString(rawOutput.stderr);  if (stderr) {    const summary = summarizeToolTextOutput(stderr);    return summary ? { content: summary } : undefined;  }   return undefined;} function projectAcpContent(value: unknown): Record<string, unknown> | undefined {  if (!Array.isArray(value)) {    return undefined;  }   const text = value    .map((entryValue) => {      const entry = asRecord(entryValue);      const content = asRecord(entry?.content);      return entry?.type === "content" && content?.type === "text"        ? asTrimmedString(content.text)        : null;    })    .filter((entry): entry is string => entry !== null)    .join("\n");  const summary = summarizeToolTextOutput(text);  return summary ? { content: summary } : undefined;} /** * Removes activity payload fields that no current client reads while retaining * the full payload in persistence and the event store. */export function projectActivityPayload(  activity: OrchestrationThreadActivity,): OrchestrationThreadActivity {  const payload = asRecord(activity.payload);  const data = asRecord(payload?.data);  if (!payload || !data) {    return activity;  }   const itemStatus = asRecord(data.item)?.status;  const statusPayload =    payload.status === "completed" && (itemStatus === "failed" || itemStatus === "declined")      ? { ...payload, status: itemStatus }      : payload;  const projectedPayload = {    ...projectPreviewToolMetadata(data, statusPayload.status),    ...statusPayload,  };  const questionInput = projectQuestionToolInput(data, payload.title);   if (payload.itemType === "mcp_tool_call") {    return {      ...activity,      payload: {        ...projectedPayload,        data: { ...projectMcpToolCallData(data), ...questionInput },      },    };  }   const projectedData: Record<string, unknown> = { ...questionInput };  const item = projectCommandData(data);  if (item) {    projectedData.item = item;  }  const command = projectCommandValue(data);  if (command !== undefined) {    projectedData.command = command;  }  const imagePath = projectViewedImagePath(data);  if (imagePath) {    projectedData.imagePath = imagePath;  }   const changedFiles: string[] = [];  collectChangedFiles(data, changedFiles, new Set<string>(), 0);  if (changedFiles.length > 0) {    // Both clients discover file names by walking objects with path-like keys.    projectedData.files = changedFiles.map((path) => ({ path }));  }   if ("toolCallId" in data) {    projectedData.toolCallId = data.toolCallId;  }  if ("kind" in data) {    projectedData.kind = data.kind;  }  if ("toolName" in data) {    projectedData.toolName = data.toolName;  }   const rawOutput =    projectRawOutput(data.rawOutput) ??    projectAcpContent(data.content) ??    (payload.itemType === "command_execution" ? summarizeMcpResult(data.result) : undefined);  if (rawOutput) {    projectedData.rawOutput = rawOutput;  }   return {    ...activity,    payload: {      ...projectedPayload,      data: projectedData,    },  };

Lines 1–500 of 671.