File size: 2,099 Bytes
e249c6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import type {
  BranchSummaryResult as CoreBranchSummaryResult,
  AgentMessage,
} from "../runtime/index.js";
import { estimateTokens } from "../runtime/index.js";

export function unwrapCoreResult<T>(
  result: { ok: true; value: T } | { ok: false; error: Error },
): T {
  if (result.ok) {
    return result.value;
  }
  throw result.error;
}

export function normalizeBranchSummaryResult(
  result:
    | { ok: true; value: CoreBranchSummaryResult }
    | { ok: false; error: { code: string; message: string } },
): {
  summary?: string;
  readFiles?: string[];
  modifiedFiles?: string[];
  aborted?: boolean;
  error?: string;
} {
  if (result.ok) {
    return result.value;
  }
  if (result.error.code === "aborted") {
    return { aborted: true, error: result.error.message };
  }
  return { error: result.error.message };
}

export function hasPersistedAssistantContent(content: unknown): boolean {
  return (typeof content === "string" || Array.isArray(content)) && content.length > 0;
}

export function extractTextContent(content: unknown): string {
  if (typeof content === "string") {
    return content;
  }
  if (!Array.isArray(content)) {
    return "";
  }
  let text = "";
  for (const block of content) {
    if (!block || typeof block !== "object") {
      continue;
    }
    const candidate = block as { type?: unknown; text?: unknown };
    if (candidate.type === "text" && typeof candidate.text === "string") {
      text += candidate.text;
    }
  }
  return text;
}

export function replaceAgentMessageInPlace(target: AgentMessage, replacement: AgentMessage): void {
  // Agent-core stores the finalized message object before emitting message_end.
  // Mutating it in place keeps agent state, later events, and persistence in sync.
  if (target === replacement) {
    return;
  }
  for (const key of Object.keys(target)) {
    Reflect.deleteProperty(target, key);
  }
  Object.assign(target, replacement);
}

export function estimateMessagesFromContent(messages: AgentMessage[]): number {
  return messages.reduce((total, message) => total + estimateTokens(message), 0);
}