@bogyie/opencode-kiro-plugin 0.3.22 → 0.3.23

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 CHANGED
@@ -59,7 +59,7 @@ For personal Kiro login with GitHub:
59
59
  }
60
60
  ```
61
61
 
62
- For AWS IAM Identity Center login, configure the default device-flow Start URL separately from the API region:
62
+ For AWS IAM Identity Center login, configure the default device-flow Start URL separately from the Kiro LLM API region:
63
63
 
64
64
  ```jsonc
65
65
  {
@@ -67,7 +67,7 @@ For AWS IAM Identity Center login, configure the default device-flow Start URL s
67
67
  [
68
68
  "@bogyie/opencode-kiro-plugin",
69
69
  {
70
- "region": "ap-northeast-2",
70
+ "region": "us-east-1",
71
71
  "login": {
72
72
  "method": "organization",
73
73
  "identityProvider": "https://example.awsapps.com/start",
@@ -79,7 +79,7 @@ For AWS IAM Identity Center login, configure the default device-flow Start URL s
79
79
  }
80
80
  ```
81
81
 
82
- For IAM Identity Center, configure `login.method: "organization"`, `login.identityProvider`, and `login.region` in plugin options. The connector opens the Identity Center device URL for that Start URL and region, then waits until the device authorization completes.
82
+ For IAM Identity Center, configure `login.method: "organization"`, `login.identityProvider`, and `login.region` in plugin options. The top-level `region` controls the Kiro LLM/API endpoint and should usually remain `us-east-1`; `login.region` controls the IAM Identity Center OIDC/device authorization endpoint, for example `ap-northeast-2`. The connector opens the Identity Center device URL for that Start URL and login region, then waits until the device authorization completes.
83
83
 
84
84
  Use the `kiro_status` plugin tool to inspect provider id, backend, region, auth method, and discovered model count. Use `kiro_refresh_models` when you explicitly want to run the configured model discovery command and update the in-memory and stored model cache. Secrets are redacted in diagnostics.
85
85
 
@@ -183,6 +183,8 @@ The plugin injects `provider.kiro` with the `auto` placeholder needed for OpenCo
183
183
  - `KIRO_ACP_TIMEOUT`: ACP did not send a `TurnEnd` notification before the prompt timeout.
184
184
  - `KIRO_ACP_PROCESS_ERROR` or `KIRO_ACP_PROCESS_EXITED`: `kiro-cli acp` could not start or exited while a request was pending.
185
185
 
186
+ If IAM Identity Center login succeeds but chat requests cannot connect or fail against the LLM endpoint, check that top-level `region` is the Kiro LLM/API region, not necessarily the IAM Identity Center region. A common organization setup is `"region": "us-east-1"` with `"login.region": "ap-northeast-2"`.
187
+
186
188
  Direct fetch mode calls Kiro's `generateAssistantResponse` endpoint and can fall back from the `q` endpoint to the CodeWhisperer endpoint on quota or upstream failures. Tune `maxAttempts` and `requestTimeoutMs` if you need stricter failure boundaries in automation. Fetch mode also accepts `endpoint`, `profileArn`, `userAgent`, and `agentMode` for controlled environments. `cli-chat` uses `requestTimeoutMs` for the `kiro-cli chat --no-interactive` child process, and ACP uses it while waiting for `session/prompt` completion and `TurnEnd`.
187
189
 
188
190
  OpenAI-compatible `temperature`, `max_tokens`, and `max_completion_tokens` are preserved for direct fetch mode through Kiro's `inferenceConfig` fields on a best-effort basis.
package/dist/plugin.d.ts CHANGED
@@ -4,6 +4,7 @@ import type { KiroPluginOptions } from "./config.js";
4
4
  import type { KiroRestTransportOptions } from "./kiro-rest-transport.js";
5
5
  type EffectiveBackend = "fetch" | "cli-chat" | "acp" | "none";
6
6
  export declare function effectiveBackend(options: Pick<KiroPluginOptions, "backend">, accessToken?: string): EffectiveBackend;
7
+ export declare function __resetKiroPluginSharedStateForTest(): void;
7
8
  export declare function acpTransportOptions(options: Pick<KiroPluginOptions, "requestTimeoutMs" | "trustAllTools">): KiroAcpTransportOptions;
8
9
  export declare function fetchTransportOptions(options: Pick<KiroPluginOptions, "region" | "endpoint" | "profileArn" | "userAgent" | "agentMode" | "maxAttempts" | "requestTimeoutMs">, accessToken?: string): KiroRestTransportOptions;
9
10
  export declare function createKiroPlugin(): Plugin;
package/dist/plugin.js CHANGED
@@ -16,6 +16,7 @@ const PLACEHOLDER_MODEL = { name: "Auto" };
16
16
  const OPENCODE_AGENT_HEADER = "x-opencode-kiro-agent";
17
17
  const LOGIN_SUPPRESSED_AGENTS = new Set(["title"]);
18
18
  const LOGIN_METHODS = new Set(["builder-id", "google", "github", "organization"]);
19
+ let sharedDeviceAuthKey;
19
20
  function discoveredProviderModels(cache) {
20
21
  return Object.fromEntries(cache.all().map((model) => [
21
22
  model.id,
@@ -113,6 +114,13 @@ function openExternalUrl(url) {
113
114
  child.on("error", () => undefined);
114
115
  child.unref();
115
116
  }
117
+ function rememberDeviceAuthKey(key) {
118
+ sharedDeviceAuthKey = key;
119
+ return key;
120
+ }
121
+ export function __resetKiroPluginSharedStateForTest() {
122
+ sharedDeviceAuthKey = undefined;
123
+ }
116
124
  function loginPrompts(options) {
117
125
  const prompts = [];
118
126
  const login = options.login;
@@ -223,7 +231,7 @@ export function createKiroPlugin() {
223
231
  }
224
232
  let discovery;
225
233
  let lastModelDiscoveryAt = 0;
226
- let startupDeviceAuthKey;
234
+ let startupDeviceAuthKey = sharedDeviceAuthKey;
227
235
  let startupLogin;
228
236
  let startupLoginAttempted = false;
229
237
  const refreshModels = async (force = false) => {
@@ -256,6 +264,7 @@ export function createKiroPlugin() {
256
264
  return discovery;
257
265
  };
258
266
  const ensureStartupAuthenticated = async () => {
267
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
259
268
  if (startupDeviceAuthKey)
260
269
  return true;
261
270
  const current = await detectAuth().catch(() => undefined);
@@ -276,7 +285,7 @@ export function createKiroPlugin() {
276
285
  region: options.region,
277
286
  ...(options.profileArn ? { profileArn: options.profileArn } : {}),
278
287
  });
279
- startupDeviceAuthKey = encodeKiroDeviceAuthKey(credential);
288
+ startupDeviceAuthKey = rememberDeviceAuthKey(encodeKiroDeviceAuthKey(credential));
280
289
  return true;
281
290
  }
282
291
  catch {
@@ -300,22 +309,23 @@ export function createKiroPlugin() {
300
309
  disabledModels: options.disabledModels,
301
310
  disablePassThrough: options.disableModelPassThrough,
302
311
  });
312
+ const localFetch = async (input, init) => {
313
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
314
+ const transport = localTransport(options, bearerToken(init) || startupDeviceAuthKey || sharedDeviceAuthKey, {
315
+ loginOnAuthFailure: shouldLoginOnAuthFailure(init),
316
+ });
317
+ return createKiroFetch({
318
+ resolver,
319
+ models: async () => {
320
+ await refreshModels(true).catch(() => []);
321
+ return Object.keys(visibleProviderModels(modelCache, configuredModels, options.hiddenModels, disabledModels));
322
+ },
323
+ ...(transport ? { transport } : {}),
324
+ })(input, init);
325
+ };
303
326
  const ensureLocalServer = async () => {
304
327
  if (localServer)
305
328
  return localServer;
306
- const localFetch = async (input, init) => {
307
- const transport = localTransport(options, bearerToken(init) || startupDeviceAuthKey, {
308
- loginOnAuthFailure: shouldLoginOnAuthFailure(init),
309
- });
310
- return createKiroFetch({
311
- resolver,
312
- models: async () => {
313
- await refreshModels(true).catch(() => []);
314
- return Object.keys(visibleProviderModels(modelCache, configuredModels, options.hiddenModels, disabledModels));
315
- },
316
- ...(transport ? { transport } : {}),
317
- })(input, init);
318
- };
319
329
  localServer = await startLocalKiroServer(localFetch);
320
330
  return localServer;
321
331
  };
@@ -334,7 +344,7 @@ export function createKiroPlugin() {
334
344
  region: options.region,
335
345
  ...(options.profileArn ? { profileArn: options.profileArn } : {}),
336
346
  });
337
- const key = encodeKiroDeviceAuthKey(credential);
347
+ const key = rememberDeviceAuthKey(encodeKiroDeviceAuthKey(credential));
338
348
  startupDeviceAuthKey = key;
339
349
  await refreshModels(true).catch(() => []);
340
350
  return {
@@ -394,6 +404,8 @@ export function createKiroPlugin() {
394
404
  provider.npm = "@ai-sdk/openai-compatible";
395
405
  provider.api = server.baseURL;
396
406
  provider.options ??= {};
407
+ provider.options.baseURL = server.baseURL;
408
+ provider.options.apiKey ??= KIRO_LOCAL_TRANSPORT_KEY;
397
409
  provider.models = visibleProviderModels(modelCache, configuredModels, options.hiddenModels, disabledModels);
398
410
  },
399
411
  auth: {
@@ -426,10 +438,12 @@ export function createKiroPlugin() {
426
438
  ],
427
439
  loader: async (auth) => {
428
440
  const apiKey = await resolveApiKey(auth);
441
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
429
442
  const server = await ensureLocalServer();
430
443
  return {
431
- apiKey: apiKey || startupDeviceAuthKey || KIRO_LOCAL_TRANSPORT_KEY,
444
+ apiKey: apiKey || startupDeviceAuthKey || sharedDeviceAuthKey || KIRO_LOCAL_TRANSPORT_KEY,
432
445
  baseURL: server.baseURL,
446
+ fetch: localFetch,
433
447
  };
434
448
  },
435
449
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bogyie/opencode-kiro-plugin",
3
- "version": "0.3.22",
3
+ "version": "0.3.23",
4
4
  "description": "OpenCode plugin for using Kiro as a provider adapter",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",