feat: Home Assistant API tools (ha_get_state, ha_get_states, ha_call_service)
Register three HA orchestrator tools so Inara can read device states and control devices via the HA REST API. ha_call_service requires admin role and user confirmation. Also includes accumulated UI fixes (setProcessing helper, wasNewSession flag cleanup). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -384,6 +384,16 @@
|
||||
updateSendBtnTitle();
|
||||
}
|
||||
|
||||
function setProcessing(state) {
|
||||
if (state) {
|
||||
headerEmoji.classList.add('processing');
|
||||
document.body.classList.add('processing');
|
||||
} else {
|
||||
headerEmoji.classList.remove('processing');
|
||||
document.body.classList.remove('processing');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Settings dropdown ─────────────────────────────────────────
|
||||
settings_btn_el.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -1148,7 +1158,7 @@
|
||||
// ── Chat fetch + SSE handler ─────────────────────────────────
|
||||
// Extracted so the retry button can call it without re-adding the
|
||||
// user message to the DOM or currentHistory.
|
||||
async function _doSend(payload, thinkingDiv) {
|
||||
async function _doSend(payload, thinkingDiv, wasNewSession = false) {
|
||||
try {
|
||||
const res = await fetch('/chat', {
|
||||
method: 'POST',
|
||||
@@ -1238,13 +1248,13 @@
|
||||
activeController = new AbortController();
|
||||
sendBtn.style.display = 'none';
|
||||
stopBtn.style.display = 'flex';
|
||||
headerEmoji.classList.add('processing');
|
||||
setProcessing(true);
|
||||
startRunTimer();
|
||||
|
||||
await _doSend(payload, thinkingDiv);
|
||||
await _doSend(payload, thinkingDiv, false);
|
||||
|
||||
activeController = null;
|
||||
headerEmoji.classList.remove('processing');
|
||||
setProcessing(false);
|
||||
sendBtn.style.display = 'block';
|
||||
stopBtn.style.display = 'none';
|
||||
stopRunTimer();
|
||||
@@ -1265,7 +1275,7 @@
|
||||
syncHeight();
|
||||
sendBtn.style.display = 'none';
|
||||
stopBtn.style.display = 'flex';
|
||||
headerEmoji.classList.add('processing');
|
||||
setProcessing(true);
|
||||
startRunTimer();
|
||||
|
||||
activeController = new AbortController();
|
||||
@@ -1294,10 +1304,10 @@
|
||||
persona: CORTEX_PERSONA,
|
||||
};
|
||||
|
||||
await _doSend(payload, thinkingDiv);
|
||||
await _doSend(payload, thinkingDiv, wasNewSession);
|
||||
|
||||
activeController = null;
|
||||
headerEmoji.classList.remove('processing');
|
||||
setProcessing(false);
|
||||
sendBtn.style.display = 'block';
|
||||
stopBtn.style.display = 'none';
|
||||
stopRunTimer();
|
||||
@@ -1437,13 +1447,13 @@
|
||||
activeController = new AbortController();
|
||||
sendBtn.style.display = 'none';
|
||||
stopBtn.style.display = 'flex';
|
||||
headerEmoji.classList.add('processing');
|
||||
setProcessing(true);
|
||||
startRunTimer();
|
||||
|
||||
await _doOrchestrate(text, thinkingDiv, userMsgDiv);
|
||||
|
||||
activeController = null;
|
||||
headerEmoji.classList.remove('processing');
|
||||
setProcessing(false);
|
||||
sendBtn.style.display = 'block';
|
||||
stopBtn.style.display = 'none';
|
||||
stopRunTimer();
|
||||
@@ -1462,7 +1472,7 @@
|
||||
syncHeight();
|
||||
sendBtn.style.display = 'none';
|
||||
stopBtn.style.display = 'flex';
|
||||
headerEmoji.classList.add('processing');
|
||||
setProcessing(true);
|
||||
startRunTimer();
|
||||
|
||||
activeController = new AbortController();
|
||||
@@ -1476,7 +1486,7 @@
|
||||
await _doOrchestrate(text, thinkingDiv, userMsgDiv);
|
||||
|
||||
activeController = null;
|
||||
headerEmoji.classList.remove('processing');
|
||||
setProcessing(false);
|
||||
sendBtn.style.display = 'block';
|
||||
stopBtn.style.display = 'none';
|
||||
stopRunTimer();
|
||||
@@ -2215,4 +2225,4 @@
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('/sw.js').catch(() => {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user