Fix calendar routing and user-local time context (#408)
* fix(chat): add user-local time context * fix(chat): route calendar follow-up phrasing * refactor(chat): log tool intent routing reasons * test(chat): align user time prompt shim --------- Co-authored-by: Alex Kenley <Alex.Kenley@threatvectorsecurity.com>
This commit is contained in:
@@ -1876,11 +1876,12 @@ function _wireAll(body) {
|
||||
}
|
||||
try {
|
||||
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
|
||||
const tzOffset = -new Date().getTimezoneOffset();
|
||||
const res = await fetch(`${API_BASE}/api/calendar/quick-parse`, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ text, tz }),
|
||||
body: JSON.stringify({ text, tz, tz_offset: tzOffset }),
|
||||
});
|
||||
const data = await res.json().catch(() => ({}));
|
||||
if (!res.ok || !data.ok) {
|
||||
|
||||
@@ -530,6 +530,9 @@ import createResearchSynapse from './researchSynapse.js';
|
||||
let _renderStream = () => {};
|
||||
let _cancelThinkingTimer = () => {};
|
||||
let _removeThinkingSpinner = () => {};
|
||||
let timeoutId = null;
|
||||
let responseTimeoutCleared = false;
|
||||
let clearResponseTimeout = () => {};
|
||||
const clearProcessingProbe = () => {
|
||||
if (processingProbeTimer) {
|
||||
clearTimeout(processingProbeTimer);
|
||||
@@ -790,13 +793,26 @@ import createResearchSynapse from './researchSynapse.js';
|
||||
|
||||
// Timeout: 6 min for research and agent mode, 3 min otherwise
|
||||
const timeoutMs = el('research-toggle').checked || _isAgent ? RESEARCH_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
|
||||
const timeoutId = setTimeout(() => {
|
||||
timeoutId = setTimeout(() => {
|
||||
if (!abortCtrl.signal.aborted) {
|
||||
timedOut = true;
|
||||
abortCtrl._reason = 'timeout';
|
||||
try {
|
||||
if (streamSessionId) {
|
||||
fetch(`/api/chat/stop/${encodeURIComponent(streamSessionId)}`, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
}).catch(() => {});
|
||||
}
|
||||
} catch (_) {}
|
||||
abortCtrl.abort();
|
||||
}
|
||||
}, timeoutMs);
|
||||
clearResponseTimeout = () => {
|
||||
if (responseTimeoutCleared) return;
|
||||
responseTimeoutCleared = true;
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
|
||||
const box = el('chat-history');
|
||||
holder = document.createElement('div');
|
||||
@@ -922,16 +938,19 @@ import createResearchSynapse from './researchSynapse.js';
|
||||
// the agent so natural-language times like "today at 9pm" are
|
||||
// interpreted in YOUR timezone, not the server's.
|
||||
const _tzOffsetMin = -new Date().getTimezoneOffset();
|
||||
const _tzName = (() => {
|
||||
try { return Intl.DateTimeFormat().resolvedOptions().timeZone || ''; }
|
||||
catch { return ''; }
|
||||
})();
|
||||
const res = await fetch(`${API_BASE}/api/chat_stream`, {
|
||||
method: 'POST',
|
||||
body: fd,
|
||||
headers: { 'X-Tz-Offset': String(_tzOffsetMin) },
|
||||
headers: { 'X-Tz-Offset': String(_tzOffsetMin), 'X-Tz-Name': _tzName },
|
||||
signal: abortCtrl.signal
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!res.ok) {
|
||||
clearResponseTimeout();
|
||||
if (res.status === 404) {
|
||||
// Session was deleted (e.g. by AI) — reload and go to welcome
|
||||
holder.remove();
|
||||
@@ -1359,7 +1378,8 @@ import createResearchSynapse from './researchSynapse.js';
|
||||
typewriterInto(roundHolder.querySelector('.body'), errMsg);
|
||||
break;
|
||||
}
|
||||
if (json.delta || json.type === 'tool_start' || json.type === 'agent_step' || json.type === 'doc_stream_delta') {
|
||||
if (json.delta || json.type === 'tool_start' || json.type === 'tool_output' || json.type === 'tool_progress' || json.type === 'agent_step' || json.type === 'doc_stream_open' || json.type === 'doc_stream_delta' || json.type === 'research_progress') {
|
||||
clearResponseTimeout();
|
||||
clearProcessingProbe();
|
||||
}
|
||||
if (json.delta) {
|
||||
@@ -2710,6 +2730,7 @@ import createResearchSynapse from './researchSynapse.js';
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
clearResponseTimeout();
|
||||
clearProcessingProbe();
|
||||
// Streaming done — let screen readers announce the settled response.
|
||||
const _chatLogDone = document.getElementById('chat-history');
|
||||
|
||||
Reference in New Issue
Block a user