@bogyie/opencode-kiro-plugin 0.3.22 → 0.3.24

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,
@@ -64,6 +65,20 @@ function bearerToken(init) {
64
65
  const match = header?.match(/^Bearer\s+(.+)$/i);
65
66
  return match?.[1] || undefined;
66
67
  }
68
+ function isLikelyKiroApiKey(value) {
69
+ return Boolean(value?.startsWith("ksk_"));
70
+ }
71
+ function localAccessToken(incoming, fallback) {
72
+ if (!incoming || incoming === KIRO_LOCAL_TRANSPORT_KEY)
73
+ return fallback ?? incoming;
74
+ if (isKiroDeviceAuthKey(incoming))
75
+ return incoming;
76
+ if (process.env.KIRO_API_KEY && incoming === process.env.KIRO_API_KEY)
77
+ return incoming;
78
+ if (isLikelyKiroApiKey(incoming))
79
+ return incoming;
80
+ return fallback;
81
+ }
67
82
  export function effectiveBackend(options, accessToken) {
68
83
  const apiKey = accessToken || process.env.KIRO_API_KEY;
69
84
  if (options.backend === "acp")
@@ -113,6 +128,13 @@ function openExternalUrl(url) {
113
128
  child.on("error", () => undefined);
114
129
  child.unref();
115
130
  }
131
+ function rememberDeviceAuthKey(key) {
132
+ sharedDeviceAuthKey = key;
133
+ return key;
134
+ }
135
+ export function __resetKiroPluginSharedStateForTest() {
136
+ sharedDeviceAuthKey = undefined;
137
+ }
116
138
  function loginPrompts(options) {
117
139
  const prompts = [];
118
140
  const login = options.login;
@@ -223,7 +245,7 @@ export function createKiroPlugin() {
223
245
  }
224
246
  let discovery;
225
247
  let lastModelDiscoveryAt = 0;
226
- let startupDeviceAuthKey;
248
+ let startupDeviceAuthKey = sharedDeviceAuthKey;
227
249
  let startupLogin;
228
250
  let startupLoginAttempted = false;
229
251
  const refreshModels = async (force = false) => {
@@ -256,6 +278,7 @@ export function createKiroPlugin() {
256
278
  return discovery;
257
279
  };
258
280
  const ensureStartupAuthenticated = async () => {
281
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
259
282
  if (startupDeviceAuthKey)
260
283
  return true;
261
284
  const current = await detectAuth().catch(() => undefined);
@@ -276,7 +299,7 @@ export function createKiroPlugin() {
276
299
  region: options.region,
277
300
  ...(options.profileArn ? { profileArn: options.profileArn } : {}),
278
301
  });
279
- startupDeviceAuthKey = encodeKiroDeviceAuthKey(credential);
302
+ startupDeviceAuthKey = rememberDeviceAuthKey(encodeKiroDeviceAuthKey(credential));
280
303
  return true;
281
304
  }
282
305
  catch {
@@ -300,22 +323,24 @@ export function createKiroPlugin() {
300
323
  disabledModels: options.disabledModels,
301
324
  disablePassThrough: options.disableModelPassThrough,
302
325
  });
326
+ const localFetch = async (input, init) => {
327
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
328
+ const accessToken = localAccessToken(bearerToken(init), startupDeviceAuthKey || sharedDeviceAuthKey);
329
+ const transport = localTransport(options, accessToken, {
330
+ loginOnAuthFailure: shouldLoginOnAuthFailure(init),
331
+ });
332
+ return createKiroFetch({
333
+ resolver,
334
+ models: async () => {
335
+ await refreshModels(true).catch(() => []);
336
+ return Object.keys(visibleProviderModels(modelCache, configuredModels, options.hiddenModels, disabledModels));
337
+ },
338
+ ...(transport ? { transport } : {}),
339
+ })(input, init);
340
+ };
303
341
  const ensureLocalServer = async () => {
304
342
  if (localServer)
305
343
  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
344
  localServer = await startLocalKiroServer(localFetch);
320
345
  return localServer;
321
346
  };
@@ -334,7 +359,7 @@ export function createKiroPlugin() {
334
359
  region: options.region,
335
360
  ...(options.profileArn ? { profileArn: options.profileArn } : {}),
336
361
  });
337
- const key = encodeKiroDeviceAuthKey(credential);
362
+ const key = rememberDeviceAuthKey(encodeKiroDeviceAuthKey(credential));
338
363
  startupDeviceAuthKey = key;
339
364
  await refreshModels(true).catch(() => []);
340
365
  return {
@@ -394,6 +419,8 @@ export function createKiroPlugin() {
394
419
  provider.npm = "@ai-sdk/openai-compatible";
395
420
  provider.api = server.baseURL;
396
421
  provider.options ??= {};
422
+ provider.options.baseURL = server.baseURL;
423
+ provider.options.apiKey ??= KIRO_LOCAL_TRANSPORT_KEY;
397
424
  provider.models = visibleProviderModels(modelCache, configuredModels, options.hiddenModels, disabledModels);
398
425
  },
399
426
  auth: {
@@ -426,10 +453,12 @@ export function createKiroPlugin() {
426
453
  ],
427
454
  loader: async (auth) => {
428
455
  const apiKey = await resolveApiKey(auth);
456
+ startupDeviceAuthKey ??= sharedDeviceAuthKey;
429
457
  const server = await ensureLocalServer();
430
458
  return {
431
- apiKey: apiKey || startupDeviceAuthKey || KIRO_LOCAL_TRANSPORT_KEY,
459
+ apiKey: apiKey || startupDeviceAuthKey || sharedDeviceAuthKey || KIRO_LOCAL_TRANSPORT_KEY,
432
460
  baseURL: server.baseURL,
461
+ fetch: localFetch,
433
462
  };
434
463
  },
435
464
  },
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.24",
4
4
  "description": "OpenCode plugin for using Kiro as a provider adapter",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",