openvibers/openvibe.chat Commits
OpenVibe Link: the new name in pages, docs and messages (#410)
Changes
@@@ -354,7 +354,7 @@ linked from the channel on the server's settings page.**A model on their own computer** (AI on your own machines; contracts 0.220.0/0.221.0). The key may instead be provider`node`: a `machine` (a `dev_` id from openvibe.bot/machines, or `any`, the fastest of theirs that is on) and a model,--with no key and nothing spent. OpenVibe.AI reaches it through OpenVibe.Bot and the person's OpenVibe Node, only where they++with no key and nothing spent. OpenVibe.AI reaches it through OpenVibe.Bot and the person's OpenVibe Link, only where theyturned on "Let my AI use this computer's models".- **The form** shows only the fields the chosen provider takes (`chat.css` `:has()`). It comes prefilled from Bot's"Use these models in OpenVibe.Chat" (`/settings?own=node&machine=dev_…|any&model=…`).@@@ -2,7 +2,7 @@/*** OpenVibe.Chat — the machine TTS route (Agent Streams S4, design 2026-11-06).*-- * The desk (OpenVibe.Node) asks Chat for the sound of a line the agent said. The desk holds a node token for++ * The desk (OpenVibe Link) asks Chat for the sound of a line the agent said. The desk holds a node token for* audience openvibe.chat that carries the capability chat.tts.speak and names the person it acts for* (`on_behalf_of`, the Network's rule for a node token acting for its owner). Chat speaks in that person's voice and* on that person's allowance.@@@ -134,7 +134,7 @@ async function start(user, text, { timezone = null } = {}) {const MODES = Object.freeze({ research: 'research', agent: 'computer', code: 'code' });const ON_IT = {research: 'On it: I am researching this as an agent task, with sources. The answer comes back right here, usually within a few minutes.',-- computer: 'On it: I am doing this on your own computer, through OpenVibe.Node, at the level you set there. I will say here what I did.',++ computer: 'On it: I am doing this on your own computer, through OpenVibe Link, at the level you set there. I will say here what I did.',code: 'On it: I sent this to OpenVibe.Codes on your own computer (through OpenVibe.Run). The pull request comes back here when it is ready.',};@@@ -97,7 +97,7 @@ const FAQ = [{ q: 'How do I start a server?', a: 'Sign in, open Servers and give it a name. It starts with text and voice channels; add more, give people roles, and share an invite link. A server can be public or private.' },{ q: 'What is Vibe?', a: 'OpenVibe\'s own assistant, free with your account: it searches the web and all of OpenVibe, reads pages and pictures you share, remembers what you ask it to, and sets up work that runs every day for you. Your chats with it are private.' },{ q: 'What are AI members?', a: 'An AI you add to a room or channel, with a name, a persona and a memory of that room. It answers when someone writes its @name, with OpenVibe\'s model, one from your own AI key, or a model on your own computer.' },-- { q: 'Can Vibe use my own model?', a: 'Yes. Under Your AI key in your settings, add a key from OpenAI, Anthropic or any OpenAI-compatible provider, or choose a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Node: free, and no port is opened), then tick Vibe thinks with it too. Its answers then have no daily limit.' },++ { q: 'Can Vibe use my own model?', a: 'Yes. Under Your AI key in your settings, add a key from OpenAI, Anthropic or any OpenAI-compatible provider, or choose a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Link: free, and no port is opened), then tick Vibe thinks with it too. Its answers then have no daily limit.' },{ q: 'Can I send pictures?', a: 'Yes, in rooms and server channels. A picture goes to OpenVibe.Pics as yours, with its hidden location and camera details removed, and shows inline in the conversation.' },{ q: 'How many people fit in a call?', a: 'Up to eight in a voice or video call, with mute, camera and kick controls. Call one person from your messages, or open a call room.' },{ q: 'Who can message me?', a: 'You decide in your settings who may start a conversation with you and whether group conversations may add you. You can block anyone from a conversation.' },@@@ -596,7 +596,7 @@ ${await aiKeySection(actor, req.query || {})}`,const vibeBox = require('../rooms/vibe').enabled() ? `<label class="oc-check"><input type="checkbox" name="vibe" value="1"${vibeOwn || offered ? ' checked' : ''}> Vibe thinks with it too (in all your chats with Vibe; its answers then have no daily limit)</label>` : '';const open = offered || q.saved || q.error ? ' open' : '';return `<details class="oc-card oc-fold oc-aikey" id="oc-ai-key"${open}><summary><span>Your AI key${key ? ` <span class="oc-muted">· ${esc(credentials.label(key))}</span>` : ''}</span>${IC.chevron}</summary>--<p class="oc-muted">AI members you add to a room, your Vibe among them, can think with your own provider and model instead of OpenVibe's: OpenAI, Anthropic, any OpenAI-compatible endpoint (OpenRouter, Groq, Together, your own server), or <strong>a model on your own computer</strong> (Ollama, LM Studio or llama.cpp through the OpenVibe Node, free, with no port opened: turn on "Let my AI use this computer's models" for it on <a href="https://openvibe.bot/machines">openvibe.bot/machines</a>). A key is kept encrypted in OpenVibe.AI and never shown again; the room's messages go to your provider or your computer when one of those members answers, and a key's replies count against your daily budget, not the room's limit.</p>++<p class="oc-muted">AI members you add to a room, your Vibe among them, can think with your own provider and model instead of OpenVibe's: OpenAI, Anthropic, any OpenAI-compatible endpoint (OpenRouter, Groq, Together, your own server), or <strong>a model on your own computer</strong> (Ollama, LM Studio or llama.cpp through the OpenVibe Link, free, with no port opened: turn on "Let my AI use this computer's models" for it on <a href="https://openvibe.bot/machines">openvibe.bot/machines</a>). A key is kept encrypted in OpenVibe.AI and never shown again; the room's messages go to your provider or your computer when one of those members answers, and a key's replies count against your daily budget, not the room's limit.</p>${offered ? notice('ok', `Save to let your AI members think with ${offered.model || 'a model'} on ${offered.machine === 'any' ? 'whichever of your computers is on' : 'your own computer'}.`) : ''}${unreachable ? notice('error', 'OpenVibe.AI did not answer, so your key cannot be shown or changed right now.') : `${key ? `<p><strong>${esc(credentials.label(key))}</strong> <span class="oc-muted">· ${keyLine}${vibeOwn ? ' · Vibe thinks with it' : ''}</span></p>` : '<p class="oc-muted">No key yet.</p>'}<form class="oc-form oc-ai-form" method="post" action="/settings/ai-key">@@@ -189,7 +189,7 @@ function turnsOf(messages, me, hows, { retrySlug = null, slug = null, waiting =const MODES = [['chat', 'Chat', 'Talk it through: Vibe answers here and now', 'Message Vibe'],['research', 'Research', 'An agent researches it and answers here with its sources', 'What should I research?'],-- ['agent', 'Agent', 'An agent does it on your own computer (OpenVibe.Node), at the level you set there', 'What should I do on your computer?'],++ ['agent', 'Agent', 'An agent does it on your own computer (OpenVibe Link), at the level you set there', 'What should I do on your computer?'],['code', 'Code', 'OpenVibe.Codes writes it on your computer and opens a pull request', 'What should I build or fix? Name the repository'],];@@@ -20,7 +20,7 @@ t('the front page leads to Vibe: the first action, an Ask Vibe box, the questionassert.match(page, /<summary>What is Vibe\?<\/summary>/);assert.match(page, /"name":"What is Vibe\?"/, 'in the FAQ JSON-LD');assert.match(page, /<summary>Can Vibe use my own model\?<\/summary>/, 'your own key or computer (AI on your own machines)');-- assert.ok(page.includes('a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Node'));++ assert.ok(page.includes('a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Link'));});t('the box opens Vibe with the question in it, signed out too', async () => {@@@ -92,7 +92,7 @@ t('Code in an existing chat: Codes on their own computer; Agent too; Chat mode aawait new Promise((res) => setTimeout(res, 150));const vibeLines = (await messagesOf(slug)).filter((m) => m.ai_member_id).map((m) => m.message);assert.ok(vibeLines.some((l) => /^On it: I sent this to OpenVibe\.Codes on your own computer/.test(l)));-- assert.ok(vibeLines.some((l) => /^On it: I am doing this on your own computer, through OpenVibe\.Node/.test(l)));++ assert.ok(vibeLines.some((l) => /^On it: I am doing this on your own computer, through OpenVibe Link/.test(l)));assert.strictEqual(turns.length, 1, 'no instant answers to the tasks');});
@@ -354,7 +354,7 @@ linked from the channel on the server's settings page.
@@ -354,7 +354,7 @@ linked from the channel on the server's settings page.
**A model on their own computer** (AI on your own machines; contracts 0.220.0/0.221.0). The key may instead be provider
**A model on their own computer** (AI on your own machines; contracts 0.220.0/0.221.0). The key may instead be provider
`node`: a `machine` (a `dev_` id from openvibe.bot/machines, or `any`, the fastest of theirs that is on) and a model,
`node`: a `machine` (a `dev_` id from openvibe.bot/machines, or `any`, the fastest of theirs that is on) and a model,
-with no key and nothing spent. OpenVibe.AI reaches it through OpenVibe.Bot and the person's OpenVibe Node, only where they
+with no key and nothing spent. OpenVibe.AI reaches it through OpenVibe.Bot and the person's OpenVibe Link, only where they
turned on "Let my AI use this computer's models".
turned on "Let my AI use this computer's models".
- **The form** shows only the fields the chosen provider takes (`chat.css` `:has()`). It comes prefilled from Bot's
- **The form** shows only the fields the chosen provider takes (`chat.css` `:has()`). It comes prefilled from Bot's
"Use these models in OpenVibe.Chat" (`/settings?own=node&machine=dev_…|any&model=…`).
"Use these models in OpenVibe.Chat" (`/settings?own=node&machine=dev_…|any&model=…`).
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
/**
/**
* OpenVibe.Chat — the machine TTS route (Agent Streams S4, design 2026-11-06).
* OpenVibe.Chat — the machine TTS route (Agent Streams S4, design 2026-11-06).
*
*
- * The desk (OpenVibe.Node) asks Chat for the sound of a line the agent said. The desk holds a node token for
+ * The desk (OpenVibe Link) asks Chat for the sound of a line the agent said. The desk holds a node token for
* audience openvibe.chat that carries the capability chat.tts.speak and names the person it acts for
* audience openvibe.chat that carries the capability chat.tts.speak and names the person it acts for
* (`on_behalf_of`, the Network's rule for a node token acting for its owner). Chat speaks in that person's voice and
* (`on_behalf_of`, the Network's rule for a node token acting for its owner). Chat speaks in that person's voice and
* on that person's allowance.
* on that person's allowance.
@@ -134,7 +134,7 @@ async function start(user, text, { timezone = null } = {}) {
@@ -134,7 +134,7 @@ async function start(user, text, { timezone = null } = {}) {
const MODES = Object.freeze({ research: 'research', agent: 'computer', code: 'code' });
const MODES = Object.freeze({ research: 'research', agent: 'computer', code: 'code' });
const ON_IT = {
const ON_IT = {
research: 'On it: I am researching this as an agent task, with sources. The answer comes back right here, usually within a few minutes.',
research: 'On it: I am researching this as an agent task, with sources. The answer comes back right here, usually within a few minutes.',
- computer: 'On it: I am doing this on your own computer, through OpenVibe.Node, at the level you set there. I will say here what I did.',
+ computer: 'On it: I am doing this on your own computer, through OpenVibe Link, at the level you set there. I will say here what I did.',
code: 'On it: I sent this to OpenVibe.Codes on your own computer (through OpenVibe.Run). The pull request comes back here when it is ready.',
code: 'On it: I sent this to OpenVibe.Codes on your own computer (through OpenVibe.Run). The pull request comes back here when it is ready.',
};
};
@@ -97,7 +97,7 @@ const FAQ = [
@@ -97,7 +97,7 @@ const FAQ = [
{ q: 'How do I start a server?', a: 'Sign in, open Servers and give it a name. It starts with text and voice channels; add more, give people roles, and share an invite link. A server can be public or private.' },
{ q: 'How do I start a server?', a: 'Sign in, open Servers and give it a name. It starts with text and voice channels; add more, give people roles, and share an invite link. A server can be public or private.' },
{ q: 'What is Vibe?', a: 'OpenVibe\'s own assistant, free with your account: it searches the web and all of OpenVibe, reads pages and pictures you share, remembers what you ask it to, and sets up work that runs every day for you. Your chats with it are private.' },
{ q: 'What is Vibe?', a: 'OpenVibe\'s own assistant, free with your account: it searches the web and all of OpenVibe, reads pages and pictures you share, remembers what you ask it to, and sets up work that runs every day for you. Your chats with it are private.' },
{ q: 'What are AI members?', a: 'An AI you add to a room or channel, with a name, a persona and a memory of that room. It answers when someone writes its @name, with OpenVibe\'s model, one from your own AI key, or a model on your own computer.' },
{ q: 'What are AI members?', a: 'An AI you add to a room or channel, with a name, a persona and a memory of that room. It answers when someone writes its @name, with OpenVibe\'s model, one from your own AI key, or a model on your own computer.' },
- { q: 'Can Vibe use my own model?', a: 'Yes. Under Your AI key in your settings, add a key from OpenAI, Anthropic or any OpenAI-compatible provider, or choose a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Node: free, and no port is opened), then tick Vibe thinks with it too. Its answers then have no daily limit.' },
+ { q: 'Can Vibe use my own model?', a: 'Yes. Under Your AI key in your settings, add a key from OpenAI, Anthropic or any OpenAI-compatible provider, or choose a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Link: free, and no port is opened), then tick Vibe thinks with it too. Its answers then have no daily limit.' },
{ q: 'Can I send pictures?', a: 'Yes, in rooms and server channels. A picture goes to OpenVibe.Pics as yours, with its hidden location and camera details removed, and shows inline in the conversation.' },
{ q: 'Can I send pictures?', a: 'Yes, in rooms and server channels. A picture goes to OpenVibe.Pics as yours, with its hidden location and camera details removed, and shows inline in the conversation.' },
{ q: 'How many people fit in a call?', a: 'Up to eight in a voice or video call, with mute, camera and kick controls. Call one person from your messages, or open a call room.' },
{ q: 'How many people fit in a call?', a: 'Up to eight in a voice or video call, with mute, camera and kick controls. Call one person from your messages, or open a call room.' },
{ q: 'Who can message me?', a: 'You decide in your settings who may start a conversation with you and whether group conversations may add you. You can block anyone from a conversation.' },
{ q: 'Who can message me?', a: 'You decide in your settings who may start a conversation with you and whether group conversations may add you. You can block anyone from a conversation.' },
@@ -596,7 +596,7 @@ ${await aiKeySection(actor, req.query || {})}`,
@@ -596,7 +596,7 @@ ${await aiKeySection(actor, req.query || {})}`,
const vibeBox = require('../rooms/vibe').enabled() ? `<label class="oc-check"><input type="checkbox" name="vibe" value="1"${vibeOwn || offered ? ' checked' : ''}> Vibe thinks with it too (in all your chats with Vibe; its answers then have no daily limit)</label>` : '';
const vibeBox = require('../rooms/vibe').enabled() ? `<label class="oc-check"><input type="checkbox" name="vibe" value="1"${vibeOwn || offered ? ' checked' : ''}> Vibe thinks with it too (in all your chats with Vibe; its answers then have no daily limit)</label>` : '';
const open = offered || q.saved || q.error ? ' open' : '';
const open = offered || q.saved || q.error ? ' open' : '';
return `<details class="oc-card oc-fold oc-aikey" id="oc-ai-key"${open}><summary><span>Your AI key${key ? ` <span class="oc-muted">· ${esc(credentials.label(key))}</span>` : ''}</span>${IC.chevron}</summary>
return `<details class="oc-card oc-fold oc-aikey" id="oc-ai-key"${open}><summary><span>Your AI key${key ? ` <span class="oc-muted">· ${esc(credentials.label(key))}</span>` : ''}</span>${IC.chevron}</summary>
-<p class="oc-muted">AI members you add to a room, your Vibe among them, can think with your own provider and model instead of OpenVibe's: OpenAI, Anthropic, any OpenAI-compatible endpoint (OpenRouter, Groq, Together, your own server), or <strong>a model on your own computer</strong> (Ollama, LM Studio or llama.cpp through the OpenVibe Node, free, with no port opened: turn on "Let my AI use this computer's models" for it on <a href="https://openvibe.bot/machines">openvibe.bot/machines</a>). A key is kept encrypted in OpenVibe.AI and never shown again; the room's messages go to your provider or your computer when one of those members answers, and a key's replies count against your daily budget, not the room's limit.</p>
+<p class="oc-muted">AI members you add to a room, your Vibe among them, can think with your own provider and model instead of OpenVibe's: OpenAI, Anthropic, any OpenAI-compatible endpoint (OpenRouter, Groq, Together, your own server), or <strong>a model on your own computer</strong> (Ollama, LM Studio or llama.cpp through the OpenVibe Link, free, with no port opened: turn on "Let my AI use this computer's models" for it on <a href="https://openvibe.bot/machines">openvibe.bot/machines</a>). A key is kept encrypted in OpenVibe.AI and never shown again; the room's messages go to your provider or your computer when one of those members answers, and a key's replies count against your daily budget, not the room's limit.</p>
${offered ? notice('ok', `Save to let your AI members think with ${offered.model || 'a model'} on ${offered.machine === 'any' ? 'whichever of your computers is on' : 'your own computer'}.`) : ''}
${offered ? notice('ok', `Save to let your AI members think with ${offered.model || 'a model'} on ${offered.machine === 'any' ? 'whichever of your computers is on' : 'your own computer'}.`) : ''}
${unreachable ? notice('error', 'OpenVibe.AI did not answer, so your key cannot be shown or changed right now.') : `${key ? `<p><strong>${esc(credentials.label(key))}</strong> <span class="oc-muted">· ${keyLine}${vibeOwn ? ' · Vibe thinks with it' : ''}</span></p>` : '<p class="oc-muted">No key yet.</p>'}
${unreachable ? notice('error', 'OpenVibe.AI did not answer, so your key cannot be shown or changed right now.') : `${key ? `<p><strong>${esc(credentials.label(key))}</strong> <span class="oc-muted">· ${keyLine}${vibeOwn ? ' · Vibe thinks with it' : ''}</span></p>` : '<p class="oc-muted">No key yet.</p>'}
<form class="oc-form oc-ai-form" method="post" action="/settings/ai-key">
<form class="oc-form oc-ai-form" method="post" action="/settings/ai-key">
@@ -189,7 +189,7 @@ function turnsOf(messages, me, hows, { retrySlug = null, slug = null, waiting =
@@ -189,7 +189,7 @@ function turnsOf(messages, me, hows, { retrySlug = null, slug = null, waiting =
const MODES = [
const MODES = [
['chat', 'Chat', 'Talk it through: Vibe answers here and now', 'Message Vibe'],
['chat', 'Chat', 'Talk it through: Vibe answers here and now', 'Message Vibe'],
['research', 'Research', 'An agent researches it and answers here with its sources', 'What should I research?'],
['research', 'Research', 'An agent researches it and answers here with its sources', 'What should I research?'],
- ['agent', 'Agent', 'An agent does it on your own computer (OpenVibe.Node), at the level you set there', 'What should I do on your computer?'],
+ ['agent', 'Agent', 'An agent does it on your own computer (OpenVibe Link), at the level you set there', 'What should I do on your computer?'],
['code', 'Code', 'OpenVibe.Codes writes it on your computer and opens a pull request', 'What should I build or fix? Name the repository'],
['code', 'Code', 'OpenVibe.Codes writes it on your computer and opens a pull request', 'What should I build or fix? Name the repository'],
];
];
@@ -20,7 +20,7 @@ t('the front page leads to Vibe: the first action, an Ask Vibe box, the question
@@ -20,7 +20,7 @@ t('the front page leads to Vibe: the first action, an Ask Vibe box, the question
assert.match(page, /<summary>What is Vibe\?<\/summary>/);
assert.match(page, /<summary>What is Vibe\?<\/summary>/);
assert.match(page, /"name":"What is Vibe\?"/, 'in the FAQ JSON-LD');
assert.match(page, /"name":"What is Vibe\?"/, 'in the FAQ JSON-LD');
assert.match(page, /<summary>Can Vibe use my own model\?<\/summary>/, 'your own key or computer (AI on your own machines)');
assert.match(page, /<summary>Can Vibe use my own model\?<\/summary>/, 'your own key or computer (AI on your own machines)');
- assert.ok(page.includes('a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Node'));
+ assert.ok(page.includes('a model on your own computer (Ollama, LM Studio or llama.cpp through the OpenVibe Link'));
});
});
t('the box opens Vibe with the question in it, signed out too', async () => {
t('the box opens Vibe with the question in it, signed out too', async () => {
@@ -92,7 +92,7 @@ t('Code in an existing chat: Codes on their own computer; Agent too; Chat mode a
@@ -92,7 +92,7 @@ t('Code in an existing chat: Codes on their own computer; Agent too; Chat mode a
await new Promise((res) => setTimeout(res, 150));
await new Promise((res) => setTimeout(res, 150));
const vibeLines = (await messagesOf(slug)).filter((m) => m.ai_member_id).map((m) => m.message);
const vibeLines = (await messagesOf(slug)).filter((m) => m.ai_member_id).map((m) => m.message);
assert.ok(vibeLines.some((l) => /^On it: I sent this to OpenVibe\.Codes on your own computer/.test(l)));
assert.ok(vibeLines.some((l) => /^On it: I sent this to OpenVibe\.Codes on your own computer/.test(l)));
- assert.ok(vibeLines.some((l) => /^On it: I am doing this on your own computer, through OpenVibe\.Node/.test(l)));
+ assert.ok(vibeLines.some((l) => /^On it: I am doing this on your own computer, through OpenVibe Link/.test(l)));
assert.strictEqual(turns.length, 1, 'no instant answers to the tasks');
assert.strictEqual(turns.length, 1, 'no instant answers to the tasks');
});
});