All files / src/tools stream-tool-calls.ts

87.23% Statements 41/47
87.87% Branches 29/33
88.88% Functions 8/9
86.95% Lines 40/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93      75x     75x       37x 34x   3x 2x 2x         1x       38x 38x       38x   38x     1x 38x 1x   1x     37x 37x 37x 37x 37x   37x       37x                   7x 354x 309x   45x 2x 2x 1x   1x 1x         43x 40x   3x     7x       190x 190x 33x   157x    
import { NimToolCall } from "../types";
 
function asRecord(value: unknown): Record<string, unknown> | undefined {
  Iif (typeof value !== "object" || value === null || Array.isArray(value)) {
    return undefined;
  }
  return value as Record<string, unknown>;
}
 
function stringifyArguments(value: unknown): string {
  if (typeof value === "string") {
    return value;
  }
  if (value && typeof value === "object") {
    try {
      return JSON.stringify(value);
    } catch {
      return "";
    }
  }
  return "";
}
 
function normalizeOneToolCall(raw: unknown): NimToolCall[] {
  const record = asRecord(raw);
  Iif (!record) {
    return [];
  }
 
  const keys = Object.keys(record);
  const looksLikeIndexMap =
    keys.length > 0 &&
    !("function" in record) &&
    !("id" in record) &&
    keys.every((key) => /^\d+$/.test(key));
  if (looksLikeIndexMap) {
    return keys
      .sort((left, right) => Number(left) - Number(right))
      .flatMap((key) => normalizeStreamToolCalls(record[key]));
  }
 
  const func = asRecord(record.function) ?? {};
  const name = typeof func.name === "string" ? func.name : "";
  const args = stringifyArguments(func.arguments);
  const id = typeof record.id === "string" ? record.id : "";
  const index = typeof record.index === "number" ? record.index : undefined;
 
  Iif (!id && !name && !args) {
    return [];
  }
 
  return [
    {
      id,
      ...(index !== undefined ? { index } : {}),
      type: "function",
      function: { name, arguments: args },
    },
  ];
}
 
export function normalizeStreamToolCalls(raw: unknown): NimToolCall[] {
  if (raw == null) {
    return [];
  }
  if (typeof raw === "string") {
    const trimmed = raw.trim();
    if (!trimmed) {
      return [];
    }
    try {
      return normalizeStreamToolCalls(JSON.parse(trimmed) as unknown);
    } catch {
      return [];
    }
  }
  if (Array.isArray(raw)) {
    return raw.flatMap((item) => normalizeOneToolCall(item));
  }
  return normalizeOneToolCall(raw);
}
 
export function collectChoiceToolCalls(choice: {
  delta?: { tool_calls?: unknown };
  message?: { tool_calls?: unknown };
}): NimToolCall[] {
  const fromDelta = normalizeStreamToolCalls(choice.delta?.tool_calls);
  if (fromDelta.length > 0) {
    return fromDelta;
  }
  return normalizeStreamToolCalls(choice.message?.tool_calls);
}