import { test } from 'node:test' import assert from 'node:assert/strict' import fs from 'node:fs' import os from 'node:os' import path from 'node:path' import { buildKiloArgs, detectRuntime, resolveRuntime } from '../src/kilocode.mjs' import { buildGuardConfigContent, guardEnv, RUNTIME_PROFILES } from '../src/guard.mjs' function tmpProject() { return fs.mkdtempSync(path.join(os.tmpdir(), 'kilo-runtime-')) } test('detectRuntime picks opencode from the binary name', () => { assert.equal(detectRuntime('/usr/local/bin/opencode'), 'opencode') assert.equal(detectRuntime('opencode'), 'opencode') assert.equal(detectRuntime('/x/@kilocode/cli/bin/kilo'), 'kilo') assert.equal(detectRuntime('kilo'), 'kilo') }) test('resolveRuntime honours an explicit runtime over auto-detection', () => { assert.equal(resolveRuntime({ runtime: 'auto' }, '/usr/bin/opencode'), 'opencode') assert.equal(resolveRuntime({ runtime: 'kilo' }, '/usr/bin/opencode'), 'kilo') assert.equal(resolveRuntime({ runtime: 'opencode' }, 'kilo'), 'opencode') assert.equal(resolveRuntime({}, 'kilo'), 'kilo') }) test('buildKiloArgs uses the runtime auto-approval flag', () => { const kilo = buildKiloArgs({ auto: true, prompt: 'x' }) assert.ok(kilo.includes('--auto')) assert.ok(!kilo.includes('--dangerously-skip-permissions')) const oc = buildKiloArgs({ auto: true, autoFlag: '--dangerously-skip-permissions', prompt: 'x' }) assert.ok(oc.includes('--dangerously-skip-permissions')) assert.ok(!oc.includes('--auto')) }) test('buildGuardConfigContent reads the runtime config file and denies destructive globs', () => { const project = tmpProject() fs.writeFileSync(path.join(project, 'opencode.json'), JSON.stringify({ permission: { glob: 'allow' } })) const content = buildGuardConfigContent(project, 'opencode') const parsed = JSON.parse(content) assert.equal(parsed.permission.bash['*git commit*'], 'deny') // A kilo config file is ignored when the runtime is opencode. fs.writeFileSync(path.join(project, 'kilo.json'), JSON.stringify({ permission: { bash: 'allow' } })) assert.ok(buildGuardConfigContent(project, 'opencode')) }) test('guardEnv targets the runtime-specific env var', () => { const project = tmpProject() fs.writeFileSync(path.join(project, 'opencode.json'), JSON.stringify({ permission: {} })) const oc = guardEnv(project, { PATH: '/bin' }, { runtime: 'opencode' }) assert.equal(oc.preExecution, true) assert.ok(oc.env[RUNTIME_PROFILES.opencode.env]) assert.equal(oc.env[RUNTIME_PROFILES.kilo.env], undefined) const kilo = guardEnv(project, { PATH: '/bin' }, { runtime: 'kilo' }) assert.equal(kilo.preExecution, true) assert.ok(kilo.env[RUNTIME_PROFILES.kilo.env]) assert.equal(kilo.env[RUNTIME_PROFILES.opencode.env], undefined) })