solver-sdk
Version:
SDK for WorkAI API - AI-powered code analysis with WorkCoins billing system
124 lines • 5.33 kB
JavaScript
/**
* Утилиты для работы с thinking блоками в SDK
*
* ✅ СОГЛАСНО ТРЕБОВАНИЯМ ANTHROPIC API:
* - signature передается как есть от API
* - НЕ модифицируем thinking блоки
*/
/**
* Менеджер thinking блоков для клиентской стороны
*/
export class ThinkingBlockManager {
/**
* Валидирует thinking блок согласно требованиям Claude API
*/
static validateAndFixThinkingBlock(block) {
if (!this.isThinkingBlockType(block)) {
return {
isValid: false,
reason: 'Блок не является thinking типом'
};
}
// ОСНОВНАЯ ВАЛИДАЦИЯ: поле "thinking" должно существовать и быть не пустым
const thinkingContent = block.thinking;
if (!thinkingContent || typeof thinkingContent !== 'string' || !thinkingContent.trim()) {
return {
isValid: false,
reason: 'Пустое содержимое thinking'
};
}
// Минимальная длина мышления
if (thinkingContent.trim().length < 10) {
return {
isValid: false,
reason: `Слишком короткое содержимое thinking (${thinkingContent.trim().length} символов)`
};
}
// ✅ КРИТИЧНО: НЕ МОДИФИЦИРУЕМ thinking блоки!
// Anthropic API СТРОГО ЗАПРЕЩАЕТ модификацию thinking блоков из API responses
// Документация: "thinking blocks cannot be modified. These blocks must remain as they were in the original response."
// Передаем signature КАК ЕСТЬ (если есть), НЕ добавляем дефолтную!
const fixedBlock = {
type: 'thinking',
thinking: thinkingContent,
// ✅ Передаем signature только если она была в оригинале (НЕ добавляем дефолтную!)
...(block.signature !== undefined && { signature: block.signature })
};
return {
isValid: true,
fixedBlock
};
}
/**
* Обеспечивает наличие signature поля (НЕ используется - оставлено для совместимости)
*/
static ensureSignatureField(signature) {
// УДАЛЕНО: Больше не проверяем signature
return signature || '';
}
/**
* Проверяет что блок имеет тип thinking
*/
static isThinkingBlockType(block) {
return block && typeof block === 'object' && block.type === 'thinking';
}
/**
* Массовая обработка thinking блоков в контенте
*/
static validateAndFixContentBlocks(content) {
if (!Array.isArray(content)) {
return { validBlocks: [], fixedCount: 0, invalidCount: 0 };
}
let fixedCount = 0;
let invalidCount = 0;
const validBlocks = [];
for (const block of content) {
if (this.isThinkingBlockType(block)) {
// ✅ ИСПРАВЛЕНО: Передаем все thinking блоки как есть
const result = this.validateAndFixThinkingBlock(block);
if (result.isValid && result.fixedBlock) {
validBlocks.push(result.fixedBlock);
fixedCount++;
}
else {
invalidCount++;
console.warn(`[INVALID] Пропущен thinking блок: ${result.reason}`);
}
}
else {
// Не thinking блоки проходят как есть
validBlocks.push(block);
}
}
return { validBlocks, fixedCount, invalidCount };
}
/**
* Создает новый валидный thinking блок
*/
static createThinkingBlock(thinking, signature) {
const validation = this.validateAndFixThinkingBlock({
type: 'thinking',
thinking,
// Передаем signature как есть
...(signature !== undefined ? { signature } : {})
});
if (!validation.isValid || !validation.fixedBlock) {
throw new Error(`Невозможно создать thinking блок: ${validation.reason}`);
}
return validation.fixedBlock;
}
/**
* Извлекает валидные thinking блоки из сообщения
*/
static extractValidThinkingBlocks(message) {
if (!message?.content || !Array.isArray(message.content)) {
return [];
}
return message.content
.filter((block) => this.isThinkingBlockType(block))
.map((block) => this.validateAndFixThinkingBlock(block))
.filter((result) => result.isValid)
.map((result) => result.fixedBlock);
}
}
//# sourceMappingURL=thinking-block-manager.js.map