openvibers/openvibe.network Commits

Frame Runs: a Vibe chat's title is its own name (#877)

OP OpenVibers committed 23 h ago · e946f509a2 · 2 files, +3 −2

Chat names a Vibe chat after its persona unless the person renamed it (OpenVibe.Chat #546), so the run's
title reads the chat's name and the persona stays the agent's face (name, glyph, hue, picture).

Changes

ddiff --git a/server/frame/runs.js b/server/frame/runs.js
iindex dcbf0857..f000c56d 100644
---- a/server/frame/runs.js
++++ b/server/frame/runs.js
@@@ -78,7 +78,7 @@ function createFrameRuns({ svcUrl = (name, fallback) => fallback, personOf = asy
const persona = c.persona && typeof c.persona === 'object' ? c.persona : null;
const at = iso(c.last_message_at || c.updated_at || c.created_at) || new Date(now()).toISOString();
const run = {
-- id: String(c.slug), ref: `chat:${c.slug}`, kind: 'chat', title: clip((persona && persona.name) || c.name || 'Vibe', 200) || 'Vibe',
++ id: String(c.slug), ref: `chat:${c.slug}`, kind: 'chat', title: clip(c.name || (persona && persona.name) || 'Vibe', 200) || 'Vibe', // the chat's own name: Chat sets it to the persona's unless the person renamed it
owner, agent: { id: 'vibe', name: clip((persona && persona.name) || 'Vibe', 160) || 'Vibe', product: 'chat', harness: 'openvibe' },
status: 'waiting', waiting: { for: 'message' },
url: httpsUrl(c.url) || `https://openvibe.chat/vibe/${encodeURIComponent(c.slug)}`,
ddiff --git a/test/frame-runs.test.js b/test/frame-runs.test.js
iindex 43f9661b..778bee0a 100644
---- a/test/frame-runs.test.js
++++ b/test/frame-runs.test.js
@@@ -26,7 +26,7 @@ const sendJson = (res, status, body) => { res.statusCode = status; res.setHeader
const chat = await listen(async (req, res) => {
seen.push({ svc: 'chat', method: req.method, url: req.url, auth: req.headers.authorization });
const u = new URL(req.url, 'http://x');
-- if (u.pathname === '/api/vibe/conversations') return sendJson(res, 200, { conversations: [{ slug: 'c_keys', name: 'Keyboard Scout', last_line: 'Three picks under $90.', last_message_at: '2026-11-12 10:00:20', site: 'https://openvibe.deals', persona: { name: 'Keyboard Scout', glyph: 'search', hue: 212 } }], count: 1 });
++ if (u.pathname === '/api/vibe/conversations') return sendJson(res, 200, { conversations: [{ slug: 'c_keys', name: 'My keyboard hunt', last_line: 'Three picks under $90.', last_message_at: '2026-11-12 10:00:20', site: 'https://openvibe.deals', persona: { name: 'Keyboard Scout', glyph: 'search', hue: 212 } }], count: 1 });
if (u.pathname === '/api/vibe/chat') {
if (u.searchParams.get('slug') !== 'c_keys') return sendJson(res, 200, { chat: null, messages: [] });
const after = Number(u.searchParams.get('after')) || 0;
@@@ -94,6 +94,7 @@ const sendJson = (res, status, body) => { res.statusCode = status; res.setHeader
assert.strictEqual(vibeRun.status, 'waiting');
assert.deepStrictEqual(vibeRun.waiting, { for: 'message' }, 'a conversation is a run waiting for a message');
assert.deepStrictEqual(vibeRun.agent, { id: 'vibe', name: 'Keyboard Scout', product: 'chat', harness: 'openvibe', glyph: 'search', hue: 212 }, 'the persona is the agent\'s face');
++ assert.strictEqual(vibeRun.title, 'My keyboard hunt', 'the chat\'s own name is its title (a person\'s rename stays theirs); the persona names the agent');
assert.strictEqual(vibeRun.updated_at, '2026-11-12T10:00:20.000Z', 'a time without a zone is UTC');
assert.deepStrictEqual(vibeRun.context, { site: 'openvibe.deals' });
assert.deepStrictEqual(vibeRun.owner, { type: 'user', id: 'usr_01K9R2V6M8Q4T0B7C3D5E9F2GH' });