@theia/ai-openai 1.72.0-next.52 → 1.72.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.
Files changed (33) hide show
  1. package/lib/browser/openai-frontend-application-contribution.d.ts +1 -0
  2. package/lib/browser/openai-frontend-application-contribution.d.ts.map +1 -1
  3. package/lib/browser/openai-frontend-application-contribution.js +7 -45
  4. package/lib/browser/openai-frontend-application-contribution.js.map +1 -1
  5. package/lib/common/openai-language-models-manager.d.ts +19 -41
  6. package/lib/common/openai-language-models-manager.d.ts.map +1 -1
  7. package/lib/common/openai-preferences.d.ts.map +1 -1
  8. package/lib/common/openai-preferences.js +4 -6
  9. package/lib/common/openai-preferences.js.map +1 -1
  10. package/lib/node/openai-language-model.d.ts +2 -1
  11. package/lib/node/openai-language-model.d.ts.map +1 -1
  12. package/lib/node/openai-language-model.js +2 -1
  13. package/lib/node/openai-language-model.js.map +1 -1
  14. package/lib/node/openai-language-models-manager-impl.d.ts +17 -2
  15. package/lib/node/openai-language-models-manager-impl.d.ts.map +1 -1
  16. package/lib/node/openai-language-models-manager-impl.js +25 -7
  17. package/lib/node/openai-language-models-manager-impl.js.map +1 -1
  18. package/lib/node/openai-model-defaults.d.ts +17 -0
  19. package/lib/node/openai-model-defaults.d.ts.map +1 -0
  20. package/lib/node/openai-model-defaults.js +65 -0
  21. package/lib/node/openai-model-defaults.js.map +1 -0
  22. package/lib/node/openai-model-defaults.spec.d.ts +2 -0
  23. package/lib/node/openai-model-defaults.spec.d.ts.map +1 -0
  24. package/lib/node/openai-model-defaults.spec.js +127 -0
  25. package/lib/node/openai-model-defaults.spec.js.map +1 -0
  26. package/package.json +7 -7
  27. package/src/browser/openai-frontend-application-contribution.ts +7 -51
  28. package/src/common/openai-language-models-manager.ts +19 -41
  29. package/src/common/openai-preferences.ts +4 -6
  30. package/src/node/openai-language-model.ts +2 -1
  31. package/src/node/openai-language-models-manager-impl.ts +40 -12
  32. package/src/node/openai-model-defaults.spec.ts +141 -0
  33. package/src/node/openai-model-defaults.ts +82 -0
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.getOpenAiModelDefaults = getOpenAiModelDefaults;
19
+ const GPT5_REASONING_SUPPORT = {
20
+ supportedLevels: ['off', 'minimal', 'low', 'medium', 'high', 'auto'],
21
+ defaultLevel: 'auto'
22
+ };
23
+ const O_SERIES_REASONING_SUPPORT = {
24
+ supportedLevels: ['off', 'low', 'medium', 'high', 'auto'],
25
+ defaultLevel: 'auto'
26
+ };
27
+ /**
28
+ * First matching prefix wins, so more specific prefixes must come before broader ones
29
+ * (e.g. `gpt-5.4-mini` before `gpt-5.4`). Snapshots inherit their family value
30
+ * (e.g. `gpt-4o-2024-08-06` matches `gpt-4o`).
31
+ */
32
+ const OPENAI_MODEL_FAMILIES = [
33
+ ['gpt-5.5', { contextWindow: 1_050_000, reasoningSupport: GPT5_REASONING_SUPPORT }],
34
+ ['gpt-5.4-mini', { contextWindow: 400_000, reasoningSupport: GPT5_REASONING_SUPPORT }],
35
+ ['gpt-5.4-nano', { contextWindow: 400_000, reasoningSupport: GPT5_REASONING_SUPPORT }],
36
+ ['gpt-5.4', { contextWindow: 1_050_000, reasoningSupport: GPT5_REASONING_SUPPORT }],
37
+ ['gpt-5', { contextWindow: 400_000, reasoningSupport: GPT5_REASONING_SUPPORT }],
38
+ ['gpt-4.1', { contextWindow: 1_047_576 }],
39
+ // gpt-4o-2024-05-13 predates structured output support; later snapshots support it.
40
+ ['gpt-4o-2024-05-13', { contextWindow: 128_000, supportsStructuredOutput: false }],
41
+ ['gpt-4o', { contextWindow: 128_000 }],
42
+ ['gpt-4-turbo', { contextWindow: 128_000, supportsStructuredOutput: false }],
43
+ ['gpt-4-32k', { contextWindow: 32_768, supportsStructuredOutput: false }],
44
+ ['gpt-4', { contextWindow: 8_192, supportsStructuredOutput: false }],
45
+ ['gpt-3.5', { contextWindow: 16_385, supportsStructuredOutput: false }],
46
+ ['o4', { contextWindow: 200_000, reasoningSupport: O_SERIES_REASONING_SUPPORT }],
47
+ ['o3', { contextWindow: 200_000, reasoningSupport: O_SERIES_REASONING_SUPPORT }],
48
+ ['o1-preview', {
49
+ contextWindow: 128_000,
50
+ reasoningSupport: O_SERIES_REASONING_SUPPORT,
51
+ developerMessageSettings: 'user',
52
+ supportsStructuredOutput: false
53
+ }],
54
+ ['o1-mini', {
55
+ contextWindow: 128_000,
56
+ reasoningSupport: O_SERIES_REASONING_SUPPORT,
57
+ developerMessageSettings: 'user',
58
+ supportsStructuredOutput: false
59
+ }],
60
+ ['o1', { contextWindow: 200_000, reasoningSupport: O_SERIES_REASONING_SUPPORT }],
61
+ ];
62
+ function getOpenAiModelDefaults(model) {
63
+ return OPENAI_MODEL_FAMILIES.find(([prefix]) => model.startsWith(prefix))?.[1] ?? {};
64
+ }
65
+ //# sourceMappingURL=openai-model-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-model-defaults.js","sourceRoot":"","sources":["../../src/node/openai-model-defaults.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAiEhF,wDAEC;AAhDD,MAAM,sBAAsB,GAAqB;IAC7C,eAAe,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;IACpE,YAAY,EAAE,MAAM;CACvB,CAAC;AAEF,MAAM,0BAA0B,GAAqB;IACjD,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;IACzD,YAAY,EAAE,MAAM;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAA4E;IACnG,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IACnF,CAAC,cAAc,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IACtF,CAAC,cAAc,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IACtF,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IACnF,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;IAC/E,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;IACzC,oFAAoF;IACpF,CAAC,mBAAmB,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;IACtC,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;IAC5E,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;IACzE,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;IACpE,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;IACvE,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAC;IAChF,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAC;IAChF,CAAC,YAAY,EAAE;YACX,aAAa,EAAE,OAAO;YACtB,gBAAgB,EAAE,0BAA0B;YAC5C,wBAAwB,EAAE,MAAM;YAChC,wBAAwB,EAAE,KAAK;SAClC,CAAC;IACF,CAAC,SAAS,EAAE;YACR,aAAa,EAAE,OAAO;YACtB,gBAAgB,EAAE,0BAA0B;YAC5C,wBAAwB,EAAE,MAAM;YAChC,wBAAwB,EAAE,KAAK;SAClC,CAAC;IACF,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,CAAC;CACnF,CAAC;AAEF,SAAgB,sBAAsB,CAAC,KAAa;IAChD,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACzF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=openai-model-defaults.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-model-defaults.spec.d.ts","sourceRoot":"","sources":["../../src/node/openai-model-defaults.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ const chai_1 = require("chai");
19
+ const openai_model_defaults_1 = require("./openai-model-defaults");
20
+ describe('getOpenAiModelDefaults', () => {
21
+ it('returns empty defaults for unknown models', () => {
22
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('totally-made-up-model')).to.deep.equal({});
23
+ });
24
+ describe('GPT-5.5', () => {
25
+ it('matches base and pro at 1,050,000 with GPT-5 reasoning', () => {
26
+ for (const id of ['gpt-5.5', 'gpt-5.5-pro']) {
27
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
28
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(1_050_000);
29
+ (0, chai_1.expect)(d.reasoningSupport?.supportedLevels, id).to.include('minimal');
30
+ }
31
+ });
32
+ });
33
+ describe('GPT-5.4', () => {
34
+ it('matches base and pro at 1,050,000', () => {
35
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-5.4').contextWindow).to.equal(1_050_000);
36
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-5.4-pro').contextWindow).to.equal(1_050_000);
37
+ });
38
+ it('matches mini and nano at 400,000 (specific prefix wins over `gpt-5.4`)', () => {
39
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-5.4-mini').contextWindow).to.equal(400_000);
40
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-5.4-nano').contextWindow).to.equal(400_000);
41
+ });
42
+ });
43
+ describe('GPT-5', () => {
44
+ it('matches base, pro, mini, nano, codex at 400,000', () => {
45
+ for (const id of ['gpt-5', 'gpt-5-pro', 'gpt-5-mini', 'gpt-5-nano', 'gpt-5-codex']) {
46
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)(id).contextWindow, id).to.equal(400_000);
47
+ }
48
+ });
49
+ it('exposes GPT-5 reasoning support (incl. `minimal`)', () => {
50
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-5');
51
+ (0, chai_1.expect)(d.reasoningSupport?.supportedLevels).to.include('minimal');
52
+ (0, chai_1.expect)(d.reasoningSupport?.defaultLevel).to.equal('auto');
53
+ });
54
+ });
55
+ describe('GPT-4.1', () => {
56
+ it('matches the family at 1,047,576 with no reasoning', () => {
57
+ for (const id of ['gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano']) {
58
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
59
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(1_047_576);
60
+ (0, chai_1.expect)(d.reasoningSupport, id).to.equal(undefined);
61
+ }
62
+ });
63
+ });
64
+ describe('GPT-4o', () => {
65
+ it('matches base, mini, and most snapshots at 128,000 with structured output enabled', () => {
66
+ for (const id of ['gpt-4o', 'gpt-4o-mini', 'gpt-4o-2024-08-06']) {
67
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
68
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(128_000);
69
+ (0, chai_1.expect)(d.supportsStructuredOutput, id).to.equal(undefined); // default true at the manager
70
+ }
71
+ });
72
+ it('flags the gpt-4o-2024-05-13 snapshot as not supporting structured output', () => {
73
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-4o-2024-05-13');
74
+ (0, chai_1.expect)(d.contextWindow).to.equal(128_000);
75
+ (0, chai_1.expect)(d.supportsStructuredOutput).to.equal(false);
76
+ });
77
+ });
78
+ describe('GPT-4 turbo / 32k / base', () => {
79
+ it('matches gpt-4-turbo at 128,000 (no structured output)', () => {
80
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-4-turbo-2024-04-09');
81
+ (0, chai_1.expect)(d.contextWindow).to.equal(128_000);
82
+ (0, chai_1.expect)(d.supportsStructuredOutput).to.equal(false);
83
+ });
84
+ it('matches gpt-4-32k at 32,768 (no structured output)', () => {
85
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-4-32k');
86
+ (0, chai_1.expect)(d.contextWindow).to.equal(32_768);
87
+ (0, chai_1.expect)(d.supportsStructuredOutput).to.equal(false);
88
+ });
89
+ it('falls back to gpt-4 (8,192) for the base model', () => {
90
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)('gpt-4-0613');
91
+ (0, chai_1.expect)(d.contextWindow).to.equal(8_192);
92
+ (0, chai_1.expect)(d.supportsStructuredOutput).to.equal(false);
93
+ });
94
+ });
95
+ describe('GPT-3.5', () => {
96
+ it('matches gpt-3.5-turbo and snapshots at 16,385 (no structured output)', () => {
97
+ for (const id of ['gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0125']) {
98
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
99
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(16_385);
100
+ (0, chai_1.expect)(d.supportsStructuredOutput, id).to.equal(false);
101
+ }
102
+ });
103
+ });
104
+ describe('o-series', () => {
105
+ it('matches o4 and o3 families at 200,000 with o-series reasoning', () => {
106
+ for (const id of ['o4-mini', 'o3', 'o3-mini', 'o3-pro']) {
107
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
108
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(200_000);
109
+ (0, chai_1.expect)(d.reasoningSupport?.supportedLevels, id).to.not.include('minimal');
110
+ }
111
+ });
112
+ it('matches o1 / o1-pro at 200,000', () => {
113
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('o1').contextWindow).to.equal(200_000);
114
+ (0, chai_1.expect)((0, openai_model_defaults_1.getOpenAiModelDefaults)('o1-pro').contextWindow).to.equal(200_000);
115
+ });
116
+ it('matches o1-preview / o1-mini at 128,000 with the legacy "user" role and no structured output', () => {
117
+ for (const id of ['o1-preview', 'o1-mini']) {
118
+ const d = (0, openai_model_defaults_1.getOpenAiModelDefaults)(id);
119
+ (0, chai_1.expect)(d.contextWindow, id).to.equal(128_000);
120
+ (0, chai_1.expect)(d.developerMessageSettings, id).to.equal('user');
121
+ (0, chai_1.expect)(d.supportsStructuredOutput, id).to.equal(false);
122
+ (0, chai_1.expect)(d.reasoningSupport, id).to.not.equal(undefined);
123
+ }
124
+ });
125
+ });
126
+ });
127
+ //# sourceMappingURL=openai-model-defaults.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-model-defaults.spec.js","sourceRoot":"","sources":["../../src/node/openai-model-defaults.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@theia/ai-openai",
3
- "version": "1.72.0-next.52+726081b2a",
3
+ "version": "1.72.0",
4
4
  "description": "Theia - OpenAI Integration",
5
5
  "dependencies": {
6
- "@theia/ai-core": "1.72.0-next.52+726081b2a",
7
- "@theia/core": "1.72.0-next.52+726081b2a",
8
- "@theia/filesystem": "1.72.0-next.52+726081b2a",
9
- "@theia/workspace": "1.72.0-next.52+726081b2a",
6
+ "@theia/ai-core": "1.72.0",
7
+ "@theia/core": "1.72.0",
8
+ "@theia/filesystem": "1.72.0",
9
+ "@theia/workspace": "1.72.0",
10
10
  "openai": "^6.35.0",
11
11
  "tslib": "^2.8.1"
12
12
  },
@@ -44,10 +44,10 @@
44
44
  "watch": "theiaext watch"
45
45
  },
46
46
  "devDependencies": {
47
- "@theia/ext-scripts": "1.71.0"
47
+ "@theia/ext-scripts": "1.72.0"
48
48
  },
49
49
  "nyc": {
50
50
  "extends": "../../configs/nyc.json"
51
51
  },
52
- "gitHead": "726081b2aa03827611ba4a323da1a6aaf0e9a9b9"
52
+ "gitHead": "5bc20bc672aa732fb7e05234cf63c1b514868896"
53
53
  }
@@ -121,6 +121,7 @@ export class OpenAiFrontendApplicationContribution implements FrontendApplicatio
121
121
  this.manager.createOrUpdateLanguageModels(...this.createCustomModelDescriptionsFromPreferences(customModels));
122
122
  }
123
123
 
124
+ /** Per-model capabilities are resolved by the backend from the model id; see `openai-model-defaults.ts`. */
124
125
  protected createOpenAIModelDescription(modelId: string): OpenAiModelDescription {
125
126
  const id = `${OPENAI_PROVIDER_ID}/${modelId}`;
126
127
  const maxRetries = this.aiCorePreferences.get(PREFERENCE_NAME_MAX_RETRIES) ?? 3;
@@ -130,12 +131,8 @@ export class OpenAiFrontendApplicationContribution implements FrontendApplicatio
130
131
  model: modelId,
131
132
  apiKey: true,
132
133
  apiVersion: true,
133
- developerMessageSettings: openAIModelsNotSupportingDeveloperMessages.includes(modelId) ? 'user' : 'developer',
134
- enableStreaming: !openAIModelsWithDisabledStreaming.includes(modelId),
135
- supportsStructuredOutput: !openAIModelsWithoutStructuredOutput.includes(modelId),
136
134
  maxRetries: maxRetries,
137
- useResponseApi: useResponseApi,
138
- reasoningSupport: reasoningSupportFor(modelId)
135
+ useResponseApi: useResponseApi
139
136
  };
140
137
  }
141
138
 
@@ -147,13 +144,6 @@ export class OpenAiFrontendApplicationContribution implements FrontendApplicatio
147
144
  if (!pref.model || !pref.url || typeof pref.model !== 'string' || typeof pref.url !== 'string') {
148
145
  return acc;
149
146
  }
150
- // Default to the model-name heuristic so reasoning-capable GPT-5 / o-series models exposed via
151
- // a custom endpoint still get the selector. Users can override via `reasoningSupport`
152
- // (set to `null` to disable, or to a full `ReasoningSupport` object to customize).
153
- const reasoningSupport: ReasoningSupport | undefined = 'reasoningSupport' in pref
154
- ? (isReasoningSupport(pref.reasoningSupport) ? pref.reasoningSupport : undefined)
155
- : reasoningSupportFor(pref.model);
156
-
157
147
  return [
158
148
  ...acc,
159
149
  {
@@ -163,12 +153,12 @@ export class OpenAiFrontendApplicationContribution implements FrontendApplicatio
163
153
  deployment: typeof pref.deployment === 'string' && pref.deployment ? pref.deployment : undefined,
164
154
  apiKey: typeof pref.apiKey === 'string' || pref.apiKey === true ? pref.apiKey : undefined,
165
155
  apiVersion: typeof pref.apiVersion === 'string' || pref.apiVersion === true ? pref.apiVersion : undefined,
166
- developerMessageSettings: pref.developerMessageSettings ?? 'developer',
167
- supportsStructuredOutput: pref.supportsStructuredOutput ?? true,
168
- enableStreaming: pref.enableStreaming ?? true,
156
+ developerMessageSettings: pref.developerMessageSettings,
157
+ supportsStructuredOutput: pref.supportsStructuredOutput,
158
+ enableStreaming: pref.enableStreaming,
169
159
  maxRetries: pref.maxRetries ?? maxRetries,
170
160
  useResponseApi: pref.useResponseApi ?? false,
171
- reasoningSupport
161
+ reasoningSupport: isReasoningSupport(pref.reasoningSupport) ? pref.reasoningSupport : undefined
172
162
  }
173
163
  ];
174
164
  }, []);
@@ -179,12 +169,7 @@ function isReasoningSupport(value: unknown): value is ReasoningSupport {
179
169
  return !!value && typeof value === 'object' && Array.isArray((value as ReasoningSupport).supportedLevels);
180
170
  }
181
171
 
182
- /**
183
- * Structural equality for {@link ReasoningSupport}. Used by {@link handleCustomModelChanges} to avoid
184
- * needless model re-creation when the user supplies an explicit `reasoningSupport` object via
185
- * preferences — each JSON deserialization yields a fresh object reference, so a `===` check would
186
- * always report a change even when the contents are identical.
187
- */
172
+ /** Structural equality — preference reads yield fresh objects, so identity comparison would always report a change. */
188
173
  function reasoningSupportEquals(a: ReasoningSupport | undefined, b: ReasoningSupport | undefined): boolean {
189
174
  if (a === b) {
190
175
  return true;
@@ -196,32 +181,3 @@ function reasoningSupportEquals(a: ReasoningSupport | undefined, b: ReasoningSup
196
181
  && a.supportedLevels.length === b.supportedLevels.length
197
182
  && a.supportedLevels.every((level, index) => level === b.supportedLevels[index]);
198
183
  }
199
-
200
- const openAIModelsWithDisabledStreaming: string[] = [];
201
- const openAIModelsNotSupportingDeveloperMessages = ['o1-preview', 'o1-mini'];
202
- const openAIModelsWithoutStructuredOutput = ['o1-preview', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo', 'o1-mini', 'gpt-4o-2024-05-13'];
203
-
204
- /** GPT-5 family: supports `minimal` in addition to `low | medium | high`. */
205
- const GPT5_REASONING = /^gpt-5(?:\.|-|$)/i;
206
- /** o-series reasoning models (o1, o3, o4): `low | medium | high`. */
207
- const O_SERIES_REASONING = /^o[134](?:-|$)/i;
208
-
209
- const GPT5_REASONING_SUPPORT: ReasoningSupport = {
210
- supportedLevels: ['off', 'minimal', 'low', 'medium', 'high', 'auto'],
211
- defaultLevel: 'auto'
212
- };
213
-
214
- const O_SERIES_REASONING_SUPPORT: ReasoningSupport = {
215
- supportedLevels: ['off', 'low', 'medium', 'high', 'auto'],
216
- defaultLevel: 'auto'
217
- };
218
-
219
- function reasoningSupportFor(modelId: string): ReasoningSupport | undefined {
220
- if (GPT5_REASONING.test(modelId)) {
221
- return GPT5_REASONING_SUPPORT;
222
- }
223
- if (O_SERIES_REASONING.test(modelId)) {
224
- return O_SERIES_REASONING_SUPPORT;
225
- }
226
- return undefined;
227
- }
@@ -21,56 +21,34 @@ export const OpenAiLanguageModelsManager = Symbol('OpenAiLanguageModelsManager')
21
21
  export const OPENAI_PROVIDER_ID = 'openai';
22
22
 
23
23
  export interface OpenAiModelDescription {
24
- /**
25
- * The identifier of the model which will be shown in the UI.
26
- */
24
+ /** The identifier of the model which will be shown in the UI. */
27
25
  id: string;
28
- /**
29
- * The model ID as used by the OpenAI API.
30
- */
26
+ /** The model ID as used by the OpenAI API. */
31
27
  model: string;
32
- /**
33
- * The OpenAI API compatible endpoint where the model is hosted. If not provided the default OpenAI endpoint will be used.
34
- */
28
+ /** The OpenAI API compatible endpoint where the model is hosted. If not provided the default OpenAI endpoint will be used. */
35
29
  url?: string;
36
- /**
37
- * The key for the model. If 'true' is provided the global OpenAI API key will be used.
38
- */
30
+ /** The key for the model. If `true` is provided the global OpenAI API key will be used. */
39
31
  apiKey: string | true | undefined;
40
- /**
41
- * The version for the api. If 'true' is provided the global OpenAI version will be used.
42
- */
32
+ /** The version for the api. If `true` is provided the global OpenAI version will be used. */
43
33
  apiVersion: string | true | undefined;
44
- /**
45
- * Optional deployment name for Azure OpenAI.
46
- */
34
+ /** Optional deployment name for Azure OpenAI. */
47
35
  deployment?: string;
48
- /**
49
- * Indicate whether the streaming API shall be used.
50
- */
51
- enableStreaming: boolean;
52
- /**
53
- * Property to configure the developer message of the model. Setting this property to 'user', 'system', or 'developer' will use that string as the role for the system message.
54
- * Setting it to 'mergeWithFollowingUserMessage' will prefix the following user message with the system message or convert the system message to user if the following message
55
- * is not a user message. 'skip' will remove the system message altogether.
56
- * Defaults to 'developer'.
57
- */
58
- developerMessageSettings?: 'user' | 'system' | 'developer' | 'mergeWithFollowingUserMessage' | 'skip';
59
- /**
60
- * Flag to configure whether the OpenAPI model supports structured output. Default is `true`.
61
- */
62
- supportsStructuredOutput: boolean;
63
- /**
64
- * Maximum number of retry attempts when a request fails. Default is 3.
65
- */
36
+ /** Maximum number of retry attempts when a request fails. Default is 3. */
66
37
  maxRetries: number;
38
+ /** Use the newer OpenAI Response API instead of the Chat Completion API. Default is `false`. */
39
+ useResponseApi?: boolean;
40
+ /** Indicate whether the streaming API shall be used. Defaults from the model id when unset. */
41
+ enableStreaming?: boolean;
67
42
  /**
68
- * Flag to configure whether to use the newer OpenAI Response API instead of the Chat Completion API.
69
- * For official OpenAI models, this defaults to `true`. For custom providers, users must explicitly enable it.
70
- * Default is `false` for custom models.
43
+ * Configures how system messages are handled. `'user' | 'system' | 'developer'` use that role for
44
+ * the system message; `'mergeWithFollowingUserMessage'` prepends the system message to the next
45
+ * user message (creating one when needed); `'skip'` removes system messages. Defaults from the
46
+ * model id when unset (typically `'developer'`).
71
47
  */
72
- useResponseApi?: boolean;
73
- /** When set, the UI exposes a reasoning selector and the level is translated to the OpenAI reasoning parameter. */
48
+ developerMessageSettings?: 'user' | 'system' | 'developer' | 'mergeWithFollowingUserMessage' | 'skip';
49
+ /** Whether the model supports structured output (`response_format` JSON schemas). Defaults from the model id when unset. */
50
+ supportsStructuredOutput?: boolean;
51
+ /** When set, the UI exposes a reasoning selector. Defaults from the model id when unset. */
74
52
  reasoningSupport?: ReasoningSupport;
75
53
  }
76
54
  export interface OpenAiLanguageModelsManager {
@@ -86,9 +86,8 @@ Best effort is made to convert non-conformant schemas, but errors are still poss
86
86
  \n\
87
87
  - specify `useResponseApi: true` to use the newer OpenAI Response API instead of the Chat Completion API (requires compatible endpoint).\
88
88
  \n\
89
- - specify `reasoningSupport` to opt in to the chat reasoning selector. By default this is inferred from the\
90
- `model` name (GPT-5 / o-series). Set to `null` to disable, or to an object with `supportedLevels` (e.g.\
91
- `["off", "low", "medium", "high", "auto"]`) and an optional `defaultLevel` to customize.\
89
+ - specify `reasoningSupport` to opt in to the chat reasoning selector. Provide an object with\
90
+ `supportedLevels` (e.g. `["off", "low", "medium", "high", "auto"]`) and an optional `defaultLevel`.\
92
91
  \n\
93
92
  Refer to [our documentation](https://theia-ide.org/docs/user_ai/#openai-compatible-models-eg-via-vllm) for more information.'),
94
93
  default: [],
@@ -148,10 +147,9 @@ Best effort is made to convert non-conformant schemas, but errors are still poss
148
147
  + 'Note: Will automatically fall back to Chat Completions API when tools are used.'),
149
148
  },
150
149
  reasoningSupport: {
151
- type: ['object', 'null'],
150
+ type: 'object',
152
151
  title: nls.localize('theia/ai/openai/customEndpoints/reasoningSupport/title',
153
- 'Declares the model\'s reasoning capabilities. When set the chat shows a reasoning selector'
154
- + ' for this model. Set to `null` to disable. Inferred from the model name by default.'),
152
+ 'Declares the model\'s reasoning capabilities. When set the chat shows a reasoning selector for this model.'),
155
153
  properties: {
156
154
  supportedLevels: {
157
155
  type: 'array',
@@ -106,7 +106,8 @@ export class OpenAiModel implements LanguageModel {
106
106
  public maxRetries: number = 3,
107
107
  public useResponseApi: boolean = false,
108
108
  public proxy?: string,
109
- public reasoningSupport?: ReasoningSupport
109
+ public reasoningSupport?: ReasoningSupport,
110
+ public maxInputTokens?: number
110
111
  ) { }
111
112
 
112
113
  /** Reasoning-level translation lives in {@link openAiReasoningFor}. */
@@ -14,13 +14,22 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { LanguageModelRegistry, LanguageModelStatus } from '@theia/ai-core';
17
+ import { LanguageModelRegistry, LanguageModelStatus, ReasoningSupport } from '@theia/ai-core';
18
18
  import { getProxyUrl } from '@theia/ai-core/lib/node';
19
19
  import { inject, injectable } from '@theia/core/shared/inversify';
20
- import { OpenAiModel, OpenAiModelUtils } from './openai-language-model';
20
+ import { DeveloperMessageSettings, OpenAiModel, OpenAiModelUtils } from './openai-language-model';
21
21
  import { OpenAiResponseApiUtils } from './openai-response-api-utils';
22
+ import { getOpenAiModelDefaults } from './openai-model-defaults';
22
23
  import { OpenAiLanguageModelsManager, OpenAiModelDescription } from '../common';
23
24
 
25
+ interface ResolvedModelMetadata {
26
+ maxInputTokens?: number;
27
+ reasoningSupport?: ReasoningSupport;
28
+ developerMessageSettings: DeveloperMessageSettings;
29
+ enableStreaming: boolean;
30
+ supportsStructuredOutput: boolean;
31
+ }
32
+
24
33
  @injectable()
25
34
  export class OpenAiLanguageModelsManagerImpl implements OpenAiLanguageModelsManager {
26
35
 
@@ -46,7 +55,7 @@ export class OpenAiLanguageModelsManagerImpl implements OpenAiLanguageModelsMana
46
55
  }
47
56
 
48
57
  protected calculateStatus(modelDescription: OpenAiModelDescription, effectiveApiKey: string | undefined): LanguageModelStatus {
49
- // Always mark custom models (models with url) as ready for now as we do not know about API Key requirements
58
+ // Custom models (with `url`) are always marked ready since their API key requirements are unknown.
50
59
  if (modelDescription.url) {
51
60
  return { status: 'ready' };
52
61
  }
@@ -80,8 +89,8 @@ export class OpenAiLanguageModelsManagerImpl implements OpenAiLanguageModelsMana
80
89
  };
81
90
  const proxyUrl = getProxyUrl(modelDescription.url ?? 'https://api.openai.com', this._proxyUrl);
82
91
 
83
- // Determine the effective API key for status
84
92
  const status = this.calculateStatus(modelDescription, apiKeyProvider());
93
+ const metadata = this.resolveMetadata(modelDescription);
85
94
 
86
95
  if (model) {
87
96
  if (!(model instanceof OpenAiModel)) {
@@ -90,18 +99,19 @@ export class OpenAiLanguageModelsManagerImpl implements OpenAiLanguageModelsMana
90
99
  }
91
100
  await this.languageModelRegistry.patchLanguageModel<OpenAiModel>(modelDescription.id, {
92
101
  model: modelDescription.model,
93
- enableStreaming: modelDescription.enableStreaming,
102
+ enableStreaming: metadata.enableStreaming,
94
103
  url: modelDescription.url,
95
104
  apiKey: apiKeyProvider,
96
105
  apiVersion: apiVersionProvider,
97
106
  deployment: modelDescription.deployment,
98
- developerMessageSettings: modelDescription.developerMessageSettings || 'developer',
99
- supportsStructuredOutput: modelDescription.supportsStructuredOutput,
107
+ developerMessageSettings: metadata.developerMessageSettings,
108
+ supportsStructuredOutput: metadata.supportsStructuredOutput,
100
109
  status,
101
110
  maxRetries: modelDescription.maxRetries,
102
111
  useResponseApi: modelDescription.useResponseApi ?? false,
103
112
  proxy: proxyUrl,
104
- reasoningSupport: modelDescription.reasoningSupport
113
+ reasoningSupport: metadata.reasoningSupport,
114
+ maxInputTokens: metadata.maxInputTokens
105
115
  });
106
116
  } else {
107
117
  this.languageModelRegistry.addLanguageModels([
@@ -109,25 +119,43 @@ export class OpenAiLanguageModelsManagerImpl implements OpenAiLanguageModelsMana
109
119
  modelDescription.id,
110
120
  modelDescription.model,
111
121
  status,
112
- modelDescription.enableStreaming,
122
+ metadata.enableStreaming,
113
123
  apiKeyProvider,
114
124
  apiVersionProvider,
115
- modelDescription.supportsStructuredOutput,
125
+ metadata.supportsStructuredOutput,
116
126
  modelDescription.url,
117
127
  modelDescription.deployment,
118
128
  this.openAiModelUtils,
119
129
  this.responseApiUtils,
120
- modelDescription.developerMessageSettings,
130
+ metadata.developerMessageSettings,
121
131
  modelDescription.maxRetries,
122
132
  modelDescription.useResponseApi ?? false,
123
133
  proxyUrl,
124
- modelDescription.reasoningSupport
134
+ metadata.reasoningSupport,
135
+ metadata.maxInputTokens
125
136
  )
126
137
  ]);
127
138
  }
128
139
  }
129
140
  }
130
141
 
142
+ /**
143
+ * Merges description overrides with model-id-based defaults from {@link getOpenAiModelDefaults}.
144
+ * Description fields win, allowing custom-endpoint preferences to override capabilities for
145
+ * non-OpenAI models. Custom endpoints (with a `url`) skip the context window lookup since we
146
+ * don't know which model is actually behind the endpoint.
147
+ */
148
+ protected resolveMetadata(description: OpenAiModelDescription): ResolvedModelMetadata {
149
+ const defaults = getOpenAiModelDefaults(description.model);
150
+ return {
151
+ maxInputTokens: description.url ? undefined : defaults.contextWindow,
152
+ reasoningSupport: description.reasoningSupport ?? defaults.reasoningSupport,
153
+ developerMessageSettings: description.developerMessageSettings ?? defaults.developerMessageSettings ?? 'developer',
154
+ enableStreaming: description.enableStreaming ?? defaults.supportsStreaming ?? true,
155
+ supportsStructuredOutput: description.supportsStructuredOutput ?? defaults.supportsStructuredOutput ?? true
156
+ };
157
+ }
158
+
131
159
  removeLanguageModels(...modelIds: string[]): void {
132
160
  this.languageModelRegistry.removeLanguageModels(modelIds);
133
161
  }