@sunerpy/opencode-kiro-auth 0.4.3 → 0.5.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
@@ -198,6 +198,13 @@ Details and the full JSON example: [docs/MODELS.md](docs/MODELS.md).
198
198
  > as "Thought: `<duration>`" above the final reply. No config needed. See
199
199
  > [Reasoning display](docs/CONFIGURATION.md#reasoning-display) for details.
200
200
 
201
+ > **Note:** Per-request thinking level via model variants — pick
202
+ > `kiro-auth/claude-opus-4-8-xhigh` (or similar) straight from the model
203
+ > list to pin an explicit Kiro effort level for that model, no `kiro.json`
204
+ > edit needed. Base models like `claude-opus-4-8` remain available and keep
205
+ > using the global `effort` setting. See [docs/VARIANTS.md](docs/VARIANTS.md)
206
+ > for the full variant list and why they exist.
207
+
201
208
  ## Troubleshooting
202
209
 
203
210
  Common issues — 403/AccessDeniedException with IAM Identity Center, "No
@@ -6,7 +6,7 @@ export const EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
6
6
  * Models that support the 5-value effort enum (including xhigh).
7
7
  * These models support up to 128k thinking tokens with max effort.
8
8
  */
9
- const XHIGH_CAPABLE_MODELS = new Set(['claude-opus-4.7', 'claude-opus-4.8']);
9
+ const XHIGH_CAPABLE_MODELS = new Set(['claude-opus-4.7', 'claude-opus-4.8', 'claude-sonnet-5']);
10
10
  /**
11
11
  * Models that support the 4-value effort enum (no xhigh).
12
12
  * xhigh requests on these models are clamped to max.
@@ -1,2 +1,23 @@
1
+ import type { Effort } from './types.js';
1
2
  export declare function resolveKiroModel(model: string): string;
3
+ export interface ResolvedModelVariant {
4
+ wireId: string;
5
+ effort?: Effort;
6
+ }
7
+ /**
8
+ * Resolve a (possibly effort-variant) model id into its Kiro wire id plus an
9
+ * optional parsed effort level.
10
+ *
11
+ * Parse rule (unambiguous, single source of truth):
12
+ * An id is an effort variant ONLY IF it ends with `-<suffix>` for some suffix
13
+ * in EFFORT_SUFFIXES AND the id with that `-<suffix>` removed is in
14
+ * VARIANT_BASE_ALLOWLIST. In that case the wire id is derived SOLELY from the
15
+ * base via MODEL_MAPPING and the effort SOLELY from the parsed suffix.
16
+ *
17
+ * This guarantees ids like `claude-opus-4-8-thinking`, `claude-sonnet-4-5-1m`,
18
+ * and the plain bases (`claude-opus-4-8`) are NEVER parsed as effort variants.
19
+ * Non-variant ids fall through to `resolveKiroModel` (existing behavior/throw)
20
+ * with `effort` left undefined.
21
+ */
22
+ export declare function resolveModelVariant(model: string): ResolvedModelVariant;
2
23
  export declare function getContextWindowSize(model: string): number;
@@ -6,6 +6,40 @@ export function resolveKiroModel(model) {
6
6
  }
7
7
  return resolved;
8
8
  }
9
+ const VARIANT_BASE_ALLOWLIST = new Set([
10
+ 'claude-opus-4-8',
11
+ 'claude-opus-4-7',
12
+ 'claude-sonnet-5',
13
+ 'claude-sonnet-4-6'
14
+ ]);
15
+ const EFFORT_SUFFIXES = ['low', 'medium', 'high', 'xhigh', 'max'];
16
+ /**
17
+ * Resolve a (possibly effort-variant) model id into its Kiro wire id plus an
18
+ * optional parsed effort level.
19
+ *
20
+ * Parse rule (unambiguous, single source of truth):
21
+ * An id is an effort variant ONLY IF it ends with `-<suffix>` for some suffix
22
+ * in EFFORT_SUFFIXES AND the id with that `-<suffix>` removed is in
23
+ * VARIANT_BASE_ALLOWLIST. In that case the wire id is derived SOLELY from the
24
+ * base via MODEL_MAPPING and the effort SOLELY from the parsed suffix.
25
+ *
26
+ * This guarantees ids like `claude-opus-4-8-thinking`, `claude-sonnet-4-5-1m`,
27
+ * and the plain bases (`claude-opus-4-8`) are NEVER parsed as effort variants.
28
+ * Non-variant ids fall through to `resolveKiroModel` (existing behavior/throw)
29
+ * with `effort` left undefined.
30
+ */
31
+ export function resolveModelVariant(model) {
32
+ for (const suffix of EFFORT_SUFFIXES) {
33
+ const marker = `-${suffix}`;
34
+ if (model.endsWith(marker)) {
35
+ const base = model.slice(0, -marker.length);
36
+ if (VARIANT_BASE_ALLOWLIST.has(base)) {
37
+ return { wireId: resolveKiroModel(base), effort: suffix };
38
+ }
39
+ }
40
+ }
41
+ return { wireId: resolveKiroModel(model), effort: undefined };
42
+ }
9
43
  export function getContextWindowSize(model) {
10
44
  return isLongContextModel(model) ? 1000000 : 200000;
11
45
  }
@@ -4,16 +4,16 @@ import { KIRO_CONSTANTS, buildUrl, extractRegionFromArn } from '../constants.js'
4
4
  import { buildHistory, extractToolNamesFromHistory, historyHasToolCalling, injectSystemPrompt } from '../infrastructure/transformers/history-builder.js';
5
5
  import { findOriginalToolCall, getContentText, mergeAdjacentMessages } from '../infrastructure/transformers/message-transformer.js';
6
6
  import { convertToolsToCodeWhisperer, deduplicateToolResults } from '../infrastructure/transformers/tool-transformer.js';
7
- import { getEffectiveEffort } from './effort.js';
7
+ import { getEffectiveEffort, resolveEffort } from './effort.js';
8
8
  import { convertImagesToKiroFormat, extractAllImages, extractTextFromParts } from './image-handler.js';
9
- import { resolveKiroModel } from './models.js';
9
+ import { resolveModelVariant } from './models.js';
10
10
  function buildCodeWhispererRequest(body, model, auth, think = false, budget = 20000, showToast) {
11
11
  const req = typeof body === 'string' ? JSON.parse(body) : body;
12
12
  const { messages, tools, system } = req;
13
13
  const convId = crypto.randomUUID();
14
14
  if (!messages || messages.length === 0)
15
15
  throw new Error('No messages');
16
- const resolved = resolveKiroModel(model);
16
+ const { wireId: resolved, effort: variantEffort } = resolveModelVariant(model);
17
17
  const systemMsgs = messages.filter((m) => m.role === 'system');
18
18
  const otherMsgs = messages.filter((m) => m.role !== 'system');
19
19
  let sys = system || '';
@@ -242,7 +242,7 @@ function buildCodeWhispererRequest(body, model, auth, think = false, budget = 20
242
242
  }
243
243
  }
244
244
  }
245
- return { request, resolved, convId };
245
+ return { request, resolved, convId, variantEffort };
246
246
  }
247
247
  export function transformToCodeWhisperer(url, body, model, auth, think = false, budget = 20000) {
248
248
  const { request, resolved, convId } = buildCodeWhispererRequest(body, model, auth, think, budget);
@@ -272,9 +272,10 @@ export function transformToCodeWhisperer(url, body, model, auth, think = false,
272
272
  };
273
273
  }
274
274
  export function transformToSdkRequest(body, model, auth, think = false, budget = 20000, showToast, effortConfig) {
275
- const { request, resolved, convId } = buildCodeWhispererRequest(body, model, auth, think, budget, showToast);
276
- // Resolve effort level based on config and model capabilities
277
- const effort = getEffectiveEffort(resolved, think, budget, effortConfig?.effort, effortConfig?.autoEffortMapping ?? true);
275
+ const { request, resolved, convId, variantEffort } = buildCodeWhispererRequest(body, model, auth, think, budget, showToast);
276
+ const effort = variantEffort
277
+ ? resolveEffort(resolved, variantEffort)
278
+ : getEffectiveEffort(resolved, think, budget, effortConfig?.effort, effortConfig?.autoEffortMapping ?? true);
278
279
  return {
279
280
  conversationState: request.conversationState,
280
281
  profileArn: request.profileArn,
package/dist/plugin.js CHANGED
@@ -61,11 +61,56 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
61
61
  limit: { context: 1000000, output: 64000 },
62
62
  modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
63
63
  },
64
+ 'claude-sonnet-4-6-low': {
65
+ name: 'Claude Sonnet 4.6 (low) (1.3x)',
66
+ limit: { context: 1000000, output: 64000 },
67
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
68
+ },
69
+ 'claude-sonnet-4-6-medium': {
70
+ name: 'Claude Sonnet 4.6 (medium) (1.3x)',
71
+ limit: { context: 1000000, output: 64000 },
72
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
73
+ },
74
+ 'claude-sonnet-4-6-high': {
75
+ name: 'Claude Sonnet 4.6 (high) (1.3x)',
76
+ limit: { context: 1000000, output: 64000 },
77
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
78
+ },
79
+ 'claude-sonnet-4-6-max': {
80
+ name: 'Claude Sonnet 4.6 (max) (1.3x)',
81
+ limit: { context: 1000000, output: 64000 },
82
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
83
+ },
64
84
  'claude-sonnet-5': {
65
85
  name: 'Claude Sonnet 5 (1.3x)',
66
86
  limit: { context: 1000000, output: 64000 },
67
87
  modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
68
88
  },
89
+ 'claude-sonnet-5-low': {
90
+ name: 'Claude Sonnet 5 (low) (1.3x)',
91
+ limit: { context: 1000000, output: 64000 },
92
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
93
+ },
94
+ 'claude-sonnet-5-medium': {
95
+ name: 'Claude Sonnet 5 (medium) (1.3x)',
96
+ limit: { context: 1000000, output: 64000 },
97
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
98
+ },
99
+ 'claude-sonnet-5-high': {
100
+ name: 'Claude Sonnet 5 (high) (1.3x)',
101
+ limit: { context: 1000000, output: 64000 },
102
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
103
+ },
104
+ 'claude-sonnet-5-xhigh': {
105
+ name: 'Claude Sonnet 5 (xhigh) (1.3x)',
106
+ limit: { context: 1000000, output: 64000 },
107
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
108
+ },
109
+ 'claude-sonnet-5-max': {
110
+ name: 'Claude Sonnet 5 (max) (1.3x)',
111
+ limit: { context: 1000000, output: 64000 },
112
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
113
+ },
69
114
  // Claude Haiku
70
115
  'claude-haiku-4-5': {
71
116
  name: 'Claude Haiku 4.5 (0.4x)',
@@ -88,11 +133,61 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
88
133
  limit: { context: 1000000, output: 64000 },
89
134
  modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
90
135
  },
136
+ 'claude-opus-4-7-low': {
137
+ name: 'Claude Opus 4.7 (low) (2.2x)',
138
+ limit: { context: 1000000, output: 64000 },
139
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
140
+ },
141
+ 'claude-opus-4-7-medium': {
142
+ name: 'Claude Opus 4.7 (medium) (2.2x)',
143
+ limit: { context: 1000000, output: 64000 },
144
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
145
+ },
146
+ 'claude-opus-4-7-high': {
147
+ name: 'Claude Opus 4.7 (high) (2.2x)',
148
+ limit: { context: 1000000, output: 64000 },
149
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
150
+ },
151
+ 'claude-opus-4-7-xhigh': {
152
+ name: 'Claude Opus 4.7 (xhigh) (2.2x)',
153
+ limit: { context: 1000000, output: 64000 },
154
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
155
+ },
156
+ 'claude-opus-4-7-max': {
157
+ name: 'Claude Opus 4.7 (max) (2.2x)',
158
+ limit: { context: 1000000, output: 64000 },
159
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
160
+ },
91
161
  'claude-opus-4-8': {
92
162
  name: 'Claude Opus 4.8 (2.2x)',
93
163
  limit: { context: 1000000, output: 64000 },
94
164
  modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
95
165
  },
166
+ 'claude-opus-4-8-low': {
167
+ name: 'Claude Opus 4.8 (low) (2.2x)',
168
+ limit: { context: 1000000, output: 64000 },
169
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
170
+ },
171
+ 'claude-opus-4-8-medium': {
172
+ name: 'Claude Opus 4.8 (medium) (2.2x)',
173
+ limit: { context: 1000000, output: 64000 },
174
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
175
+ },
176
+ 'claude-opus-4-8-high': {
177
+ name: 'Claude Opus 4.8 (high) (2.2x)',
178
+ limit: { context: 1000000, output: 64000 },
179
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
180
+ },
181
+ 'claude-opus-4-8-xhigh': {
182
+ name: 'Claude Opus 4.8 (xhigh) (2.2x)',
183
+ limit: { context: 1000000, output: 64000 },
184
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
185
+ },
186
+ 'claude-opus-4-8-max': {
187
+ name: 'Claude Opus 4.8 (max) (2.2x)',
188
+ limit: { context: 1000000, output: 64000 },
189
+ modalities: { input: ['text', 'image', 'pdf'], output: ['text'] }
190
+ },
96
191
  'claude-opus-4-8-thinking': {
97
192
  name: 'Claude Opus 4.8 Thinking (2.2x)',
98
193
  limit: { context: 1000000, output: 64000 },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunerpy/opencode-kiro-auth",
3
- "version": "0.4.3",
3
+ "version": "0.5.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",