fix(schedule): auto-create reminders when agent only writes schedule items

When schedule_create_item includes a start time and reminder intent, create the
matching h5_schedule_reminders row in the same tool call so 10:00 pushes are not
lost. Also reconcile Goose SSE request ids with the portal agent-run gate to keep
MindSpace chat streaming reliable.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-12 08:11:43 +08:00
parent 32fb2cdeaf
commit 97d0e8d970
9 changed files with 552 additions and 21 deletions
+30 -16
View File
@@ -52,6 +52,7 @@ import { buildContextPrefix } from '../utils/mindspaceChatContext';
import { buildUserAddressPrefix } from '../utils/userAddress';
import { buildAutoChatSkillPrefix } from '../../chat-skills.mjs';
import {
reconcileSessionEventRequestContext,
resolvePostAgentRunChatState,
shouldPromoteSessionIdToStreaming,
} from '../../chat-agent-run-gate.mjs';
@@ -989,19 +990,22 @@ export function useTKMindChat(
(event) => {
let rid = activeRequestId.current;
if (event.type === 'ActiveRequests') {
if (!rid && event.request_ids.length > 0) {
// SSE reconnected while agent was running — adopt the active request.
const activeRequestContext = reconcileSessionEventRequestContext({
activeRequestId: rid,
chatState: chatStateRef.current,
eventType: event.type,
activeRequestIds: event.request_ids,
});
if (
activeRequestContext.activeRequestId &&
activeRequestContext.activeRequestId !== rid
) {
clearActiveRequestMissingTimer();
activeRequestId.current = event.request_ids[0];
setChatState('streaming');
activeRequestId.current = activeRequestContext.activeRequestId;
rid = activeRequestContext.activeRequestId;
} else if (rid && event.request_ids.includes(rid)) {
clearActiveRequestMissingTimer();
} else if (rid && !event.request_ids.includes(rid)) {
// While waiting for the agent run gate, keep request context alive so
// Goose streaming events are not dropped before the UI subscribes.
if (chatStateRef.current === 'waiting') {
return;
}
} else if (activeRequestContext.allowMissingGrace) {
// The backend can briefly report no active request between tool phases.
// Confirm the absence before turning the UI idle, otherwise MindSpace
// refreshes the page while tools are still mutating it.
@@ -1016,18 +1020,28 @@ export function useTKMindChat(
}, ACTIVE_REQUEST_MISSING_GRACE_MS);
}
}
if (activeRequestContext.promoteStreaming) {
setChatState('streaming');
}
return;
}
const eventRequestId = getSessionEventRequestId(event);
const eventRequestContext = reconcileSessionEventRequestContext({
activeRequestId: rid,
chatState: chatStateRef.current,
eventType: event.type,
eventRequestId,
});
if (
!rid &&
eventRequestId &&
(chatStateRef.current === 'waiting' || chatStateRef.current === 'streaming') &&
(event.type === 'Message' || event.type === 'Finish')
eventRequestContext.activeRequestId &&
eventRequestContext.activeRequestId !== rid
) {
activeRequestId.current = eventRequestId;
rid = eventRequestId;
clearActiveRequestMissingTimer();
activeRequestId.current = eventRequestContext.activeRequestId;
rid = eventRequestContext.activeRequestId;
if (eventRequestContext.promoteStreaming) {
setChatState('streaming');
}
}
if (
rid ||