@sunerpy/opencode-kiro-auth 0.2.1 → 0.3.0

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
@@ -179,6 +179,12 @@ Thinking budgets map to Kiro's native `effort` field automatically:
179
179
 
180
180
  Details and the full JSON example: [docs/MODELS.md](docs/MODELS.md).
181
181
 
182
+ > **Note:** OpenCode's per-agent thinking level (`--variant` / an agent's
183
+ > `variant` in `oh-my-openagent.json`) isn't honored per agent by this
184
+ > plugin — OpenCode consumes it upstream. Use the global `effort` key in
185
+ > `kiro.json` instead. See
186
+ > [Reasoning effort](docs/CONFIGURATION.md#reasoning-effort) for details.
187
+
182
188
  ## Troubleshooting
183
189
 
184
190
  Common issues — 403/AccessDeniedException with IAM Identity Center, "No
@@ -17,8 +17,19 @@ export declare class AuthHandler {
17
17
  /** Ends the auth flow cleanly with no key prompt and no credential written. */
18
18
  private endWithoutCredential;
19
19
  /**
20
- * Self-drawn account-removal flow returning method:'auto' + failed-callback in
21
- * all cases, so the auth flow ends with no key prompt and NO credential written.
20
+ * Ends the flow after a successful deletion. If a healthy account (or any
21
+ * account with a usable access token) remains, returns a SUCCESS callback
22
+ * keyed on that account's token so OpenCode shows success and persists a
23
+ * still-valid credential. If nothing usable remains, falls back to a failed
24
+ * callback (nothing left to authorize with).
25
+ */
26
+ private endWithRemainingCredentialOrFailed;
27
+ /**
28
+ * Self-drawn account-removal flow. No-op paths (cancel / no accounts /
29
+ * not-confirmed / non-TTY) end with method:'auto' + a failed callback so no
30
+ * key prompt appears and no bogus success is shown. The actual-deletion path
31
+ * ends with a remaining-account success (or failed if none remain), so a
32
+ * successful removal is not misreported as "Failed to authorize".
22
33
  */
23
34
  private authorizeRemoveAccounts;
24
35
  }
@@ -215,8 +215,34 @@ export class AuthHandler {
215
215
  };
216
216
  }
217
217
  /**
218
- * Self-drawn account-removal flow returning method:'auto' + failed-callback in
219
- * all cases, so the auth flow ends with no key prompt and NO credential written.
218
+ * Ends the flow after a successful deletion. If a healthy account (or any
219
+ * account with a usable access token) remains, returns a SUCCESS callback
220
+ * keyed on that account's token so OpenCode shows success and persists a
221
+ * still-valid credential. If nothing usable remains, falls back to a failed
222
+ * callback (nothing left to authorize with).
223
+ */
224
+ endWithRemainingCredentialOrFailed(instructions) {
225
+ const remaining = this.accountManager?.getAccounts?.() ?? [];
226
+ const hasToken = (acc) => typeof acc?.accessToken === 'string' && acc.accessToken.length > 0;
227
+ const fallback = remaining.find((acc) => acc?.isHealthy && hasToken(acc)) ??
228
+ remaining.find((acc) => hasToken(acc));
229
+ if (fallback) {
230
+ const key = fallback.accessToken;
231
+ return {
232
+ url: '',
233
+ instructions: `${instructions} Using ${fallback.email || 'a remaining account'} for future requests.`,
234
+ method: 'auto',
235
+ callback: async () => ({ type: 'success', key })
236
+ };
237
+ }
238
+ return this.endWithoutCredential(`${instructions} No accounts remain — run \`opencode auth login\` to reauthenticate.`);
239
+ }
240
+ /**
241
+ * Self-drawn account-removal flow. No-op paths (cancel / no accounts /
242
+ * not-confirmed / non-TTY) end with method:'auto' + a failed callback so no
243
+ * key prompt appears and no bogus success is shown. The actual-deletion path
244
+ * ends with a remaining-account success (or failed if none remain), so a
245
+ * successful removal is not misreported as "Failed to authorize".
220
246
  */
221
247
  async authorizeRemoveAccounts() {
222
248
  const accounts = this.accountManager?.getAccounts?.() ?? [];
@@ -248,6 +274,6 @@ export class AuthHandler {
248
274
  this.accountManager.removeAccount(target);
249
275
  logger.log('Removed Kiro account', { email: target.email, accountId: String(target.id) });
250
276
  process.stdout.write('Account deleted.\n');
251
- return this.endWithoutCredential(`Account deleted: ${target.email || 'unknown'}.`);
277
+ return this.endWithRemainingCredentialOrFailed(`Account deleted: ${target.email || 'unknown'}.`);
252
278
  }
253
279
  }
@@ -106,6 +106,28 @@ export class RequestHandler {
106
106
  continue;
107
107
  }
108
108
  const sdkPrep = this.prepareSdkRequest(init?.body, model, auth, think, budget, showToast);
109
+ if (this.config.enable_log_effort_debug) {
110
+ try {
111
+ logger.log('[effort-debug] request effort resolution', {
112
+ model,
113
+ effectiveModel: sdkPrep.effectiveModel,
114
+ think,
115
+ budget,
116
+ resolvedEffort: sdkPrep.effort ?? 'undefined (not effort-capable or not thinking)',
117
+ inboundBodyKeys: Object.keys(body),
118
+ messagesCount: body.messages?.length,
119
+ reasoningSubtree: {
120
+ reasoningEffort: body.reasoningEffort,
121
+ reasoning_effort: body.reasoning_effort,
122
+ reasoning: body.reasoning,
123
+ providerOptions: body.providerOptions,
124
+ thinkingConfig: body.thinkingConfig,
125
+ providerOptionsThinkingConfig: body.providerOptions?.thinkingConfig
126
+ }
127
+ });
128
+ }
129
+ catch (e) { }
130
+ }
109
131
  const apiTimestamp = this.config.enable_log_api_request ? logger.getTimestamp() : null;
110
132
  if (apiTimestamp) {
111
133
  this.logSdkRequest(sdkPrep, acc, apiTimestamp);
@@ -31,6 +31,13 @@ export declare const KiroConfigSchema: z.ZodObject<{
31
31
  usage_tracking_enabled: z.ZodDefault<z.ZodBoolean>;
32
32
  auto_sync_kiro_cli: z.ZodDefault<z.ZodBoolean>;
33
33
  enable_log_api_request: z.ZodDefault<z.ZodBoolean>;
34
+ /**
35
+ * Enable config-gated debug logging that records the inbound
36
+ * OpenAI-compatible request body shape (top-level keys, reasoning-related
37
+ * fields only — no message content) and the resolved Kiro effort for each
38
+ * request. Independent from `enable_log_api_request`; off by default.
39
+ */
40
+ enable_log_effort_debug: z.ZodDefault<z.ZodBoolean>;
34
41
  /**
35
42
  * Default effort level for thinking models. Controls reasoning depth.
36
43
  * When set, this overrides the automatic budget-based mapping.
@@ -57,6 +64,7 @@ export declare const KiroConfigSchema: z.ZodObject<{
57
64
  usage_tracking_enabled: boolean;
58
65
  auto_sync_kiro_cli: boolean;
59
66
  enable_log_api_request: boolean;
67
+ enable_log_effort_debug: boolean;
60
68
  auto_effort_mapping: boolean;
61
69
  $schema?: string | undefined;
62
70
  idc_start_url?: string | undefined;
@@ -81,6 +89,7 @@ export declare const KiroConfigSchema: z.ZodObject<{
81
89
  usage_tracking_enabled?: boolean | undefined;
82
90
  auto_sync_kiro_cli?: boolean | undefined;
83
91
  enable_log_api_request?: boolean | undefined;
92
+ enable_log_effort_debug?: boolean | undefined;
84
93
  effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
85
94
  auto_effort_mapping?: boolean | undefined;
86
95
  }>;
@@ -63,6 +63,13 @@ export const KiroConfigSchema = z.object({
63
63
  usage_tracking_enabled: z.boolean().default(true),
64
64
  auto_sync_kiro_cli: z.boolean().default(true),
65
65
  enable_log_api_request: z.boolean().default(false),
66
+ /**
67
+ * Enable config-gated debug logging that records the inbound
68
+ * OpenAI-compatible request body shape (top-level keys, reasoning-related
69
+ * fields only — no message content) and the resolved Kiro effort for each
70
+ * request. Independent from `enable_log_api_request`; off by default.
71
+ */
72
+ enable_log_effort_debug: z.boolean().default(false),
66
73
  /**
67
74
  * Default effort level for thinking models. Controls reasoning depth.
68
75
  * When set, this overrides the automatic budget-based mapping.
@@ -90,5 +97,6 @@ export const DEFAULT_CONFIG = {
90
97
  usage_tracking_enabled: true,
91
98
  auto_sync_kiro_cli: true,
92
99
  enable_log_api_request: false,
100
+ enable_log_effort_debug: false,
93
101
  auto_effort_mapping: true
94
102
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunerpy/opencode-kiro-auth",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "OpenCode plugin for AWS Kiro (CodeWhisperer) providing access to Claude models",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",