Source of truth for container runtime config moves from
groups/<folder>/container.json to a new container_configs table.
The file becomes a materialized view written at spawn time.
- New container_configs table with scalar columns (provider, model,
effort, image_tag, assistant_name, max_messages_per_prompt) and
JSON columns (mcp_servers, packages_apt, packages_npm, skills,
additional_mounts)
- Startup backfill seeds DB from existing container.json files
- materializeContainerJson() replaces readContainerConfig + ensureRuntimeFields
- Self-mod handlers (install_packages, add_mcp_server) write to DB
- Provider cascade simplified: session -> container_configs -> 'claude'
- ncl groups config-{get,update,add-mcp-server,remove-mcp-server,
add-package,remove-package} custom operations
- restartAgentGroupContainers() helper for config change propagation
- Container side unchanged (still reads /workspace/agent/container.json)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
28 lines
920 B
TypeScript
28 lines
920 B
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { resolveProviderName } from './container-runner.js';
|
|
|
|
describe('resolveProviderName', () => {
|
|
it('prefers session over container config', () => {
|
|
expect(resolveProviderName('codex', 'claude')).toBe('codex');
|
|
});
|
|
|
|
it('falls back to container config when session is null', () => {
|
|
expect(resolveProviderName(null, 'opencode')).toBe('opencode');
|
|
});
|
|
|
|
it('defaults to claude when nothing is set', () => {
|
|
expect(resolveProviderName(null, undefined)).toBe('claude');
|
|
});
|
|
|
|
it('lowercases the resolved name', () => {
|
|
expect(resolveProviderName('CODEX', null)).toBe('codex');
|
|
expect(resolveProviderName(null, 'Claude')).toBe('claude');
|
|
});
|
|
|
|
it('treats empty string as unset (falls through)', () => {
|
|
expect(resolveProviderName('', 'opencode')).toBe('opencode');
|
|
expect(resolveProviderName(null, '')).toBe('claude');
|
|
});
|
|
});
|