96 lines
6.4 KiB
JavaScript
96 lines
6.4 KiB
JavaScript
// Row 125 (#1619, REQ-LIMIT-3, REQ-LIMIT-4): the runtime wires the limit checks. The limits verb
|
|
// carries each token limit's count, a reset moves since and the count follows, and the host's
|
|
// mayLaunch asks the shipped token-limit through the real loader.
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, rmSync, mkdirSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
|
|
const SINCE = '2026-10-18T07:00:00.000Z';
|
|
const CODER = ['tokens', 'instances', 'coder'];
|
|
|
|
async function setup(t, plugins, limit = 0) {
|
|
const { startBroker } = await import('../src/runtime.mjs');
|
|
const { businessDoc, rolesCopy, systemFor, writeJson } = await import('../../organization/tests/helpers.mjs');
|
|
const root = mkdtempSync(join(tmpdir(), 'mosaic-limits-tokens-')), rolesDir = rolesCopy(root), doc = businessDoc(root, 'demo');
|
|
doc.plugins = { 'limit-check': plugins, harness: ['pi'] };
|
|
doc.launch.limits = { ...doc.launch.limits, tokens: { instances: { coder: { limit, since: SINCE } } } };
|
|
writeJson(join(root, 'businesses/demo.json'), doc);
|
|
mkdirSync(join(root, 'data'), { mode: 0o700 });
|
|
const bus = await startBroker({ dataRoot: join(root, 'data'),
|
|
businesses: { demo: { id: 'demo', human: 'jason', arbiters: { technical: 'chief', delivery: 'chief' },
|
|
roles: {chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } }, coder: { definition: 'coder', authority: { withinRole: [], crossRole: [] } } }, definitions: { coder: {} }, projects: { stack: { root: '/nonexistent' } } } },
|
|
organization: { dir: root, rolesDir, system: systemFor(root) } });
|
|
t.after(async () => { await bus.close(); rmSync(root, { recursive: true, force: true }); });
|
|
return { bus, human: bus.broker.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true }) };
|
|
}
|
|
|
|
test('REQ-LIMIT-3 REQ-LIMIT-4 runtime: limits carries the token count, mayLaunch refuses at the limit, a reset moves since', async t => {
|
|
const { bus, human } = await setup(t, ['token-limit']);
|
|
const view = bus.broker.request(human, { verb: 'limits' });
|
|
assert.equal(view.tokens.length, 1);
|
|
assert.deepEqual({ ...view.tokens[0], count: Number(view.tokens[0].count) },
|
|
{ path: CODER, limit: 0, since: SINCE, status: 'counted', check: 'token-limit', count: 0,
|
|
kinds: view.tokens[0].kinds, unknownTurns: 0 });
|
|
assert.deepEqual(await bus.mayLaunch({ business: 'demo', instance: 'coder', provider: 'zai', model: 'glm-5.3-flash' }),
|
|
{ allow: false, check: 'token-limit', hit: { path: CODER, limit: 0, count: view.tokens[0].count, unknownTurns: 0 } });
|
|
// An instance with no limit launches.
|
|
assert.deepEqual(await bus.mayLaunch({ business: 'demo', instance: 'reviewer', provider: 'zai', model: 'glm-5.3-flash' }), { allow: true });
|
|
const done = bus.broker.request(human, { verb: 'limits.set', args: { revision: view.revision, reset: [CODER] } });
|
|
assert.ok(done.tokens[0].since > SINCE, done.tokens[0].since);
|
|
assert.equal(done.tokens[0].status, 'counted');
|
|
});
|
|
|
|
test('REQ-LIMIT-3 runtime: with no limit check switched on, the limit shows not enforced and every launch is allowed', async t => {
|
|
const { bus, human } = await setup(t, []);
|
|
assert.deepEqual(bus.broker.request(human, { verb: 'limits' }).tokens,
|
|
[{ path: CODER, limit: 0, since: SINCE, status: 'not-enforced', reason: null }]);
|
|
assert.deepEqual(await bus.mayLaunch({ business: 'demo', instance: 'coder', provider: 'zai', model: 'glm-5.3-flash' }), { allow: true });
|
|
});
|
|
|
|
test('REQ-LIMIT-4 runtime: the broker asks the shipped token-limit after a turn, and the run at its limit stops on its next receive', async t => {
|
|
const { bus, human } = await setup(t, ['token-limit']);
|
|
const { broker } = bus;
|
|
const coder = broker.bindLaunch({ business: 'demo', role: 'coder', run: 'run1', harness: 'pi', provider: 'zai', model: 'glm-5.3-flash' });
|
|
broker.request(coder, { verb: 'role.claim' });
|
|
const { id } = broker.request(human, { verb: 'message.send', args: { to: 'coder', body: 'work' } });
|
|
broker.request(coder, { verb: 'message.receive' });
|
|
await broker.request(coder, { verb: 'usage.begin', args: { turn: id } });
|
|
await broker.request(coder, { verb: 'usage.end', args: { turn: id } });
|
|
assert.throws(() => broker.request(coder, { verb: 'message.receive' }), { code: 'not-holder' });
|
|
// endLaunch reads the reason from the claim row the stop wrote with by='limit-check'.
|
|
assert.deepEqual(bus.endLaunch({ business: 'demo', run: 'run1', reason: 'exited', exitCode: 22 }),
|
|
{ released: false, limit: 'limit: token-limit tokens.instances.coder limit 0 count 0' });
|
|
});
|
|
|
|
test('REQ-LIMIT-4 runtime: with no usage source a turn is unknown, counts zero and stops nothing under a limit of 1', async t => {
|
|
const { bus, human } = await setup(t, ['token-limit'], 1);
|
|
const { broker } = bus;
|
|
const coder = broker.bindLaunch({ business: 'demo', role: 'coder', run: 'run1', harness: 'pi', provider: 'zai', model: 'glm-5.3-flash' });
|
|
broker.request(coder, { verb: 'role.claim' });
|
|
const { id } = broker.request(human, { verb: 'message.send', args: { to: 'coder', body: 'work' } });
|
|
broker.request(coder, { verb: 'message.receive' });
|
|
await broker.request(coder, { verb: 'usage.begin', args: { turn: id } });
|
|
await broker.request(coder, { verb: 'usage.end', args: { turn: id } });
|
|
broker.request(coder, { verb: 'message.receive' });
|
|
const [row] = broker.request(human, { verb: 'limits' }).tokens;
|
|
assert.deepEqual({ count: row.count, unknownTurns: row.unknownTurns, status: row.status }, { count: 0, unknownTurns: 1, status: 'counted' });
|
|
assert.deepEqual(await bus.mayLaunch({ business: 'demo', instance: 'coder', provider: 'zai', model: 'glm-5.3-flash' }), { allow: true });
|
|
});
|
|
|
|
test('REQ-LIMIT-3 runtime: switching a limit check on with plugins.set loads it without a launch or a turn', async t => {
|
|
const { bus, human } = await setup(t, []);
|
|
const { revision } = bus.broker.request(human, { verb: 'plugins' });
|
|
bus.broker.request(human, { verb: 'plugins.set', args: { revision, plugins: { 'limit-check': ['token-limit'] } } });
|
|
let row;
|
|
for (let i = 0; i < 100; i++) {
|
|
[row] = bus.broker.request(human, { verb: 'limits' }).tokens;
|
|
if (row.status === 'counted') break;
|
|
await delay(20);
|
|
}
|
|
assert.equal(row.status, 'counted', JSON.stringify(row));
|
|
assert.equal(row.check, 'token-limit');
|
|
});
|