blob: dd17dec549e161ddb7068e684e8d943f88cf8903 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { RuntimeHostProtocolError } from '../protocol/errors.js';
import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { decodeClientFrame, decodeHostFrame } from '../protocol/index.js';
const EXPECTED = {
connectionId: '00000000-0000-4000-8000-000000000001',
revision: 1,
};
describe('Runtime Host connection effects protocol', () => {
test('bounds transient onboarding secrets, models, and save selections', () => {
const verify = request('connection.onboarding.verify', {
target: { kind: 'create', providerType: 'openrouter' },
apiKey: 'transient-secret',
baseUrl: null,
});
const save = request('connection.onboarding.save', {
target: {
kind: 'existing',
connectionId: '00000000-0000-4000-8000-000000000002',
},
apiKey: 'transient-secret',
baseUrl: 'https://relay.example.test/v1',
enabledModelIds: ['relay/model'],
});
assert.deepEqual(decodeClientFrame(verify), verify);
assert.deepEqual(decodeClientFrame(save), save);
assert.deepEqual(
decodeHostFrame(
response('connection.onboarding.verify', {
kind: 'verified',
models: [{ id: 'openrouter/free', contextWindow: 128_000 }],
}),
),
response('connection.onboarding.verify', {
kind: 'verified',
models: [{ id: 'openrouter/free', contextWindow: 128_000 }],
}),
);
assert.deepEqual(
decodeHostFrame(
response('connection.onboarding.save', {
kind: 'saved',
connection: {
connectionId: '00000000-0000-4000-8000-000000000002',
revision: 2,
slug: 'relay-2',
providerType: 'openai-compatible',
},
}),
),
response('connection.onboarding.save', {
kind: 'saved',
connection: {
connectionId: '00000000-0000-4000-8000-000000000002',
revision: 2,
slug: 'relay-2',
providerType: 'openai-compatible',
},
}),
);
// A save whose discovery basis was concurrently changed is superseded.
assert.deepEqual(
decodeHostFrame(
response('connection.onboarding.save', { kind: 'rejected', reason: 'superseded' }),
),
response('connection.onboarding.save', { kind: 'rejected', reason: 'superseded' }),
);
const adoptAllDiscovered = request('connection.onboarding.save', {
target: { kind: 'create', providerType: 'openrouter' },
apiKey: 'transient-secret',
baseUrl: null,
enabledModelIds: [],
});
assert.deepEqual(decodeClientFrame(adoptAllDiscovered), adoptAllDiscovered);
// Provider-specific URL semantics are resolved after an existing target's
// canonical provider is loaded; the wire still bounds the raw value.
assertInvalidRequest('connection.onboarding.verify', {
target: { kind: 'create', providerType: 'openai-compatible' },
apiKey: 'transient-secret',
baseUrl: 'x'.repeat(2_049),
});
assertInvalidRequest('connection.onboarding.verify', {
providerType: 'openai-compatible',
connectionId: null,
apiKey: 'transient-secret',
baseUrl: null,
});
assertInvalidRequest('connection.onboarding.verify', {
target: {
kind: 'existing',
connectionId: 42,
},
apiKey: 'transient-secret',
baseUrl: null,
});
// A create target may carry a caller-chosen slug/name (#4605); both
// decode through the same catalog codecs as the rest of the wire.
const namedVerify = request('connection.onboarding.verify', {
target: { kind: 'create', providerType: 'openrouter', slug: 'openrouter-work', name: 'Work' },
apiKey: 'transient-secret',
baseUrl: null,
});
assert.deepEqual(decodeClientFrame(namedVerify), namedVerify);
// …but a malformed requested slug fails decode like any other bad input.
assertInvalidRequest('connection.onboarding.verify', {
target: { kind: 'create', providerType: 'openrouter', slug: 'NOT A SLUG' },
apiKey: 'transient-secret',
baseUrl: null,
});
// …and the create target stays closed to fields it does not define.
assertInvalidRequest('connection.onboarding.verify', {
target: { kind: 'create', providerType: 'openai-compatible', slug2: 'surface-owned' },
apiKey: 'transient-secret',
baseUrl: null,
});
// slug_taken is the create target's collision answer, on both halves.
assert.deepEqual(
decodeHostFrame(
response('connection.onboarding.verify', { kind: 'rejected', reason: 'slug_taken' }),
),
response('connection.onboarding.verify', { kind: 'rejected', reason: 'slug_taken' }),
);
assert.deepEqual(
decodeHostFrame(
response('connection.onboarding.save', { kind: 'rejected', reason: 'slug_taken' }),
),
response('connection.onboarding.save', { kind: 'rejected', reason: 'slug_taken' }),
);
assertInvalidResponse('connection.onboarding.verify', {
kind: 'verified',
models: [],
});
assertInvalidResponse('connection.onboarding.save', {
kind: 'failed',
errorClass: 'auth',
secret: 'forbidden',
});
assertInvalidResponse('connection.onboarding.save', {
kind: 'saved',
connection: {
connectionId: '00000000-0000-4000-8000-000000000002',
revision: 0,
slug: 'relay-2',
providerType: 'openai-compatible',
},
});
});
test('requires a stable connection identity and an explicit nullable test model', () => {
const fetch = request('connection.models.fetch', { connectionId: EXPECTED.connectionId });
const connectionTest = request('connection.test.run', {
connectionId: EXPECTED.connectionId,
modelId: 'model-1',
});
const defaultModelTest = request('connection.test.run', {
connectionId: EXPECTED.connectionId,
modelId: null,
});
assert.deepEqual(decodeClientFrame(fetch), fetch);
assert.deepEqual(decodeClientFrame(connectionTest), connectionTest);
assert.deepEqual(decodeClientFrame(defaultModelTest), defaultModelTest);
assertInvalidRequest('connection.models.fetch', {
connectionId: EXPECTED.connectionId,
secret: 'forbidden',
});
assertInvalidRequest('connection.test.run', { connectionId: EXPECTED.connectionId });
assertInvalidRequest('connection.test.run', {
connectionId: EXPECTED.connectionId,
modelId: 'x'.repeat(1_025),
});
});
test('accepts bounded model summaries and rejects model arrays or raw failures', () => {
const committedResult = {
kind: 'committed',
catalogRevision: 2,
connection: { ...EXPECTED, revision: 2 },
modelCount: 2_048,
source: 'fetched',
fetchedAt: 1_000,
};
const committed = response('connection.models.fetch', committedResult);
assert.deepEqual(decodeHostFrame(committed), committed);
for (const result of [
{ kind: 'failed', errorClass: 'timeout' },
{ kind: 'rejected', reason: 'credential_not_configured' },
{ kind: 'superseded', changed: ['credential', 'network_proxy'] },
]) {
const frame = response('connection.models.fetch', result);
assert.deepEqual(decodeHostFrame(frame), frame);
}
assertInvalidResponse('connection.models.fetch', {
...committedResult,
models: [{ id: 'secret-model-list' }],
});
assertInvalidResponse('connection.models.fetch', {
kind: 'failed',
errorClass: 'network',
message: 'raw provider response',
});
assertInvalidResponse('connection.models.fetch', {
kind: 'superseded',
changed: ['credential', 'credential'],
});
});
test('keeps one exact and bounded connection test projection', () => {
const verified = response('connection.test.run', {
kind: 'committed',
catalogRevision: 2,
connection: { ...EXPECTED, revision: 2 },
test: {
kind: 'verified',
checkedAt: '2026-07-29T00:00:00.000Z',
modelId: 'model-1',
latencyMs: 42,
},
});
const failedResult = {
kind: 'committed',
catalogRevision: 2,
connection: { ...EXPECTED, revision: 2 },
test: {
kind: 'failed',
checkedAt: '2026-07-29T00:00:00.000Z',
modelId: 'model-1',
latencyMs: 42,
statusCode: 401,
errorClass: 'auth',
},
};
const failed = response('connection.test.run', failedResult);
const invalidResponse = response('connection.test.run', {
...failedResult,
test: {
...failedResult.test,
statusCode: null,
errorClass: 'invalid_response',
},
});
assert.deepEqual(decodeHostFrame(verified), verified);
assert.deepEqual(decodeHostFrame(failed), failed);
assert.deepEqual(decodeHostFrame(invalidResponse), invalidResponse);
assertInvalidResponse('connection.test.run', {
...failedResult,
summary: {
status: 'needs_reauth',
checkedAt: '2026-07-29T00:00:00.000Z',
errorClass: 'auth',
},
});
assertInvalidResponse('connection.test.run', {
...failedResult,
test: { ...failedResult.test, providerBody: 'secret response' },
});
assertInvalidResponse('connection.test.run', {
...failedResult,
test: { ...failedResult.test, modelId: 'x'.repeat(1_025) },
});
assertInvalidResponse('connection.test.run', {
...failedResult,
test: { ...failedResult.test, statusCode: 600 },
});
});
});
function request(operation: string, input: unknown) {
return { requestId: 'request-1', operation, input };
}
function response(operation: string, result: unknown) {
return { requestId: 'request-1', operation, ok: true, result };
}
function assertInvalidRequest(operation: string, input: unknown): void {
assert.throws(() => decodeClientFrame(request(operation, input)), isInvalidFrame);
}
function assertInvalidResponse(operation: string, result: unknown): void {
assert.throws(() => decodeHostFrame(response(operation, result)), isInvalidFrame);
}
function isInvalidFrame(error: unknown): boolean {
return error instanceof RuntimeHostProtocolError && error.code === 'invalid_frame';
}