openvibers/openvibe.codes Commits
Two more harnesses the router can select: MiniMax Code and Claude Code on another provider (#172)
Changes
@@@ -15,7 +15,7 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","iovalkey": "^0.4.0",-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0","pg": "^8.23.0"@@@ -1149,9 +1149,9 @@}},"node_modules/openvibe-contracts": {-- "version": "0.245.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",-- "integrity": "sha512-H0L5BpMkwnKP6KDuecT16Iv9fH6o/6tDM78VFaxcAiNhj5HRsddRWuzrd2zIylkITYzmsxNkuojJUIqTwHAk9A==",++ "version": "0.246.1",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1",++ "integrity": "sha512-FPW+xWfwDc95j5UraDix/qMIrbEgsZ8DM67jmt50V662UtEurFij6M6jUnqKPhoMbu08QFvySZuvJ9hJy7G/iA==","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -30,7 +30,7 @@"express-rate-limit": "^7.5.0","helmet": "^8.1.0","iovalkey": "^0.4.0",-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0","pg": "^8.23.0"@@@ -51,6 +51,58 @@}]},++ {++ "id": "claude-other",++ "name": "Claude Code (another provider)",++ "provider": "custom",++ "capabilities": {++ "host_access": true,++ "mcp": true,++ "long_autonomy": true,++ "resume": true,++ "edit": true,++ "review": true,++ "tools": true,++ "vision": true,++ "browser": false,++ "computer_use": false,++ "runtimes": [++ "code"++ ]++ },++ "address": {++ "kind": "cli",++ "target": "claude"++ },++ "price": {++ "amount_usd": 0,++ "unit": "hour"++ },++ "limits": {++ "max_duration_seconds": 14400,++ "max_concurrent_runs": 4,++ "max_context_tokens": 200000++ },++ "agents": [++ {++ "id": "claude-other-default",++ "harness": "claude-other",++ "provider": "custom",++ "model": "claude-other",++ "context_limits": {++ "input_tokens": 200000,++ "output_tokens": 64000++ },++ "concurrency": 4,++ "price_per_1k_tokens": {++ "fresh_usd": 0,++ "cached_usd": 0,++ "output_usd": 0++ },++ "availability_windows": []++ }++ ]++ },{"id": "codex","name": "Codex",@@@ -207,6 +259,58 @@}]},++ {++ "id": "minimax-code",++ "name": "MiniMax Code",++ "provider": "minimax",++ "capabilities": {++ "host_access": true,++ "mcp": false,++ "long_autonomy": true,++ "resume": true,++ "edit": true,++ "review": true,++ "tools": true,++ "vision": false,++ "browser": false,++ "computer_use": false,++ "runtimes": [++ "code"++ ]++ },++ "address": {++ "kind": "cli",++ "target": "mcode"++ },++ "price": {++ "amount_usd": 0,++ "unit": "hour"++ },++ "limits": {++ "max_duration_seconds": 14400,++ "max_concurrent_runs": 4,++ "max_context_tokens": 200000++ },++ "agents": [++ {++ "id": "minimax-code-default",++ "harness": "minimax-code",++ "provider": "minimax",++ "model": "minimax-code",++ "context_limits": {++ "input_tokens": 200000,++ "output_tokens": 32000++ },++ "concurrency": 4,++ "price_per_1k_tokens": {++ "fresh_usd": 0,++ "cached_usd": 0,++ "output_usd": 0++ },++ "availability_windows": []++ }++ ]++ },{"id": "aider","name": "Aider",@@@ -27,14 +27,14 @@ function createHarnesses({ catalogPath = DEFAULT_CATALOG } = {}) {for (const [index, row] of rows.entries()) {if (!row || typeof row !== 'object' || Array.isArray(row)) throw invalid(`row ${index} is not an offer`);const { agents, ...offer } = row;-- const harnessCheck = contracts.validate('platform.harness-offer@1', offer);++ // A row is one contract instance: the offer and the agents (models) it runs. platform.harness-offer@1++ // carries the agents (contracts 0.246.0), so the whole row is checked against it in one go.++ const harnessCheck = contracts.validate('platform.harness-offer@1', row);if (!harnessCheck.valid) throw invalid(`row ${index} harness offer: ${JSON.stringify(harnessCheck.errors)}`);if (ids.has(offer.id)) throw invalid(`duplicate id ${offer.id}`);ids.add(offer.id);if (!Array.isArray(agents)) throw invalid(`row ${index} needs agents[]`);-- for (const [agentIndex, agent] of agents.entries()) {-- const agentCheck = contracts.validate('platform.agent-offer@1', agent);-- if (!agentCheck.valid) throw invalid(`row ${index} agent ${agentIndex}: ${JSON.stringify(agentCheck.errors)}`);++ for (const agent of agents) {if (ids.has(agent.id)) throw invalid(`duplicate id ${agent.id}`);if (agent.harness !== offer.id) throw invalid(`agent ${agent.id} refers to another harness`);ids.add(agent.id);@@@ -23,7 +23,7 @@const USER = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;/** The harnesses that speak Anthropic's Messages API (the rest speak OpenAI's Chat Completions). */--const ANTHROPIC_HARNESSES = ['claude-code'];++const ANTHROPIC_HARNESSES = ['claude-code', 'claude-other'];/** The claims of a JWT, decoded but not verified (the receiver verifies; this is for the jti and the expiry). */function claims(token) {@@@ -100,6 +100,17 @@ const router = require('../engine/router');assert.ok(router.pick(prompt, base), 'without a map of connections the ladder is as it was');});++ await check('a run on Claude Code (another provider) gets the Anthropic-shaped environment', async () => {++ // claude-other is the same claude CLI, so it reads ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN, and the++ // credential header names the provider the person's key is kept under (custom: their own endpoint).++ const minted = await t.ctx.runTokens.mint({ subject: ada.subject, task: null, attempt: null, harness: 'claude-other', provider: 'custom', ownKey: true });++ assert.ok(minted.token, 'a run token was minted');++ assert.ok(minted.env.ANTHROPIC_BASE_URL, 'the harness gets OpenVibe.AI\'s address');++ assert.ok(minted.env.ANTHROPIC_AUTH_TOKEN, 'and the run token');++ assert.strictEqual(minted.env.ANTHROPIC_CUSTOM_HEADERS, 'x-openvibe-credential: custom');++ assert.strictEqual('OPENAI_BASE_URL' in minted.env, false, 'not the OpenAI-shaped environment');++ });++await check('the run token is redacted by the transcript normaliser', async () => {const minted = await t.ctx.runTokens.mint({ subject: ada.subject, task: null, attempt: null, harness: 'claude-code', provider: 'anthropic', ownKey: true });assert.ok(minted.token, 'a run token was minted');@@@ -65,7 +65,7 @@ function priced(row, freshUsd) {await check('every seed offer validates as platform.resource-offer@1 of kind harness', async () => {const harnesses = createHarnesses({ catalogPath });const offers = harnesses.list().flatMap((harness) => harnesses.agents(harness.id).map((agent) => [harness, toOffer(harness, agent, { now })]));-- assert.strictEqual(offers.length, 8);++ assert.strictEqual(offers.length, 10);for (const [harness, offer] of offers) {const result = contracts.validate('platform.resource-offer@1', JSON.parse(JSON.stringify(offer)));assert.ok(result.valid, `${offer.offer_id}: ${JSON.stringify(result.errors)}`);@@@ -130,7 +130,7 @@ function priced(row, freshUsd) {const [harnessId] = r.selected.split(':');assert.ok(toOffer(harnesses.get(harnessId), harnesses.agents(harnessId)[0]).capabilities.includes('task:review'));assert.ok(r.reasons.length);-- assert.deepStrictEqual(r.candidates.map((c) => c.id), ['claude-code:claude-code-sonnet', 'codex:codex-default', 'command-code:command-code-default', 'opencode:opencode-default', 'aider:aider-default', 'deepseek:deepseek-chat', 'openvibe-ai:openvibe-ai-router', 'openai-compatible:openai-compatible-local']);++ assert.deepStrictEqual(r.candidates.map((c) => c.id), ['claude-code:claude-code-sonnet', 'claude-other:claude-other-default', 'codex:codex-default', 'command-code:command-code-default', 'opencode:opencode-default', 'minimax-code:minimax-code-default', 'aider:aider-default', 'deepseek:deepseek-chat', 'openvibe-ai:openvibe-ai-router', 'openai-compatible:openai-compatible-local']);});await check('an offer whose health is down is excluded with a reason', async () => {@@@ -153,7 +153,8 @@ function priced(row, freshUsd) {});await check('with equal latency the cheaper eligible offer wins', async () => {-- const [claude, codex] = rows;++ const claude = rows.find((row) => row.id === 'claude-code');++ const codex = rows.find((row) => row.id === 'codex');const harnesses = stub([priced(claude, 0.015), priced(codex, 0.003)]);const opts = { 'claude-code:claude-code-sonnet': { latencyMs: 500 }, 'codex:codex-default': { latencyMs: 500 } };const r = route({ task: 'edit', harnesses, opts, now });@@@ -164,7 +165,8 @@ function priced(row, freshUsd) {});await check('a task:browse requirement excludes harnesses without it', async () => {-- const [claude, codex] = rows;++ const claude = rows.find((row) => row.id === 'claude-code');++ const codex = rows.find((row) => row.id === 'codex');const harnesses = stub([{ ...claude, task_capabilities: ['edit', 'review', 'browse'] }, codex]);const r = route({ task: 'edit', extra: { capabilities: ['task:browse'] }, harnesses, now });assert.strictEqual(r.selected, 'claude-code:claude-code-sonnet');@@@ -40,6 +40,19 @@ const rows = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'server', 'daassert.ok(body.candidates.some((c) => c.id === body.selected && c.included === true));});++ await check('the router can select each of the harnesses the engine adapters added', async () => {++ // minimax-code and claude-other: the two adapters Codes' engine gained (C5) that the catalogue lacked.++ for (const id of ['minimax-code:minimax-code-default', 'claude-other:claude-other-default']) {++ const r = await post({ task: 'edit', requirements: { objective: 'correctness', authority: id } });++ assert.strictEqual(r.status, 200, r.text.slice(0, 300));++ const body = r.json();++ const candidate = body.candidates.find((c) => c.id === id);++ assert.ok(candidate, `${id} is a candidate`);++ assert.strictEqual(candidate.included, true, `${id} can take the task`);++ assert.strictEqual(body.selected, id, `the router selects ${id}`);++ }++ });++await check('a bad body is 422 harness.invalid', async () => {for (const json of [{}, { task: '' }, { task: 7 }, { task: 'review', requirements: 'x' }, { task: 'review', requirements: [] }, { task: 'review', requirements: { capabilities: 5 } }]) {const r = await post(json);@@@ -13,10 +13,12 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));(async () => {await check('every seed row matches the pinned harness and agent contracts', async () => {-- assert.strictEqual(rows.length, 8);-- for (const { agents, ...offer } of rows) {-- const harnessCheck = contracts.validate('platform.harness-offer@1', offer);++ assert.strictEqual(rows.length, 10);++ for (const row of rows) {++ // The row is one contract instance: the offer and the agents (models) it runs.++ const harnessCheck = contracts.validate('platform.harness-offer@1', row);assert.strictEqual(harnessCheck.valid, true, JSON.stringify(harnessCheck.errors));++ const { agents, ...offer } = row;assert.ok(Array.isArray(agents));for (const agent of agents) {const agentCheck = contracts.validate('platform.agent-offer@1', agent);@@@ -26,6 +28,32 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));}});++ await check('the two engine adapters Codes gained are in the catalogue', async () => {++ // engine/adapters/minimax-code.js and engine/adapters/claude-code.js (the claude-other one).++ const minimax = rows.find((row) => row.id === 'minimax-code');++ assert.ok(minimax, 'the catalogue has minimax-code');++ assert.strictEqual(minimax.name, 'MiniMax Code');++ assert.strictEqual(minimax.address.kind, 'cli');++ assert.strictEqual(minimax.address.target, 'mcode');++ assert.ok(minimax.agents.length > 0, 'minimax-code runs at least one model');++ const other = rows.find((row) => row.id === 'claude-other');++ assert.ok(other, 'the catalogue has claude-other');++ assert.strictEqual(other.name, 'Claude Code (another provider)');++ assert.strictEqual(other.address.kind, 'cli');++ assert.strictEqual(other.address.target, 'claude');++ assert.ok(other.agents.length > 0, 'claude-other runs at least one model');++ for (const row of [minimax, other]) {++ assert.strictEqual(row.agents.every((agent) => agent.harness === row.id), true);++ }++ });++++ await check('every engine adapter has a catalogue row, so the router can select it', async () => {++ const { ids: adapterIds } = require('../engine/adapters');++ for (const id of adapterIds()) {++ assert.ok(rows.some((row) => row.id === id), `the catalogue has ${id}`);++ }++ });++await check('harness and agent ids are unique', async () => {const ids = rows.flatMap((row) => [row.id, ...row.agents.map((agent) => agent.id)]);assert.strictEqual(new Set(ids).size, ids.length);@@@ -12,7 +12,7 @@ const { spawn } = require('child_process');const { measure, check, format } = require('openvibe-shared/perf-budget');const BUDGETS = {-- htmlRawKB: 40, // 35.7 with the Part of OpenVibe section (Shared 4.13, 2026-10-26); 31.5 with the home's quick start, OpenVibe Git and six FAQs with their FAQPage JSON-LD (2026-10-22; in production the forge's eight repositories add about 2.5); measured 27.0 (fresh database; the showcase home, 2026-09-29: sections + six inline ring icons)++ htmlRawKB: 42, // 40.4 with the ten harnesses the catalogue holds (2026-10-30: MiniMax Code and Claude Code on another provider joined it, and the home lists every one); 35.7 with the Part of OpenVibe section (Shared 4.13, 2026-10-26); 31.5 with the home's quick start, OpenVibe Git and six FAQs with their FAQPage JSON-LD (2026-10-22; in production the forge's eight repositories add about 2.5); measured 27.0 (fresh database; the showcase home, 2026-09-29: sections + six inline ring icons)htmlBrotliKB: 11, // 9.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 7.7 with those sections (2026-10-22); 6.7jsFiles: 6, // C4 adds the live task stream client to the shared theme, navbar, footer and boost scripts.jsRawKB: 317, // 315.6 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 307.8 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); 300.5 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 293 openvibe-shared 4.22.0: the navbar's magnifier search button and More dropdown (search.js and loading.js load only when used); 287.2 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 273.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 263.4 with shared 4.11.0's seasonal navbar; 254.1 with openvibe-shared 4.9.0 (status text twins in every theme, 2026-10-23); 246.2 with openvibe-shared 4.2.x (Ask Actor in the navbar, 2026-10-15); 239.1 (212.2 before openvibe-shared/shell's web-runtime.js)
@@ -15,7 +15,7 @@
@@ -15,7 +15,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
@@ -1149,9 +1149,9 @@
@@ -1149,9 +1149,9 @@
}
}
},
},
"node_modules/openvibe-contracts": {
"node_modules/openvibe-contracts": {
- "version": "0.245.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",
- "integrity": "sha512-H0L5BpMkwnKP6KDuecT16Iv9fH6o/6tDM78VFaxcAiNhj5HRsddRWuzrd2zIylkITYzmsxNkuojJUIqTwHAk9A==",
+ "version": "0.246.1",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1",
+ "integrity": "sha512-FPW+xWfwDc95j5UraDix/qMIrbEgsZ8DM67jmt50V662UtEurFij6M6jUnqKPhoMbu08QFvySZuvJ9hJy7G/iA==",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -30,7 +30,7 @@
@@ -30,7 +30,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.245.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.246.1",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.73.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.48.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
@@ -51,6 +51,58 @@
@@ -51,6 +51,58 @@
}
}
]
]
},
},
+ {
+ "id": "claude-other",
+ "name": "Claude Code (another provider)",
+ "provider": "custom",
+ "capabilities": {
+ "host_access": true,
+ "mcp": true,
+ "long_autonomy": true,
+ "resume": true,
+ "edit": true,
+ "review": true,
+ "tools": true,
+ "vision": true,
+ "browser": false,
+ "computer_use": false,
+ "runtimes": [
+ "code"
+ ]
+ },
+ "address": {
+ "kind": "cli",
+ "target": "claude"
+ },
+ "price": {
+ "amount_usd": 0,
+ "unit": "hour"
+ },
+ "limits": {
+ "max_duration_seconds": 14400,
+ "max_concurrent_runs": 4,
+ "max_context_tokens": 200000
+ },
+ "agents": [
+ {
+ "id": "claude-other-default",
+ "harness": "claude-other",
+ "provider": "custom",
+ "model": "claude-other",
+ "context_limits": {
+ "input_tokens": 200000,
+ "output_tokens": 64000
+ },
+ "concurrency": 4,
+ "price_per_1k_tokens": {
+ "fresh_usd": 0,
+ "cached_usd": 0,
+ "output_usd": 0
+ },
+ "availability_windows": []
+ }
+ ]
+ },
{
{
"id": "codex",
"id": "codex",
"name": "Codex",
"name": "Codex",
@@ -207,6 +259,58 @@
@@ -207,6 +259,58 @@
}
}
]
]
},
},
+ {
+ "id": "minimax-code",
+ "name": "MiniMax Code",
+ "provider": "minimax",
+ "capabilities": {
+ "host_access": true,
+ "mcp": false,
+ "long_autonomy": true,
+ "resume": true,
+ "edit": true,
+ "review": true,
+ "tools": true,
+ "vision": false,
+ "browser": false,
+ "computer_use": false,
+ "runtimes": [
+ "code"
+ ]
+ },
+ "address": {
+ "kind": "cli",
+ "target": "mcode"
+ },
+ "price": {
+ "amount_usd": 0,
+ "unit": "hour"
+ },
+ "limits": {
+ "max_duration_seconds": 14400,
+ "max_concurrent_runs": 4,
+ "max_context_tokens": 200000
+ },
+ "agents": [
+ {
+ "id": "minimax-code-default",
+ "harness": "minimax-code",
+ "provider": "minimax",
+ "model": "minimax-code",
+ "context_limits": {
+ "input_tokens": 200000,
+ "output_tokens": 32000
+ },
+ "concurrency": 4,
+ "price_per_1k_tokens": {
+ "fresh_usd": 0,
+ "cached_usd": 0,
+ "output_usd": 0
+ },
+ "availability_windows": []
+ }
+ ]
+ },
{
{
"id": "aider",
"id": "aider",
"name": "Aider",
"name": "Aider",
@@ -27,14 +27,14 @@ function createHarnesses({ catalogPath = DEFAULT_CATALOG } = {}) {
@@ -27,14 +27,14 @@ function createHarnesses({ catalogPath = DEFAULT_CATALOG } = {}) {
for (const [index, row] of rows.entries()) {
for (const [index, row] of rows.entries()) {
if (!row || typeof row !== 'object' || Array.isArray(row)) throw invalid(`row ${index} is not an offer`);
if (!row || typeof row !== 'object' || Array.isArray(row)) throw invalid(`row ${index} is not an offer`);
const { agents, ...offer } = row;
const { agents, ...offer } = row;
- const harnessCheck = contracts.validate('platform.harness-offer@1', offer);
+ // A row is one contract instance: the offer and the agents (models) it runs. platform.harness-offer@1
+ // carries the agents (contracts 0.246.0), so the whole row is checked against it in one go.
+ const harnessCheck = contracts.validate('platform.harness-offer@1', row);
if (!harnessCheck.valid) throw invalid(`row ${index} harness offer: ${JSON.stringify(harnessCheck.errors)}`);
if (!harnessCheck.valid) throw invalid(`row ${index} harness offer: ${JSON.stringify(harnessCheck.errors)}`);
if (ids.has(offer.id)) throw invalid(`duplicate id ${offer.id}`);
if (ids.has(offer.id)) throw invalid(`duplicate id ${offer.id}`);
ids.add(offer.id);
ids.add(offer.id);
if (!Array.isArray(agents)) throw invalid(`row ${index} needs agents[]`);
if (!Array.isArray(agents)) throw invalid(`row ${index} needs agents[]`);
- for (const [agentIndex, agent] of agents.entries()) {
- const agentCheck = contracts.validate('platform.agent-offer@1', agent);
- if (!agentCheck.valid) throw invalid(`row ${index} agent ${agentIndex}: ${JSON.stringify(agentCheck.errors)}`);
+ for (const agent of agents) {
if (ids.has(agent.id)) throw invalid(`duplicate id ${agent.id}`);
if (ids.has(agent.id)) throw invalid(`duplicate id ${agent.id}`);
if (agent.harness !== offer.id) throw invalid(`agent ${agent.id} refers to another harness`);
if (agent.harness !== offer.id) throw invalid(`agent ${agent.id} refers to another harness`);
ids.add(agent.id);
ids.add(agent.id);
@@ -23,7 +23,7 @@
@@ -23,7 +23,7 @@
const USER = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;
const USER = /^usr_[0-9A-HJKMNP-TV-Z]{26}$/;
/** The harnesses that speak Anthropic's Messages API (the rest speak OpenAI's Chat Completions). */
/** The harnesses that speak Anthropic's Messages API (the rest speak OpenAI's Chat Completions). */
-const ANTHROPIC_HARNESSES = ['claude-code'];
+const ANTHROPIC_HARNESSES = ['claude-code', 'claude-other'];
/** The claims of a JWT, decoded but not verified (the receiver verifies; this is for the jti and the expiry). */
/** The claims of a JWT, decoded but not verified (the receiver verifies; this is for the jti and the expiry). */
function claims(token) {
function claims(token) {
@@ -100,6 +100,17 @@ const router = require('../engine/router');
@@ -100,6 +100,17 @@ const router = require('../engine/router');
assert.ok(router.pick(prompt, base), 'without a map of connections the ladder is as it was');
assert.ok(router.pick(prompt, base), 'without a map of connections the ladder is as it was');
});
});
+ await check('a run on Claude Code (another provider) gets the Anthropic-shaped environment', async () => {
+ // claude-other is the same claude CLI, so it reads ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN, and the
+ // credential header names the provider the person's key is kept under (custom: their own endpoint).
+ const minted = await t.ctx.runTokens.mint({ subject: ada.subject, task: null, attempt: null, harness: 'claude-other', provider: 'custom', ownKey: true });
+ assert.ok(minted.token, 'a run token was minted');
+ assert.ok(minted.env.ANTHROPIC_BASE_URL, 'the harness gets OpenVibe.AI\'s address');
+ assert.ok(minted.env.ANTHROPIC_AUTH_TOKEN, 'and the run token');
+ assert.strictEqual(minted.env.ANTHROPIC_CUSTOM_HEADERS, 'x-openvibe-credential: custom');
+ assert.strictEqual('OPENAI_BASE_URL' in minted.env, false, 'not the OpenAI-shaped environment');
+ });
+
await check('the run token is redacted by the transcript normaliser', async () => {
await check('the run token is redacted by the transcript normaliser', async () => {
const minted = await t.ctx.runTokens.mint({ subject: ada.subject, task: null, attempt: null, harness: 'claude-code', provider: 'anthropic', ownKey: true });
const minted = await t.ctx.runTokens.mint({ subject: ada.subject, task: null, attempt: null, harness: 'claude-code', provider: 'anthropic', ownKey: true });
assert.ok(minted.token, 'a run token was minted');
assert.ok(minted.token, 'a run token was minted');
@@ -65,7 +65,7 @@ function priced(row, freshUsd) {
@@ -65,7 +65,7 @@ function priced(row, freshUsd) {
await check('every seed offer validates as platform.resource-offer@1 of kind harness', async () => {
await check('every seed offer validates as platform.resource-offer@1 of kind harness', async () => {
const harnesses = createHarnesses({ catalogPath });
const harnesses = createHarnesses({ catalogPath });
const offers = harnesses.list().flatMap((harness) => harnesses.agents(harness.id).map((agent) => [harness, toOffer(harness, agent, { now })]));
const offers = harnesses.list().flatMap((harness) => harnesses.agents(harness.id).map((agent) => [harness, toOffer(harness, agent, { now })]));
- assert.strictEqual(offers.length, 8);
+ assert.strictEqual(offers.length, 10);
for (const [harness, offer] of offers) {
for (const [harness, offer] of offers) {
const result = contracts.validate('platform.resource-offer@1', JSON.parse(JSON.stringify(offer)));
const result = contracts.validate('platform.resource-offer@1', JSON.parse(JSON.stringify(offer)));
assert.ok(result.valid, `${offer.offer_id}: ${JSON.stringify(result.errors)}`);
assert.ok(result.valid, `${offer.offer_id}: ${JSON.stringify(result.errors)}`);
@@ -130,7 +130,7 @@ function priced(row, freshUsd) {
@@ -130,7 +130,7 @@ function priced(row, freshUsd) {
const [harnessId] = r.selected.split(':');
const [harnessId] = r.selected.split(':');
assert.ok(toOffer(harnesses.get(harnessId), harnesses.agents(harnessId)[0]).capabilities.includes('task:review'));
assert.ok(toOffer(harnesses.get(harnessId), harnesses.agents(harnessId)[0]).capabilities.includes('task:review'));
assert.ok(r.reasons.length);
assert.ok(r.reasons.length);
- assert.deepStrictEqual(r.candidates.map((c) => c.id), ['claude-code:claude-code-sonnet', 'codex:codex-default', 'command-code:command-code-default', 'opencode:opencode-default', 'aider:aider-default', 'deepseek:deepseek-chat', 'openvibe-ai:openvibe-ai-router', 'openai-compatible:openai-compatible-local']);
+ assert.deepStrictEqual(r.candidates.map((c) => c.id), ['claude-code:claude-code-sonnet', 'claude-other:claude-other-default', 'codex:codex-default', 'command-code:command-code-default', 'opencode:opencode-default', 'minimax-code:minimax-code-default', 'aider:aider-default', 'deepseek:deepseek-chat', 'openvibe-ai:openvibe-ai-router', 'openai-compatible:openai-compatible-local']);
});
});
await check('an offer whose health is down is excluded with a reason', async () => {
await check('an offer whose health is down is excluded with a reason', async () => {
@@ -153,7 +153,8 @@ function priced(row, freshUsd) {
@@ -153,7 +153,8 @@ function priced(row, freshUsd) {
});
});
await check('with equal latency the cheaper eligible offer wins', async () => {
await check('with equal latency the cheaper eligible offer wins', async () => {
- const [claude, codex] = rows;
+ const claude = rows.find((row) => row.id === 'claude-code');
+ const codex = rows.find((row) => row.id === 'codex');
const harnesses = stub([priced(claude, 0.015), priced(codex, 0.003)]);
const harnesses = stub([priced(claude, 0.015), priced(codex, 0.003)]);
const opts = { 'claude-code:claude-code-sonnet': { latencyMs: 500 }, 'codex:codex-default': { latencyMs: 500 } };
const opts = { 'claude-code:claude-code-sonnet': { latencyMs: 500 }, 'codex:codex-default': { latencyMs: 500 } };
const r = route({ task: 'edit', harnesses, opts, now });
const r = route({ task: 'edit', harnesses, opts, now });
@@ -164,7 +165,8 @@ function priced(row, freshUsd) {
@@ -164,7 +165,8 @@ function priced(row, freshUsd) {
});
});
await check('a task:browse requirement excludes harnesses without it', async () => {
await check('a task:browse requirement excludes harnesses without it', async () => {
- const [claude, codex] = rows;
+ const claude = rows.find((row) => row.id === 'claude-code');
+ const codex = rows.find((row) => row.id === 'codex');
const harnesses = stub([{ ...claude, task_capabilities: ['edit', 'review', 'browse'] }, codex]);
const harnesses = stub([{ ...claude, task_capabilities: ['edit', 'review', 'browse'] }, codex]);
const r = route({ task: 'edit', extra: { capabilities: ['task:browse'] }, harnesses, now });
const r = route({ task: 'edit', extra: { capabilities: ['task:browse'] }, harnesses, now });
assert.strictEqual(r.selected, 'claude-code:claude-code-sonnet');
assert.strictEqual(r.selected, 'claude-code:claude-code-sonnet');
@@ -40,6 +40,19 @@ const rows = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'server', 'da
@@ -40,6 +40,19 @@ const rows = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'server', 'da
assert.ok(body.candidates.some((c) => c.id === body.selected && c.included === true));
assert.ok(body.candidates.some((c) => c.id === body.selected && c.included === true));
});
});
+ await check('the router can select each of the harnesses the engine adapters added', async () => {
+ // minimax-code and claude-other: the two adapters Codes' engine gained (C5) that the catalogue lacked.
+ for (const id of ['minimax-code:minimax-code-default', 'claude-other:claude-other-default']) {
+ const r = await post({ task: 'edit', requirements: { objective: 'correctness', authority: id } });
+ assert.strictEqual(r.status, 200, r.text.slice(0, 300));
+ const body = r.json();
+ const candidate = body.candidates.find((c) => c.id === id);
+ assert.ok(candidate, `${id} is a candidate`);
+ assert.strictEqual(candidate.included, true, `${id} can take the task`);
+ assert.strictEqual(body.selected, id, `the router selects ${id}`);
+ }
+ });
+
await check('a bad body is 422 harness.invalid', async () => {
await check('a bad body is 422 harness.invalid', async () => {
for (const json of [{}, { task: '' }, { task: 7 }, { task: 'review', requirements: 'x' }, { task: 'review', requirements: [] }, { task: 'review', requirements: { capabilities: 5 } }]) {
for (const json of [{}, { task: '' }, { task: 7 }, { task: 'review', requirements: 'x' }, { task: 'review', requirements: [] }, { task: 'review', requirements: { capabilities: 5 } }]) {
const r = await post(json);
const r = await post(json);
@@ -13,10 +13,12 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
@@ -13,10 +13,12 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
(async () => {
(async () => {
await check('every seed row matches the pinned harness and agent contracts', async () => {
await check('every seed row matches the pinned harness and agent contracts', async () => {
- assert.strictEqual(rows.length, 8);
- for (const { agents, ...offer } of rows) {
- const harnessCheck = contracts.validate('platform.harness-offer@1', offer);
+ assert.strictEqual(rows.length, 10);
+ for (const row of rows) {
+ // The row is one contract instance: the offer and the agents (models) it runs.
+ const harnessCheck = contracts.validate('platform.harness-offer@1', row);
assert.strictEqual(harnessCheck.valid, true, JSON.stringify(harnessCheck.errors));
assert.strictEqual(harnessCheck.valid, true, JSON.stringify(harnessCheck.errors));
+ const { agents, ...offer } = row;
assert.ok(Array.isArray(agents));
assert.ok(Array.isArray(agents));
for (const agent of agents) {
for (const agent of agents) {
const agentCheck = contracts.validate('platform.agent-offer@1', agent);
const agentCheck = contracts.validate('platform.agent-offer@1', agent);
@@ -26,6 +28,32 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
@@ -26,6 +28,32 @@ const rows = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
}
}
});
});
+ await check('the two engine adapters Codes gained are in the catalogue', async () => {
+ // engine/adapters/minimax-code.js and engine/adapters/claude-code.js (the claude-other one).
+ const minimax = rows.find((row) => row.id === 'minimax-code');
+ assert.ok(minimax, 'the catalogue has minimax-code');
+ assert.strictEqual(minimax.name, 'MiniMax Code');
+ assert.strictEqual(minimax.address.kind, 'cli');
+ assert.strictEqual(minimax.address.target, 'mcode');
+ assert.ok(minimax.agents.length > 0, 'minimax-code runs at least one model');
+ const other = rows.find((row) => row.id === 'claude-other');
+ assert.ok(other, 'the catalogue has claude-other');
+ assert.strictEqual(other.name, 'Claude Code (another provider)');
+ assert.strictEqual(other.address.kind, 'cli');
+ assert.strictEqual(other.address.target, 'claude');
+ assert.ok(other.agents.length > 0, 'claude-other runs at least one model');
+ for (const row of [minimax, other]) {
+ assert.strictEqual(row.agents.every((agent) => agent.harness === row.id), true);
+ }
+ });
+
+ await check('every engine adapter has a catalogue row, so the router can select it', async () => {
+ const { ids: adapterIds } = require('../engine/adapters');
+ for (const id of adapterIds()) {
+ assert.ok(rows.some((row) => row.id === id), `the catalogue has ${id}`);
+ }
+ });
+
await check('harness and agent ids are unique', async () => {
await check('harness and agent ids are unique', async () => {
const ids = rows.flatMap((row) => [row.id, ...row.agents.map((agent) => agent.id)]);
const ids = rows.flatMap((row) => [row.id, ...row.agents.map((agent) => agent.id)]);
assert.strictEqual(new Set(ids).size, ids.length);
assert.strictEqual(new Set(ids).size, ids.length);
@@ -12,7 +12,7 @@ const { spawn } = require('child_process');
@@ -12,7 +12,7 @@ const { spawn } = require('child_process');
const { measure, check, format } = require('openvibe-shared/perf-budget');
const { measure, check, format } = require('openvibe-shared/perf-budget');
const BUDGETS = {
const BUDGETS = {
- htmlRawKB: 40, // 35.7 with the Part of OpenVibe section (Shared 4.13, 2026-10-26); 31.5 with the home's quick start, OpenVibe Git and six FAQs with their FAQPage JSON-LD (2026-10-22; in production the forge's eight repositories add about 2.5); measured 27.0 (fresh database; the showcase home, 2026-09-29: sections + six inline ring icons)
+ htmlRawKB: 42, // 40.4 with the ten harnesses the catalogue holds (2026-10-30: MiniMax Code and Claude Code on another provider joined it, and the home lists every one); 35.7 with the Part of OpenVibe section (Shared 4.13, 2026-10-26); 31.5 with the home's quick start, OpenVibe Git and six FAQs with their FAQPage JSON-LD (2026-10-22; in production the forge's eight repositories add about 2.5); measured 27.0 (fresh database; the showcase home, 2026-09-29: sections + six inline ring icons)
htmlBrotliKB: 11, // 9.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 7.7 with those sections (2026-10-22); 6.7
htmlBrotliKB: 11, // 9.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 7.7 with those sections (2026-10-22); 6.7
jsFiles: 6, // C4 adds the live task stream client to the shared theme, navbar, footer and boost scripts.
jsFiles: 6, // C4 adds the live task stream client to the shared theme, navbar, footer and boost scripts.
jsRawKB: 317, // 315.6 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 307.8 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); 300.5 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 293 openvibe-shared 4.22.0: the navbar's magnifier search button and More dropdown (search.js and loading.js load only when used); 287.2 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 273.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 263.4 with shared 4.11.0's seasonal navbar; 254.1 with openvibe-shared 4.9.0 (status text twins in every theme, 2026-10-23); 246.2 with openvibe-shared 4.2.x (Ask Actor in the navbar, 2026-10-15); 239.1 (212.2 before openvibe-shared/shell's web-runtime.js)
jsRawKB: 317, // 315.6 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 307.8 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); 300.5 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 293 openvibe-shared 4.22.0: the navbar's magnifier search button and More dropdown (search.js and loading.js load only when used); 287.2 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 273.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 263.4 with shared 4.11.0's seasonal navbar; 254.1 with openvibe-shared 4.9.0 (status text twins in every theme, 2026-10-23); 246.2 with openvibe-shared 4.2.x (Ask Actor in the navbar, 2026-10-15); 239.1 (212.2 before openvibe-shared/shell's web-runtime.js)