Skip to content
Source
Sign inSign up

driver.test.ts

144 lines5.8 KB

1import * as NodeCrypto from "@effect/platform-node/NodeCrypto";
2import * as NodeServices from "@effect/platform-node/NodeServices";
3import { assert, describe, it } from "@effect/vitest";
4import { ProviderInstanceId } from "@t3tools/contracts";
5import * as IdAllocator from "@t3tools/provider-core/server/IdAllocator";
6import * as McpProviderSessions from "@t3tools/provider-core/server/McpProviderSessions";
7import * as ProviderEventLoggers from "@t3tools/provider-core/server/ProviderEventLoggers";
8import * as TestProviderHost from "@t3tools/provider-testing/TestProviderHost";
9import * as HostProcess from "@t3tools/shared/HostProcess";
10import * as Effect from "effect/Effect";
11import * as Layer from "effect/Layer";
12import * as Path from "effect/Path";
13import * as Schema from "effect/Schema";
14import * as Sink from "effect/Sink";
15import * as Stream from "effect/Stream";
16import * as ChildProcess from "effect/process/ChildProcess";
17import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
18​
19import { KiroSettings } from "../settings.ts";
20import { buildKiroAcpSpawnInput } from "./acpSupport.ts";
21import { KiroDriver } from "./driver.ts";
22import { kiroAuthFromWhoami } from "./status.ts";
23​
24const decodeSettings = Schema.decodeUnknownSync(KiroSettings);
25​
26describe("KiroDriver", () => {
27 it("launches the V3 ACP engine with CLI-owned auth from the configured binary", () => {
28 assert.deepEqual(buildKiroAcpSpawnInput(decodeSettings({}), "/work"), {
29 command: "kiro-cli",
30 args: ["acp", "--agent-engine=v3", "--auth-method=cli"],
31 cwd: "/work",
32 });
33 const custom = buildKiroAcpSpawnInput(
34 decodeSettings({ binaryPath: "/opt/kiro/bin/kiro-cli" }),
35 "/work",
36 { KIRO_API_KEY: "ksk_test" },
37 );
38 assert.equal(custom.command, "/opt/kiro/bin/kiro-cli");
39 assert.deepEqual(custom.args, ["acp", "--agent-engine=v3", "--auth-method=cli"]);
40 assert.deepEqual(custom.env, { KIRO_API_KEY: "ksk_test" });
41 });
42​
43 // Outputs recorded from `kiro-cli whoami --format json` on Kiro CLI 2.27.0.
44 it("reads the sign-in state from kiro-cli whoami", () => {
45 assert.deepEqual(kiroAuthFromWhoami({ code: 1, stdout: '{"account":null}\n' }, {}), {
46 status: "unauthenticated",
47 });
48 assert.deepEqual(
49 kiroAuthFromWhoami({ code: 0, stdout: '{"accountType":"ApiKey","email":null}\n' }, {}),
50 { status: "authenticated", type: "api_key", label: "Kiro API key" },
51 );
52 assert.deepEqual(
53 kiroAuthFromWhoami(
54 { code: 0, stdout: '{"accountType":"BuilderId","email":"dev@example.com"}\n' },
55 {},
56 ),
57 { status: "authenticated", label: "Kiro account", email: "dev@example.com" },
58 );
59 assert.deepEqual(kiroAuthFromWhoami({ code: 2, stdout: "error: service error" }, {}), {
60 status: "unknown",
61 });
62 assert.deepEqual(kiroAuthFromWhoami(undefined, {}), { status: "unknown" });
63 });
64​
65 // Reported from Kiro CLI 2.27.1 with an IAM Identity Center login (exit 0;
66 // values are placeholders, layout unchanged).
67 it("keeps the account email when whoami appends an Identity Center profile", () => {
68 const stdout = [
69 '{"accountType":"IamIdentityCenter","email":"jane.doe@example.com","region":"us-east-1","startUrl":"https://d-0123456789.awsapps.com/start"}',
70 "",
71 "Profile:",
72 "KiroProfile-us-east-1",
73 "arn:aws:codewhisperer:us-east-1:111122223333:profile/EXAMPLE12345",
74 "",
75 ].join("\n");
76 assert.deepEqual(kiroAuthFromWhoami({ code: 0, stdout }, {}), {
77 status: "authenticated",
78 label: "Kiro account",
79 email: "jane.doe@example.com",
80 });
81 });
82});
83​
84const layerTest = TestProviderHost.layer({ runBackgroundWork: false }).pipe(
85 Layer.provideMerge(Layer.mergeAll(NodeServices.layer, NodeCrypto.layer)),
86 Layer.provideMerge(IdAllocator.layer),
87 Layer.provideMerge(McpProviderSessions.layer),
88 Layer.provideMerge(
89 Layer.succeed(
90 ProviderEventLoggers.ProviderEventLoggers,
91 ProviderEventLoggers.NoOpProviderEventLoggers,
92 ),
93 ),
94);
95​
96/** Records each spawned command and answers only `--version`. */
97function recordingSpawner(launches: Array<string>) {
98 return ChildProcessSpawner.make((command) => {
99 const standard = ChildProcess.isStandardCommand(command);
100 if (standard) launches.push(command.command);
101 const version = standard && command.args.join(" ") === "--version";
102 return Effect.succeed(
103 ChildProcessSpawner.makeHandle({
104 pid: ChildProcessSpawner.ProcessId(1),
105 exitCode: Effect.succeed(ChildProcessSpawner.ExitCode(version ? 0 : 2)),
106 isRunning: Effect.succeed(false),
107 kill: () => Effect.void,
108 unref: Effect.succeed(Effect.void),
109 stdin: Sink.drain,
110 stdout: version ? Stream.encodeText(Stream.make("2.32.0\n")) : Stream.empty,
111 stderr: Stream.empty,
112 all: Stream.empty,
113 getInputFd: () => Sink.drain,
114 getOutputFd: () => Stream.empty,
115 }),
116 );
117 });
119​
120it.layer(layerTest)("KiroDriver binary path", (it) => {
121 it.effect("probes a ~/ binary path from the home directory", () =>
122 Effect.gen(function* () {
123 const path = yield* Path.Path;
124 const launches: Array<string> = [];
125 const instance = yield* KiroDriver.create({
126 instanceId: ProviderInstanceId.make("kiro-home"),
127 displayName: undefined,
128 enabled: true,
129 environment: [],
130 config: decodeSettings({ binaryPath: "~/.local/bin/kiro-cli" }),
131 }).pipe(
132 Effect.provideService(HostProcess.HomeDirectory, "/test-home"),
133 Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, recordingSpawner(launches)),
134 );
135 const snapshot = yield* instance.snapshot.refresh;
136 assert.isNotEmpty(launches);
137 assert.deepEqual(
138 [...new Set(launches)],
139 [path.join("/test-home", ".local", "bin", "kiro-cli")],
140 );
141 assert.isTrue(snapshot.installed);
142 }),
143 );
144});