@sunerpy/opencode-kiro-auth 0.12.0 → 0.13.1
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/dist/constants.d.ts +3 -0
- package/dist/constants.js +33 -1
- package/dist/core/request/error-handler.d.ts +1 -0
- package/dist/core/request/error-handler.js +7 -0
- package/dist/core/request/request-handler.js +19 -7
- package/dist/plugin/effort.d.ts +9 -0
- package/dist/plugin/effort.js +27 -1
- package/dist/plugin/models.d.ts +1 -0
- package/dist/plugin/models.js +24 -3
- package/dist/plugin/sdk-client.js +5 -8
- package/dist/plugin.js +78 -3
- package/package.json +1 -1
package/dist/constants.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ export declare const KIRO_CONSTANTS: {
|
|
|
19
19
|
export declare const MODEL_MAPPING: Record<string, string>;
|
|
20
20
|
export declare const SUPPORTED_MODELS: string[];
|
|
21
21
|
export declare function isLongContextModel(model: string): boolean;
|
|
22
|
+
export declare const DEFAULT_MODEL_CONTEXT_LIMIT = 200000;
|
|
23
|
+
export declare const MODEL_CONTEXT_LIMITS: Record<string, number>;
|
|
24
|
+
export declare function getModelContextLimit(baseModel: string): number;
|
|
22
25
|
export declare const KIRO_AUTH_SERVICE: {
|
|
23
26
|
ENDPOINT: string;
|
|
24
27
|
SSO_OIDC_ENDPOINT: string;
|
package/dist/constants.js
CHANGED
|
@@ -81,7 +81,8 @@ export const MODEL_MAPPING = {
|
|
|
81
81
|
'minimax-m2.5': 'minimax-m2.5',
|
|
82
82
|
'minimax-m2.1': 'minimax-m2.1',
|
|
83
83
|
'qwen3-coder-next': 'qwen3-coder-next',
|
|
84
|
-
// OpenAI GPT 5.6 — probe-confirmed (200, us-east-1); other naming guesses 400.
|
|
84
|
+
// OpenAI GPT 5.6 — probe-confirmed (200, us-east-1); other naming guesses 400.
|
|
85
|
+
// Effort variants (-low..-max) are parsed by resolveModelVariant, not mapped here.
|
|
85
86
|
'gpt-5.6-sol': 'gpt-5.6-sol',
|
|
86
87
|
'gpt-5.6-terra': 'gpt-5.6-terra',
|
|
87
88
|
'gpt-5.6-luna': 'gpt-5.6-luna',
|
|
@@ -97,6 +98,37 @@ const LONG_CONTEXT_MODELS = new Set(Object.keys(MODEL_MAPPING).filter((k) => k.i
|
|
|
97
98
|
export function isLongContextModel(model) {
|
|
98
99
|
return LONG_CONTEXT_MODELS.has(model);
|
|
99
100
|
}
|
|
101
|
+
// SSOT for token accounting, keyed by BASE model id (effort/thinking suffix
|
|
102
|
+
// stripped). Values MUST equal the limit.context advertised in src/plugin.ts —
|
|
103
|
+
// enforced by context-window.test.ts. Drift makes OpenCode under-count usage and
|
|
104
|
+
// skip auto-compaction until Kiro hard-rejects with 400 "Input is too long."
|
|
105
|
+
export const DEFAULT_MODEL_CONTEXT_LIMIT = 200000;
|
|
106
|
+
export const MODEL_CONTEXT_LIMITS = {
|
|
107
|
+
auto: 200000,
|
|
108
|
+
'claude-haiku-4-5': 200000,
|
|
109
|
+
'claude-sonnet-4': 200000,
|
|
110
|
+
'claude-sonnet-4-5': 200000,
|
|
111
|
+
'claude-sonnet-4-5-1m': 1000000,
|
|
112
|
+
'claude-sonnet-4-6': 1000000,
|
|
113
|
+
'claude-sonnet-4-6-1m': 1000000,
|
|
114
|
+
'claude-sonnet-5': 1000000,
|
|
115
|
+
'claude-opus-4-5': 200000,
|
|
116
|
+
'claude-opus-4-6': 1000000,
|
|
117
|
+
'claude-opus-4-6-1m': 1000000,
|
|
118
|
+
'claude-opus-4-7': 1000000,
|
|
119
|
+
'claude-opus-4-8': 1000000,
|
|
120
|
+
'deepseek-3.2': 128000,
|
|
121
|
+
'glm-5': 200000,
|
|
122
|
+
'minimax-m2.5': 200000,
|
|
123
|
+
'minimax-m2.1': 200000,
|
|
124
|
+
'qwen3-coder-next': 256000,
|
|
125
|
+
'gpt-5.6-sol': 272000,
|
|
126
|
+
'gpt-5.6-terra': 272000,
|
|
127
|
+
'gpt-5.6-luna': 272000
|
|
128
|
+
};
|
|
129
|
+
export function getModelContextLimit(baseModel) {
|
|
130
|
+
return MODEL_CONTEXT_LIMITS[baseModel] ?? DEFAULT_MODEL_CONTEXT_LIMIT;
|
|
131
|
+
}
|
|
100
132
|
export const KIRO_AUTH_SERVICE = {
|
|
101
133
|
ENDPOINT: 'https://prod.{{region}}.auth.desktop.kiro.dev',
|
|
102
134
|
SSO_OIDC_ENDPOINT: 'https://oidc.{{region}}.amazonaws.com',
|
|
@@ -3,6 +3,7 @@ import type { AccountManager } from '../../plugin/accounts.js';
|
|
|
3
3
|
import type { ManagedAccount } from '../../plugin/types.js';
|
|
4
4
|
import type { ForceRefreshResult } from '../auth/token-refresher.js';
|
|
5
5
|
type ToastFunction = (message: string, variant: 'info' | 'warning' | 'success' | 'error') => void;
|
|
6
|
+
export declare function isKiroContextOverflowBody(text: string): boolean;
|
|
6
7
|
export interface RequestContext {
|
|
7
8
|
retry: number;
|
|
8
9
|
forcedRefreshAccountIds?: Set<string>;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { isAccessTokenError, toDeadReason } from '../../plugin/health.js';
|
|
2
|
+
// Unambiguous Kiro size-overflow 400 signals only. The generic "Improperly
|
|
3
|
+
// formed request." is deliberately excluded: it has no size discriminator in
|
|
4
|
+
// the body, so matching it would wrongly reclassify unrelated 400s as overflow.
|
|
5
|
+
const KIRO_CONTEXT_OVERFLOW_PATTERNS = [/input is too long/i, /CONTENT_LENGTH_EXCEEDS_THRESHOLD/i];
|
|
6
|
+
export function isKiroContextOverflowBody(text) {
|
|
7
|
+
return KIRO_CONTEXT_OVERFLOW_PATTERNS.some((p) => p.test(text));
|
|
8
|
+
}
|
|
2
9
|
export class ErrorHandler {
|
|
3
10
|
config;
|
|
4
11
|
accountManager;
|
|
@@ -7,7 +7,7 @@ import { syncFromKiroCli } from '../../plugin/sync/kiro-cli.js';
|
|
|
7
7
|
import { AccountSelector } from '../account/account-selector.js';
|
|
8
8
|
import { UsageTracker } from '../account/usage-tracker.js';
|
|
9
9
|
import { TokenRefresher } from '../auth/token-refresher.js';
|
|
10
|
-
import { ErrorHandler } from './error-handler.js';
|
|
10
|
+
import { ErrorHandler, isKiroContextOverflowBody } from './error-handler.js';
|
|
11
11
|
import { ResponseHandler } from './response-handler.js';
|
|
12
12
|
import { RetryStrategy } from './retry-strategy.js';
|
|
13
13
|
const KIRO_API_PATTERN = /^(https?:\/\/)?q\.[a-z0-9-]+\.amazonaws\.com/;
|
|
@@ -155,12 +155,14 @@ export class RequestHandler {
|
|
|
155
155
|
if (apiTimestamp) {
|
|
156
156
|
this.logSdkError(sdkPrep, e, acc, apiTimestamp);
|
|
157
157
|
}
|
|
158
|
-
const
|
|
158
|
+
const errorBody = JSON.stringify({ message: e.message, __type: e.name });
|
|
159
|
+
const errorStatusText = e.name || 'Error';
|
|
160
|
+
const jsonHeaders = { 'Content-Type': 'application/json' };
|
|
161
|
+
const errorResult = await this.errorHandler.handle(e, new Response(errorBody, {
|
|
159
162
|
status: httpStatus,
|
|
160
|
-
statusText:
|
|
161
|
-
headers:
|
|
162
|
-
});
|
|
163
|
-
const errorResult = await this.errorHandler.handle(e, mockResponse, acc, handlerContext, showToast);
|
|
163
|
+
statusText: errorStatusText,
|
|
164
|
+
headers: jsonHeaders
|
|
165
|
+
}), acc, handlerContext, showToast);
|
|
164
166
|
if (errorResult.shouldRetry) {
|
|
165
167
|
if (errorResult.newContext) {
|
|
166
168
|
handlerContext = errorResult.newContext;
|
|
@@ -170,7 +172,17 @@ export class RequestHandler {
|
|
|
170
172
|
}
|
|
171
173
|
continue;
|
|
172
174
|
}
|
|
173
|
-
|
|
175
|
+
// Terminal, non-retryable HTTP error. Return a fresh Response carrying
|
|
176
|
+
// the real Kiro body so @ai-sdk/openai-compatible produces an
|
|
177
|
+
// APICallError with status+body (not a bare Error that OpenCode
|
|
178
|
+
// degrades to UnknownError). Remap size-overflow 400s to 413 so
|
|
179
|
+
// OpenCode classifies context_overflow and auto-compacts.
|
|
180
|
+
const terminalStatus = httpStatus === 400 && isKiroContextOverflowBody(e.message ?? '') ? 413 : httpStatus;
|
|
181
|
+
return new Response(errorBody, {
|
|
182
|
+
status: terminalStatus,
|
|
183
|
+
statusText: errorStatusText,
|
|
184
|
+
headers: jsonHeaders
|
|
185
|
+
});
|
|
174
186
|
}
|
|
175
187
|
const networkResult = await this.errorHandler.handleNetworkError(e, handlerContext, showToast);
|
|
176
188
|
if (networkResult.shouldRetry) {
|
package/dist/plugin/effort.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export declare function supportsEffort(kiroModel: string): boolean;
|
|
|
11
11
|
* Check if a model supports xhigh effort level.
|
|
12
12
|
*/
|
|
13
13
|
export declare function supportsXHighEffort(kiroModel: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Build the additionalModelRequestFields payload carrying the effort level.
|
|
16
|
+
*
|
|
17
|
+
* GPT and Claude take effort through different, mutually-exclusive wire fields
|
|
18
|
+
* (each rejects the other's with HTTP 400, probe-confirmed):
|
|
19
|
+
* - GPT (Mantle): `reasoning.effort`
|
|
20
|
+
* - Claude: `output_config.effort`
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildEffortRequestFields(kiroModel: string, effort: Effort): Record<string, unknown>;
|
|
14
23
|
/**
|
|
15
24
|
* Resolve effort level for a given model.
|
|
16
25
|
* - Returns undefined if model doesn't support effort
|
package/dist/plugin/effort.js
CHANGED
|
@@ -2,11 +2,23 @@
|
|
|
2
2
|
* Effort levels ordered from lowest to highest reasoning depth.
|
|
3
3
|
*/
|
|
4
4
|
export const EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
5
|
+
/**
|
|
6
|
+
* OpenAI GPT models (Kiro proxies these via Mantle). They accept the effort enum
|
|
7
|
+
* through a DIFFERENT wire field than Claude — see buildEffortRequestFields.
|
|
8
|
+
* All five levels (incl. xhigh/max) are probe-confirmed: credit usage scales
|
|
9
|
+
* monotonically low<medium<high<xhigh<max (.omo/evidence/task-gpt56-effort-probe.txt).
|
|
10
|
+
*/
|
|
11
|
+
const GPT_REASONING_MODELS = new Set(['gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna']);
|
|
5
12
|
/**
|
|
6
13
|
* Models that support the 5-value effort enum (including xhigh).
|
|
7
14
|
* These models support up to 128k thinking tokens with max effort.
|
|
8
15
|
*/
|
|
9
|
-
const XHIGH_CAPABLE_MODELS = new Set([
|
|
16
|
+
const XHIGH_CAPABLE_MODELS = new Set([
|
|
17
|
+
'claude-opus-4.7',
|
|
18
|
+
'claude-opus-4.8',
|
|
19
|
+
'claude-sonnet-5',
|
|
20
|
+
...GPT_REASONING_MODELS
|
|
21
|
+
]);
|
|
10
22
|
/**
|
|
11
23
|
* Models that support the 4-value effort enum (no xhigh).
|
|
12
24
|
* xhigh requests on these models are clamped to max.
|
|
@@ -33,6 +45,20 @@ export function supportsEffort(kiroModel) {
|
|
|
33
45
|
export function supportsXHighEffort(kiroModel) {
|
|
34
46
|
return XHIGH_CAPABLE_MODELS.has(kiroModel);
|
|
35
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Build the additionalModelRequestFields payload carrying the effort level.
|
|
50
|
+
*
|
|
51
|
+
* GPT and Claude take effort through different, mutually-exclusive wire fields
|
|
52
|
+
* (each rejects the other's with HTTP 400, probe-confirmed):
|
|
53
|
+
* - GPT (Mantle): `reasoning.effort`
|
|
54
|
+
* - Claude: `output_config.effort`
|
|
55
|
+
*/
|
|
56
|
+
export function buildEffortRequestFields(kiroModel, effort) {
|
|
57
|
+
if (GPT_REASONING_MODELS.has(kiroModel)) {
|
|
58
|
+
return { reasoning: { effort } };
|
|
59
|
+
}
|
|
60
|
+
return { output_config: { effort } };
|
|
61
|
+
}
|
|
36
62
|
/**
|
|
37
63
|
* Resolve effort level for a given model.
|
|
38
64
|
* - Returns undefined if model doesn't support effort
|
package/dist/plugin/models.d.ts
CHANGED
|
@@ -20,4 +20,5 @@ export interface ResolvedModelVariant {
|
|
|
20
20
|
* with `effort` left undefined.
|
|
21
21
|
*/
|
|
22
22
|
export declare function resolveModelVariant(model: string): ResolvedModelVariant;
|
|
23
|
+
export declare function stripModelSuffix(model: string): string;
|
|
23
24
|
export declare function getContextWindowSize(model: string): number;
|
package/dist/plugin/models.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MODEL_MAPPING, SUPPORTED_MODELS,
|
|
1
|
+
import { MODEL_MAPPING, SUPPORTED_MODELS, getModelContextLimit } from '../constants.js';
|
|
2
2
|
export function resolveKiroModel(model) {
|
|
3
3
|
const resolved = MODEL_MAPPING[model];
|
|
4
4
|
if (!resolved) {
|
|
@@ -10,7 +10,10 @@ const VARIANT_BASE_ALLOWLIST = new Set([
|
|
|
10
10
|
'claude-opus-4-8',
|
|
11
11
|
'claude-opus-4-7',
|
|
12
12
|
'claude-sonnet-5',
|
|
13
|
-
'claude-sonnet-4-6'
|
|
13
|
+
'claude-sonnet-4-6',
|
|
14
|
+
'gpt-5.6-sol',
|
|
15
|
+
'gpt-5.6-terra',
|
|
16
|
+
'gpt-5.6-luna'
|
|
14
17
|
]);
|
|
15
18
|
const EFFORT_SUFFIXES = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
16
19
|
/**
|
|
@@ -40,6 +43,24 @@ export function resolveModelVariant(model) {
|
|
|
40
43
|
}
|
|
41
44
|
return { wireId: resolveKiroModel(model), effort: undefined };
|
|
42
45
|
}
|
|
46
|
+
export function stripModelSuffix(model) {
|
|
47
|
+
for (const suffix of EFFORT_SUFFIXES) {
|
|
48
|
+
const marker = `-${suffix}`;
|
|
49
|
+
if (model.endsWith(marker)) {
|
|
50
|
+
const base = model.slice(0, -marker.length);
|
|
51
|
+
if (VARIANT_BASE_ALLOWLIST.has(base)) {
|
|
52
|
+
return base;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (model.endsWith('-thinking')) {
|
|
57
|
+
const base = model.slice(0, -'-thinking'.length);
|
|
58
|
+
if (MODEL_MAPPING[base]) {
|
|
59
|
+
return base;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return model;
|
|
63
|
+
}
|
|
43
64
|
export function getContextWindowSize(model) {
|
|
44
|
-
return
|
|
65
|
+
return getModelContextLimit(stripModelSuffix(model));
|
|
45
66
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CodeWhispererStreamingClient } from '@aws/codewhisperer-streaming-client';
|
|
2
2
|
import { KIRO_CONSTANTS } from '../constants.js';
|
|
3
|
+
import { buildEffortRequestFields } from './effort.js';
|
|
3
4
|
const clientCache = new Map();
|
|
4
5
|
const KIRO_CLI_MAX_ATTEMPTS = 3;
|
|
5
6
|
export function createSdkClient(auth, region, effort) {
|
|
@@ -22,19 +23,15 @@ export function createSdkClient(auth, region, effort) {
|
|
|
22
23
|
args.request.headers['x-amzn-kiro-agent-mode'] = 'vibe';
|
|
23
24
|
return next(args);
|
|
24
25
|
}, { step: 'build', name: 'addKiroHeaders' });
|
|
25
|
-
//
|
|
26
|
+
// Effort wire shape differs per family (GPT: reasoning.effort, Claude:
|
|
27
|
+
// output_config.effort; each 400s the other), so derive it from the body's modelId.
|
|
26
28
|
if (effort) {
|
|
27
29
|
client.middlewareStack.add((next) => async (args) => {
|
|
28
|
-
// The SDK serializes input to args.input, we need to modify the body
|
|
29
|
-
// before it's sent. The body is in args.request.body as a string.
|
|
30
30
|
if (args.request?.body) {
|
|
31
31
|
try {
|
|
32
32
|
const body = JSON.parse(args.request.body);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
effort
|
|
36
|
-
}
|
|
37
|
-
};
|
|
33
|
+
const wireModel = body?.conversationState?.currentMessage?.userInputMessage?.modelId;
|
|
34
|
+
body.additionalModelRequestFields = buildEffortRequestFields(wireModel, effort);
|
|
38
35
|
args.request.body = JSON.stringify(body);
|
|
39
36
|
}
|
|
40
37
|
catch {
|
package/dist/plugin.js
CHANGED
|
@@ -263,17 +263,92 @@ export const createKiroPlugin = (id) => async ({ client, directory }) => {
|
|
|
263
263
|
'gpt-5.6-sol': {
|
|
264
264
|
name: 'GPT 5.6 Sol (2.4x)',
|
|
265
265
|
limit: { context: 272000, output: 64000 },
|
|
266
|
-
modalities: { input: ['text'], output: ['text'] }
|
|
266
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
267
|
+
},
|
|
268
|
+
'gpt-5.6-sol-low': {
|
|
269
|
+
name: 'GPT 5.6 Sol (low) (2.4x)',
|
|
270
|
+
limit: { context: 272000, output: 64000 },
|
|
271
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
272
|
+
},
|
|
273
|
+
'gpt-5.6-sol-medium': {
|
|
274
|
+
name: 'GPT 5.6 Sol (medium) (2.4x)',
|
|
275
|
+
limit: { context: 272000, output: 64000 },
|
|
276
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
277
|
+
},
|
|
278
|
+
'gpt-5.6-sol-high': {
|
|
279
|
+
name: 'GPT 5.6 Sol (high) (2.4x)',
|
|
280
|
+
limit: { context: 272000, output: 64000 },
|
|
281
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
282
|
+
},
|
|
283
|
+
'gpt-5.6-sol-xhigh': {
|
|
284
|
+
name: 'GPT 5.6 Sol (xhigh) (2.4x)',
|
|
285
|
+
limit: { context: 272000, output: 64000 },
|
|
286
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
287
|
+
},
|
|
288
|
+
'gpt-5.6-sol-max': {
|
|
289
|
+
name: 'GPT 5.6 Sol (max) (2.4x)',
|
|
290
|
+
limit: { context: 272000, output: 64000 },
|
|
291
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
267
292
|
},
|
|
268
293
|
'gpt-5.6-terra': {
|
|
269
294
|
name: 'GPT 5.6 Terra (1.2x)',
|
|
270
295
|
limit: { context: 272000, output: 64000 },
|
|
271
|
-
modalities: { input: ['text'], output: ['text'] }
|
|
296
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
297
|
+
},
|
|
298
|
+
'gpt-5.6-terra-low': {
|
|
299
|
+
name: 'GPT 5.6 Terra (low) (1.2x)',
|
|
300
|
+
limit: { context: 272000, output: 64000 },
|
|
301
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
302
|
+
},
|
|
303
|
+
'gpt-5.6-terra-medium': {
|
|
304
|
+
name: 'GPT 5.6 Terra (medium) (1.2x)',
|
|
305
|
+
limit: { context: 272000, output: 64000 },
|
|
306
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
307
|
+
},
|
|
308
|
+
'gpt-5.6-terra-high': {
|
|
309
|
+
name: 'GPT 5.6 Terra (high) (1.2x)',
|
|
310
|
+
limit: { context: 272000, output: 64000 },
|
|
311
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
312
|
+
},
|
|
313
|
+
'gpt-5.6-terra-xhigh': {
|
|
314
|
+
name: 'GPT 5.6 Terra (xhigh) (1.2x)',
|
|
315
|
+
limit: { context: 272000, output: 64000 },
|
|
316
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
317
|
+
},
|
|
318
|
+
'gpt-5.6-terra-max': {
|
|
319
|
+
name: 'GPT 5.6 Terra (max) (1.2x)',
|
|
320
|
+
limit: { context: 272000, output: 64000 },
|
|
321
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
272
322
|
},
|
|
273
323
|
'gpt-5.6-luna': {
|
|
274
324
|
name: 'GPT 5.6 Luna',
|
|
275
325
|
limit: { context: 272000, output: 64000 },
|
|
276
|
-
modalities: { input: ['text'], output: ['text'] }
|
|
326
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
327
|
+
},
|
|
328
|
+
'gpt-5.6-luna-low': {
|
|
329
|
+
name: 'GPT 5.6 Luna (low)',
|
|
330
|
+
limit: { context: 272000, output: 64000 },
|
|
331
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
332
|
+
},
|
|
333
|
+
'gpt-5.6-luna-medium': {
|
|
334
|
+
name: 'GPT 5.6 Luna (medium)',
|
|
335
|
+
limit: { context: 272000, output: 64000 },
|
|
336
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
337
|
+
},
|
|
338
|
+
'gpt-5.6-luna-high': {
|
|
339
|
+
name: 'GPT 5.6 Luna (high)',
|
|
340
|
+
limit: { context: 272000, output: 64000 },
|
|
341
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
342
|
+
},
|
|
343
|
+
'gpt-5.6-luna-xhigh': {
|
|
344
|
+
name: 'GPT 5.6 Luna (xhigh)',
|
|
345
|
+
limit: { context: 272000, output: 64000 },
|
|
346
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
347
|
+
},
|
|
348
|
+
'gpt-5.6-luna-max': {
|
|
349
|
+
name: 'GPT 5.6 Luna (max)',
|
|
350
|
+
limit: { context: 272000, output: 64000 },
|
|
351
|
+
modalities: { input: ['text', 'image'], output: ['text'] }
|
|
277
352
|
}
|
|
278
353
|
};
|
|
279
354
|
}
|