P3 - SubAgent SDK: - src/subagent.ts: researcher, coder, analyst, content-writer - Mind.runSubAgent() → SubAgentFactory.create() → execute() - Результаты сохраняются в long-term memory - Heartbeat.notify(subagent-complete) после завершения P4 - SQLite persistence (5 таблиц, WAL): - src/database.ts: thoughts, notepads, self_observations, long_term, embeddings - memory.ts → Database (полная замена in-memory) - index.ts: dbPath → ~/.local/share/spark-mind/spark-mind.db P5 - Telegram Channel Layer: - src/telegram.ts: https module (SNI fix), MAX Messenger API - mind.ts: sendReply() → Telegram + console fallback - index.ts: TelegramMessenger(config) → Mind Fixes: - FK constraint: long_term INSERT → long_term_embeddings INSERT - JSON parse: nested objects, markdown fences - P5 telegram: graceful degradation on SSL error
87 lines
2.2 KiB
TypeScript
87 lines
2.2 KiB
TypeScript
/**
|
||
* Telegram Channel Layer — отправка ответов через MAX Messenger API.
|
||
*
|
||
* Бот: nik_bot (user_id: 140245519).
|
||
* API endpoint: https://bot.qw4.ru/bot/nik_bot/message
|
||
*
|
||
* FIX: SNI issue с Node.js — используем https модуль с правильными опциями.
|
||
*/
|
||
|
||
import * as https from 'node:https';
|
||
|
||
export interface TelegramConfig {
|
||
botUrl: string;
|
||
userId: string;
|
||
}
|
||
|
||
export interface MessageResult {
|
||
messageId: string;
|
||
sentAt: number;
|
||
}
|
||
|
||
/**
|
||
* Telegram Messenger — отправка сообщений через MAX API.
|
||
* Поддержка SNI для HTTPS запросов.
|
||
*/
|
||
export class TelegramMessenger {
|
||
private botUrl: string;
|
||
private userId: string;
|
||
|
||
constructor(config: TelegramConfig) {
|
||
this.botUrl = config.botUrl;
|
||
this.userId = config.userId;
|
||
}
|
||
|
||
/** Отправить сообщение через https module (SNI fix). */
|
||
async sendMessage(text: string): Promise<MessageResult> {
|
||
// Парсим URL
|
||
const url = new URL(this.botUrl);
|
||
const path = `/message`;
|
||
|
||
const postData = JSON.stringify({
|
||
user_id: this.userId,
|
||
text,
|
||
});
|
||
|
||
const options = {
|
||
hostname: url.hostname,
|
||
port: 443,
|
||
path: path,
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Content-Length': Buffer.byteLength(postData),
|
||
'SNI': url.hostname, // Explicit SNI
|
||
},
|
||
// SNI fix для Node.js
|
||
servername: url.hostname,
|
||
};
|
||
|
||
return new Promise((resolve, reject) => {
|
||
const req = https.request(options, (res) => {
|
||
let body = '';
|
||
res.on('data', (chunk: Buffer) => body += chunk);
|
||
res.on('end', () => {
|
||
if (res.statusCode !== 200) {
|
||
reject(new Error(`Telegram send error: ${res.statusCode}`));
|
||
return;
|
||
}
|
||
try {
|
||
const data: any = JSON.parse(body);
|
||
resolve({
|
||
messageId: data.message_id ?? `msg-${Date.now()}`,
|
||
sentAt: Date.now(),
|
||
});
|
||
} catch (e) {
|
||
reject(e);
|
||
}
|
||
});
|
||
});
|
||
|
||
req.on('error', reject);
|
||
req.write(postData);
|
||
req.end();
|
||
});
|
||
}
|
||
}
|