pre-task cleanup (reduce log spam)
This commit is contained in:
parent
36df6444f1
commit
eb37a22771
@ -36,11 +36,7 @@ export class OllamaAiApi extends AiApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async listModels(): Promise<IAiModelListResult> {
|
async listModels(): Promise<IAiModelListResult> {
|
||||||
await this.log.debug("OllamaAiApi.listModels called");
|
|
||||||
|
|
||||||
const response = await this.client.list();
|
const response = await this.client.list();
|
||||||
await this.log.debug("Ollama list response", { models: response.models });
|
|
||||||
|
|
||||||
const models = response.models.map((model) => {
|
const models = response.models.map((model) => {
|
||||||
const parameterCount = this.parseParameterCount(
|
const parameterCount = this.parseParameterCount(
|
||||||
model.details.parameter_size,
|
model.details.parameter_size,
|
||||||
@ -58,21 +54,9 @@ export class OllamaAiApi extends AiApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async probeModel(modelId: string): Promise<IAiModelProbeResult> {
|
async probeModel(modelId: string): Promise<IAiModelProbeResult> {
|
||||||
await this.log.debug("OllamaAiApi.probeModel called", { modelId });
|
|
||||||
|
|
||||||
const response = await this.client.show({ model: modelId });
|
const response = await this.client.show({ model: modelId });
|
||||||
await this.log.debug("Ollama show response", {
|
|
||||||
modelId,
|
|
||||||
capabilities: response.capabilities,
|
|
||||||
details: response.details,
|
|
||||||
modelInfo: response.model_info,
|
|
||||||
template: response.template,
|
|
||||||
system: response.system,
|
|
||||||
});
|
|
||||||
|
|
||||||
const capabilities = this.analyzeCapabilities(response, modelId);
|
const capabilities = this.analyzeCapabilities(response, modelId);
|
||||||
const settings = this.extractSettings(response);
|
const settings = this.extractSettings(response);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
capabilities,
|
capabilities,
|
||||||
settings,
|
settings,
|
||||||
@ -108,7 +92,8 @@ export class OllamaAiApi extends AiApi {
|
|||||||
!!modelInfo?.["vision_model"] ||
|
!!modelInfo?.["vision_model"] ||
|
||||||
!!modelInfo?.["clip"],
|
!!modelInfo?.["clip"],
|
||||||
hasEmbedding: capabilities.includes("embeddings"),
|
hasEmbedding: capabilities.includes("embeddings"),
|
||||||
hasThinking: capabilities.includes("thinking") || capabilities.includes("reasoning"),
|
hasThinking:
|
||||||
|
capabilities.includes("thinking") || capabilities.includes("reasoning"),
|
||||||
isInstructTuned:
|
isInstructTuned:
|
||||||
modelId.toLowerCase().includes("instruct") ||
|
modelId.toLowerCase().includes("instruct") ||
|
||||||
modelId.toLowerCase().includes("chat") ||
|
modelId.toLowerCase().includes("chat") ||
|
||||||
@ -164,19 +149,18 @@ export class OllamaAiApi extends AiApi {
|
|||||||
|
|
||||||
let lastChunk;
|
let lastChunk;
|
||||||
for await (const chunk of response) {
|
for await (const chunk of response) {
|
||||||
await this.log.debug("stream chunk received", { chunk });
|
|
||||||
lastChunk = chunk;
|
lastChunk = chunk;
|
||||||
|
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
if (chunk.thinking) {
|
if (chunk.thinking) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'thinking',
|
type: "thinking",
|
||||||
data: chunk.thinking,
|
data: chunk.thinking,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (chunk.response) {
|
if (chunk.response) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'response',
|
type: "response",
|
||||||
data: chunk.response,
|
data: chunk.response,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -223,54 +207,59 @@ export class OllamaAiApi extends AiApi {
|
|||||||
|
|
||||||
// Build messages array like OpenAI does
|
// Build messages array like OpenAI does
|
||||||
const messages: OllamaMessage[] = [];
|
const messages: OllamaMessage[] = [];
|
||||||
|
|
||||||
// Add system prompt if present
|
// Add system prompt if present
|
||||||
if (options.systemPrompt) {
|
if (options.systemPrompt) {
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'system',
|
role: "system",
|
||||||
content: options.systemPrompt,
|
content: options.systemPrompt,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add context messages
|
// Add context messages
|
||||||
if (options.context) {
|
if (options.context) {
|
||||||
for (const msg of options.context) {
|
for (const msg of options.context) {
|
||||||
if (msg.content && msg.content.trim()) {
|
if (msg.content && msg.content.trim()) {
|
||||||
if (msg.role === 'tool') {
|
if (msg.role === "tool") {
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'tool',
|
role: "tool",
|
||||||
content: msg.content,
|
content: msg.content,
|
||||||
tool_name: msg.toolName,
|
tool_name: msg.toolName,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
messages.push({
|
messages.push({
|
||||||
role: msg.role as 'user' | 'assistant' | 'system',
|
role: msg.role as "user" | "assistant" | "system",
|
||||||
content: msg.content,
|
content: msg.content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add user prompt (required)
|
// Add user prompt (required)
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'user',
|
role: "user",
|
||||||
content: options.userPrompt,
|
content: options.userPrompt,
|
||||||
});
|
});
|
||||||
|
|
||||||
// VALIDATE: Ensure messages array is not empty before calling API
|
// VALIDATE: Ensure messages array is not empty before calling API
|
||||||
if (messages.length === 0) {
|
if (messages.length === 0) {
|
||||||
throw new Error("Messages array is empty - cannot call Ollama API with no messages");
|
throw new Error(
|
||||||
|
"Messages array is empty - cannot call Ollama API with no messages",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Log what we're sending to Ollama
|
// DEBUG: Log what we're sending to Ollama
|
||||||
await this.log.debug("Ollama chat request", {
|
await this.log.debug("Ollama chat request", {
|
||||||
messagesCount: messages.length,
|
messagesCount: messages.length,
|
||||||
messages: messages.map(m => ({ role: m.role, contentLength: m.content?.length || 0 })),
|
messages: messages.map((m) => ({
|
||||||
|
role: m.role,
|
||||||
|
contentLength: m.content?.length || 0,
|
||||||
|
})),
|
||||||
userPrompt: options.userPrompt?.slice(0, 100),
|
userPrompt: options.userPrompt?.slice(0, 100),
|
||||||
contextCount: options.context?.length || 0,
|
contextCount: options.context?.length || 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const allToolCallResults: IToolCallResult[] = [];
|
const allToolCallResults: IToolCallResult[] = [];
|
||||||
const allToolCalls: IToolCall[] = [];
|
const allToolCalls: IToolCall[] = [];
|
||||||
let totalAccumulatedResponse = "";
|
let totalAccumulatedResponse = "";
|
||||||
@ -307,21 +296,20 @@ export class OllamaAiApi extends AiApi {
|
|||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
for await (const chunk of response) {
|
for await (const chunk of response) {
|
||||||
await this.log.debug("stream chunk received", { chunk });
|
|
||||||
lastChunk = chunk;
|
lastChunk = chunk;
|
||||||
|
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
if (chunk.message.thinking) {
|
if (chunk.message.thinking) {
|
||||||
accumulatedThinking += chunk.message.thinking;
|
accumulatedThinking += chunk.message.thinking;
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'thinking',
|
type: "thinking",
|
||||||
data: chunk.message.thinking,
|
data: chunk.message.thinking,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (chunk.message.content) {
|
if (chunk.message.content) {
|
||||||
accumulatedResponse += chunk.message.content;
|
accumulatedResponse += chunk.message.content;
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'response',
|
type: "response",
|
||||||
data: chunk.message.content,
|
data: chunk.message.content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -329,7 +317,7 @@ export class OllamaAiApi extends AiApi {
|
|||||||
for (const tc of chunk.message.tool_calls) {
|
for (const tc of chunk.message.tool_calls) {
|
||||||
const params = JSON.stringify(tc.function.arguments);
|
const params = JSON.stringify(tc.function.arguments);
|
||||||
const callId = `tool_${tc.function.name}_${Date.now()}`;
|
const callId = `tool_${tc.function.name}_${Date.now()}`;
|
||||||
|
|
||||||
const toolCall: IToolCall = {
|
const toolCall: IToolCall = {
|
||||||
callId,
|
callId,
|
||||||
function: {
|
function: {
|
||||||
@ -339,9 +327,9 @@ export class OllamaAiApi extends AiApi {
|
|||||||
};
|
};
|
||||||
streamedToolCalls.push(toolCall);
|
streamedToolCalls.push(toolCall);
|
||||||
allToolCalls.push(toolCall);
|
allToolCalls.push(toolCall);
|
||||||
|
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'toolCall',
|
type: "toolCall",
|
||||||
data: params,
|
data: params,
|
||||||
toolCallId: callId,
|
toolCallId: callId,
|
||||||
toolName: tc.function.name,
|
toolName: tc.function.name,
|
||||||
@ -356,7 +344,7 @@ export class OllamaAiApi extends AiApi {
|
|||||||
// Use accumulated thinking/response for final response
|
// Use accumulated thinking/response for final response
|
||||||
const finalThinking = accumulatedThinking || lastChunk.message.thinking;
|
const finalThinking = accumulatedThinking || lastChunk.message.thinking;
|
||||||
const finalResponse = accumulatedResponse || lastChunk.message.content;
|
const finalResponse = accumulatedResponse || lastChunk.message.content;
|
||||||
|
|
||||||
// Accumulate across iterations
|
// Accumulate across iterations
|
||||||
totalAccumulatedResponse += finalResponse || "";
|
totalAccumulatedResponse += finalResponse || "";
|
||||||
totalAccumulatedThinking += finalThinking || "";
|
totalAccumulatedThinking += finalThinking || "";
|
||||||
@ -371,7 +359,8 @@ export class OllamaAiApi extends AiApi {
|
|||||||
response: totalAccumulatedResponse,
|
response: totalAccumulatedResponse,
|
||||||
thinking: totalAccumulatedThinking,
|
thinking: totalAccumulatedThinking,
|
||||||
toolCalls: allToolCalls.length > 0 ? allToolCalls : undefined,
|
toolCalls: allToolCalls.length > 0 ? allToolCalls : undefined,
|
||||||
toolCallResults: allToolCallResults.length > 0 ? allToolCallResults : undefined,
|
toolCallResults:
|
||||||
|
allToolCallResults.length > 0 ? allToolCallResults : undefined,
|
||||||
stats: {
|
stats: {
|
||||||
duration: {
|
duration: {
|
||||||
seconds: lastChunk.total_duration,
|
seconds: lastChunk.total_duration,
|
||||||
@ -392,16 +381,6 @@ export class OllamaAiApi extends AiApi {
|
|||||||
);
|
);
|
||||||
allToolCallResults.push(...toolCallResults);
|
allToolCallResults.push(...toolCallResults);
|
||||||
|
|
||||||
// DEBUG: Log tool results being added to context
|
|
||||||
await this.log.debug("tool results ready for context", {
|
|
||||||
toolCallResults: toolCallResults.map(r => ({
|
|
||||||
callId: r.callId,
|
|
||||||
functionName: r.functionName,
|
|
||||||
resultLength: r.result?.length || 0,
|
|
||||||
hasError: !!r.error,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
const assistantMsg: OllamaMessage = {
|
const assistantMsg: OllamaMessage = {
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
content: accumulatedResponse || lastChunk.message.content,
|
content: accumulatedResponse || lastChunk.message.content,
|
||||||
@ -415,34 +394,19 @@ export class OllamaAiApi extends AiApi {
|
|||||||
messages.push(assistantMsg);
|
messages.push(assistantMsg);
|
||||||
|
|
||||||
for (const result of toolCallResults) {
|
for (const result of toolCallResults) {
|
||||||
const toolContent = result.error
|
const toolContent = result.error
|
||||||
? `Error executing ${result.functionName}: ${result.error}`
|
? `Error executing ${result.functionName}: ${result.error}`
|
||||||
: result.result;
|
: result.result;
|
||||||
|
|
||||||
const toolMsg = {
|
const toolMsg = {
|
||||||
role: "tool" as const,
|
role: "tool" as const,
|
||||||
content: toolContent,
|
content: toolContent,
|
||||||
};
|
};
|
||||||
await this.log.debug("adding tool result to messages", {
|
|
||||||
contentLength: toolMsg.content?.length || 0,
|
|
||||||
hasContent: !!(toolMsg.content && toolMsg.content.length),
|
|
||||||
});
|
|
||||||
messages.push(toolMsg);
|
messages.push(toolMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Log full messages array before next iteration
|
|
||||||
await this.log.debug("messages array for next Ollama API call", {
|
|
||||||
messageCount: messages.length,
|
|
||||||
messages: messages.map(m => ({
|
|
||||||
role: m.role,
|
|
||||||
contentLength: m.content?.length || 0,
|
|
||||||
tool_name: (m as any).tool_name,
|
|
||||||
contentPreview: m.content?.slice(0, 200),
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
// VALIDATE: Ensure tool results are in messages
|
// VALIDATE: Ensure tool results are in messages
|
||||||
const toolMessages = messages.filter(m => m.role === 'tool');
|
const toolMessages = messages.filter((m) => m.role === "tool");
|
||||||
if (toolMessages.length === 0 && toolCallResults.length > 0) {
|
if (toolMessages.length === 0 && toolCallResults.length > 0) {
|
||||||
await this.log.error("CRITICAL: tool results NOT in messages array", {
|
await this.log.error("CRITICAL: tool results NOT in messages array", {
|
||||||
toolCallResultsCount: toolCallResults.length,
|
toolCallResultsCount: toolCallResults.length,
|
||||||
|
|||||||
@ -69,17 +69,10 @@ export class OpenAiApi extends AiApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async listModels(): Promise<IAiModelListResult> {
|
async listModels(): Promise<IAiModelListResult> {
|
||||||
await this.log.debug("OpenAiApi.listModels called");
|
|
||||||
|
|
||||||
const response = await this.client.models.list();
|
const response = await this.client.models.list();
|
||||||
await this.log.debug("OpenAI models list response", {
|
|
||||||
data: response.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
const models = response.data.map((model) => {
|
const models = response.data.map((model) => {
|
||||||
const modelInfo = model as unknown as OpenAIModelInfo;
|
const modelInfo = model as unknown as OpenAIModelInfo;
|
||||||
const maxTokens = modelInfo.max_tokens || modelInfo.context_window;
|
const maxTokens = modelInfo.max_tokens || modelInfo.context_window;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: model.id,
|
id: model.id,
|
||||||
name: model.id,
|
name: model.id,
|
||||||
@ -93,40 +86,21 @@ export class OpenAiApi extends AiApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async probeModel(modelId: string): Promise<IAiModelProbeResult> {
|
async probeModel(modelId: string): Promise<IAiModelProbeResult> {
|
||||||
await this.log.debug("OpenAiApi.probeModel called", { modelId });
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.client.models.retrieve(modelId);
|
const response = await this.client.models.retrieve(modelId);
|
||||||
const modelInfo = response as unknown as OpenAIModelInfo;
|
const modelInfo = response as unknown as OpenAIModelInfo;
|
||||||
|
|
||||||
await this.log.debug("OpenAI model retrieve response", {
|
|
||||||
modelId,
|
|
||||||
features: modelInfo.features,
|
|
||||||
supported_methods: modelInfo.supported_methods,
|
|
||||||
capabilities: modelInfo.capabilities,
|
|
||||||
});
|
|
||||||
|
|
||||||
const capabilities = this.analyzeCapabilities(modelInfo);
|
const capabilities = this.analyzeCapabilities(modelInfo);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
capabilities,
|
capabilities,
|
||||||
settings: undefined,
|
settings: undefined,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await this.log.debug("Failed to retrieve model details, using fallback", {
|
|
||||||
modelId,
|
|
||||||
error: (error as Error).message,
|
|
||||||
});
|
|
||||||
|
|
||||||
const listResponse = await this.client.models.list();
|
const listResponse = await this.client.models.list();
|
||||||
const modelFromList = listResponse.data.find((m) => m.id === modelId);
|
const modelFromList = listResponse.data.find((m) => m.id === modelId);
|
||||||
|
|
||||||
if (modelFromList) {
|
if (modelFromList) {
|
||||||
const modelInfo = modelFromList as unknown as OpenAIModelInfo;
|
const modelInfo = modelFromList as unknown as OpenAIModelInfo;
|
||||||
if (modelInfo.capabilities) {
|
if (modelInfo.capabilities) {
|
||||||
await this.log.debug("Using capabilities from list endpoint", {
|
|
||||||
modelId,
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
capabilities: this.analyzeCapabilities(modelInfo),
|
capabilities: this.analyzeCapabilities(modelInfo),
|
||||||
settings: undefined,
|
settings: undefined,
|
||||||
@ -204,7 +178,12 @@ export class OpenAiApi extends AiApi {
|
|||||||
],
|
],
|
||||||
stream: true,
|
stream: true,
|
||||||
...(typeof model.params.reasoning === "string"
|
...(typeof model.params.reasoning === "string"
|
||||||
? { reasoning_effort: model.params.reasoning as "low" | "medium" | "high" }
|
? {
|
||||||
|
reasoning_effort: model.params.reasoning as
|
||||||
|
| "low"
|
||||||
|
| "medium"
|
||||||
|
| "high",
|
||||||
|
}
|
||||||
: {}),
|
: {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -218,16 +197,16 @@ export class OpenAiApi extends AiApi {
|
|||||||
accumulatedResponse += delta.content;
|
accumulatedResponse += delta.content;
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'response',
|
type: "response",
|
||||||
data: delta.content,
|
data: delta.content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('reasoning' in delta && delta.reasoning) {
|
if ("reasoning" in delta && delta.reasoning) {
|
||||||
accumulatedThinking += delta.reasoning as string;
|
accumulatedThinking += delta.reasoning as string;
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'thinking',
|
type: "thinking",
|
||||||
data: delta.reasoning as string,
|
data: delta.reasoning as string,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -276,11 +255,11 @@ export class OpenAiApi extends AiApi {
|
|||||||
}
|
}
|
||||||
if (options.context) {
|
if (options.context) {
|
||||||
for (const msg of options.context) {
|
for (const msg of options.context) {
|
||||||
if (msg.role === 'tool') {
|
if (msg.role === "tool") {
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'tool',
|
role: "tool",
|
||||||
content: msg.content,
|
content: msg.content,
|
||||||
tool_call_id: msg.callId || '',
|
tool_call_id: msg.callId || "",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
messages.push({
|
messages.push({
|
||||||
@ -320,7 +299,12 @@ export class OpenAiApi extends AiApi {
|
|||||||
tools,
|
tools,
|
||||||
stream: true,
|
stream: true,
|
||||||
...(typeof model.params.reasoning === "string"
|
...(typeof model.params.reasoning === "string"
|
||||||
? { reasoning_effort: model.params.reasoning as "low" | "medium" | "high" }
|
? {
|
||||||
|
reasoning_effort: model.params.reasoning as
|
||||||
|
| "low"
|
||||||
|
| "medium"
|
||||||
|
| "high",
|
||||||
|
}
|
||||||
: {}),
|
: {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -335,16 +319,16 @@ export class OpenAiApi extends AiApi {
|
|||||||
accumulatedResponse += delta.content;
|
accumulatedResponse += delta.content;
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'response',
|
type: "response",
|
||||||
data: delta.content,
|
data: delta.content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ('reasoning' in delta && delta.reasoning) {
|
if ("reasoning" in delta && delta.reasoning) {
|
||||||
accumulatedThinking += delta.reasoning as string;
|
accumulatedThinking += delta.reasoning as string;
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'thinking',
|
type: "thinking",
|
||||||
data: delta.reasoning as string,
|
data: delta.reasoning as string,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -363,7 +347,7 @@ export class OpenAiApi extends AiApi {
|
|||||||
allToolCalls.push(toolCall);
|
allToolCalls.push(toolCall);
|
||||||
if (streamCallback) {
|
if (streamCallback) {
|
||||||
await streamCallback({
|
await streamCallback({
|
||||||
type: 'toolCall',
|
type: "toolCall",
|
||||||
data: tc.function.arguments || "",
|
data: tc.function.arguments || "",
|
||||||
toolCallId: tc.id,
|
toolCallId: tc.id,
|
||||||
toolName: tc.function.name,
|
toolName: tc.function.name,
|
||||||
@ -392,7 +376,8 @@ export class OpenAiApi extends AiApi {
|
|||||||
response: accumulatedResponse,
|
response: accumulatedResponse,
|
||||||
thinking: accumulatedThinking || undefined,
|
thinking: accumulatedThinking || undefined,
|
||||||
toolCalls: allToolCalls.length > 0 ? allToolCalls : undefined,
|
toolCalls: allToolCalls.length > 0 ? allToolCalls : undefined,
|
||||||
toolCallResults: allToolCallResults.length > 0 ? allToolCallResults : undefined,
|
toolCallResults:
|
||||||
|
allToolCallResults.length > 0 ? allToolCallResults : undefined,
|
||||||
stats: {
|
stats: {
|
||||||
duration: {
|
duration: {
|
||||||
seconds: (Date.now() - startTime) / 1000,
|
seconds: (Date.now() - startTime) / 1000,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user