test/kiro-adapter-init.test.js
Rama main · réplica de lectura del repositorio original.
var test = require("node:test");
var assert = require("node:assert");
var EventEmitter = require("node:events");
var { createKiroAdapter } = require("../lib/yoke/adapters/kiro");
var yoke = require("../lib/yoke");
function createHarness(outcomes) {
var instances = [];
function FakeAcpServer(binaryPath, options) {
var proc = new EventEmitter();
proc.exitCode = null;
proc.signalCode = null;
proc.kills = [];
proc.kill = function(signal) {
proc.kills.push(signal);
proc.exitCode = 0;
proc.emit("exit", 0, signal);
return true;
};
this.proc = proc;
this.options = options;
this.started = false;
this.index = instances.length;
instances.push(this);
}
FakeAcpServer.prototype.start = function() {
this.started = true;
return Promise.resolve();
};
FakeAcpServer.prototype.send = function(method) {
assert.strictEqual(method, "initialize");
var outcome = outcomes[this.index];
if (outcome instanceof Error) return Promise.reject(outcome);
return Promise.resolve(outcome || { protocolVersion: 1 });
};
FakeAcpServer.prototype.addRequestHandler = function(method, fn) {
this.requestHandlerMethod = method;
this.requestHandler = fn;
};
FakeAcpServer.prototype.stop = function() {
this.started = false;
this.proc.kill("SIGTERM");
};
function createAdapter() {
return createKiroAdapter({
cwd: process.cwd(),
_binaryPath: "/fake/kiro-cli",
_AcpServerCtor: FakeAcpServer,
_fetchModels: function() {
return Promise.resolve({ models: ["auto"], defaultModel: "auto" });
},
});
}
return { instances: instances, createAdapter: createAdapter };
}
test("a failed init does not poison the next retry", async function() {
var harness = createHarness([new Error("handshake failed"), null]);
var adapter = harness.createAdapter();
var firstAttempt = adapter.init();
await assert.rejects(firstAttempt, /handshake failed/);
var secondAttempt = adapter.init();
assert.notStrictEqual(secondAttempt, firstAttempt);
await secondAttempt;
assert.strictEqual(harness.instances.length, 2);
});
test("Kiro forwards the scoped environment to its ACP process", async function() {
var harness = createHarness([null]);
var adapter = harness.createAdapter();
await adapter.init({ env: { PROJECT_TOKEN: "scoped" } });
assert.strictEqual(harness.instances[0].options.env.PROJECT_TOKEN, "scoped");
await adapter.shutdown();
});
test("a failed init stops the spawned ACP child", async function() {
var harness = createHarness([new Error("initialize timeout")]);
var adapter = harness.createAdapter();
await assert.rejects(adapter.init(), /initialize timeout/);
assert.strictEqual(harness.instances.length, 1);
assert.deepStrictEqual(harness.instances[0].proc.kills, ["SIGTERM"]);
assert.strictEqual(harness.instances[0].started, false);
});
test("a started child without a completed handshake is not reported ready", async function() {
var harness = createHarness([new Error("protocol mismatch"), { protocolVersion: 1 }]);
var adapter = harness.createAdapter();
await assert.rejects(adapter.init(), /protocol mismatch/);
var ready = await adapter.init();
assert.strictEqual(harness.instances.length, 2, "init must spawn a fresh child after handshake failure");
assert.deepStrictEqual(ready.models, ["auto"]);
});
test("idle reclaim works after an init failure and successful retry", async function() {
var harness = createHarness([new Error("logged out"), null]);
var adapter = harness.createAdapter();
await assert.rejects(adapter.init(), /logged out/);
await adapter.init();
await new Promise(function(resolve) { setTimeout(resolve, 5); });
var reclaimed = await adapter.shutdownIfIdle(0);
assert.strictEqual(reclaimed, true);
assert.deepStrictEqual(harness.instances[1].proc.kills, ["SIGTERM"]);
});
test("lazy creation refuses Kiro for an OS-isolated user", async function() {
var adapters = {};
var result = await yoke.lazyCreateAdapter(adapters, "kiro", {
cwd: process.cwd(),
linuxUser: "clay-user",
});
assert.strictEqual(result, null);
assert.deepStrictEqual(adapters, {});
});