Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ import { CapabilityOfferCard } from './CapabilityOfferCard';
import { PendingIntegrationKeys } from '@/components/sessions/PendingIntegrationKeys';
import { openIntegrationKeyDialog } from '@/components/sessions/integration-key-dialog';
import { useSessionTitlePropagation } from './use-session-title-propagation';
import { MemorySavedMessage } from '@/components/ai-elements/MemorySavedMessage';

import {
AcpMessageItem,
Expand Down Expand Up @@ -941,6 +942,9 @@ export function FastSessionTranscript({
);
const renderCapabilityOfferMessage = useCallback(
(message: AcpUiMessage) => {
if (message.updateType === ACP_ENVELOPE_EVENT_TYPES.MemorySaved) {
return <MemorySavedMessage message={message} />;
}
const offer = capabilityOffersByMessageId.get(message.id);
if (!offer) return undefined;
const introMessage: AcpUiMessage = {
Expand Down
11 changes: 11 additions & 0 deletions apps/web/src/app/(sandbox)/task/[taskId]/Messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import {
useStickToBottomContext,
type ScrollToBottom,
} from 'use-stick-to-bottom';
import { ACP_ENVELOPE_EVENT_TYPES } from '@roomote/types';

import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements';
import { MemorySavedMessage } from '@/components/ai-elements/MemorySavedMessage';
import {
MessageUiOptionsProvider,
type MessageUiOptions,
Expand All @@ -40,6 +42,7 @@ import {
useSandboxTaskPhase,
type TaskSession,
} from './hooks';
import type { AcpUiMessage } from './types';
import { useInternalTranscriptRowsVisible } from './useInternalTranscriptRowsVisible';

import { SleepWakeMessages } from './messages/index';
Expand Down Expand Up @@ -303,6 +306,13 @@ const MessagesBase = ({
resetKey: session.taskId,
isWorking: taskPhase === 'running',
});
const renderMemoryMessage = useCallback(
(message: AcpUiMessage) =>
message.updateType === ACP_ENVELOPE_EVENT_TYPES.MemorySaved ? (
<MemorySavedMessage message={message} />
) : undefined,
[],
);
const shouldShowWorking =
taskPhase === 'running' && !hasVisibleAssistantOutput(renderBlocks);

Expand Down Expand Up @@ -332,6 +342,7 @@ const MessagesBase = ({
blocks={renderBlocks}
showInternalMessages={showInternalMessages}
onSuppress={suppressMessage}
renderMessage={renderMemoryMessage}
/>
{session.taskRun && <SleepWakeMessages taskRun={session.taskRun} />}
{shouldShowWorking && <DelayedWorkingMessage />}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions apps/web/src/components/ai-elements/MemorySavedMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
ACP_ENVELOPE_EVENT_TYPES,
MEMORY_SAVED_EVENT_TEXT,
parseMemorySavedEventPayload,
} from '@roomote/types';

import { Brain } from '@/components/system';
import type { AcpUiMessage } from '@/app/(sandbox)/task/[taskId]/types';

export function MemorySavedMessage({ message }: { message: AcpUiMessage }) {
if (message.updateType !== ACP_ENVELOPE_EVENT_TYPES.MemorySaved) {
return null;
}

const payload = parseMemorySavedEventPayload(message.data);

return (
<details className="group my-2 text-xs text-muted-foreground">
<summary className="flex cursor-pointer list-none items-center gap-1.5 rounded-md px-1 py-1 hover:bg-muted/60 [&::-webkit-details-marker]:hidden">
<Brain className="size-3.5" />
<span>{MEMORY_SAVED_EVENT_TEXT}</span>
{payload ? (
<span className="text-muted-foreground/70">
{payload.memories.length}
</span>
) : null}
</summary>
{payload ? (
<ul className="mt-1 space-y-1 border-l border-border pl-5 text-muted-foreground">
{payload.memories.map((memory) => (
<li key={memory} className="whitespace-pre-line">
{memory}
</li>
))}
</ul>
) : null}
</details>
);
}
28 changes: 28 additions & 0 deletions apps/web/src/lib/server/task-messages.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { db, sql } from '@roomote/db/server';

const AUTOMATION_SETTINGS_TEST_LOCK = [20260910, 2451] as const;
const EXCLUSIVE_LOCK_HOOK_TIMEOUT_MS = 60_000;

/** Serializes suites that replace deployment-wide automation settings rows. */
export function registerExclusiveAutomationSettingsDatabaseLock() {
Expand All @@ -27,10 +28,10 @@ export function registerExclusiveAutomationSettingsDatabaseLock() {
});
void lockTransaction.catch((error) => rejectAcquired?.(error));
await acquired;
});
}, EXCLUSIVE_LOCK_HOOK_TIMEOUT_MS);

afterAll(async () => {
releaseLock?.();
await lockTransaction;
});
}, EXCLUSIVE_LOCK_HOOK_TIMEOUT_MS);
}
Loading
Loading