openvibers/openvibe.ai Commits
AI: the home names the OpenAI-compatible endpoint and a project's own provider, and stops claiming metered models for production apps (#76)
Changes
@@@ -61,14 +61,15 @@ function sections({ siteUrl }) {return showcase.hero({eyebrow: 'OpenVibe.AI · alpha',title: 'Many models, one API.', accent: 'Every answer explained.',-- lede: 'Chat, generate, summarize, classify, extract and embed through one API. OpenVibe.AI picks a model by price, measured latency '-- + 'and health, falls back when a provider fails, and tells you on every run which model answered, why it was chosen and what it cost.',++ lede: 'Chat, generate, summarize, classify, extract and embed through one API, or point any OpenAI client at it. OpenVibe.AI picks a '++ + 'model by price, measured latency and health, falls back when a provider fails, and tells you on every run which model answered, '++ + 'why it was chosen and what it cost.',actions: [{ label: 'Start building', href: PROJECTS_URL, primary: true }, { label: 'See prices and latency', href: '/stats' }],note: 'Alpha. OpenVibe.Live and OpenVibe.Network already run their AI here in production; developer apps start in the sandbox, on free and local capacity.',}) + showcase.features({title: 'What you get',items: [-- { icon: 'ov:text', title: 'Six operations', text: 'Chat, generate, summarize, classify, extract and embed, with structured JSON output when you ask for a schema.' },++ { icon: 'ov:text', title: 'Six operations, and OpenAI\'s API', text: 'Chat, generate, summarize, classify, extract and embed, with JSON output on a schema. Any OpenAI client works too: point it at /v1 for Chat Completions with tools.' },{ icon: 'ov:map', title: 'Routing you can read', text: 'Every run carries an explanation: what it optimised for, the model it picked, and every other candidate with its estimated cost and latency.' },{ icon: 'ov:history', title: 'Fallbacks on the record', text: 'A provider that is down, out of credentials or too slow is skipped and logged. When a fallback answers, the run says so.' },{ icon: 'ov:host', title: 'Free and local first', text: 'A small open model runs on OpenVibe\'s own server, beside free providers. Sandbox apps use only that capacity, so trying it costs nothing.' },@@@ -98,7 +99,8 @@ function sections({ siteUrl }) {columns: ['Sandbox', 'Production'],rows: [{ label: 'Access to ai.app.run', values: ['Every sandbox app, without asking', 'Once OpenVibe staff add it to the project'] },-- { label: 'Models', values: ['Free and local capacity only', 'Free and local capacity; metered models under a project budget'] },++ { label: 'Models', values: ['Free and local capacity only', 'Free and local capacity; metered models open with project budgets'] },++ { label: 'Your project\'s own provider', values: ['On /v1/chat/completions, keyed by a project secret granted to ai', 'The same'] },{ label: 'Free allowance', values: ['Per project, per provider', 'Per project, per provider'] },{ label: 'Who can read a run', values: ['The project that made it', 'The project that made it'] },{ label: 'A person\'s own provider key', values: ['Never used', 'Never used'] },@@@ -38,6 +38,9 @@ t.test('GET / as a browser: the home page, its CSP and a private cache', async (assert.match(r.headers.get('vary'), /Accept/);assert.strictEqual((r.text.match(/<h1\b/g) || []).length, 1, 'exactly one h1');assert.ok(r.text.includes('Many models, one API.'), 'the hero');++ assert.ok(r.text.includes('point it at /v1 for Chat Completions with tools'), 'the OpenAI-compatible endpoint is on the home');++ assert.ok(r.text.includes('Your project's own provider') || r.text.includes("Your project's own provider"), 'the project\'s own provider row');++ assert.ok(!r.text.includes('metered models under a project budget'), 'production app runs are free-only until project budgets open');assert.ok(r.text.includes(`<link rel="canonical" href="${SITE}/">`), 'the canonical public origin');assert.ok(r.text.includes(`${SITE}/api/v1/chat`), 'the examples call the public origin');assert.ok(r.text.includes('https://openvibe.services/projects'), 'where a project and an app are made');
@@ -61,14 +61,15 @@ function sections({ siteUrl }) {
@@ -61,14 +61,15 @@ function sections({ siteUrl }) {
return showcase.hero({
return showcase.hero({
eyebrow: 'OpenVibe.AI · alpha',
eyebrow: 'OpenVibe.AI · alpha',
title: 'Many models, one API.', accent: 'Every answer explained.',
title: 'Many models, one API.', accent: 'Every answer explained.',
- lede: 'Chat, generate, summarize, classify, extract and embed through one API. OpenVibe.AI picks a model by price, measured latency '
- + 'and health, falls back when a provider fails, and tells you on every run which model answered, why it was chosen and what it cost.',
+ lede: 'Chat, generate, summarize, classify, extract and embed through one API, or point any OpenAI client at it. OpenVibe.AI picks a '
+ + 'model by price, measured latency and health, falls back when a provider fails, and tells you on every run which model answered, '
+ + 'why it was chosen and what it cost.',
actions: [{ label: 'Start building', href: PROJECTS_URL, primary: true }, { label: 'See prices and latency', href: '/stats' }],
actions: [{ label: 'Start building', href: PROJECTS_URL, primary: true }, { label: 'See prices and latency', href: '/stats' }],
note: 'Alpha. OpenVibe.Live and OpenVibe.Network already run their AI here in production; developer apps start in the sandbox, on free and local capacity.',
note: 'Alpha. OpenVibe.Live and OpenVibe.Network already run their AI here in production; developer apps start in the sandbox, on free and local capacity.',
}) + showcase.features({
}) + showcase.features({
title: 'What you get',
title: 'What you get',
items: [
items: [
- { icon: 'ov:text', title: 'Six operations', text: 'Chat, generate, summarize, classify, extract and embed, with structured JSON output when you ask for a schema.' },
+ { icon: 'ov:text', title: 'Six operations, and OpenAI\'s API', text: 'Chat, generate, summarize, classify, extract and embed, with JSON output on a schema. Any OpenAI client works too: point it at /v1 for Chat Completions with tools.' },
{ icon: 'ov:map', title: 'Routing you can read', text: 'Every run carries an explanation: what it optimised for, the model it picked, and every other candidate with its estimated cost and latency.' },
{ icon: 'ov:map', title: 'Routing you can read', text: 'Every run carries an explanation: what it optimised for, the model it picked, and every other candidate with its estimated cost and latency.' },
{ icon: 'ov:history', title: 'Fallbacks on the record', text: 'A provider that is down, out of credentials or too slow is skipped and logged. When a fallback answers, the run says so.' },
{ icon: 'ov:history', title: 'Fallbacks on the record', text: 'A provider that is down, out of credentials or too slow is skipped and logged. When a fallback answers, the run says so.' },
{ icon: 'ov:host', title: 'Free and local first', text: 'A small open model runs on OpenVibe\'s own server, beside free providers. Sandbox apps use only that capacity, so trying it costs nothing.' },
{ icon: 'ov:host', title: 'Free and local first', text: 'A small open model runs on OpenVibe\'s own server, beside free providers. Sandbox apps use only that capacity, so trying it costs nothing.' },
@@ -98,7 +99,8 @@ function sections({ siteUrl }) {
@@ -98,7 +99,8 @@ function sections({ siteUrl }) {
columns: ['Sandbox', 'Production'],
columns: ['Sandbox', 'Production'],
rows: [
rows: [
{ label: 'Access to ai.app.run', values: ['Every sandbox app, without asking', 'Once OpenVibe staff add it to the project'] },
{ label: 'Access to ai.app.run', values: ['Every sandbox app, without asking', 'Once OpenVibe staff add it to the project'] },
- { label: 'Models', values: ['Free and local capacity only', 'Free and local capacity; metered models under a project budget'] },
+ { label: 'Models', values: ['Free and local capacity only', 'Free and local capacity; metered models open with project budgets'] },
+ { label: 'Your project\'s own provider', values: ['On /v1/chat/completions, keyed by a project secret granted to ai', 'The same'] },
{ label: 'Free allowance', values: ['Per project, per provider', 'Per project, per provider'] },
{ label: 'Free allowance', values: ['Per project, per provider', 'Per project, per provider'] },
{ label: 'Who can read a run', values: ['The project that made it', 'The project that made it'] },
{ label: 'Who can read a run', values: ['The project that made it', 'The project that made it'] },
{ label: 'A person\'s own provider key', values: ['Never used', 'Never used'] },
{ label: 'A person\'s own provider key', values: ['Never used', 'Never used'] },
@@ -38,6 +38,9 @@ t.test('GET / as a browser: the home page, its CSP and a private cache', async (
@@ -38,6 +38,9 @@ t.test('GET / as a browser: the home page, its CSP and a private cache', async (
assert.match(r.headers.get('vary'), /Accept/);
assert.match(r.headers.get('vary'), /Accept/);
assert.strictEqual((r.text.match(/<h1\b/g) || []).length, 1, 'exactly one h1');
assert.strictEqual((r.text.match(/<h1\b/g) || []).length, 1, 'exactly one h1');
assert.ok(r.text.includes('Many models, one API.'), 'the hero');
assert.ok(r.text.includes('Many models, one API.'), 'the hero');
+ assert.ok(r.text.includes('point it at /v1 for Chat Completions with tools'), 'the OpenAI-compatible endpoint is on the home');
+ assert.ok(r.text.includes('Your project's own provider') || r.text.includes("Your project's own provider"), 'the project\'s own provider row');
+ assert.ok(!r.text.includes('metered models under a project budget'), 'production app runs are free-only until project budgets open');
assert.ok(r.text.includes(`<link rel="canonical" href="${SITE}/">`), 'the canonical public origin');
assert.ok(r.text.includes(`<link rel="canonical" href="${SITE}/">`), 'the canonical public origin');
assert.ok(r.text.includes(`${SITE}/api/v1/chat`), 'the examples call the public origin');
assert.ok(r.text.includes(`${SITE}/api/v1/chat`), 'the examples call the public origin');
assert.ok(r.text.includes('https://openvibe.services/projects'), 'where a project and an app are made');
assert.ok(r.text.includes('https://openvibe.services/projects'), 'where a project and an app are made');