UNPKG

consortium

Version:

Remote control and session sharing CLI for AI coding agents

201 lines (197 loc) 6.07 kB
'use strict'; var node_crypto = require('node:crypto'); var persistence = require('./types-B_i6lpTn.cjs'); class BaseReasoningProcessor { accumulator = ""; inTitleCapture = false; titleBuffer = ""; contentBuffer = ""; hasTitle = false; currentCallId = null; toolCallStarted = false; currentTitle = null; onMessage = null; constructor(onMessage) { this.onMessage = onMessage || null; this.reset(); } /** * Set the message callback for sending messages directly. */ setMessageCallback(callback) { this.onMessage = callback; } /** * Process a reasoning section break - indicates a new reasoning section is starting. */ handleSectionBreak() { this.finishCurrentToolCall("canceled"); this.resetState(); persistence.logger.debug(`${this.getLogPrefix()} Section break - reset state`); } /** * Process a reasoning delta/chunk and accumulate content. */ processInput(input) { this.accumulator += input; if (!this.inTitleCapture && !this.hasTitle && !this.contentBuffer) { if (this.accumulator.startsWith("**")) { this.inTitleCapture = true; this.titleBuffer = this.accumulator.substring(2); persistence.logger.debug(`${this.getLogPrefix()} Started title capture`); } else if (this.accumulator.length > 0) { this.contentBuffer = this.accumulator; } } else if (this.inTitleCapture) { this.titleBuffer = this.accumulator.substring(2); const titleEndIndex = this.titleBuffer.indexOf("**"); if (titleEndIndex !== -1) { const title = this.titleBuffer.substring(0, titleEndIndex); const afterTitle = this.titleBuffer.substring(titleEndIndex + 2); this.hasTitle = true; this.inTitleCapture = false; this.currentTitle = title; this.contentBuffer = afterTitle; this.currentCallId = node_crypto.randomUUID(); persistence.logger.debug(`${this.getLogPrefix()} Title captured: "${title}"`); this.sendToolCallStart(title); } } else if (this.hasTitle) { const titleStartIndex = this.accumulator.indexOf("**"); if (titleStartIndex !== -1) { this.contentBuffer = this.accumulator.substring( titleStartIndex + 2 + this.currentTitle.length + 2 ); } } else { this.contentBuffer = this.accumulator; } } /** * Send the tool call start message. */ sendToolCallStart(title) { if (!this.currentCallId || this.toolCallStarted) { return; } const toolCall = { type: "tool-call", name: this.getToolName(), callId: this.currentCallId, input: { title }, id: node_crypto.randomUUID() }; persistence.logger.debug(`${this.getLogPrefix()} Sending tool call start for: "${title}"`); this.onMessage?.(toolCall); this.toolCallStarted = true; } /** * Complete the reasoning section. * Returns true if reasoning was completed, false if there was nothing to complete. */ completeReasoning(fullText) { const text = fullText ?? this.accumulator; if (!text.trim() && !this.toolCallStarted) { persistence.logger.debug(`${this.getLogPrefix()} Complete called but no content accumulated, skipping`); return false; } let title; let content = text; if (text.startsWith("**")) { const titleEndIndex = text.indexOf("**", 2); if (titleEndIndex !== -1) { title = text.substring(2, titleEndIndex); content = text.substring(titleEndIndex + 2).trim(); } } persistence.logger.debug(`${this.getLogPrefix()} Complete reasoning - Title: "${title}", Has content: ${content.length > 0}`); if (title && !this.toolCallStarted) { this.currentCallId = this.currentCallId || node_crypto.randomUUID(); this.sendToolCallStart(title); } if (this.toolCallStarted && this.currentCallId) { const toolResult = { type: "tool-call-result", callId: this.currentCallId, output: { content, status: "completed" }, id: node_crypto.randomUUID() }; persistence.logger.debug(`${this.getLogPrefix()} Sending tool call result`); this.onMessage?.(toolResult); } else if (content.trim()) { const reasoningMessage = { type: "reasoning", message: content, id: node_crypto.randomUUID() }; persistence.logger.debug(`${this.getLogPrefix()} Sending reasoning message`); this.onMessage?.(reasoningMessage); } this.resetState(); return true; } /** * Abort the current reasoning section. */ abort() { persistence.logger.debug(`${this.getLogPrefix()} Abort called`); this.finishCurrentToolCall("canceled"); this.resetState(); } /** * Reset the processor state. */ reset() { this.finishCurrentToolCall("canceled"); this.resetState(); } /** * Finish current tool call if one is in progress. */ finishCurrentToolCall(status) { if (this.toolCallStarted && this.currentCallId) { const toolResult = { type: "tool-call-result", callId: this.currentCallId, output: { content: this.contentBuffer || "", status }, id: node_crypto.randomUUID() }; persistence.logger.debug(`${this.getLogPrefix()} Sending tool call result with status: ${status}`); this.onMessage?.(toolResult); } } /** * Reset internal state. */ resetState() { this.accumulator = ""; this.inTitleCapture = false; this.titleBuffer = ""; this.contentBuffer = ""; this.hasTitle = false; this.currentCallId = null; this.toolCallStarted = false; this.currentTitle = null; } /** * Get the current call ID for tool result matching. */ getCurrentCallId() { return this.currentCallId; } /** * Check if a tool call has been started. */ hasStartedToolCall() { return this.toolCallStarted; } } exports.BaseReasoningProcessor = BaseReasoningProcessor;