bug fixes for correct loading of chat and graph panels
This commit is contained in:
parent
2bf5763eb1
commit
8bf1394e6f
|
|
@ -9,7 +9,6 @@ export class HistoryPanel {
|
||||||
container: HTMLElement;
|
container: HTMLElement;
|
||||||
props: {
|
props: {
|
||||||
graphs: any[];
|
graphs: any[];
|
||||||
onGraphSelect: (data: { graphId: string; currentNode: string | null }) => void;
|
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
};
|
};
|
||||||
graphs: any[];
|
graphs: any[];
|
||||||
|
|
@ -23,7 +22,6 @@ export class HistoryPanel {
|
||||||
container: HTMLElement,
|
container: HTMLElement,
|
||||||
props: {
|
props: {
|
||||||
graphs: any[];
|
graphs: any[];
|
||||||
onGraphSelect: (data: { graphId: string; currentNode: string | null }) => void;
|
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
@ -103,8 +101,8 @@ export class HistoryPanel {
|
||||||
item.addEventListener('click', (e) => {
|
item.addEventListener('click', (e) => {
|
||||||
if (!(e.target as HTMLElement).classList.contains('chat-item-options-button')) {
|
if (!(e.target as HTMLElement).classList.contains('chat-item-options-button')) {
|
||||||
const graphId = (item as HTMLElement).dataset.graphId;
|
const graphId = (item as HTMLElement).dataset.graphId;
|
||||||
if (graphId && this.props.onGraphSelect) {
|
if (graphId) {
|
||||||
this.props.onGraphSelect({ graphId: graphId, currentNode: null });
|
this.props.eventBus.emit('graph-selected', { graphId: graphId, currentNode: null });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ export class ChatView extends ItemView {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Подписываемся на события
|
// Подписываемся на события
|
||||||
this.plugin.eventBus.on('node-selected', this.handleNodeSelected.bind(this));
|
this.plugin.eventBus.on('node-selected', this.handleNodeSelected.bind(this));
|
||||||
this.plugin.eventBus.on('new-chat', this.handleNewChat.bind(this));
|
this.plugin.eventBus.on('new-chat', this.handleNewChat.bind(this));
|
||||||
this.plugin.eventBus.on('graph-selected', this.handleGraphSelected.bind(this));
|
this.plugin.eventBus.on('graph-selected', this.handleGraphSelected.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onClose(): Promise<void> {
|
async onClose(): Promise<void> {
|
||||||
if (this.chatPanel) {
|
if (this.chatPanel) {
|
||||||
|
|
@ -72,133 +72,130 @@ export class ChatView extends ItemView {
|
||||||
|
|
||||||
// ----------------------------------------------- API Methods ---------------------------------------------------------------
|
// ----------------------------------------------- API Methods ---------------------------------------------------------------
|
||||||
|
|
||||||
// TODO: проблемное место
|
// TODO: проблемное место
|
||||||
/**
|
/**
|
||||||
* Загружает историю сообщений от корня до указанного узла графа.
|
* Загружает историю сообщений от корня до указанного узла графа.
|
||||||
* Обновляет `chatHistory` и отображение в `chatPanel`.
|
* Обновляет `chatHistory` и отображение в `chatPanel`.
|
||||||
* @param {string} nodeId - ID конечного узла для загрузки истории.
|
* @param {string} nodeId - ID конечного узла для загрузки истории.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async fetchMessagesFromRootToNode(nodeId: string): Promise<void> {
|
async fetchMessagesFromRootToNode(nodeId: string | null): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Убедимся, что selectedGraphId установлен
|
// Убедимся, что selectedGraphId установлен
|
||||||
if (!this.selectedGraphId) {
|
if (!this.selectedGraphId) {
|
||||||
console.warn('selectedGraphId не установлен. Невозможно загрузить сообщения.');
|
console.warn('selectedGraphId не установлен. Невозможно загрузить сообщения.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/messages/${this.selectedGraphId}/${nodeId}`);
|
|
||||||
if (!response.ok) {
|
const url = nodeId
|
||||||
const errorText = await response.text();
|
? `${this.plugin.settings.apiBaseUrl}/messages/${this.selectedGraphId}/${nodeId}`
|
||||||
throw new Error(`Ошибка загрузки сообщений: ${response.status} - ${errorText}`);
|
: `${this.plugin.settings.apiBaseUrl}/messages/${this.selectedGraphId}/last`;
|
||||||
}
|
const response = await fetch(url);
|
||||||
const data = await response.json();
|
|
||||||
// ИСПРАВЛЕНО: Убедиться, что type передается, если это возможно
|
if (!response.ok) {
|
||||||
this.chatHistory = data.map((msg: any) => ({
|
const errorText = await response.text();
|
||||||
...msg,
|
throw new Error(`Ошибка загрузки сообщений: ${response.status} - ${errorText}`);
|
||||||
type: msg.type || msg.role // Используем type, если есть, иначе role как fallback
|
}
|
||||||
})) || [];
|
const data = await response.json();
|
||||||
if (this.chatPanel) {
|
// ИСПРАВЛЕНО: Убедиться, что type передается, если это возможно
|
||||||
this.chatPanel.updateHistory(this.chatHistory);
|
this.chatHistory =
|
||||||
}
|
data.map((msg: any) => ({
|
||||||
} catch (error) {
|
...msg,
|
||||||
console.error('Ошибка загрузки сообщений:', error);
|
type: msg.type || msg.role // Используем type, если есть, иначе role как fallback
|
||||||
// Optionally: show a notice to the user
|
})) || [];
|
||||||
// new Notice(`Ошибка загрузки сообщений: ${error.message}`);
|
if (this.chatPanel) {
|
||||||
}
|
this.chatPanel.updateHistory(this.chatHistory);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка загрузки сообщений:', error);
|
||||||
|
// Optionally: show a notice to the user
|
||||||
|
// new Notice(`Ошибка загрузки сообщений: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------- Event Handlers ---------------------------------------------------------------
|
// ----------------------------------------------- Event Handlers ---------------------------------------------------------------
|
||||||
|
|
||||||
async handleSendMessage(message: string): Promise<void> {
|
async handleSendMessage(message: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/chat`, {
|
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/chat`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
message: message,
|
message: message,
|
||||||
graph_id: this.selectedGraphId,
|
graph_id: this.selectedGraphId,
|
||||||
parent_node_id: this.currentNode,
|
parent_node_id: this.currentNode
|
||||||
}),
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
// Пытаемся прочитать ошибку из тела ответа, если это возможно
|
// Пытаемся прочитать ошибку из тела ответа, если это возможно
|
||||||
const errorData = await response.json().catch(() => ({ message: response.statusText }));
|
const errorData = await response.json().catch(() => ({ message: response.statusText }));
|
||||||
throw new Error(`HTTP ошибка при отправке сообщения! Статус: ${response.status} - ${errorData.message}`);
|
throw new Error(`HTTP ошибка при отправке сообщения! Статус: ${response.status} - ${errorData.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|
||||||
// Обновляем graph_id и current_node_id всегда
|
|
||||||
this.selectedGraphId = result.graph_id;
|
|
||||||
const newCurrentNodeId = result.graph_visualization_data.current_node_id;
|
|
||||||
this.currentNode = newCurrentNodeId;
|
|
||||||
|
|
||||||
// Сначала обновим GraphView, чтобы он запросил последнюю версию графа
|
// Обновляем graph_id и current_node_id всегда
|
||||||
// Это предотвратит состояние гонки, когда разные запросы возвращают частичные графы.
|
this.selectedGraphId = result.graph_id;
|
||||||
// Вместо того, чтобы отправлять частичные данные, мы запрашиваем полный граф у бэкенда.
|
const newCurrentNodeId = result.graph_visualization_data.current_node_id;
|
||||||
this.plugin.eventBus.emit('graph-selected', { graphId: this.selectedGraphId, currentNode: this.currentNode });
|
this.currentNode = newCurrentNodeId;
|
||||||
|
|
||||||
// Затем обновим ChatView, загрузив историю до нового current_node_id
|
|
||||||
if (newCurrentNodeId) {
|
|
||||||
await this.fetchMessagesFromRootToNode(newCurrentNodeId);
|
|
||||||
} else if (this.selectedGraphId) {
|
|
||||||
// Если newCurrentNodeId по какой-то причине не вернулся, но graph_id есть,
|
|
||||||
// пытаемся загрузить историю по последнему известному узлу или просто весь граф (чтобы отобразить пустую историю, если граф новый).
|
|
||||||
// В этом случае, если current_node_id отсутствует, historyPanel должна очиститься.
|
|
||||||
this.currentNode = null; // Сбрасываем, если no current_node_id
|
|
||||||
this.fetchMessagesFromRootToNode(''); // Передаем пустую строку или null, чтобы очистить историю
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
// Сначала обновим GraphView, чтобы он запросил последнюю версию графа
|
||||||
console.error('Ошибка отправки сообщения:', error);
|
// Это предотвратит состояние гонки, когда разные запросы возвращают частичные графы.
|
||||||
}
|
// Вместо того, чтобы отправлять частичные данные, мы запрашиваем полный граф у бэкенда.
|
||||||
}
|
this.plugin.eventBus.emit('graph-selected', { graphId: this.selectedGraphId, currentNode: this.currentNode });
|
||||||
|
|
||||||
/**
|
// Затем обновим ChatView, загрузив историю до нового current_node_id
|
||||||
* Обрабатывает выбор узла на графе. Загружает историю сообщений до выбранного узла
|
if (newCurrentNodeId) {
|
||||||
* и обновляет панель чата.
|
await this.fetchMessagesFromRootToNode(newCurrentNodeId);
|
||||||
* @param {{ nodeId: string }} data - Объект, содержащий ID выбранного узла.
|
} else if (this.selectedGraphId) {
|
||||||
*/
|
// Если newCurrentNodeId по какой-то причине не вернулся, но graph_id есть,
|
||||||
handleNodeSelected(data: { nodeId: string }): void {
|
// пытаемся загрузить историю по последнему известному узлу или просто весь граф (чтобы отобразить пустую историю, если граф новый).
|
||||||
this.currentNode = data.nodeId;
|
// В этом случае, если current_node_id отсутствует, historyPanel должна очиститься.
|
||||||
if (this.selectedGraphId) {
|
this.currentNode = null; // Сбрасываем, если no current_node_id
|
||||||
this.fetchMessagesFromRootToNode(data.nodeId);
|
this.fetchMessagesFromRootToNode(''); // Передаем пустую строку или null, чтобы очистить историю
|
||||||
}
|
}
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error('Ошибка отправки сообщения:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обрабатывает событие начала нового чата. Сбрасывает текущее состояние чата
|
* Обрабатывает выбор узла на графе. Загружает историю сообщений до выбранного узла
|
||||||
* и очищает отображение истории.
|
* и обновляет панель чата.
|
||||||
*/
|
* @param {{ nodeId: string }} data - Объект, содержащий ID выбранного узла.
|
||||||
handleNewChat(): void {
|
*/
|
||||||
this.chatHistory = [];
|
handleNodeSelected(data: { nodeId: string }): void {
|
||||||
this.currentNode = null;
|
this.currentNode = data.nodeId;
|
||||||
this.selectedGraphId = null;
|
if (this.selectedGraphId) {
|
||||||
if (this.chatPanel) {
|
this.fetchMessagesFromRootToNode(data.nodeId);
|
||||||
this.chatPanel.updateHistory(this.chatHistory);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обрабатывает выбор графа из `GraphView`. Устанавливает выбранный граф и обновляет
|
* Обрабатывает событие начала нового чата. Сбрасывает текущее состояние чата
|
||||||
* историю чата, загружая сообщения, относящиеся к этому графу.
|
* и очищает отображение истории.
|
||||||
* @param {{ graphId: string; currentNode: string | null }} data - Объект, содержащий ID выбранного графа и текущий узел.
|
*/
|
||||||
* @returns {Promise<void>}
|
handleNewChat(): void {
|
||||||
*/
|
this.chatHistory = [];
|
||||||
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
this.currentNode = null;
|
||||||
this.selectedGraphId = data.graphId;
|
this.selectedGraphId = null;
|
||||||
this.currentNode = data.currentNode;
|
if (this.chatPanel) {
|
||||||
if (this.currentNode) {
|
this.chatPanel.updateHistory(this.chatHistory);
|
||||||
await this.fetchMessagesFromRootToNode(this.currentNode);
|
}
|
||||||
} else {
|
}
|
||||||
// Если текущего узла нет (например, пустой граф), очищаем историю
|
|
||||||
this.chatHistory = [];
|
/**
|
||||||
if (this.chatPanel) {
|
* Обрабатывает выбор графа из `GraphView`. Устанавливает выбранный граф и обновляет
|
||||||
this.chatPanel.updateHistory(this.chatHistory);
|
* историю чата, загружая сообщения, относящиеся к этому графу.
|
||||||
}
|
* @param {{ graphId: string; currentNode: string | null }} data - Объект, содержащий ID выбранного графа и текущий узел.
|
||||||
}
|
* @returns {Promise<void>}
|
||||||
}
|
*/
|
||||||
|
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
||||||
|
this.selectedGraphId = data.graphId;
|
||||||
|
this.currentNode = data.currentNode; // Может быть пустым, но это не проблема
|
||||||
|
await this.fetchMessagesFromRootToNode(data.currentNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,6 @@ export class GraphView extends ItemView {
|
||||||
// Инициализируем панель истории
|
// Инициализируем панель истории
|
||||||
this.historyPanel = new HistoryPanel(this.historyContainer, {
|
this.historyPanel = new HistoryPanel(this.historyContainer, {
|
||||||
graphs: this.graphsList,
|
graphs: this.graphsList,
|
||||||
onGraphSelect: this.handleGraphSelected.bind(this),
|
|
||||||
eventBus: this.plugin.eventBus
|
eventBus: this.plugin.eventBus
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user