Skip to content

A real-time chat between two users#2

Open
xilosada wants to merge 6 commits into
mainfrom
ai-builder/a-real-tim-91d96b
Open

A real-time chat between two users#2
xilosada wants to merge 6 commits into
mainfrom
ai-builder/a-real-tim-91d96b

Conversation

@xilosada

@xilosada xilosada commented May 19, 2026

Copy link
Copy Markdown
Member

Publish com.calimero-studio.test.one-on-one-chat1@0.1.0


Note

High Risk
High risk because it commits large .playwright-data artifacts (RocksDB auth state, logs, node keypairs) and introduces new automation that starts/stops local merod processes, which can impact CI and leak sensitive data.

Overview
Introduces a new app/ frontend package (Vite + React) and documents the chat feature plan in IMPLEMENTATION_PLAN.md, alongside project setup tweaks (.nvmrc, expanded .gitignore).

Adds Playwright E2E coverage with a global setup/teardown that spawns up to 3 local merod nodes, authenticates via embedded auth, installs the built .mpk, and runs sender/recipient/history scenarios.

Notably, the PR also commits generated runtime/test artifacts under app/.playwright-data/ (node configs, auth RocksDB files, and very large logs).

Reviewed by Cursor Bugbot for commit 749b127. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented May 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workshop-apps Ready Ready Preview, Comment May 19, 2026 1:31pm

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for all 3 issues found in the latest run.

  • ✅ Fixed: Wrong package in env file
    • Updated .env VITE_PACKAGE_NAME from 'com.calimero.chat' to 'com.calimero-studio.test.one-on-one-chat1' to match studio.config.json.
  • ✅ Fixed: Message times use wrong units
    • Removed the multiplication by 1000 in formatTime since created_at from the chat service is already in milliseconds, not seconds.
  • ✅ Fixed: Join does not select namespace
    • Added setSelectedNsId(nsId) and persistSelectedNamespaceId(nsId) calls after successful joinNamespace to select the joined namespace.

Create PR

Or push these changes by commenting:

@cursor push f6cb19548e
Preview (f6cb19548e)
diff --git a/app/.env b/app/.env
--- a/app/.env
+++ b/app/.env
@@ -1 +1 @@
-VITE_PACKAGE_NAME=com.calimero.chat
+VITE_PACKAGE_NAME=com.calimero-studio.test.one-on-one-chat1

diff --git a/app/src/components/MessageBubble.tsx b/app/src/components/MessageBubble.tsx
--- a/app/src/components/MessageBubble.tsx
+++ b/app/src/components/MessageBubble.tsx
@@ -11,11 +11,11 @@
 }
 
 /**
- * Format a Unix-second timestamp as a local time string.
- * `created_at` from the chat service is in seconds (u64).
+ * Format a Unix-millisecond timestamp as a local time string.
+ * `created_at` from the chat service is in milliseconds (u64).
  */
-function formatTime(createdAtSec: number): string {
-  const d = new Date(createdAtSec * 1_000);
+function formatTime(createdAtMs: number): string {
+  const d = new Date(createdAtMs);
   return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
 }
 

diff --git a/app/src/hooks/useChatLobby.ts b/app/src/hooks/useChatLobby.ts
--- a/app/src/hooks/useChatLobby.ts
+++ b/app/src/hooks/useChatLobby.ts
@@ -319,6 +319,8 @@
       const result = await joinNamespace(nsId, { invitation, groupAlias });
 
       if (result) {
+        setSelectedNsId(nsId);
+        persistSelectedNamespaceId(nsId);
         await refetchNamespaces();
         return true;
       }

You can send follow-ups to the cloud agent here.

Comment thread app/.env
@@ -0,0 +1 @@
VITE_PACKAGE_NAME=com.calimero.chat

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong package in env file

High Severity

VITE_PACKAGE_NAME is set to com.calimero.chat, while studio.config.json and APP_PACKAGE use com.calimero-studio.test.one-on-one-chat1. App.tsx prefers the env value for MeroProvider, so the UI can target a different Calimero package than the published bundle and backend.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 478473a. Configure here.

*/
function formatTime(createdAtSec: number): string {
const d = new Date(createdAtSec * 1_000);
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message times use wrong units

Medium Severity

formatTime treats created_at as Unix seconds, but the chat service stores created_at (and edited_at) in milliseconds. Multiplying by 1,000 before Date yields incorrect clock labels in the message list.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 478473a. Configure here.


if (result) {
await refetchNamespaces();
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Join does not select namespace

Medium Severity

After a successful joinNamespace, joinLobbyViaInvitation only refetches namespaces and never sets the active namespace to the one from the invitation. The UI can stay on another conversation while the user has joined a different chat.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 478473a. Configure here.

The foundation template ships app/.env VITE_PACKAGE_NAME=com.calimero.chat,
which shadowed APP_PACKAGE and made the deployed app request a package that
is not in the registry. Make APP_PACKAGE (studio.config.json) authoritative.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 4 total unresolved issues (including 3 from previous reviews).

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: clearAuth wrong storage key
    • Updated clearAuth to dynamically derive the storage key from studio.config.json using loadStudioConfig() helper, ensuring it clears the correct app-specific key.

Create PR

Or push these changes by commenting:

@cursor push bd78ad5b57
Preview (bd78ad5b57)
diff --git a/app/e2e/helpers.ts b/app/e2e/helpers.ts
--- a/app/e2e/helpers.ts
+++ b/app/e2e/helpers.ts
@@ -6,19 +6,27 @@
 const __dirname = path.dirname(fileURLToPath(import.meta.url));
 const STATE_FILE = path.resolve(__dirname, '..', '.playwright-data', 'pw-state.json');
 
-// App-agnostic post-auth route — read from studio.config.json so this
+// App-agnostic config — read from studio.config.json so this
 // infra file is identical across the foundation and every generated app
-// (no per-app patching). Foundation chat → "/chat".
-function appRoute(): string {
+// (no per-app patching).
+function loadStudioConfig(): { appName?: string; metadata?: { route?: string } } {
   try {
     const cfgPath = path.resolve(__dirname, '..', '..', 'studio.config.json');
-    const cfg = JSON.parse(readFileSync(cfgPath, 'utf-8'));
-    return cfg?.metadata?.route || '/';
+    return JSON.parse(readFileSync(cfgPath, 'utf-8'));
   } catch {
-    return '/';
+    return {};
   }
 }
 
+function appRoute(): string {
+  return loadStudioConfig()?.metadata?.route || '/';
+}
+
+function selectedNamespaceKey(): string {
+  const appName = loadStudioConfig()?.appName || 'chat';
+  return `${appName}:selectedNamespaceId`;
+}
+
 interface NodeState {
   name: string;
   adminUrl: string;
@@ -70,12 +78,13 @@
   try {
     const url = page.url();
     if (url === 'about:blank' || !url.startsWith('http')) return;
-    await page.evaluate(() => {
+    const nsKey = selectedNamespaceKey();
+    await page.evaluate((namespaceKey) => {
       [
         'mero:access_token', 'mero:refresh_token', 'mero:expires_at',
         'mero:node_url', 'mero:application_id', 'mero:context_id',
-        'mero:context_identity', 'chat:selectedNamespaceId',
+        'mero:context_identity', namespaceKey,
       ].forEach((k) => localStorage.removeItem(k));
-    });
+    }, nsKey);
   } catch { /* page may be closed */ }
 }

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 6c44fe1. Configure here.

Comment thread app/e2e/helpers.ts
[
'mero:access_token', 'mero:refresh_token', 'mero:expires_at',
'mero:node_url', 'mero:application_id', 'mero:context_id',
'mero:context_identity', 'chat:selectedNamespaceId',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearAuth wrong storage key

Low Severity

clearAuth removes chat:selectedNamespaceId, but the app persists selection under one-on-one-chat:selectedNamespaceId from SELECTED_NAMESPACE_KEY, so e2e cleanup leaves stale conversation selection in localStorage.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6c44fe1. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant