@bogyie/opencode-kiro-plugin 0.2.13 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli-transport.d.ts +1 -0
- package/dist/cli-transport.js +17 -1
- package/dist/kiro-rest-transport.d.ts +1 -0
- package/dist/kiro-rest-transport.js +16 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ The plugin resolves credentials in this order:
|
|
|
40
40
|
|
|
41
41
|
When no usable Kiro CLI session is available, open OpenCode's provider connector, choose Kiro, and select `Kiro CLI login`. The plugin starts `kiro-cli login --use-device-flow`, waits until the verification URL/device code is visible, returns them to the connector, and then waits until `kiro-cli whoami` succeeds. The same auth method also works from OpenCode's CLI provider connect flow.
|
|
42
42
|
|
|
43
|
-
The plugin does not start login during OpenCode startup
|
|
43
|
+
The plugin does not start login during OpenCode startup. Direct fetch mode uses a usable API key/token when one is configured; otherwise it reads the active Kiro CLI session token and calls Kiro's REST/EventStream endpoint directly. If a model request fails because credentials are missing or rejected, the plugin starts one shared Kiro CLI login session and still returns `KIRO_AUTH_ERROR` for that failed request; retry after the login completes. `cli-chat` mode uses the official `kiro-cli chat --no-interactive` surface and applies the same login-on-auth-failure behavior. `acp` mode uses the official `kiro-cli acp` surface, but is still treated as an explicit backend while its real-world protocol behavior is validated across Kiro CLI versions.
|
|
44
44
|
|
|
45
45
|
Use the `kiro_status` plugin tool to inspect provider id, backend, region, auth method, and discovered model count. Secrets are redacted in diagnostics.
|
|
46
46
|
|
package/dist/cli-transport.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { type ChildProcess } from "node:child_process";
|
|
|
6
6
|
export interface CliChatTransportOptions {
|
|
7
7
|
readonly runner?: CommandRunner;
|
|
8
8
|
readonly spawner?: CliChatSpawner;
|
|
9
|
+
readonly loginStarter?: () => void;
|
|
9
10
|
readonly trustAllTools?: boolean;
|
|
10
11
|
readonly requestTimeoutMs?: number;
|
|
11
12
|
}
|
package/dist/cli-transport.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runCommand } from "./auth.js";
|
|
1
|
+
import { runCommand, startKiroCliLoginOnce } from "./auth.js";
|
|
2
2
|
import { KiroPluginError } from "./errors.js";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
export function promptForCli(request) {
|
|
@@ -84,20 +84,34 @@ class AsyncQueue {
|
|
|
84
84
|
export class KiroCliChatTransport {
|
|
85
85
|
#runner;
|
|
86
86
|
#spawner;
|
|
87
|
+
#loginStarter;
|
|
87
88
|
#trustAllTools;
|
|
88
89
|
#requestTimeoutMs;
|
|
89
90
|
constructor(options = {}) {
|
|
90
91
|
this.#runner = options.runner ?? runCommand;
|
|
91
92
|
this.#spawner = options.spawner ?? ((command, args) => spawn(command, [...args], { stdio: ["ignore", "pipe", "pipe"] }));
|
|
93
|
+
this.#loginStarter = options.loginStarter ?? (() => {
|
|
94
|
+
startKiroCliLoginOnce();
|
|
95
|
+
});
|
|
92
96
|
this.#trustAllTools = options.trustAllTools === true;
|
|
93
97
|
this.#requestTimeoutMs = options.requestTimeoutMs ?? 120_000;
|
|
94
98
|
}
|
|
99
|
+
#startLoginAfterAuthFailure() {
|
|
100
|
+
try {
|
|
101
|
+
this.#loginStarter();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Keep the original model-call auth error visible to OpenCode.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
async generate(request) {
|
|
96
108
|
const result = await this.#runner("kiro-cli", cliChatArgs(request, { trustAllTools: this.#trustAllTools }), {
|
|
97
109
|
timeoutMs: this.#requestTimeoutMs,
|
|
98
110
|
});
|
|
99
111
|
if (!result.ok) {
|
|
100
112
|
const authError = result.stderr.toLowerCase().includes("not logged in");
|
|
113
|
+
if (authError)
|
|
114
|
+
this.#startLoginAfterAuthFailure();
|
|
101
115
|
throw new KiroPluginError(result.stderr.trim() || "kiro-cli chat failed", authError ? "KIRO_AUTH_ERROR" : "KIRO_CLI_FAILED", authError ? 401 : 502);
|
|
102
116
|
}
|
|
103
117
|
const text = sanitizeCliChatOutput(result.stdout);
|
|
@@ -149,6 +163,8 @@ export class KiroCliChatTransport {
|
|
|
149
163
|
return;
|
|
150
164
|
}
|
|
151
165
|
const authError = stderr.toLowerCase().includes("not logged in");
|
|
166
|
+
if (authError)
|
|
167
|
+
this.#startLoginAfterAuthFailure();
|
|
152
168
|
queue.fail(new KiroPluginError(stderr.trim() || `kiro-cli chat exited${code === null ? "" : ` with code ${code}`}${signal ? ` and signal ${signal}` : ""}`, authError ? "KIRO_AUTH_ERROR" : "KIRO_CLI_FAILED", authError ? 401 : 502));
|
|
153
169
|
});
|
|
154
170
|
try {
|
|
@@ -17,6 +17,7 @@ export type KiroRestFetch = (input: RequestInfo | URL, init?: RequestInit) => Pr
|
|
|
17
17
|
export interface KiroRestTransportDependencies {
|
|
18
18
|
readonly fetcher?: KiroRestFetch;
|
|
19
19
|
readonly credentialProvider?: KiroCredentialProvider;
|
|
20
|
+
readonly loginStarter?: () => void;
|
|
20
21
|
}
|
|
21
22
|
export declare function toKiroRestPayload(request: KiroGenerateRequest, profileArn?: string): Record<string, unknown>;
|
|
22
23
|
export declare class KiroRestTransport implements KiroTransport {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KiroPluginError } from "./errors.js";
|
|
2
|
-
import { readKiroCliSessionCredential, regionFromProfileArn, } from "./auth.js";
|
|
2
|
+
import { readKiroCliSessionCredential, regionFromProfileArn, startKiroCliLoginOnce, } from "./auth.js";
|
|
3
3
|
const DEFAULT_USER_AGENT = "KiroIDE";
|
|
4
4
|
const DEFAULT_AGENT_MODE = "vibe";
|
|
5
5
|
const STREAMING_SDK_VERSION = "1.0.34";
|
|
@@ -313,15 +313,28 @@ export class KiroRestTransport {
|
|
|
313
313
|
#options;
|
|
314
314
|
#fetcher;
|
|
315
315
|
#credentialProvider;
|
|
316
|
+
#loginStarter;
|
|
316
317
|
constructor(options, dependencies = {}) {
|
|
317
318
|
this.#options = options;
|
|
318
319
|
this.#fetcher = dependencies.fetcher ?? fetch;
|
|
319
320
|
this.#credentialProvider = dependencies.credentialProvider ?? (() => readKiroCliSessionCredential());
|
|
321
|
+
this.#loginStarter = dependencies.loginStarter ?? (() => {
|
|
322
|
+
startKiroCliLoginOnce();
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
#startLoginAfterAuthFailure() {
|
|
326
|
+
try {
|
|
327
|
+
this.#loginStarter();
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
// Keep the original model-call auth error visible to OpenCode.
|
|
331
|
+
}
|
|
320
332
|
}
|
|
321
333
|
async #credentials() {
|
|
322
334
|
const session = this.#options.accessToken ? undefined : await this.#credentialProvider();
|
|
323
335
|
const accessToken = this.#options.accessToken ?? session?.accessToken;
|
|
324
336
|
if (!accessToken) {
|
|
337
|
+
this.#startLoginAfterAuthFailure();
|
|
325
338
|
throw new KiroPluginError("No Kiro API token or Kiro CLI session token found. Connect Kiro from OpenCode's provider connector or run `kiro-cli login`.", "KIRO_AUTH_ERROR", 401);
|
|
326
339
|
}
|
|
327
340
|
const profileArn = this.#options.profileArn ?? session?.profileArn;
|
|
@@ -355,6 +368,8 @@ export class KiroRestTransport {
|
|
|
355
368
|
lastError = new KiroPluginError(message, code, response.status);
|
|
356
369
|
if (response.status === 429 || response.status >= 500)
|
|
357
370
|
continue;
|
|
371
|
+
if (code === "KIRO_AUTH_ERROR")
|
|
372
|
+
this.#startLoginAfterAuthFailure();
|
|
358
373
|
throw lastError;
|
|
359
374
|
}
|
|
360
375
|
if (!response.body)
|