feat: integrate 5 feature branches + daemon/job 命令层级化 + 跨平台后台引擎 + TypeScript 错误修复

Squashed merge of:
1. fix/mcp-tsc-errors — 修复上游 MCP 重构后的 tsc 错误和测试失败
2. feat/pipe-mute-disconnect — Pipe IPC 逻辑断开、/lang 命令、mute 状态机
3. feat/stub-recovery-all — 实现全部 stub 恢复 (task 001-012)
4. feat/kairos-activation — KAIROS 激活解除阻塞 + 工具实现
5. codex/openclaw-autonomy-pr — 自治权限系统、运行记录、managed flows

Additional:
6. daemon/job 命令层级化重构 (subcommand 架构)
7. 跨平台后台引擎抽象 (detached/tmux engines)
8. 修复 src/ 中 43 个预存在的 TypeScript 类型错误
9. 修复 langfuse isolated test mock 完整性
10. 修复 CodeRabbit 审查的 Critical/Major/Minor 问题
11. remote-control-server logger 抽象 (测试 stderr 静默化)
12. /simplify 审查修复 (代码复用、质量、效率)
This commit is contained in:
unraid
2026-04-14 14:19:00 +08:00
parent dad3ad2b8d
commit 637c9081f6
123 changed files with 13536 additions and 1887 deletions

View File

@@ -1,99 +1,100 @@
import { describe, expect, test } from "bun:test";
import { Command } from "@commander-js/extra-typings";
import { describe, expect, test } from 'bun:test'
import { Command } from '@commander-js/extra-typings'
// Test Commander.js option parsing independently from main.tsx initialization.
// main.tsx has heavy bootstrap dependencies; we test the CLI argument parsing
// patterns it uses to ensure correct behavior.
function createTestProgram(): Command {
const program = new Command();
const program = new Command()
program
.name("claude-code")
.description("CLI test")
.name('claude-code')
.description('CLI test')
.exitOverride() // prevent process.exit during tests
.option("-p, --print", "pipe mode")
.option("--resume", "resume session")
.option("-v, --verbose", "verbose output")
.option("--model <model>", "model to use")
.option("--system-prompt <prompt>", "system prompt")
.option("--allowedTools <tools...>", "allowed tools")
.option("--max-turns <n>", "max conversation turns", parseInt)
.version("1.0.0", "-V, --version", "display version");
return program;
.configureOutput({ writeErr: () => {}, writeOut: () => {} })
.option('-p, --print', 'pipe mode')
.option('--resume', 'resume session')
.option('-v, --verbose', 'verbose output')
.option('--model <model>', 'model to use')
.option('--system-prompt <prompt>', 'system prompt')
.option('--allowedTools <tools...>', 'allowed tools')
.option('--max-turns <n>', 'max conversation turns', parseInt)
.version('1.0.0', '-V, --version', 'display version')
return program
}
describe("CLI arguments: option parsing", () => {
test("no flags returns empty opts", () => {
const program = createTestProgram();
program.parse(["node", "test"]);
expect(program.opts()).toEqual({});
});
describe('CLI arguments: option parsing', () => {
test('no flags returns empty opts', () => {
const program = createTestProgram()
program.parse(['node', 'test'])
expect(program.opts()).toEqual({})
})
test("-p sets print flag", () => {
const program = createTestProgram();
program.parse(["node", "test", "-p"]);
expect(program.opts().print).toBe(true);
});
test('-p sets print flag', () => {
const program = createTestProgram()
program.parse(['node', 'test', '-p'])
expect(program.opts().print).toBe(true)
})
test("--print is equivalent to -p", () => {
const program = createTestProgram();
program.parse(["node", "test", "--print"]);
expect(program.opts().print).toBe(true);
});
test('--print is equivalent to -p', () => {
const program = createTestProgram()
program.parse(['node', 'test', '--print'])
expect(program.opts().print).toBe(true)
})
test("--resume sets resume flag", () => {
const program = createTestProgram();
program.parse(["node", "test", "--resume"]);
expect(program.opts().resume).toBe(true);
});
test('--resume sets resume flag', () => {
const program = createTestProgram()
program.parse(['node', 'test', '--resume'])
expect(program.opts().resume).toBe(true)
})
test("-v sets verbose flag", () => {
const program = createTestProgram();
program.parse(["node", "test", "-v"]);
expect(program.opts().verbose).toBe(true);
});
test('-v sets verbose flag', () => {
const program = createTestProgram()
program.parse(['node', 'test', '-v'])
expect(program.opts().verbose).toBe(true)
})
test("--model captures string value", () => {
const program = createTestProgram();
program.parse(["node", "test", "--model", "claude-opus-4-6"]);
expect(program.opts().model).toBe("claude-opus-4-6");
});
test('--model captures string value', () => {
const program = createTestProgram()
program.parse(['node', 'test', '--model', 'claude-opus-4-6'])
expect(program.opts().model).toBe('claude-opus-4-6')
})
test("--system-prompt captures string value", () => {
const program = createTestProgram();
program.parse(["node", "test", "--system-prompt", "Be concise"]);
expect(program.opts().systemPrompt).toBe("Be concise");
});
test('--system-prompt captures string value', () => {
const program = createTestProgram()
program.parse(['node', 'test', '--system-prompt', 'Be concise'])
expect(program.opts().systemPrompt).toBe('Be concise')
})
test("--max-turns parses integer value", () => {
const program = createTestProgram();
program.parse(["node", "test", "--max-turns", "10"]);
expect(program.opts().maxTurns).toBe(10);
});
test('--max-turns parses integer value', () => {
const program = createTestProgram()
program.parse(['node', 'test', '--max-turns', '10'])
expect(program.opts().maxTurns).toBe(10)
})
test("multiple flags can be combined", () => {
const program = createTestProgram();
program.parse(["node", "test", "-p", "-v", "--model", "opus"]);
expect(program.opts().print).toBe(true);
expect(program.opts().verbose).toBe(true);
expect(program.opts().model).toBe("opus");
});
test('multiple flags can be combined', () => {
const program = createTestProgram()
program.parse(['node', 'test', '-p', '-v', '--model', 'opus'])
expect(program.opts().print).toBe(true)
expect(program.opts().verbose).toBe(true)
expect(program.opts().model).toBe('opus')
})
test("--version throws Commander.CommandError with exit code 0", () => {
const program = createTestProgram();
let error: any;
test('--version throws Commander.CommandError with exit code 0', () => {
const program = createTestProgram()
let error: any
try {
program.parse(["node", "test", "--version"]);
program.parse(['node', 'test', '--version'])
} catch (e) {
error = e;
error = e
}
expect(error).toBeDefined();
expect(error.code).toBe("commander.version");
expect(error.exitCode).toBe(0);
});
expect(error).toBeDefined()
expect(error.code).toBe('commander.version')
expect(error.exitCode).toBe(0)
})
test("unknown flags throw CommanderError", () => {
const program = createTestProgram();
expect(() => program.parse(["node", "test", "--nonexistent"])).toThrow();
});
});
test('unknown flags throw CommanderError', () => {
const program = createTestProgram()
expect(() => program.parse(['node', 'test', '--nonexistent'])).toThrow()
})
})

View File

@@ -1,15 +1,13 @@
import { mkdtemp, rm, writeFile, mkdir } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { mkdtemp, rm, writeFile, mkdir } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
export async function createTempDir(
prefix = "claude-test-",
): Promise<string> {
return mkdtemp(join(tmpdir(), prefix));
export async function createTempDir(prefix = 'claude-test-'): Promise<string> {
return mkdtemp(join(tmpdir(), prefix))
}
export async function cleanupTempDir(dir: string): Promise<void> {
await rm(dir, { recursive: true, force: true });
await rm(dir, { recursive: true, force: true })
}
export async function writeTempFile(
@@ -17,16 +15,18 @@ export async function writeTempFile(
name: string,
content: string,
): Promise<string> {
const path = join(dir, name);
await writeFile(path, content, "utf-8");
return path;
const path = join(dir, name)
const parentDir = dirname(path)
await mkdir(parentDir, { recursive: true })
await writeFile(path, content, 'utf-8')
return path
}
export async function createTempSubdir(
dir: string,
name: string,
): Promise<string> {
const path = join(dir, name);
await mkdir(path, { recursive: true });
return path;
const path = join(dir, name)
await mkdir(path, { recursive: true })
return path
}