Skip to content
Source
Sign inSign up

triage.test.ts

75 lines3.0 KB

1// @effect-diagnostics nodeBuiltinImport:off - CLI integration spawns a fake agent from PATH.
2import * as NodeFS from "node:fs";
3import * as NodePath from "node:path";
4​
5import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
6import * as NodeServices from "@effect/platform-node/NodeServices";
7import { TRIAGE_PROMPT_FILE_NAME } from "@t3tools/contracts";
8import * as NetService from "@t3tools/shared/Net";
9import { assert, it } from "@effect/vitest";
10import * as Effect from "effect/Effect";
11import * as FileSystem from "effect/FileSystem";
12import * as Layer from "effect/Layer";
13import * as TestConsole from "effect/testing/TestConsole";
14import { Command } from "effect/cli";
15import { vi } from "vite-plus/test";
16​
17import { cli } from "../binCli.ts";
18import { buildTriageLaunchPrompt } from "../triage/triagePrompt.ts";
19​
20const FAILING_AGENT_POSIX = `#!/bin/sh
21echo "Error: There is not enough space on the disk. (os error 112)" >&2
22exit 1
23`;
24const FAILING_AGENT_WINDOWS = `@echo Error: There is not enough space on the disk. (os error 112) 1>&2
25@exit /b 1
26`;
27​
28it.live("a failed agent launch points at the prompt it could not run", () =>
29 Effect.gen(function* () {
30 const fs = yield* FileSystem.FileSystem;
31 const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-triage-cli-" });
32 const binDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-triage-bin-" });
33 const codexHome = NodePath.join(baseDir, "codex-home");
34 NodeFS.writeFileSync(NodePath.join(binDir, "codex"), FAILING_AGENT_POSIX, { mode: 0o755 });
35 NodeFS.writeFileSync(NodePath.join(binDir, "codex.cmd"), FAILING_AGENT_WINDOWS);
36 yield* Effect.acquireRelease(
37 // PATH holds only the fake agent, so a broken fixture can never fall through to a real codex.
38 Effect.sync(() => {
39 vi.stubEnv("PATH", binDir);
40 vi.stubEnv("CODEX_HOME", codexHome);
41 }),
42 () => Effect.sync(() => vi.unstubAllEnvs()),
43 );
44 const previousExitCode = process.exitCode;
45 yield* Effect.addFinalizer(() =>
46 Effect.sync(() => {
47 process.exitCode = previousExitCode;
48 }),
49 );
50​
51 yield* Command.runWith(cli, { version: "0.0.0" })([
52 "triage",
53 "--agent",
54 "codex",
55 "--base-dir",
56 baseDir,
57 ]);
58 const output = (yield* TestConsole.logLines).join("\n");
59​
60 assert.equal(process.exitCode, 1);
61 const promptFilePath = NodeFS.readdirSync(baseDir, { recursive: true, encoding: "utf8" })
62 .filter((entry) => NodePath.basename(entry) === TRIAGE_PROMPT_FILE_NAME)
63 .map((entry) => NodePath.join(baseDir, entry))[0];
64 assert.isDefined(promptFilePath);
65 assert.include(output, promptFilePath);
66 assert.include(output, buildTriageLaunchPrompt(promptFilePath));
67 assert.include(output, NodePath.join(NodePath.dirname(promptFilePath), "context.md"));
68 assert.include(output, `Codex keeps its state in ${codexHome}.`);
69 assert.include(output, "set CODEX_HOME to a folder on another drive");
70 }).pipe(
71 Effect.provide(
72 Layer.mergeAll(NodeServices.layer, NodeCrypto.layer, NetService.layer, TestConsole.layer),
73 ),
74 ),
75);