308 lines · 9.6 KB · TypeScript
RawDownload
import type { V2ItemSupport } from "@t3tools/client-runtime/state/item-support";import type { ThreadId } from "@t3tools/contracts";import { formatDuration } from "@t3tools/shared/orchestrationTiming";import * as DateTime from "effect/DateTime"; import type { ThreadFeedActivity } from "./threadActivity"; export interface ThreadActivityInspectorField {  readonly label: string;  readonly value: string;} export interface ThreadActivityInspectorBlock {  readonly label: string;  readonly value: string;  readonly monospaced: boolean;} export interface ThreadActivityFileLink {  readonly label: string;  readonly path: string;  readonly line?: number;} export interface ThreadActivityWebLink {  readonly label: string;  readonly url: string;} export interface ThreadActivityInspectorModel {  readonly fields: ReadonlyArray<ThreadActivityInspectorField>;  readonly blocks: ReadonlyArray<ThreadActivityInspectorBlock>;  readonly fileLinks: ReadonlyArray<ThreadActivityFileLink>;  readonly webLinks: ReadonlyArray<ThreadActivityWebLink>;  readonly canRollback: boolean;  readonly rollbackTarget: {    readonly threadId: ThreadId;    readonly checkpointId: string;    readonly scopeId: string;  } | null;  readonly structuredDetails: string;} function formatStructured(value: unknown): string {  if (typeof value === "string") return value;  try {    return JSON.stringify(value, null, 2) ?? String(value);  } catch {    return String(value);  }} function durationLabel(  startedAt: DateTime.Utc | null,  completedAt: DateTime.Utc | null,): string | null {  if (startedAt === null) return null;  const start = DateTime.toEpochMillis(startedAt);  const end = completedAt === null ? Date.now() : DateTime.toEpochMillis(completedAt);  return formatDuration(Math.max(0, end - start));} function addBlock(  blocks: ThreadActivityInspectorBlock[],  label: string,  value: unknown,  monospaced = true,): void {  if (value === undefined || value === null || value === "") return;  blocks.push({ label, value: formatStructured(value), monospaced });} export function buildThreadActivityInspector(  activity: ThreadFeedActivity,  support: V2ItemSupport,  currentThreadId: ThreadId,): ThreadActivityInspectorModel {  const row = activity.projectedItem;  const item = row.item;  const fields: ThreadActivityInspectorField[] = [    { label: "Item", value: item.type.replaceAll("_", " ") },    { label: "Status", value: item.status.replaceAll("_", " ") },  ];  const duration = durationLabel(item.startedAt, item.completedAt);  if (duration) fields.push({ label: "Duration", value: duration });  if (row.visibility !== "local") fields.push({ label: "Visibility", value: row.visibility });  if (support.run) fields.push({ label: "Run", value: support.run.status });   const latestAttempt = support.attempts.at(-1);  if (latestAttempt) {    fields.push({      label: "Attempt",      value: `${latestAttempt.attemptOrdinal} · ${latestAttempt.status} · ${latestAttempt.reason.replaceAll("_", " ")}`,    });  }  if (support.node) {    fields.push({      label: "Node",      value: `${support.node.kind.replaceAll("_", " ")} · ${support.node.status}`,    });  }  if (support.providerThread) {    fields.push({      label: "Provider thread",      value: `${support.providerThread.providerInstanceId} · ${support.providerThread.status}`,    });  }  if (support.providerTurn) {    fields.push({ label: "Provider turn", value: support.providerTurn.status });  }  if (support.providerSession) {    fields.push({      label: "Session",      value: `${support.providerSession.status} · ${support.providerSession.model ?? "default model"}`,    });    fields.push({ label: "Working directory", value: support.providerSession.cwd });  }  if (support.runtimeRequest) {    fields.push({      label: "Request",      value: `${support.runtimeRequest.status} · ${support.runtimeRequest.responseCapability.type.replaceAll("_", " ")}`,    });  }   const blocks: ThreadActivityInspectorBlock[] = [];  const fileLinks: ThreadActivityFileLink[] = [];  const webLinks: ThreadActivityWebLink[] = [];   if (support.attempts.length > 1) {    addBlock(      blocks,      "Attempt history",      support.attempts        .map(          (attempt) =>            `Attempt ${attempt.attemptOrdinal} · ${attempt.status} · ${attempt.reason.replaceAll("_", " ")}`,        )        .join("\n"),    );  }   switch (item.type) {    case "reasoning":      addBlock(blocks, "Reasoning", item.text, false);      break;    case "command_execution":      addBlock(blocks, "Command", item.input);      addBlock(blocks, "Output", item.output);      if (item.exitCode !== undefined) {        addBlock(blocks, "Exit", `Process exited with code ${item.exitCode}`);      }      break;    case "file_change":      fileLinks.push({ label: item.fileName, path: item.fileName });      if (item.additions !== undefined || item.deletions !== undefined) {        fields.push({          label: "Changes",          value: `+${item.additions ?? 0} −${item.deletions ?? 0}`,        });      }      addBlock(blocks, "Patch", item.diffStr);      addBlock(blocks, "Before", item.oldStr);      addBlock(blocks, "After", item.newStr);      break;    case "file_search":      addBlock(blocks, "Query", item.pattern);      for (const result of item.results ?? []) {        fileLinks.push({          label: result.preview ? `${result.fileName} — ${result.preview}` : result.fileName,          path: result.fileName,          ...(result.line === undefined ? {} : { line: result.line }),        });      }      break;    case "web_search":      addBlock(blocks, "Queries", item.patterns?.join("\n"));      for (const result of item.results ?? []) {        if (result.url) {          webLinks.push({            label: result.title ?? result.url,            url: result.url,          });        }        if (result.snippet)          addBlock(blocks, result.title ?? "Search result", result.snippet, false);      }      break;    case "dynamic_tool":      addBlock(blocks, "Input", item.input);      addBlock(blocks, "Output", item.output);      break;    case "approval_request":      addBlock(blocks, "Prompt", item.prompt, false);      break;    case "user_input_request":      addBlock(        blocks,        "Questions",        item.questions.map((question) => question.question).join("\n"),        false,      );      break;    case "checkpoint":      addBlock(        blocks,        "Files",        item.files          .map((file) => `${file.path}  +${file.additions} −${file.deletions}  ${file.kind}`)          .join("\n"),      );      break;    case "subagent":      addBlock(blocks, "Prompt", item.prompt, false);      addBlock(blocks, "Progress", support.subagent?.progress ?? item.progress, false);      addBlock(blocks, "Result", support.subagent?.result ?? item.result, false);      if (support.subagent) {        fields.push({          label: "Delegated task",          value: `${support.subagent.origin.replaceAll("_", " ")} · ${support.subagent.status}`,        });      }      break;    case "handoff":      addBlock(blocks, "Summary", item.summary, false);      fields.push({        label: "Handoff",        value: `${item.strategy.replaceAll("_", " ")} · ${support.contextHandoff?.status ?? item.status}`,      });      if (support.contextTransfer) {        fields.push({          label: "Transfer",          value: `${support.contextTransfer.type.replaceAll("_", " ")} · ${support.contextTransfer.status}`,        });        if (support.contextTransfer.resolution) {          fields.push({            label: "Context",            value: support.contextTransfer.resolution.strategy.replaceAll("_", " "),          });        }      }      break;    case "error":      addBlock(blocks, "Error", item.failure.message, false);      if (item.failure.code) fields.push({ label: "Code", value: item.failure.code });      if (item.failure.retryable !== null) {        fields.push({ label: "Retryable", value: item.failure.retryable ? "yes" : "no" });      }      break;    case "proposed_plan":      addBlock(blocks, "Plan", item.markdown, false);      break;    case "todo_list":      addBlock(        blocks,        "Tasks",        item.steps          .map((step) => `${step.status === "completed" ? "✓" : "○"} ${step.text}`)          .join("\n"),        false,      );      addBlock(blocks, "Explanation", item.explanation, false);      break;    case "compaction":      addBlock(blocks, "Summary", item.summary, false);      if (item.beforeTokenCount !== undefined || item.afterTokenCount !== undefined) {        fields.push({          label: "Context tokens",          value: `${item.beforeTokenCount ?? "?"} → ${item.afterTokenCount ?? "?"}`,        });      }      break;    case "run_interrupt_request":    case "run_interrupt_result":      addBlock(blocks, "Message", item.message, false);      break;    case "fork":    case "thread_created":    case "user_message":    case "assistant_message":      break;  }   const checkpoint =    item.type === "checkpoint" && row.sourceThreadId === currentThreadId      ? support.checkpoint      : null;  return {    fields,    blocks,    fileLinks,    webLinks,    canRollback: checkpoint?.status === "ready",    rollbackTarget:      checkpoint?.status === "ready"        ? {            threadId: row.sourceThreadId,            checkpointId: checkpoint.id,            scopeId: checkpoint.scopeId,          }        : null,    structuredDetails: formatStructured({      visibility: row.visibility,      sourceThreadId: row.sourceThreadId,      sourceItemId: row.sourceItemId,      item,    }),  };}