Files
shiro-neko/test/agents.test.ts
T
Muhammad Zakir Ramadhan 5b8503fcd9 Initial commit: shiro-neko 0.1.0-beta.1
Agentic coding CLI on Bun, Ink, and the AI SDK.

Core: streamText loop with SDK-level tool approval so a denied call provably never executes; endpoint fallback for OpenAI reasoning models; retry with backoff.

Tools: read/write/edit/glob/grep/bash, path-jailed, gitignore-aware, ripgrep with a JS fallback, binary rejection, live bash streaming.

Agents: five variants crossing thinking level with tool restriction; plan and review withhold mutating tools from the model.

Extensibility: frontmatter skills with on-demand bodies, plugin host with blocking hooks, MCP stdio and HTTP, read-only subagents.

State: durable per-project memory, session task lists, session persistence, compaction that repairs provider-item dependencies.

Distribution: five-platform cross-compiled binaries with checksums, install scripts, CI on three operating systems.

404 tests, typecheck clean.
2026-09-02 17:30:18 +07:00

94 lines
3.4 KiB
TypeScript

import { expect, test } from 'bun:test';
import { DEFAULT_VARIANT, isThinkingLevel, renderAgent, resolveAgent, sdkReasoning, THINKING_LEVELS, VARIANTS, variantByName } from '../src/agents';
test('every variant has a name, summary, and thinking level', () => {
for (const v of VARIANTS) {
expect(v.name).toBeTruthy();
expect(v.summary).toBeTruthy();
expect(THINKING_LEVELS).toContain(v.thinking);
}
});
test('variant names are unique', () => {
const names = VARIANTS.map((v) => v.name);
expect(new Set(names).size).toBe(names.length);
});
test('thinking levels map to the SDK vocabulary', () => {
expect(sdkReasoning('off')).toBe('none');
expect(sdkReasoning('low')).toBe('low');
expect(sdkReasoning('medium')).toBe('medium');
expect(sdkReasoning('high')).toBe('high');
expect(sdkReasoning('max')).toBe('xhigh');
});
test('isThinkingLevel accepts the five levels and nothing else', () => {
for (const l of THINKING_LEVELS) expect(isThinkingLevel(l)).toBe(true);
expect(isThinkingLevel('ultra')).toBe(false);
expect(isThinkingLevel('')).toBe(false);
});
test('the default variant is balanced and unrestricted', () => {
expect(DEFAULT_VARIANT.name).toBe('default');
expect(DEFAULT_VARIANT.thinking).toBe('medium');
expect(DEFAULT_VARIANT.allowTools).toBeUndefined();
});
test('quick spends no thinking budget and caps steps', () => {
const quick = variantByName('quick')!;
expect(quick.thinking).toBe('off');
expect(quick.maxSteps).toBeLessThan(20);
});
test('deep asks for maximum thinking and allows more steps', () => {
const deep = variantByName('deep')!;
expect(deep.thinking).toBe('max');
expect(deep.maxSteps).toBeGreaterThan(50);
});
test('plan and review are read-only: no write, edit, or bash', () => {
for (const name of ['plan', 'review']) {
const v = variantByName(name)!;
expect(v.allowTools).toBeDefined();
expect(v.allowTools).not.toContain('write_file');
expect(v.allowTools).not.toContain('edit_file');
expect(v.allowTools).not.toContain('bash');
expect(v.allowTools).toContain('read_file');
expect(v.allowTools).toContain('grep');
}
});
test('resolveAgent with no arguments yields the default', () => {
expect(resolveAgent(undefined, undefined).name).toBe('default');
});
test('resolveAgent looks a variant up by name', () => {
expect(resolveAgent('deep', undefined).name).toBe('deep');
});
test('an explicit thinking level overrides the variant default', () => {
const v = resolveAgent('deep', 'low');
expect(v.name).toBe('deep');
expect(v.thinking).toBe('low');
// The override must not mutate the shared preset.
expect(variantByName('deep')!.thinking).toBe('max');
});
test('an unknown agent name is rejected with the available list', () => {
expect(() => resolveAgent('turbo', undefined)).toThrow(/Unknown agent "turbo"/);
expect(() => resolveAgent('turbo', undefined)).toThrow(/default/);
});
test('an unknown thinking level is rejected', () => {
expect(() => resolveAgent('deep', 'ludicrous')).toThrow(/Unknown thinking level/);
});
test('renderAgent emits nothing for the default so the prompt stays clean', () => {
expect(renderAgent(DEFAULT_VARIANT)).toBe('');
});
test('renderAgent emits the appendix for a shaped variant', () => {
expect(renderAgent(variantByName('plan')!)).toContain('planning mode');
expect(renderAgent(variantByName('review')!)).toContain('reviewing code');
});