Route OpenClaw chat by HA user
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
* + subscribes to openclaw_message_received events.
|
||||
*/
|
||||
|
||||
const CARD_VERSION = "0.3.13";
|
||||
const CARD_VERSION = "0.3.14";
|
||||
|
||||
// Max time (ms) to show the thinking indicator before falling back to an error (default; overridable via card config `thinking_timeout` in seconds)
|
||||
const THINKING_TIMEOUT_MS = 120_000;
|
||||
@@ -96,6 +96,9 @@ class OpenClawChatCard extends HTMLElement {
|
||||
this._autoScrollPinned = true;
|
||||
this._lastHassRenderSignature = null;
|
||||
this._integrationThinkingTimeout = null;
|
||||
this._backendHaUserId = null;
|
||||
this._activeAgentId = null;
|
||||
this._lastStorageIdentity = null;
|
||||
}
|
||||
|
||||
// ── HA card interface ───────────────────────────────────────────────
|
||||
@@ -128,8 +131,15 @@ class OpenClawChatCard extends HTMLElement {
|
||||
|
||||
set hass(hass) {
|
||||
const firstSet = !this._hass;
|
||||
const previousStorageIdentity = this._getStorageIdentity();
|
||||
this._hass = hass;
|
||||
const currentSignature = this._getHassRenderSignature(hass);
|
||||
const currentStorageIdentity = this._getStorageIdentity();
|
||||
if (currentStorageIdentity !== previousStorageIdentity) {
|
||||
this._lastStorageIdentity = currentStorageIdentity;
|
||||
this._resetTransientChatState();
|
||||
this._restoreMessages();
|
||||
}
|
||||
if (firstSet) {
|
||||
this._subscribeToEvents();
|
||||
this._syncHistoryFromBackend();
|
||||
@@ -252,11 +262,19 @@ class OpenClawChatCard extends HTMLElement {
|
||||
const data = event.data;
|
||||
if (!data || !data.message) return;
|
||||
|
||||
const haUserId = this._getHaUserId();
|
||||
if (data.ha_user_id && haUserId === "unknown") {
|
||||
this._syncHistoryFromBackend(1);
|
||||
return;
|
||||
}
|
||||
if (data.ha_user_id && haUserId !== "unknown" && data.ha_user_id !== haUserId) return;
|
||||
if (data.agent_id && this._activeAgentId && data.agent_id !== this._activeAgentId) return;
|
||||
|
||||
// Check if this event is for our session
|
||||
const sessionId = this._getSessionId();
|
||||
if (data.session_id && data.session_id !== sessionId) return;
|
||||
|
||||
const signature = `${sessionId}|${data.timestamp || ""}|${String(data.message)}`;
|
||||
const signature = `${haUserId}|${data.agent_id || ""}|${sessionId}|${data.timestamp || ""}|${String(data.message)}`;
|
||||
if (signature === this._lastAssistantEventSignature) {
|
||||
return;
|
||||
}
|
||||
@@ -295,7 +313,16 @@ class OpenClawChatCard extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
_clearChat() {
|
||||
async _clearChat() {
|
||||
if (this._hass) {
|
||||
try {
|
||||
await this._hass.callService("openclaw", "clear_history", {
|
||||
session_id: this._getSessionId(),
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn("OpenClaw: backend history clear failed:", err);
|
||||
}
|
||||
}
|
||||
this._messages = [];
|
||||
this._isProcessing = false;
|
||||
this._pendingResponses = 0;
|
||||
@@ -304,11 +331,31 @@ class OpenClawChatCard extends HTMLElement {
|
||||
this._render();
|
||||
}
|
||||
|
||||
_resetTransientChatState() {
|
||||
this._isProcessing = false;
|
||||
this._pendingResponses = 0;
|
||||
this._clearThinkingTimer();
|
||||
this._lastAssistantEventSignature = null;
|
||||
}
|
||||
|
||||
// ── Message persistence ──────────────────────────────────────────────
|
||||
|
||||
_getHaUserId() {
|
||||
return (
|
||||
this._hass?.user?.id ||
|
||||
this._backendHaUserId ||
|
||||
"unknown"
|
||||
);
|
||||
}
|
||||
|
||||
_getStorageIdentity() {
|
||||
return `${this._getHaUserId()}|${this._getSessionId()}`;
|
||||
}
|
||||
|
||||
_getStorageKey() {
|
||||
const userId = this._getHaUserId();
|
||||
const session = this._getSessionId();
|
||||
return `${STORAGE_PREFIX}${session}`;
|
||||
return `${STORAGE_PREFIX}${userId}_${session}`;
|
||||
}
|
||||
|
||||
_getSessionId() {
|
||||
@@ -329,9 +376,8 @@ class OpenClawChatCard extends HTMLElement {
|
||||
_restoreMessages() {
|
||||
try {
|
||||
const stored = sessionStorage.getItem(this._getStorageKey());
|
||||
if (stored) {
|
||||
this._messages = JSON.parse(stored);
|
||||
}
|
||||
const parsed = stored ? JSON.parse(stored) : [];
|
||||
this._messages = Array.isArray(parsed) ? parsed : [];
|
||||
} catch (e) {
|
||||
// Corrupted data — start fresh
|
||||
this._messages = [];
|
||||
@@ -357,6 +403,18 @@ class OpenClawChatCard extends HTMLElement {
|
||||
});
|
||||
}
|
||||
|
||||
const previousStorageIdentity = this._getStorageIdentity();
|
||||
if (result?.ha_user_id) {
|
||||
this._backendHaUserId = result.ha_user_id;
|
||||
}
|
||||
if (result?.agent_id) {
|
||||
this._activeAgentId = result.agent_id;
|
||||
}
|
||||
if (this._getStorageIdentity() !== previousStorageIdentity) {
|
||||
this._resetTransientChatState();
|
||||
this._restoreMessages();
|
||||
}
|
||||
|
||||
const serverMessages = Array.isArray(result?.messages) ? result.messages : [];
|
||||
if (!serverMessages.length) return;
|
||||
|
||||
@@ -426,6 +484,17 @@ class OpenClawChatCard extends HTMLElement {
|
||||
typeof result?.thinking_timeout === "number" && result.thinking_timeout >= 10
|
||||
? result.thinking_timeout * 1000
|
||||
: null;
|
||||
const previousStorageIdentity = this._getStorageIdentity();
|
||||
if (result?.ha_user_id) {
|
||||
this._backendHaUserId = result.ha_user_id;
|
||||
}
|
||||
if (result?.agent_id) {
|
||||
this._activeAgentId = result.agent_id;
|
||||
}
|
||||
if (this._getStorageIdentity() !== previousStorageIdentity) {
|
||||
this._resetTransientChatState();
|
||||
this._restoreMessages();
|
||||
}
|
||||
|
||||
if (includePipeline) {
|
||||
try {
|
||||
@@ -2185,7 +2254,11 @@ class OpenClawChatCard extends HTMLElement {
|
||||
const clearBtn = this.shadowRoot.getElementById("clear-btn");
|
||||
if (clearBtn) {
|
||||
clearBtn.addEventListener("click", () => {
|
||||
if (confirm("Clear chat history?")) this._clearChat();
|
||||
if (confirm("Clear chat history?")) {
|
||||
this._clearChat().catch((err) => {
|
||||
console.error("OpenClaw: clear chat failed", err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user