Julius MarmingeT3 Code Mobile [WIP] (#2013)b3e8c035 months agoHistory
942 lines · 27.4 KB · TypeScript
RawDownload
import { ApprovalRequestId, isToolLifecycleItemType } from "@t3tools/contracts";import type {  CommandId,  EnvironmentId,  MessageId,  OrchestrationThread,  OrchestrationThreadActivity,  TurnId,  ToolLifecycleItemType,  ThreadId,  UserInputQuestion,} from "@t3tools/contracts"; import type { DraftComposerImageAttachment } from "./composerImages";import * as Arr from "effect/Array";import * as Order from "effect/Order"; export interface PendingApproval {  readonly requestId: ApprovalRequestId;  readonly requestKind: "command" | "file-read" | "file-change";  readonly createdAt: string;  readonly detail?: string;} export interface PendingUserInput {  readonly requestId: ApprovalRequestId;  readonly createdAt: string;  readonly questions: ReadonlyArray<UserInputQuestion>;} export interface PendingUserInputDraftAnswer {  readonly selectedOptionLabel?: string;  readonly customAnswer?: string;} export interface QueuedThreadMessage {  readonly environmentId: EnvironmentId;  readonly threadId: ThreadId;  readonly messageId: MessageId;  readonly commandId: CommandId;  readonly text: string;  readonly attachments: ReadonlyArray<DraftComposerImageAttachment>;  readonly createdAt: string;} export interface ThreadFeedActivity {  readonly id: string;  readonly createdAt: string;  readonly summary: string;  readonly detail: string | null;  readonly status: string | null;} interface WorkLogEntry {  id: string;  createdAt: string;  label: string;  detail?: string;  command?: string;  rawCommand?: string;  changedFiles?: ReadonlyArray<string>;  tone: "thinking" | "tool" | "info" | "error";  toolTitle?: string;  itemType?: ToolLifecycleItemType;  requestKind?: PendingApproval["requestKind"];} interface DerivedWorkLogEntry extends WorkLogEntry {  activityKind: OrchestrationThreadActivity["kind"];  collapseKey?: string;} type RawThreadFeedEntry =  | {      readonly type: "message";      readonly id: string;      readonly createdAt: string;      readonly message: OrchestrationThread["messages"][number];    }  | {      readonly type: "queued-message";      readonly id: string;      readonly createdAt: string;      readonly queuedMessage: QueuedThreadMessage;      readonly sending: boolean;    }  | {      readonly type: "activity";      readonly id: string;      readonly createdAt: string;      readonly activity: ThreadFeedActivity;    }; export type ThreadFeedEntry =  | Extract<RawThreadFeedEntry, { type: "message" | "queued-message" }>  | {      readonly type: "activity-group";      readonly id: string;      readonly createdAt: string;      readonly activities: ReadonlyArray<ThreadFeedActivity>;    }; function requestKindFromRequestType(requestType: unknown): PendingApproval["requestKind"] | null {  switch (requestType) {    case "command_execution_approval":    case "exec_command_approval":      return "command";    case "file_read_approval":      return "file-read";    case "file_change_approval":    case "apply_patch_approval":      return "file-change";    default:      return null;  }} function isStalePendingRequestFailureDetail(detail: string | undefined): boolean {  const normalized = detail?.toLowerCase();  if (!normalized) {    return false;  }  return (    normalized.includes("stale pending approval request") ||    normalized.includes("stale pending user-input request") ||    normalized.includes("unknown pending approval request") ||    normalized.includes("unknown pending permission request") ||    normalized.includes("unknown pending user-input request")  );} function parseApprovalRequestId(value: unknown): ApprovalRequestId | null {  return typeof value === "string" && value.length > 0 ? ApprovalRequestId.make(value) : null;} function parseUserInputQuestions(  payload: Record<string, unknown> | null,): ReadonlyArray<UserInputQuestion> | null {  const questions = payload?.questions;  if (!Array.isArray(questions)) {    return null;  }   const parsed = questions    .map<UserInputQuestion | null>((entry) => {      if (!entry || typeof entry !== "object") return null;      const question = entry as Record<string, unknown>;      if (        typeof question.id !== "string" ||        typeof question.header !== "string" ||        typeof question.question !== "string" ||        !Array.isArray(question.options)      ) {        return null;      }      const options = question.options        .map<UserInputQuestion["options"][number] | null>((option) => {          if (!option || typeof option !== "object") return null;          const record = option as Record<string, unknown>;          if (typeof record.label !== "string" || typeof record.description !== "string") {            return null;          }          return {            label: record.label,            description: record.description,          };        })        .filter((option): option is UserInputQuestion["options"][number] => option !== null);      if (options.length === 0) {        return null;      }      return {        id: question.id,        header: question.header,        question: question.question,        options,        multiSelect: question.multiSelect === true,      };    })    .filter((question): question is UserInputQuestion => question !== null);   return parsed.length > 0 ? parsed : null;} function normalizeDraftAnswer(value: string | undefined): string | null {  if (typeof value !== "string") {    return null;  }  const trimmed = value.trim();  return trimmed.length > 0 ? trimmed : null;} function resolvePendingUserInputAnswer(  draft: PendingUserInputDraftAnswer | undefined,): string | null {  const customAnswer = normalizeDraftAnswer(draft?.customAnswer);  if (customAnswer) {    return customAnswer;  }  return normalizeDraftAnswer(draft?.selectedOptionLabel);} function deriveWorkLogEntries(  activities: ReadonlyArray<OrchestrationThreadActivity>,  latestTurnId: TurnId | undefined,): WorkLogEntry[] {  const ordered = Arr.sort(activities, activityOrder);  const entries: DerivedWorkLogEntry[] = [];  for (const activity of ordered) {    if (latestTurnId && activity.turnId !== latestTurnId) continue;    if (activity.kind === "tool.started") continue;    if (activity.kind === "task.started" || activity.kind === "task.completed") continue;    if (activity.kind === "context-window.updated") continue;    if (activity.summary === "Checkpoint captured") continue;    if (isPlanBoundaryToolActivity(activity)) continue;    entries.push(toDerivedWorkLogEntry(activity));  }  return collapseDerivedWorkLogEntries(entries).map(    ({ activityKind: _activityKind, collapseKey: _collapseKey, ...entry }) => entry,  );} function isPlanBoundaryToolActivity(activity: OrchestrationThreadActivity): boolean {  if (activity.kind !== "tool.updated" && activity.kind !== "tool.completed") {    return false;  }   const payload =    activity.payload && typeof activity.payload === "object"      ? (activity.payload as Record<string, unknown>)      : null;  return typeof payload?.detail === "string" && payload.detail.startsWith("ExitPlanMode:");} function toDerivedWorkLogEntry(activity: OrchestrationThreadActivity): DerivedWorkLogEntry {  const payload =    activity.payload && typeof activity.payload === "object"      ? (activity.payload as Record<string, unknown>)      : null;  const commandPreview = extractToolCommand(payload);  const changedFiles = extractChangedFiles(payload);  const title = extractToolTitle(payload);  const entry: DerivedWorkLogEntry = {    id: activity.id,    createdAt: activity.createdAt,    label: activity.summary,    tone: activity.tone === "approval" ? "info" : activity.tone,    activityKind: activity.kind,  };  const itemType = extractWorkLogItemType(payload);  const requestKind = extractWorkLogRequestKind(payload);  if (payload && typeof payload.detail === "string" && payload.detail.length > 0) {    const detail = stripTrailingExitCode(payload.detail).output;    if (detail) {      entry.detail = detail;    }  }  if (commandPreview.command) {    entry.command = commandPreview.command;  }  if (commandPreview.rawCommand) {    entry.rawCommand = commandPreview.rawCommand;  }  if (changedFiles.length > 0) {    entry.changedFiles = changedFiles;  }  if (title) {    entry.toolTitle = title;  }  if (itemType) {    entry.itemType = itemType;  }  if (requestKind) {    entry.requestKind = requestKind;  }  const collapseKey = deriveToolLifecycleCollapseKey(entry);  if (collapseKey) {    entry.collapseKey = collapseKey;  }  return entry;} function collapseDerivedWorkLogEntries(  entries: ReadonlyArray<DerivedWorkLogEntry>,): DerivedWorkLogEntry[] {  const collapsed: DerivedWorkLogEntry[] = [];  for (const entry of entries) {    const previous = collapsed.at(-1);    if (previous && shouldCollapseToolLifecycleEntries(previous, entry)) {      collapsed[collapsed.length - 1] = mergeDerivedWorkLogEntries(previous, entry);      continue;    }    collapsed.push(entry);  }  return collapsed;} function shouldCollapseToolLifecycleEntries(  previous: DerivedWorkLogEntry,  next: DerivedWorkLogEntry,): boolean {  if (previous.activityKind !== "tool.updated" && previous.activityKind !== "tool.completed") {    return false;  }  if (next.activityKind !== "tool.updated" && next.activityKind !== "tool.completed") {    return false;  }  if (previous.activityKind === "tool.completed") {    return false;  }  return previous.collapseKey !== undefined && previous.collapseKey === next.collapseKey;} function mergeDerivedWorkLogEntries(  previous: DerivedWorkLogEntry,  next: DerivedWorkLogEntry,): DerivedWorkLogEntry {  const changedFiles = mergeChangedFiles(previous.changedFiles, next.changedFiles);  const detail = next.detail ?? previous.detail;  const command = next.command ?? previous.command;  const rawCommand = next.rawCommand ?? previous.rawCommand;  const toolTitle = next.toolTitle ?? previous.toolTitle;  const itemType = next.itemType ?? previous.itemType;  const requestKind = next.requestKind ?? previous.requestKind;  const collapseKey = next.collapseKey ?? previous.collapseKey;  return {    ...previous,    ...next,    ...(detail ? { detail } : {}),    ...(command ? { command } : {}),    ...(rawCommand ? { rawCommand } : {}),    ...(changedFiles.length > 0 ? { changedFiles } : {}),    ...(toolTitle ? { toolTitle } : {}),    ...(itemType ? { itemType } : {}),    ...(requestKind ? { requestKind } : {}),    ...(collapseKey ? { collapseKey } : {}),  };} function mergeChangedFiles(  previous: ReadonlyArray<string> | undefined,  next: ReadonlyArray<string> | undefined,): string[] {  const merged = [...(previous ?? []), ...(next ?? [])];  if (merged.length === 0) {    return [];  }  return [...new Set(merged)];} function deriveToolLifecycleCollapseKey(entry: DerivedWorkLogEntry): string | undefined {  if (entry.activityKind !== "tool.updated" && entry.activityKind !== "tool.completed") {    return undefined;  }  const normalizedLabel = normalizeCompactToolLabel(entry.toolTitle ?? entry.label);  const detail = entry.detail?.trim() ?? "";  const itemType = entry.itemType ?? "";  if (normalizedLabel.length === 0 && detail.length === 0 && itemType.length === 0) {    return undefined;  }  return [itemType, normalizedLabel, detail].join("\u001f");} function normalizeCompactToolLabel(value: string): string {  return value.replace(/\s+(?:complete|completed)\s*$/i, "").trim();} function workEntryPreview(  workEntry: Pick<WorkLogEntry, "detail" | "command" | "changedFiles">,): string | null {  if (workEntry.command) return workEntry.command;  if (workEntry.detail) return workEntry.detail;  if ((workEntry.changedFiles?.length ?? 0) === 0) return null;  const [firstPath] = workEntry.changedFiles ?? [];  if (!firstPath) return null;  return workEntry.changedFiles!.length === 1    ? firstPath    : `${firstPath} +${workEntry.changedFiles!.length - 1} more`;} function capitalizePhrase(value: string): string {  const trimmed = value.trim();  if (trimmed.length === 0) {    return value;  }  return `${trimmed.charAt(0).toUpperCase()}${trimmed.slice(1)}`;} function workEntryHeading(workEntry: WorkLogEntry): string {  if (!workEntry.toolTitle) {    return capitalizePhrase(normalizeCompactToolLabel(workEntry.label));  }  return capitalizePhrase(normalizeCompactToolLabel(workEntry.toolTitle));} function asRecord(value: unknown): Record<string, unknown> | null {  return value && typeof value === "object" ? (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 trimMatchingOuterQuotes(value: string): string {  const trimmed = value.trim();  if (    (trimmed.startsWith("'") && trimmed.endsWith("'")) ||    (trimmed.startsWith('"') && trimmed.endsWith('"'))  ) {    const unquoted = trimmed.slice(1, -1).trim();    return unquoted.length > 0 ? unquoted : trimmed;  }  return trimmed;} function executableBasename(value: string): string | null {  const trimmed = trimMatchingOuterQuotes(value);  if (trimmed.length === 0) {    return null;  }  const normalized = trimmed.replace(/\\/g, "/");  const segments = normalized.split("/");  const last = segments.at(-1)?.trim() ?? "";  return last.length > 0 ? last.toLowerCase() : null;} function splitExecutableAndRest(value: string): { executable: string; rest: string } | null {  const trimmed = value.trim();  if (trimmed.length === 0) {    return null;  }   if (trimmed.startsWith('"') || trimmed.startsWith("'")) {    const quote = trimmed.charAt(0);    const closeIndex = trimmed.indexOf(quote, 1);    if (closeIndex <= 0) {      return null;    }    return {      executable: trimmed.slice(0, closeIndex + 1),      rest: trimmed.slice(closeIndex + 1).trim(),    };  }   const firstWhitespace = trimmed.search(/\s/);  if (firstWhitespace < 0) {    return {      executable: trimmed,      rest: "",    };  }   return {    executable: trimmed.slice(0, firstWhitespace),    rest: trimmed.slice(firstWhitespace).trim(),  };} const SHELL_WRAPPER_SPECS = [  {    executables: ["pwsh", "pwsh.exe", "powershell", "powershell.exe"],    wrapperFlagPattern: /(?:^|\s)-command\s+/i,  },  {    executables: ["cmd", "cmd.exe"],    wrapperFlagPattern: /(?:^|\s)\/c\s+/i,  },  {    executables: ["bash", "sh", "zsh"],    wrapperFlagPattern: /(?:^|\s)-(?:l)?c\s+/i,  },] as const; function findShellWrapperSpec(shell: string) {  return SHELL_WRAPPER_SPECS.find((spec) =>    (spec.executables as ReadonlyArray<string>).includes(shell),  );} function unwrapCommandRemainder(value: string, wrapperFlagPattern: RegExp): string | null {  const match = wrapperFlagPattern.exec(value);  if (!match) {    return null;  }   const command = value.slice(match.index + match[0].length).trim();  if (command.length === 0) {    return null;  }   const unwrapped = trimMatchingOuterQuotes(command);  return unwrapped.length > 0 ? unwrapped : null;} function unwrapKnownShellCommandWrapper(value: string): string {  const split = splitExecutableAndRest(value);

Lines 1–500 of 942.