@glwhappen/web-code 1.32.9 → 1.32.11

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 (167) hide show
  1. package/README.de.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/README.ru.md +1 -1
  5. package/README.tr.md +1 -1
  6. package/README.zh-CN.md +1 -1
  7. package/dist/api-docs.html +6 -7
  8. package/dist/assets/{index-D_7CSvqO.js → index-CBo8yakG.js} +276 -261
  9. package/dist/assets/index-Dl5QP21C.css +32 -0
  10. package/dist/index.html +2 -2
  11. package/dist/modelConstants.js +841 -0
  12. package/dist-server/server/claude-sdk.js +57 -34
  13. package/dist-server/server/claude-sdk.js.map +1 -1
  14. package/dist-server/server/cursor-cli.js +6 -3
  15. package/dist-server/server/cursor-cli.js.map +1 -1
  16. package/dist-server/server/gemini-cli.js +3 -1
  17. package/dist-server/server/gemini-cli.js.map +1 -1
  18. package/dist-server/server/gemini-response-handler.js +34 -0
  19. package/dist-server/server/gemini-response-handler.js.map +1 -1
  20. package/dist-server/server/index.js +131 -19
  21. package/dist-server/server/index.js.map +1 -1
  22. package/dist-server/server/modules/database/index.js +1 -0
  23. package/dist-server/server/modules/database/index.js.map +1 -1
  24. package/dist-server/server/modules/projects/services/project-management.service.js +1 -0
  25. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -1
  26. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +4 -0
  27. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
  28. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +143 -0
  29. package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -0
  30. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  31. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  32. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +84 -0
  33. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -0
  34. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +7 -39
  35. package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
  36. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  37. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  38. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +754 -0
  39. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -0
  40. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +2 -15
  41. package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
  42. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +2 -0
  43. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
  44. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +27 -0
  45. package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -0
  46. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +3 -9
  47. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
  48. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +2 -0
  49. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
  50. package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js +92 -0
  51. package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js.map +1 -0
  52. package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js +181 -0
  53. package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js.map +1 -0
  54. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +267 -0
  55. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -0
  56. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +115 -0
  57. package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -0
  58. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +410 -0
  59. package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -0
  60. package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js +62 -0
  61. package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js.map +1 -0
  62. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +19 -0
  63. package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -0
  64. package/dist-server/server/modules/providers/provider.registry.js +2 -0
  65. package/dist-server/server/modules/providers/provider.registry.js.map +1 -1
  66. package/dist-server/server/modules/providers/provider.routes.js +42 -1
  67. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  68. package/dist-server/server/modules/providers/services/mcp.service.js +1 -9
  69. package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
  70. package/dist-server/server/modules/providers/services/provider-models.service.js +199 -0
  71. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -0
  72. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +1 -0
  73. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
  74. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +7 -0
  75. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
  76. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
  77. package/dist-server/server/modules/providers/tests/mcp.test.js +73 -6
  78. package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -1
  79. package/dist-server/server/modules/providers/tests/opencode-models.test.js +66 -0
  80. package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -0
  81. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +264 -0
  82. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -0
  83. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +270 -0
  84. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -0
  85. package/dist-server/server/modules/providers/tests/skills.test.js +33 -0
  86. package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
  87. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +18 -1
  88. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  89. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +9 -1
  90. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
  91. package/dist-server/server/openai-codex.js +32 -4
  92. package/dist-server/server/openai-codex.js.map +1 -1
  93. package/dist-server/server/opencode-cli.js +287 -0
  94. package/dist-server/server/opencode-cli.js.map +1 -0
  95. package/dist-server/server/opencode-cli.test.js +84 -0
  96. package/dist-server/server/opencode-cli.test.js.map +1 -0
  97. package/dist-server/server/routes/agent.js +21 -8
  98. package/dist-server/server/routes/agent.js.map +1 -1
  99. package/dist-server/server/routes/commands.js +202 -209
  100. package/dist-server/server/routes/commands.js.map +1 -1
  101. package/dist-server/server/routes/cursor.js +2 -2
  102. package/dist-server/server/routes/cursor.js.map +1 -1
  103. package/dist-server/server/routes/settings.js +0 -10
  104. package/dist-server/server/routes/settings.js.map +1 -1
  105. package/dist-server/server/routes/tests/commands.test.js +76 -0
  106. package/dist-server/server/routes/tests/commands.test.js.map +1 -0
  107. package/dist-server/server/shared/utils.js +286 -0
  108. package/dist-server/server/shared/utils.js.map +1 -1
  109. package/package.json +3 -1
  110. package/public/api-docs.html +878 -0
  111. package/public/modelConstants.js +841 -0
  112. package/server/claude-sdk.js +64 -35
  113. package/server/cursor-cli.js +6 -3
  114. package/server/gemini-cli.js +7 -1
  115. package/server/gemini-response-handler.js +38 -0
  116. package/server/index.js +150 -19
  117. package/server/modules/database/index.ts +1 -0
  118. package/server/modules/projects/services/project-management.service.ts +2 -0
  119. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +7 -1
  120. package/server/modules/providers/README.md +11 -3
  121. package/server/modules/providers/list/claude/claude-models.provider.ts +193 -0
  122. package/server/modules/providers/list/claude/claude.provider.ts +3 -0
  123. package/server/modules/providers/list/codex/codex-models.provider.ts +125 -0
  124. package/server/modules/providers/list/codex/codex-skills.provider.ts +10 -50
  125. package/server/modules/providers/list/codex/codex.provider.ts +3 -0
  126. package/server/modules/providers/list/cursor/cursor-models.provider.ts +820 -0
  127. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +7 -20
  128. package/server/modules/providers/list/cursor/cursor.provider.ts +3 -0
  129. package/server/modules/providers/list/gemini/gemini-models.provider.ts +42 -0
  130. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +3 -10
  131. package/server/modules/providers/list/gemini/gemini.provider.ts +3 -0
  132. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +111 -0
  133. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -0
  134. package/server/modules/providers/list/opencode/opencode-models.provider.ts +339 -0
  135. package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +158 -0
  136. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +506 -0
  137. package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -0
  138. package/server/modules/providers/list/opencode/opencode.provider.ts +27 -0
  139. package/server/modules/providers/provider.registry.ts +2 -0
  140. package/server/modules/providers/provider.routes.ts +62 -2
  141. package/server/modules/providers/services/mcp.service.ts +1 -12
  142. package/server/modules/providers/services/provider-models.service.ts +325 -0
  143. package/server/modules/providers/services/session-synchronizer.service.ts +1 -0
  144. package/server/modules/providers/services/sessions-watcher.service.ts +8 -0
  145. package/server/modules/providers/shared/base/abstract.provider.ts +2 -0
  146. package/server/modules/providers/tests/mcp.test.ts +93 -6
  147. package/server/modules/providers/tests/opencode-models.test.ts +73 -0
  148. package/server/modules/providers/tests/opencode-sessions.test.ts +336 -0
  149. package/server/modules/providers/tests/provider-models.service.test.ts +318 -0
  150. package/server/modules/providers/tests/skills.test.ts +66 -0
  151. package/server/modules/websocket/services/chat-websocket.service.ts +21 -1
  152. package/server/modules/websocket/services/shell-websocket.service.ts +9 -0
  153. package/server/openai-codex.js +40 -4
  154. package/server/opencode-cli.js +336 -0
  155. package/server/opencode-cli.test.js +95 -0
  156. package/server/routes/agent.js +22 -8
  157. package/server/routes/commands.js +254 -233
  158. package/server/routes/cursor.js +2 -2
  159. package/server/routes/settings.js +1 -10
  160. package/server/routes/tests/commands.test.js +82 -0
  161. package/server/shared/interfaces.ts +45 -0
  162. package/server/shared/types.ts +88 -1
  163. package/server/shared/utils.ts +384 -0
  164. package/dist/assets/index-DdxLnCfK.css +0 -32
  165. package/dist-server/shared/modelConstants.js +0 -99
  166. package/dist-server/shared/modelConstants.js.map +0 -1
  167. package/shared/modelConstants.js +0 -107
@@ -0,0 +1,820 @@
1
+ import { access, readdir } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+
6
+ import crossSpawn from 'cross-spawn';
7
+
8
+ import type { IProviderModels } from '@/shared/interfaces.js';
9
+ import type {
10
+ ProviderChangeActiveModelInput,
11
+ ProviderCurrentActiveModel,
12
+ ProviderModelOption,
13
+ ProviderModelsDefinition,
14
+ ProviderSessionActiveModelChange,
15
+ } from '@/shared/types.js';
16
+ import {
17
+ buildDefaultProviderCurrentActiveModel,
18
+ sanitizeLeafDirectoryName,
19
+ writeProviderSessionActiveModelChange,
20
+ } from '@/shared/utils.js';
21
+
22
+ export const CURSOR_FALLBACK_MODELS: ProviderModelsDefinition = {
23
+ OPTIONS: [
24
+ {
25
+ value: "auto",
26
+ label: "auto",
27
+ description: "Auto",
28
+ },
29
+ {
30
+ value: "composer-2-fast",
31
+ label: "composer-2-fast",
32
+ description: "Composer 2 Fast",
33
+ },
34
+ {
35
+ value: "composer-2",
36
+ label: "composer-2",
37
+ description: "Composer 2",
38
+ },
39
+ {
40
+ value: "gpt-5.3-codex-low",
41
+ label: "gpt-5.3-codex-low",
42
+ description: "Codex 5.3 Low",
43
+ },
44
+ {
45
+ value: "gpt-5.3-codex-low-fast",
46
+ label: "gpt-5.3-codex-low-fast",
47
+ description: "Codex 5.3 Low Fast",
48
+ },
49
+ {
50
+ value: "gpt-5.3-codex",
51
+ label: "gpt-5.3-codex",
52
+ description: "Codex 5.3",
53
+ },
54
+ {
55
+ value: "gpt-5.3-codex-fast",
56
+ label: "gpt-5.3-codex-fast",
57
+ description: "Codex 5.3 Fast",
58
+ },
59
+ {
60
+ value: "gpt-5.3-codex-high",
61
+ label: "gpt-5.3-codex-high",
62
+ description: "Codex 5.3 High",
63
+ },
64
+ {
65
+ value: "gpt-5.3-codex-high-fast",
66
+ label: "gpt-5.3-codex-high-fast",
67
+ description: "Codex 5.3 High Fast",
68
+ },
69
+ {
70
+ value: "gpt-5.3-codex-xhigh",
71
+ label: "gpt-5.3-codex-xhigh",
72
+ description: "Codex 5.3 Extra High",
73
+ },
74
+ {
75
+ value: "gpt-5.3-codex-xhigh-fast",
76
+ label: "gpt-5.3-codex-xhigh-fast",
77
+ description: "Codex 5.3 Extra High Fast",
78
+ },
79
+ {
80
+ value: "gpt-5.2",
81
+ label: "gpt-5.2",
82
+ description: "GPT-5.2",
83
+ },
84
+ {
85
+ value: "gpt-5.2-codex-low",
86
+ label: "gpt-5.2-codex-low",
87
+ description: "Codex 5.2 Low",
88
+ },
89
+ {
90
+ value: "gpt-5.2-codex-low-fast",
91
+ label: "gpt-5.2-codex-low-fast",
92
+ description: "Codex 5.2 Low Fast",
93
+ },
94
+ {
95
+ value: "gpt-5.2-codex",
96
+ label: "gpt-5.2-codex",
97
+ description: "Codex 5.2",
98
+ },
99
+ {
100
+ value: "gpt-5.2-codex-fast",
101
+ label: "gpt-5.2-codex-fast",
102
+ description: "Codex 5.2 Fast",
103
+ },
104
+ {
105
+ value: "gpt-5.2-codex-high",
106
+ label: "gpt-5.2-codex-high",
107
+ description: "Codex 5.2 High",
108
+ },
109
+ {
110
+ value: "gpt-5.2-codex-high-fast",
111
+ label: "gpt-5.2-codex-high-fast",
112
+ description: "Codex 5.2 High Fast",
113
+ },
114
+ {
115
+ value: "gpt-5.2-codex-xhigh",
116
+ label: "gpt-5.2-codex-xhigh",
117
+ description: "Codex 5.2 Extra High",
118
+ },
119
+ {
120
+ value: "gpt-5.2-codex-xhigh-fast",
121
+ label: "gpt-5.2-codex-xhigh-fast",
122
+ description: "Codex 5.2 Extra High Fast",
123
+ },
124
+ {
125
+ value: "gpt-5.1-codex-max-low",
126
+ label: "gpt-5.1-codex-max-low",
127
+ description: "Codex 5.1 Max Low",
128
+ },
129
+ {
130
+ value: "gpt-5.1-codex-max-low-fast",
131
+ label: "gpt-5.1-codex-max-low-fast",
132
+ description: "Codex 5.1 Max Low Fast",
133
+ },
134
+ {
135
+ value: "gpt-5.1-codex-max-medium",
136
+ label: "gpt-5.1-codex-max-medium",
137
+ description: "Codex 5.1 Max",
138
+ },
139
+ {
140
+ value: "gpt-5.1-codex-max-medium-fast",
141
+ label: "gpt-5.1-codex-max-medium-fast",
142
+ description: "Codex 5.1 Max Medium Fast",
143
+ },
144
+ {
145
+ value: "gpt-5.1-codex-max-high",
146
+ label: "gpt-5.1-codex-max-high",
147
+ description: "Codex 5.1 Max High",
148
+ },
149
+ {
150
+ value: "gpt-5.1-codex-max-high-fast",
151
+ label: "gpt-5.1-codex-max-high-fast",
152
+ description: "Codex 5.1 Max High Fast",
153
+ },
154
+ {
155
+ value: "gpt-5.1-codex-max-xhigh",
156
+ label: "gpt-5.1-codex-max-xhigh",
157
+ description: "Codex 5.1 Max Extra High",
158
+ },
159
+ {
160
+ value: "gpt-5.1-codex-max-xhigh-fast",
161
+ label: "gpt-5.1-codex-max-xhigh-fast",
162
+ description: "Codex 5.1 Max Extra High Fast",
163
+ },
164
+ {
165
+ value: "composer-2.5",
166
+ label: "composer-2.5",
167
+ description: "Composer 2.5",
168
+ },
169
+ {
170
+ value: "gpt-5.5-high",
171
+ label: "gpt-5.5-high",
172
+ description: "GPT-5.5 1M High",
173
+ },
174
+ {
175
+ value: "gpt-5.5-high-fast",
176
+ label: "gpt-5.5-high-fast",
177
+ description: "GPT-5.5 High Fast",
178
+ },
179
+ {
180
+ value: "claude-opus-4-7-thinking-high",
181
+ label: "claude-opus-4-7-thinking-high",
182
+ description: "Opus 4.7 1M High Thinking",
183
+ },
184
+ {
185
+ value: "gpt-5.4-high",
186
+ label: "gpt-5.4-high",
187
+ description: "GPT-5.4 1M High",
188
+ },
189
+ {
190
+ value: "gpt-5.4-high-fast",
191
+ label: "gpt-5.4-high-fast",
192
+ description: "GPT-5.4 High Fast",
193
+ },
194
+ {
195
+ value: "claude-4.6-opus-high-thinking",
196
+ label: "claude-4.6-opus-high-thinking",
197
+ description: "Opus 4.6 1M Thinking",
198
+ },
199
+ {
200
+ value: "claude-4.6-opus-high-thinking-fast",
201
+ label: "claude-4.6-opus-high-thinking-fast",
202
+ description: "Opus 4.6 1M Thinking Fast",
203
+ },
204
+ {
205
+ value: "composer-2.5-fast",
206
+ label: "composer-2.5-fast",
207
+ description: "Composer 2.5 Fast",
208
+ },
209
+ {
210
+ value: "gpt-5.5-none",
211
+ label: "gpt-5.5-none",
212
+ description: "GPT-5.5 1M None",
213
+ },
214
+ {
215
+ value: "gpt-5.5-none-fast",
216
+ label: "gpt-5.5-none-fast",
217
+ description: "GPT-5.5 None Fast",
218
+ },
219
+ {
220
+ value: "gpt-5.5-low",
221
+ label: "gpt-5.5-low",
222
+ description: "GPT-5.5 1M Low",
223
+ },
224
+ {
225
+ value: "gpt-5.5-low-fast",
226
+ label: "gpt-5.5-low-fast",
227
+ description: "GPT-5.5 Low Fast",
228
+ },
229
+ {
230
+ value: "gpt-5.5-medium",
231
+ label: "gpt-5.5-medium",
232
+ description: "GPT-5.5 1M",
233
+ },
234
+ {
235
+ value: "gpt-5.5-medium-fast",
236
+ label: "gpt-5.5-medium-fast",
237
+ description: "GPT-5.5 Fast",
238
+ },
239
+ {
240
+ value: "gpt-5.5-extra-high",
241
+ label: "gpt-5.5-extra-high",
242
+ description: "GPT-5.5 1M Extra High",
243
+ },
244
+ {
245
+ value: "gpt-5.5-extra-high-fast",
246
+ label: "gpt-5.5-extra-high-fast",
247
+ description: "GPT-5.5 Extra High Fast",
248
+ },
249
+ {
250
+ value: "claude-4.6-sonnet-medium",
251
+ label: "claude-4.6-sonnet-medium",
252
+ description: "Sonnet 4.6 1M",
253
+ },
254
+ {
255
+ value: "claude-4.6-sonnet-medium-thinking",
256
+ label: "claude-4.6-sonnet-medium-thinking",
257
+ description: "Sonnet 4.6 1M Thinking",
258
+ },
259
+ {
260
+ value: "claude-opus-4-7-low",
261
+ label: "claude-opus-4-7-low",
262
+ description: "Opus 4.7 1M Low",
263
+ },
264
+ {
265
+ value: "claude-opus-4-7-low-fast",
266
+ label: "claude-opus-4-7-low-fast",
267
+ description: "Opus 4.7 1M Low Fast",
268
+ },
269
+ {
270
+ value: "claude-opus-4-7-medium",
271
+ label: "claude-opus-4-7-medium",
272
+ description: "Opus 4.7 1M Medium",
273
+ },
274
+ {
275
+ value: "claude-opus-4-7-medium-fast",
276
+ label: "claude-opus-4-7-medium-fast",
277
+ description: "Opus 4.7 1M Medium Fast",
278
+ },
279
+ {
280
+ value: "claude-opus-4-7-high",
281
+ label: "claude-opus-4-7-high",
282
+ description: "Opus 4.7 1M High",
283
+ },
284
+ {
285
+ value: "claude-opus-4-7-high-fast",
286
+ label: "claude-opus-4-7-high-fast",
287
+ description: "Opus 4.7 1M High Fast",
288
+ },
289
+ {
290
+ value: "claude-opus-4-7-xhigh",
291
+ label: "claude-opus-4-7-xhigh",
292
+ description: "Opus 4.7 1M",
293
+ },
294
+ {
295
+ value: "claude-opus-4-7-xhigh-fast",
296
+ label: "claude-opus-4-7-xhigh-fast",
297
+ description: "Opus 4.7 1M Fast",
298
+ },
299
+ {
300
+ value: "claude-opus-4-7-max",
301
+ label: "claude-opus-4-7-max",
302
+ description: "Opus 4.7 1M Max",
303
+ },
304
+ {
305
+ value: "claude-opus-4-7-max-fast",
306
+ label: "claude-opus-4-7-max-fast",
307
+ description: "Opus 4.7 1M Max Fast",
308
+ },
309
+ {
310
+ value: "claude-opus-4-7-thinking-low",
311
+ label: "claude-opus-4-7-thinking-low",
312
+ description: "Opus 4.7 1M Low Thinking",
313
+ },
314
+ {
315
+ value: "claude-opus-4-7-thinking-low-fast",
316
+ label: "claude-opus-4-7-thinking-low-fast",
317
+ description: "Opus 4.7 1M Low Thinking Fast",
318
+ },
319
+ {
320
+ value: "claude-opus-4-7-thinking-medium",
321
+ label: "claude-opus-4-7-thinking-medium",
322
+ description: "Opus 4.7 1M Medium Thinking",
323
+ },
324
+ {
325
+ value: "claude-opus-4-7-thinking-medium-fast",
326
+ label: "claude-opus-4-7-thinking-medium-fast",
327
+ description: "Opus 4.7 1M Medium Thinking Fast",
328
+ },
329
+ {
330
+ value: "claude-opus-4-7-thinking-high-fast",
331
+ label: "claude-opus-4-7-thinking-high-fast",
332
+ description: "Opus 4.7 1M High Thinking Fast",
333
+ },
334
+ {
335
+ value: "claude-opus-4-7-thinking-xhigh",
336
+ label: "claude-opus-4-7-thinking-xhigh",
337
+ description: "Opus 4.7 1M Thinking",
338
+ },
339
+ {
340
+ value: "claude-opus-4-7-thinking-xhigh-fast",
341
+ label: "claude-opus-4-7-thinking-xhigh-fast",
342
+ description: "Opus 4.7 1M Thinking Fast",
343
+ },
344
+ {
345
+ value: "claude-opus-4-7-thinking-max",
346
+ label: "claude-opus-4-7-thinking-max",
347
+ description: "Opus 4.7 1M Max Thinking",
348
+ },
349
+ {
350
+ value: "claude-opus-4-7-thinking-max-fast",
351
+ label: "claude-opus-4-7-thinking-max-fast",
352
+ description: "Opus 4.7 1M Max Thinking Fast",
353
+ },
354
+ {
355
+ value: "grok-build-0.1",
356
+ label: "grok-build-0.1",
357
+ description: "Grok Build 0.1 1M",
358
+ },
359
+ {
360
+ value: "gpt-5.4-low",
361
+ label: "gpt-5.4-low",
362
+ description: "GPT-5.4 1M Low",
363
+ },
364
+ {
365
+ value: "gpt-5.4-medium",
366
+ label: "gpt-5.4-medium",
367
+ description: "GPT-5.4 1M",
368
+ },
369
+ {
370
+ value: "gpt-5.4-medium-fast",
371
+ label: "gpt-5.4-medium-fast",
372
+ description: "GPT-5.4 Fast",
373
+ },
374
+ {
375
+ value: "gpt-5.4-xhigh",
376
+ label: "gpt-5.4-xhigh",
377
+ description: "GPT-5.4 1M Extra High",
378
+ },
379
+ {
380
+ value: "gpt-5.4-xhigh-fast",
381
+ label: "gpt-5.4-xhigh-fast",
382
+ description: "GPT-5.4 Extra High Fast",
383
+ },
384
+ {
385
+ value: "claude-4.6-opus-high",
386
+ label: "claude-4.6-opus-high",
387
+ description: "Opus 4.6 1M",
388
+ },
389
+ {
390
+ value: "claude-4.6-opus-max",
391
+ label: "claude-4.6-opus-max",
392
+ description: "Opus 4.6 1M Max",
393
+ },
394
+ {
395
+ value: "claude-4.6-opus-max-thinking",
396
+ label: "claude-4.6-opus-max-thinking",
397
+ description: "Opus 4.6 1M Max Thinking",
398
+ },
399
+ {
400
+ value: "claude-4.6-opus-max-thinking-fast",
401
+ label: "claude-4.6-opus-max-thinking-fast",
402
+ description: "Opus 4.6 1M Max Thinking Fast",
403
+ },
404
+ {
405
+ value: "claude-4.5-opus-high",
406
+ label: "claude-4.5-opus-high",
407
+ description: "Opus 4.5",
408
+ },
409
+ {
410
+ value: "claude-4.5-opus-high-thinking",
411
+ label: "claude-4.5-opus-high-thinking",
412
+ description: "Opus 4.5 Thinking",
413
+ },
414
+ {
415
+ value: "gpt-5.2-low",
416
+ label: "gpt-5.2-low",
417
+ description: "GPT-5.2 Low",
418
+ },
419
+ {
420
+ value: "gpt-5.2-low-fast",
421
+ label: "gpt-5.2-low-fast",
422
+ description: "GPT-5.2 Low Fast",
423
+ },
424
+ {
425
+ value: "gpt-5.2-fast",
426
+ label: "gpt-5.2-fast",
427
+ description: "GPT-5.2 Fast",
428
+ },
429
+ {
430
+ value: "gpt-5.2-high",
431
+ label: "gpt-5.2-high",
432
+ description: "GPT-5.2 High",
433
+ },
434
+ {
435
+ value: "gpt-5.2-high-fast",
436
+ label: "gpt-5.2-high-fast",
437
+ description: "GPT-5.2 High Fast",
438
+ },
439
+ {
440
+ value: "gpt-5.2-xhigh",
441
+ label: "gpt-5.2-xhigh",
442
+ description: "GPT-5.2 Extra High",
443
+ },
444
+ {
445
+ value: "gpt-5.2-xhigh-fast",
446
+ label: "gpt-5.2-xhigh-fast",
447
+ description: "GPT-5.2 Extra High Fast",
448
+ },
449
+ {
450
+ value: "gemini-3.1-pro",
451
+ label: "gemini-3.1-pro",
452
+ description: "Gemini 3.1 Pro",
453
+ },
454
+ {
455
+ value: "gpt-5.4-mini-none",
456
+ label: "gpt-5.4-mini-none",
457
+ description: "GPT-5.4 Mini None",
458
+ },
459
+ {
460
+ value: "gpt-5.4-mini-low",
461
+ label: "gpt-5.4-mini-low",
462
+ description: "GPT-5.4 Mini Low",
463
+ },
464
+ {
465
+ value: "gpt-5.4-mini-medium",
466
+ label: "gpt-5.4-mini-medium",
467
+ description: "GPT-5.4 Mini",
468
+ },
469
+ {
470
+ value: "gpt-5.4-mini-high",
471
+ label: "gpt-5.4-mini-high",
472
+ description: "GPT-5.4 Mini High",
473
+ },
474
+ {
475
+ value: "gpt-5.4-mini-xhigh",
476
+ label: "gpt-5.4-mini-xhigh",
477
+ description: "GPT-5.4 Mini Extra High",
478
+ },
479
+ {
480
+ value: "gpt-5.4-nano-none",
481
+ label: "gpt-5.4-nano-none",
482
+ description: "GPT-5.4 Nano None",
483
+ },
484
+ {
485
+ value: "gpt-5.4-nano-low",
486
+ label: "gpt-5.4-nano-low",
487
+ description: "GPT-5.4 Nano Low",
488
+ },
489
+ {
490
+ value: "gpt-5.4-nano-medium",
491
+ label: "gpt-5.4-nano-medium",
492
+ description: "GPT-5.4 Nano",
493
+ },
494
+ {
495
+ value: "gpt-5.4-nano-high",
496
+ label: "gpt-5.4-nano-high",
497
+ description: "GPT-5.4 Nano High",
498
+ },
499
+ {
500
+ value: "gpt-5.4-nano-xhigh",
501
+ label: "gpt-5.4-nano-xhigh",
502
+ description: "GPT-5.4 Nano Extra High",
503
+ },
504
+ {
505
+ value: "grok-4.3",
506
+ label: "grok-4.3",
507
+ description: "Grok 4.3 1M",
508
+ },
509
+ {
510
+ value: "claude-4.5-sonnet",
511
+ label: "claude-4.5-sonnet",
512
+ description: "Sonnet 4.5",
513
+ },
514
+ {
515
+ value: "claude-4.5-sonnet-thinking",
516
+ label: "claude-4.5-sonnet-thinking",
517
+ description: "Sonnet 4.5 Thinking",
518
+ },
519
+ {
520
+ value: "gpt-5.1-low",
521
+ label: "gpt-5.1-low",
522
+ description: "GPT-5.1 Low",
523
+ },
524
+ {
525
+ value: "gpt-5.1",
526
+ label: "gpt-5.1",
527
+ description: "GPT-5.1",
528
+ },
529
+ {
530
+ value: "gpt-5.1-high",
531
+ label: "gpt-5.1-high",
532
+ description: "GPT-5.1 High",
533
+ },
534
+ {
535
+ value: "gemini-3-flash",
536
+ label: "gemini-3-flash",
537
+ description: "Gemini 3 Flash",
538
+ },
539
+ {
540
+ value: "gemini-3.5-flash",
541
+ label: "gemini-3.5-flash",
542
+ description: "Gemini 3.5 Flash",
543
+ },
544
+ {
545
+ value: "gpt-5.1-codex-mini-low",
546
+ label: "gpt-5.1-codex-mini-low",
547
+ description: "Codex 5.1 Mini Low",
548
+ },
549
+ {
550
+ value: "gpt-5.1-codex-mini",
551
+ label: "gpt-5.1-codex-mini",
552
+ description: "Codex 5.1 Mini",
553
+ },
554
+ {
555
+ value: "gpt-5.1-codex-mini-high",
556
+ label: "gpt-5.1-codex-mini-high",
557
+ description: "Codex 5.1 Mini High",
558
+ },
559
+ {
560
+ value: "claude-4-sonnet",
561
+ label: "claude-4-sonnet",
562
+ description: "Sonnet 4",
563
+ },
564
+ {
565
+ value: "claude-4-sonnet-thinking",
566
+ label: "claude-4-sonnet-thinking",
567
+ description: "Sonnet 4 Thinking",
568
+ },
569
+ {
570
+ value: "gpt-5-mini",
571
+ label: "gpt-5-mini",
572
+ description: "GPT-5 Mini",
573
+ },
574
+ {
575
+ value: "kimi-k2.5",
576
+ label: "kimi-k2.5",
577
+ description: "Kimi K2.5",
578
+ },
579
+ ],
580
+ DEFAULT: "composer-2.5-fast",
581
+ };
582
+
583
+ type CursorModelRow = {
584
+ name: string;
585
+ description: string;
586
+ current: boolean;
587
+ default: boolean;
588
+ };
589
+
590
+ const CURSOR_MODELS_TIMEOUT_MS = 10_000;
591
+ const CURSOR_CHATS_ROOT = path.join(os.homedir(), '.cursor', 'chats');
592
+ const spawnFunction = process.platform === 'win32' ? crossSpawn : spawn;
593
+ const ANSI_PATTERN = new RegExp(
594
+ // eslint-disable-next-line no-control-regex
595
+ '[\\u001B\\u009B][[\\]()#;?]*(?:'
596
+ + '(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]'
597
+ + '|(?:[\\dA-PR-TZcf-ntqry=><~]))',
598
+ 'g',
599
+ );
600
+
601
+ const stripAnsi = (value: string): string => value.replace(ANSI_PATTERN, '');
602
+
603
+ const parseModelLine = (line: string): CursorModelRow | null => {
604
+ const trimmed = line.trim();
605
+
606
+ if (
607
+ !trimmed
608
+ || trimmed === 'Available models'
609
+ || trimmed.startsWith('Loading models')
610
+ || trimmed.startsWith('Tip:')
611
+ ) {
612
+ return null;
613
+ }
614
+
615
+ const match = trimmed.match(/^(.+?)\s+-\s+(.+)$/);
616
+ if (!match) {
617
+ return null;
618
+ }
619
+
620
+ const name = match[1].trim();
621
+ let description = match[2].trim();
622
+ const current = /\(current\)/i.test(description);
623
+ const defaultModel = /\(default\)/i.test(description);
624
+
625
+ description = description.replace(/\s*\((current|default)\)/gi, '').replace(/\s{2,}/g, ' ').trim();
626
+
627
+ return {
628
+ name,
629
+ description,
630
+ current,
631
+ default: defaultModel,
632
+ };
633
+ };
634
+
635
+ const parseModelsOutput = (text: string): CursorModelRow[] => {
636
+ const models: CursorModelRow[] = [];
637
+
638
+ for (const line of stripAnsi(text).split(/\r?\n/)) {
639
+ const parsed = parseModelLine(line);
640
+ if (parsed) {
641
+ models.push(parsed);
642
+ }
643
+ }
644
+
645
+ return models;
646
+ };
647
+
648
+ const runCursorListModels = (): Promise<string> => new Promise((resolve, reject) => {
649
+ const cursorProcess = spawnFunction('cursor-agent', ['--list-models'], {
650
+ env: { ...process.env },
651
+ });
652
+
653
+ let stdout = '';
654
+ let stderr = '';
655
+ let settled = false;
656
+
657
+ const timer = setTimeout(() => {
658
+ cursorProcess.kill('SIGTERM');
659
+ if (!settled) {
660
+ settled = true;
661
+ reject(new Error('cursor-agent --list-models timed out'));
662
+ }
663
+ }, CURSOR_MODELS_TIMEOUT_MS);
664
+
665
+ const finish = (error: Error | null, output: string) => {
666
+ if (settled) {
667
+ return;
668
+ }
669
+
670
+ settled = true;
671
+ clearTimeout(timer);
672
+
673
+ if (error) {
674
+ reject(error);
675
+ return;
676
+ }
677
+
678
+ resolve(output);
679
+ };
680
+
681
+ cursorProcess.stdout?.on('data', (chunk: Buffer) => {
682
+ stdout += chunk.toString();
683
+ });
684
+
685
+ cursorProcess.stderr?.on('data', (chunk: Buffer) => {
686
+ stderr += chunk.toString();
687
+ });
688
+
689
+ cursorProcess.on('error', (error) => {
690
+ finish(error instanceof Error ? error : new Error(String(error)), '');
691
+ });
692
+
693
+ cursorProcess.on('close', (code) => {
694
+ if (code !== 0) {
695
+ finish(new Error(stderr.trim() || `cursor-agent --list-models exited with code ${code}`), '');
696
+ return;
697
+ }
698
+
699
+ finish(null, stdout);
700
+ });
701
+ });
702
+
703
+ const buildCursorModelsDefinition = (models: CursorModelRow[]): ProviderModelsDefinition => {
704
+ const options: ProviderModelOption[] = [];
705
+ const seenValues = new Set<string>();
706
+
707
+ for (const model of models) {
708
+ if (seenValues.has(model.name)) {
709
+ continue;
710
+ }
711
+
712
+ seenValues.add(model.name);
713
+ options.push({
714
+ value: model.name,
715
+ label: model.name,
716
+ description: model.description || undefined,
717
+ });
718
+ }
719
+
720
+ if (options.length === 0) {
721
+ return CURSOR_FALLBACK_MODELS;
722
+ }
723
+
724
+ const defaultValue = models.find((model) => model.default)?.name
725
+ ?? models.find((model) => model.current)?.name
726
+ ?? options[0]?.value
727
+ ?? CURSOR_FALLBACK_MODELS.DEFAULT;
728
+
729
+ return {
730
+ OPTIONS: options,
731
+ DEFAULT: defaultValue,
732
+ };
733
+ };
734
+
735
+ const resolveCursorSessionStorePath = async (sessionId: string): Promise<string | null> => {
736
+ const safeSessionId = sanitizeLeafDirectoryName(sessionId, 'cursor session id');
737
+
738
+ try {
739
+ const workspaceEntries = await readdir(CURSOR_CHATS_ROOT, { withFileTypes: true });
740
+ for (const workspaceEntry of workspaceEntries) {
741
+ if (!workspaceEntry.isDirectory()) {
742
+ continue;
743
+ }
744
+
745
+ const storeDbPath = path.join(CURSOR_CHATS_ROOT, workspaceEntry.name, safeSessionId, 'store.db');
746
+ try {
747
+ await access(storeDbPath);
748
+ return storeDbPath;
749
+ } catch {
750
+ // Keep scanning sibling workspaces until the matching session directory is found.
751
+ }
752
+ }
753
+ } catch {
754
+ return null;
755
+ }
756
+
757
+ return null;
758
+ };
759
+
760
+ export class CursorProviderModels implements IProviderModels {
761
+ async getSupportedModels(): Promise<ProviderModelsDefinition> {
762
+ try {
763
+ const stdout = await runCursorListModels();
764
+ const models = parseModelsOutput(stdout);
765
+ return buildCursorModelsDefinition(models);
766
+ } catch {
767
+ return CURSOR_FALLBACK_MODELS;
768
+ }
769
+ }
770
+
771
+ async getCurrentActiveModel(sessionId?: string): Promise<ProviderCurrentActiveModel> {
772
+ if (!sessionId?.trim()) {
773
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
774
+ }
775
+
776
+ try {
777
+ const storeDbPath = await resolveCursorSessionStorePath(sessionId);
778
+ if (!storeDbPath) {
779
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
780
+ }
781
+
782
+ const { default: Database } = await import('better-sqlite3');
783
+ const db = new Database(storeDbPath, { readonly: true, fileMustExist: true });
784
+
785
+ try {
786
+ const row = db.prepare(`SELECT value FROM meta WHERE key='0' LIMIT 1;`).get() as {
787
+ value?: Buffer | string;
788
+ } | undefined;
789
+ const metadataText = Buffer.isBuffer(row?.value)
790
+ ? row.value.toString('utf8')
791
+ : typeof row?.value === 'string' && row.value.trim()
792
+ ? Buffer.from(row.value.trim(), 'hex').toString('utf8')
793
+ : '';
794
+ if (!metadataText) {
795
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
796
+ }
797
+
798
+ const metadata = JSON.parse(metadataText) as { lastUsedModel?: string };
799
+ if (typeof metadata.lastUsedModel === 'string' && metadata.lastUsedModel.trim()) {
800
+ return {
801
+ model: metadata.lastUsedModel.trim(),
802
+ };
803
+ }
804
+ } finally {
805
+ db.close();
806
+ }
807
+ } catch {
808
+ // Fall through to the provider default when Cursor metadata cannot be read.
809
+ }
810
+
811
+ return buildDefaultProviderCurrentActiveModel(await this.getSupportedModels());
812
+ }
813
+
814
+ async changeActiveModel(
815
+ input: ProviderChangeActiveModelInput,
816
+ ): Promise<ProviderSessionActiveModelChange> {
817
+ return writeProviderSessionActiveModelChange('cursor', input);
818
+ }
819
+ }
820
+