- 品牌替换:OpenCode/opencode → AirCoding/aircoding(16+ 文件) - Logo ASCII art:修复 left/right 行数不匹配导致的启动崩溃 - 启动诊断:添加 OPENCODE_PRINT_TIMING 计时探针 - dev 模式默认 --pure 跳过外部插件加载 - AGENTS.md 模板:追加 AirCoding 多 Agent 专项段落 - architect prompt + plugin:强化 AGENTS.md 产出验证
72 lines
1.7 KiB
TypeScript
72 lines
1.7 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { Readable } from "node:stream"
|
|
import { INTERACTIVE_INPUT_ERROR, resolveInteractiveStdin } from "@/cli/cmd/run/runtime.stdin"
|
|
|
|
function stream(isTTY: boolean) {
|
|
return Object.assign(new Readable({ read() {} }), { isTTY }) as NodeJS.ReadStream
|
|
}
|
|
|
|
describe("run interactive stdin", () => {
|
|
test("reuses stdin when it is already a tty", () => {
|
|
const stdin = stream(true)
|
|
const seen: string[] = []
|
|
const result = resolveInteractiveStdin(
|
|
stdin,
|
|
(path) => {
|
|
seen.push(path)
|
|
return stream(true)
|
|
},
|
|
"linux",
|
|
)
|
|
|
|
expect(result.stdin).toBe(stdin)
|
|
expect(result.cleanup).toBeUndefined()
|
|
expect(seen).toEqual([])
|
|
})
|
|
|
|
test("opens the controlling terminal when stdin is piped", () => {
|
|
const tty = stream(true)
|
|
const seen: string[] = []
|
|
const result = resolveInteractiveStdin(
|
|
stream(false),
|
|
(path) => {
|
|
seen.push(path)
|
|
return tty
|
|
},
|
|
"linux",
|
|
)
|
|
|
|
expect(result.stdin).toBe(tty)
|
|
expect(seen).toEqual(["/dev/tty"])
|
|
|
|
result.cleanup?.()
|
|
expect(tty.destroyed).toBe(true)
|
|
})
|
|
|
|
test("uses CONIN$ on windows", () => {
|
|
const seen: string[] = []
|
|
resolveInteractiveStdin(
|
|
stream(false),
|
|
(path) => {
|
|
seen.push(path)
|
|
return stream(true)
|
|
},
|
|
"win32",
|
|
)
|
|
|
|
expect(seen).toEqual(["CONIN$"])
|
|
})
|
|
|
|
test("throws a clear error when no controlling terminal is available", () => {
|
|
expect(() =>
|
|
resolveInteractiveStdin(
|
|
stream(false),
|
|
() => {
|
|
throw new Error("open failed")
|
|
},
|
|
"linux",
|
|
),
|
|
).toThrow(INTERACTIVE_INPUT_ERROR)
|
|
})
|
|
})
|