ocx-cursor 1.0.5 → 1.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ocx-cursor",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Use OpenCodex models in Cursor through an authenticated HTTPS gateway",
5
5
  "keywords": [
6
6
  "opencodex",
@@ -16,12 +16,21 @@ export const cursorPatchMarker = "/*ocx-cursor-model-metadata-v6*/";
16
16
  export const legacyCursorPatchMarker = "/*ocx-cursor-model-metadata*/";
17
17
  export const cursorByokRoutingPatchMarker = "/*ocx-cursor-byok-model-routing-v1*/";
18
18
  export const cursorSubagentModelsPatchMarker = "/*ocx-cursor-subagent-models-v1*/";
19
- export const cursorSubagentCredentialsPatchMarker = "/*ocx-cursor-subagent-credentials-v1*/";
20
- export const cursorSubagentLegacyDetailsPatchMarker = "/*ocx-cursor-subagent-legacy-details-v1*/";
19
+ export const cursorSubagentCredentialsPatchMarker = "/*ocx-cursor-subagent-credentials-v2*/";
20
+ export const legacyCursorSubagentCredentialsPatchMarker = "/*ocx-cursor-subagent-credentials-v1*/";
21
+ export const cursorSubagentLegacyDetailsPatchMarker = "/*ocx-cursor-subagent-legacy-details-v2*/";
22
+ export const legacyCursorSubagentLegacyDetailsPatchMarker = "/*ocx-cursor-subagent-legacy-details-v1*/";
21
23
  export const cursorSubagentPromptRoutingPatchMarker = "/*ocx-cursor-subagent-prompt-routing-v3*/";
22
24
  export const cursorSubagentExecutionRoutingPatchMarker = "/*ocx-cursor-subagent-execution-routing-v5*/";
23
25
  export const cursorSubagentRunRoutingPatchMarker = "/*ocx-cursor-subagent-run-routing-v1*/";
24
26
  export const cursorSubagentRuntimeCredentialsPatchMarker = "/*ocx-cursor-subagent-runtime-credentials-v1*/";
27
+ export const cursorSubagentModelDisplayPatchMarker = "/*ocx-cursor-subagent-model-display-v2*/";
28
+ export const legacyCursorSubagentModelDisplayPatchMarker = "/*ocx-cursor-subagent-model-display-v1*/";
29
+ export const cursorSubagentTaskArgsDisplayPatchMarker = "/*ocx-cursor-subagent-task-args-display-v5*/";
30
+ export const legacyCursorSubagentTaskArgsDisplayV4PatchMarker = "/*ocx-cursor-subagent-task-args-display-v4*/";
31
+ export const legacyCursorSubagentTaskArgsDisplayV3PatchMarker = "/*ocx-cursor-subagent-task-args-display-v3*/";
32
+ export const legacyCursorSubagentTaskArgsDisplayV2PatchMarker = "/*ocx-cursor-subagent-task-args-display-v2*/";
33
+ export const legacyCursorSubagentTaskArgsDisplayPatchMarker = "/*ocx-cursor-subagent-task-args-display-v1*/";
25
34
  export const cursorRoutedSubagentTypesPatchMarker = "/*ocx-cursor-hide-routed-subagent-types-v1*/";
26
35
  export const cursorLocalModeDisabled = "localMode:!1";
27
36
  export const cursorLocalModeEnabled = "localMode:!0";
@@ -39,10 +48,12 @@ const previousCatalogInjection = /\/\*ocx-cursor-model-metadata(?:-v[2-5])?\*\/(
39
48
  const byokModelRouting = /function (?<functionName>[A-Za-z_$][\w$]*)\((?<model>[A-Za-z_$][\w$]*),(?<settings>[A-Za-z_$][\w$]*)\)\{return (?<isClaude>[A-Za-z_$][\w$]*)\(\k<model>\)\?\k<settings>\.useClaudeKey\?"anthropic":void 0:(?<isGemini>[A-Za-z_$][\w$]*)\(\k<model>\)\?\k<settings>\.useGoogleKey\?"google":void 0:\k<settings>\.useOpenAIKey\?"openai":void 0\}/g;
40
49
  const explicitSubagentModelFilter = /function (?<functionName>[A-Za-z_$][\w$]*)\((?<model>[A-Za-z_$][\w$]*),(?<isUserAdded>[A-Za-z_$][\w$]*),(?<storage>[A-Za-z_$][\w$]*)\)\{return \k<isUserAdded>===!0\?!0:(?<hasProviderOverride>[A-Za-z_$][\w$]*)\(\k<storage>\)\|\|(?<usesByok>[A-Za-z_$][\w$]*)\(\k<model>,\k<storage>\)\}(?=function [A-Za-z_$][\w$]*\([A-Za-z_$][\w$]*\)\{const\{modelDetails:)/g;
41
50
  const explicitSubagentModelSelection = /function (?<functionName>[A-Za-z_$][\w$]*)\((?<input>[A-Za-z_$][\w$]*)\)\{const\{modelDetails:(?<modelDetails>[A-Za-z_$][\w$]*),flagEnabled:(?<flagEnabled>[A-Za-z_$][\w$]*),availableModels:(?<availableModels>[A-Za-z_$][\w$]*),storage:(?<storage>[A-Za-z_$][\w$]*),resolveModelParametersForSubmission:(?<resolveParameters>[A-Za-z_$][\w$]*)\}=\k<input>,(?<maxMode>[A-Za-z_$][\w$]*)=\k<modelDetails>\.maxMode===!0;/g;
51
+ const explicitSubagentByokGuard = /if\((?<hasByok>[A-Za-z_$][\w$]*)\((?<modelDetails>[A-Za-z_$][\w$]*)\)\|\|!\((?<flagEnabled>[A-Za-z_$][\w$]*)\|\|(?<maxMode>[A-Za-z_$][\w$]*)\)\)return\{\};/g;
42
52
  const explicitSubagentRequestedModel = /new (?<requestedModelType>[A-Za-z_$][\w$]*)\(\{modelId:(?<model>[A-Za-z_$][\w$]*)\.name,maxMode:(?<maxMode>[A-Za-z_$][\w$]*),parameters:(?<parameters>[A-Za-z_$][\w$]*)\.map\((?<parameter>[A-Za-z_$][\w$]*)=>new (?<parameterType>[A-Za-z_$][\w$]*)\(\{id:\k<parameter>\.id,value:\k<parameter>\.value\}\)\)\}\)(?=\}\)\}\})/g;
43
53
  const explicitSubagentSelectionCall = /getSelectedSubagentModelSelections\((?<modelDetails>[A-Za-z_$][\w$]*)\)\{return (?<selector>[A-Za-z_$][\w$]*)\(\{modelDetails:\k<modelDetails>,flagEnabled:(?<featureGate>[\s\S]*?),availableModels:this\.modelConfigService\.getAvailableDefaultModels\(\),storage:this\.reactiveStorageService\.applicationUserPersistentStorage,resolveModelParametersForSubmission:\((?<model>[A-Za-z_$][\w$]*),(?<maxMode>[A-Za-z_$][\w$]*)\)=>this\.modelConfigService\.resolveModelParametersForSubmission\(\k<model>,void 0,\k<maxMode>\)\}\)\}/g;
44
54
  const agentModelDetailsType = /(?<type>[A-Za-z_$][\w$]*)=[A-Za-z_$][\w$]*\.makeMessageType\("agent\.v1\.ModelDetails"/g;
45
55
  const selectedSubagentLegacyDetails = /selectedSubagentModelDetails:(?<options>[A-Za-z_$][\w$]*)\.selectedSubagentModelsLegacy/g;
56
+ const legacySelectedSubagentDetailsInjection = /selectedSubagentModelDetails:\/\*ocx-cursor-subagent-legacy-details-v1\*\/(?<options>[A-Za-z_$][\w$]*)\.selectedSubagentModelsLegacy\?\.length\?[\s\S]*?credentials:ocxCursorModel\.credentials\}\)\)/g;
46
57
  const agentCustomSystemPrompt = /customSystemPrompt:(?<options>[A-Za-z_$][\w$]*)\.customSystemPrompt(?=,harness:)/g;
47
58
  const agentRequestAction = /(?<prefix>conversationState:[A-Za-z_$][\w$]*\([A-Za-z_$][\w$]*\),action:)(?<action>[A-Za-z_$][\w$]*)(?=,modelDetails:)/g;
48
59
  const legacySubagentPromptRouting = /customSystemPrompt:\(\(\)=>\{\/\*ocx-cursor-subagent-prompt-routing-v1\*\/const ocxCursorModelIds=\((?<options>[A-Za-z_$][\w$]*)\.selectedSubagentModels[\s\S]*?\}\)\(\)(?=,harness:)/g;
@@ -55,6 +66,13 @@ const appendSubagentComposer = /(?<declaration>const (?<result>[A-Za-z_$][\w$]*)
55
66
  const runSubagentWithHandle = /async runSubagentWithHandle\((?<input>[A-Za-z_$][\w$]*),(?<handle>[A-Za-z_$][\w$]*)\)\{return this\._runSubagent\(\k<input>,\k<handle>\)\}/g;
56
67
  const runSubagentModelConfigFixup = /(?<fixed>[A-Za-z_$][\w$]*)=\(typeof this\._modelConfigService\.fixupModelConfigForCurrentFlag=="function"\?this\._modelConfigService\.fixupModelConfigForCurrentFlag\(\{modelName:(?<resolved>[A-Za-z_$][\w$]*),maxMode:(?<maxMode>[A-Za-z_$][\w$]*)\}\):void 0\)\?\.selectedModels\?\?\[\],(?<stored>[A-Za-z_$][\w$]*)=(?<config>[A-Za-z_$][\w$]*)\?\.selectedModels\?\?\[\]/g;
57
68
  const requestedModelCredentials = /(?<prefix>new [A-Za-z_$][\w$]*\(\{modelId:(?<model>[A-Za-z_$][\w$]*),maxMode:(?<details>[A-Za-z_$][\w$]*)\.maxMode,parameters:[\s\S]*?,credentials:)this\.convertModelDetailsToCredentials\(\k<details>\)(?<suffix>\}\))(?=\}convertModelDetailsToCredentials)/g;
69
+ const subagentModelDisplaySelection = /function (?<functionName>[A-Za-z_$][\w$]*)\((?<input>[A-Za-z_$][\w$]*)\)\{return \k<input>\.resumeTargetComposerId!==void 0\?\k<input>\.subagentModelName:\k<input>\.bestOfNModelName!==void 0\?\k<input>\.bestOfNModelName:\k<input>\.taskParamModelName\?\?\k<input>\.subagentModelName\}/g;
70
+ const legacySubagentModelDisplaySelection = /function (?<functionName>[A-Za-z_$][\w$]*)\((?<input>[A-Za-z_$][\w$]*)\)\{\/\*ocx-cursor-subagent-model-display-v1\*\/return \k<input>\.subagentModelName\?\.startsWith\("opencodex\/"\)\?\k<input>\.subagentModelName:\k<input>\.resumeTargetComposerId!==void 0\?\k<input>\.subagentModelName:\k<input>\.bestOfNModelName!==void 0\?\k<input>\.bestOfNModelName:\k<input>\.taskParamModelName\?\?\k<input>\.subagentModelName\}/g;
71
+ const subagentTaskArgsContext = /(?<args>[A-Za-z_$][\w$]*)=(?<argsExtractor>[A-Za-z_$][\w$]*)\((?<bubble>[A-Za-z_$][\w$]*)\),(?<resume>[A-Za-z_$][\w$]*)=(?<resumeExtractor>[A-Za-z_$][\w$]*)\(\k<args>\),[\s\S]{0,400}?(?<taskModel>[A-Za-z_$][\w$]*)=\k<resume>===void 0\?\k<bubble>\.params\?\.model:void 0/g;
72
+ const legacySubagentTaskArgsDisplayV4 = /taskParamModelName:\/\*ocx-cursor-subagent-task-args-display-v4\*\/\(\(\)=>\{[\s\S]*?\}\)\(\)/g;
73
+ const legacySubagentTaskArgsDisplayV3 = /taskParamModelName:\/\*ocx-cursor-subagent-task-args-display-v3\*\/\(\(\)=>\{[\s\S]*?return ocxCursorTaskModel\}\)\(\)/g;
74
+ const legacySubagentTaskArgsDisplayV2 = /taskParamModelName:\/\*ocx-cursor-subagent-task-args-display-v2\*\/\(\(\)=>\{[\s\S]*?return ocxCursorTaskModel\}\)\(\)/g;
75
+ const legacySubagentTaskArgsDisplay = /taskParamModelName:\/\*ocx-cursor-subagent-task-args-display-v1\*\/(?<taskModel>[A-Za-z_$][\w$]*)\?\?(?<args>[A-Za-z_$][\w$]*)\?\.model/g;
58
76
  const rawSubagentLoad = /(?<raw>[A-Za-z_$][\w$]*)=this\.subagentsService\.peekRawSubagents\(\)/g;
59
77
  const localModelConstructor = /function (?<functionName>[A-Za-z_$][\w$]*)\(e,t\)\{return new (?<modelType>[A-Za-z_$][\w$]*\.[A-Za-z_$][\w$]*)\(\{modelId:e,displayModelId:e,displayName:null!=t\?t:e,displayNameShort:null!=t\?t:e,aliases:\[\]\}\)\}/g;
60
78
  const localRuntimeVisionCapability = /"boolean"==typeof (?<object>[A-Za-z_$][\w$]*)\.supports_vision\?\{supports_vision:\k<object>\.supports_vision\}:\{\}\)/g;
@@ -75,8 +93,17 @@ export function clearCursorAppQuarantine(options = {}) {
75
93
  export function finalizeCursorAppPatch(options = {}) {
76
94
  const execute = options.execFileSync || execFileSync;
77
95
  const appPath = options.appPath || cursorAppPath;
96
+ const verifyArgs = ["--verify", "--deep", "--strict", appPath];
97
+ let signatureIsValid = false;
98
+ try {
99
+ execute("/usr/bin/codesign", verifyArgs, { stdio: "ignore" });
100
+ signatureIsValid = true;
101
+ } catch {
102
+ // A rewritten bundle invalidates Cursor's signature and needs a fresh ad-hoc signature.
103
+ }
104
+ if (signatureIsValid) return;
78
105
  execute("/usr/bin/codesign", ["--force", "--sign", "-", appPath], { stdio: "ignore" });
79
- execute("/usr/bin/codesign", ["--verify", "--deep", "--strict", appPath], { stdio: "ignore" });
106
+ execute("/usr/bin/codesign", verifyArgs, { stdio: "ignore" });
80
107
  clearCursorAppQuarantine({ ...options, appPath, execFileSync: execute });
81
108
  }
82
109
 
@@ -158,6 +185,14 @@ export function patchCursorExplicitSubagentModelsSource(source) {
158
185
 
159
186
  export function patchCursorSubagentCredentialsSource(source) {
160
187
  if (source.includes(cursorSubagentCredentialsPatchMarker)) return { status: "already-patched", source };
188
+ if (source.includes(legacyCursorSubagentCredentialsPatchMarker)) {
189
+ let upgraded = source.replace(legacyCursorSubagentCredentialsPatchMarker, cursorSubagentCredentialsPatchMarker);
190
+ upgraded = replaceSingleMatch(upgraded, explicitSubagentByokGuard, (match) => {
191
+ const { hasByok, modelDetails, flagEnabled, maxMode } = match.groups;
192
+ return `if(${hasByok}(${modelDetails})&&!${modelDetails}.modelName?.startsWith("opencodex/")||!(${flagEnabled}||${maxMode}))return{};`;
193
+ }, "explicit subagent BYOK guard");
194
+ return { status: "patched", source: upgraded };
195
+ }
161
196
  let patched = replaceSingleMatch(source, explicitSubagentModelSelection, (match) => {
162
197
  const { functionName, input, modelDetails, flagEnabled, availableModels, storage, resolveParameters, maxMode } = match.groups;
163
198
  return `function ${functionName}(${input}){${cursorSubagentCredentialsPatchMarker}const{modelDetails:${modelDetails},flagEnabled:${flagEnabled},availableModels:${availableModels},storage:${storage},resolveModelParametersForSubmission:${resolveParameters},resolveCredentialsForSubmission:ocxCursorResolveCredentials}=${input},${maxMode}=${modelDetails}.maxMode===!0;`;
@@ -170,19 +205,29 @@ export function patchCursorSubagentCredentialsSource(source) {
170
205
  const { modelDetails, selector, featureGate, model, maxMode } = match.groups;
171
206
  return `getSelectedSubagentModelSelections(${modelDetails}){return ${selector}({modelDetails:${modelDetails},flagEnabled:${featureGate},availableModels:this.modelConfigService.getAvailableDefaultModels(),storage:this.reactiveStorageService.applicationUserPersistentStorage,resolveModelParametersForSubmission:(${model},${maxMode})=>this.modelConfigService.resolveModelParametersForSubmission(${model},void 0,${maxMode}),resolveCredentialsForSubmission:ocxCursorModel=>ocxCursorModel.startsWith("opencodex/")?this.convertModelDetailsToCredentials({apiKey:this.cursorAuthenticationService.openAIKey()??void 0,openaiApiBaseUrl:this.reactiveStorageService.applicationUserPersistentStorage.openAIBaseUrl}):void 0})}`;
172
207
  }, "explicit subagent selection caller");
208
+ patched = replaceSingleMatch(patched, explicitSubagentByokGuard, (match) => {
209
+ const { hasByok, modelDetails, flagEnabled, maxMode } = match.groups;
210
+ return `if(${hasByok}(${modelDetails})&&!${modelDetails}.modelName?.startsWith("opencodex/")||!(${flagEnabled}||${maxMode}))return{};`;
211
+ }, "explicit subagent BYOK guard");
173
212
  return { status: "patched", source: patched };
174
213
  }
175
214
 
176
215
  export function patchCursorSubagentLegacyDetailsSource(source) {
177
216
  if (source.includes(cursorSubagentLegacyDetailsPatchMarker)) return { status: "already-patched", source };
178
- const modelDetailsMatches = [...source.matchAll(agentModelDetailsType)];
217
+ let restored = source;
218
+ if (restored.includes(legacyCursorSubagentLegacyDetailsPatchMarker)) {
219
+ restored = replaceSingleMatch(restored, legacySelectedSubagentDetailsInjection, (match) => {
220
+ return `selectedSubagentModelDetails:${match.groups.options}.selectedSubagentModelsLegacy`;
221
+ }, "legacy explicit subagent model details");
222
+ }
223
+ const modelDetailsMatches = [...restored.matchAll(agentModelDetailsType)];
179
224
  if (modelDetailsMatches.length !== 1) {
180
225
  throw new Error(`Expected one Cursor agent model details type, found ${modelDetailsMatches.length}`);
181
226
  }
182
227
  const modelDetailsType = modelDetailsMatches[0].groups.type;
183
- const patched = replaceSingleMatch(source, selectedSubagentLegacyDetails, (match) => {
228
+ const patched = replaceSingleMatch(restored, selectedSubagentLegacyDetails, (match) => {
184
229
  const { options } = match.groups;
185
- return `selectedSubagentModelDetails:${cursorSubagentLegacyDetailsPatchMarker}${options}.selectedSubagentModelsLegacy?.length?${options}.selectedSubagentModelsLegacy:${options}.selectedSubagentModels?.filter(ocxCursorModel=>ocxCursorModel.modelId.startsWith("opencodex/")).map(ocxCursorModel=>new ${modelDetailsType}({modelId:ocxCursorModel.modelId,displayModelId:ocxCursorModel.modelId,displayName:ocxCursorModel.modelId,displayNameShort:ocxCursorModel.modelId,aliases:[],maxMode:ocxCursorModel.maxMode,credentials:ocxCursorModel.credentials}))`;
230
+ return `selectedSubagentModelDetails:${cursorSubagentLegacyDetailsPatchMarker}[...(${options}.selectedSubagentModelsLegacy??[]),...(${options}.selectedSubagentModels??[]).filter(ocxCursorModel=>ocxCursorModel.modelId.startsWith("opencodex/")&&!(${options}.selectedSubagentModelsLegacy??[]).some(ocxCursorLegacyModel=>ocxCursorLegacyModel.modelId===ocxCursorModel.modelId)).map(ocxCursorModel=>new ${modelDetailsType}({modelId:ocxCursorModel.modelId,displayModelId:ocxCursorModel.modelId,displayName:ocxCursorModel.modelId,displayNameShort:ocxCursorModel.modelId,aliases:[],maxMode:ocxCursorModel.maxMode,credentials:ocxCursorModel.credentials}))]`;
186
231
  }, "legacy explicit subagent model details");
187
232
  return { status: "patched", source: patched };
188
233
  }
@@ -261,6 +306,51 @@ export function patchCursorSubagentRuntimeCredentialsSource(source) {
261
306
  return { status: "patched", source: patched };
262
307
  }
263
308
 
309
+ export function patchCursorSubagentModelDisplaySource(source) {
310
+ if (source.includes(cursorSubagentModelDisplayPatchMarker)) return { status: "already-patched", source };
311
+ let restored = source;
312
+ if (restored.includes(legacyCursorSubagentModelDisplayPatchMarker)) {
313
+ restored = replaceSingleMatch(restored, legacySubagentModelDisplaySelection, (match) => {
314
+ const { functionName, input } = match.groups;
315
+ return `function ${functionName}(${input}){return ${input}.resumeTargetComposerId!==void 0?${input}.subagentModelName:${input}.bestOfNModelName!==void 0?${input}.bestOfNModelName:${input}.taskParamModelName??${input}.subagentModelName}`;
316
+ }, "legacy subagent model display selector");
317
+ }
318
+ const patched = replaceSingleMatch(restored, subagentModelDisplaySelection, (match) => {
319
+ const { functionName, input } = match.groups;
320
+ return `function ${functionName}(${input}){${cursorSubagentModelDisplayPatchMarker}return ${input}.resumeTargetComposerId!==void 0?${input}.subagentModelName:${input}.bestOfNModelName!==void 0?${input}.bestOfNModelName:${input}.taskParamModelName?.startsWith("opencodex/")?${input}.taskParamModelName:${input}.taskParamModelName?.startsWith("composer-")&&${input}.subagentModelName?.startsWith("opencodex/")?${input}.subagentModelName:${input}.taskParamModelName??${input}.subagentModelName}`;
321
+ }, "subagent model display selector");
322
+ return { status: "patched", source: patched };
323
+ }
324
+
325
+ export function patchCursorSubagentTaskArgsDisplaySource(source) {
326
+ if (source.includes(cursorSubagentTaskArgsDisplayPatchMarker)) return { status: "already-patched", source };
327
+ const contexts = [...source.matchAll(subagentTaskArgsContext)];
328
+ if (contexts.length !== 1) {
329
+ throw new Error(`Expected one Cursor subagent task args context, found ${contexts.length}`);
330
+ }
331
+ const { args, bubble, taskModel } = contexts[0].groups;
332
+ const replacement = `taskParamModelName:${cursorSubagentTaskArgsDisplayPatchMarker}/<ocx-subagent-model>(opencodex\\/[^<]+)<\\/ocx-subagent-model>/.exec(${bubble}.params?.prompt??${args}?.prompt??"")?.[1]??${taskModel}??${args}?.model`;
333
+ if (source.includes(legacyCursorSubagentTaskArgsDisplayV4PatchMarker)) {
334
+ const upgraded = replaceSingleMatch(source, legacySubagentTaskArgsDisplayV4, replacement, "v4 subagent task args model display field");
335
+ return { status: "patched", source: upgraded };
336
+ }
337
+ if (source.includes(legacyCursorSubagentTaskArgsDisplayV3PatchMarker)) {
338
+ const upgraded = replaceSingleMatch(source, legacySubagentTaskArgsDisplayV3, replacement, "v3 subagent task args model display field");
339
+ return { status: "patched", source: upgraded };
340
+ }
341
+ if (source.includes(legacyCursorSubagentTaskArgsDisplayV2PatchMarker)) {
342
+ const upgraded = replaceSingleMatch(source, legacySubagentTaskArgsDisplayV2, replacement, "v2 subagent task args model display field");
343
+ return { status: "patched", source: upgraded };
344
+ }
345
+ if (source.includes(legacyCursorSubagentTaskArgsDisplayPatchMarker)) {
346
+ const upgraded = replaceSingleMatch(source, legacySubagentTaskArgsDisplay, replacement, "legacy subagent task args model display field");
347
+ return { status: "patched", source: upgraded };
348
+ }
349
+ const field = new RegExp(`taskParamModelName:${taskModel}(?=[},])`, "g");
350
+ const patched = replaceSingleMatch(source, field, replacement, "subagent task args model display field");
351
+ return { status: "patched", source: patched };
352
+ }
353
+
264
354
  export function patchCursorRoutedSubagentTypesSource(source) {
265
355
  if (source.includes(cursorRoutedSubagentTypesPatchMarker)) return { status: "already-patched", source };
266
356
  const patched = replaceSingleMatch(source, rawSubagentLoad, (match) => {
@@ -280,9 +370,11 @@ export function patchCursorWorkbenchSource(source) {
280
370
  const executionRouting = patchCursorSubagentExecutionRoutingSource(promptRouting.source);
281
371
  const runRouting = patchCursorSubagentRunRoutingSource(executionRouting.source);
282
372
  const runtimeCredentials = patchCursorSubagentRuntimeCredentialsSource(runRouting.source);
283
- const subagentTypes = patchCursorRoutedSubagentTypesSource(runtimeCredentials.source);
373
+ const modelDisplay = patchCursorSubagentModelDisplaySource(runtimeCredentials.source);
374
+ const taskArgsDisplay = patchCursorSubagentTaskArgsDisplaySource(modelDisplay.source);
375
+ const subagentTypes = patchCursorRoutedSubagentTypesSource(taskArgsDisplay.source);
284
376
  return {
285
- status: metadata.status === "patched" || routing.status === "patched" || subagents.status === "patched" || credentials.status === "patched" || legacyDetails.status === "patched" || promptRouting.status === "patched" || executionRouting.status === "patched" || runRouting.status === "patched" || runtimeCredentials.status === "patched" || subagentTypes.status === "patched"
377
+ status: metadata.status === "patched" || routing.status === "patched" || subagents.status === "patched" || credentials.status === "patched" || legacyDetails.status === "patched" || promptRouting.status === "patched" || executionRouting.status === "patched" || runRouting.status === "patched" || runtimeCredentials.status === "patched" || modelDisplay.status === "patched" || taskArgsDisplay.status === "patched" || subagentTypes.status === "patched"
286
378
  ? "patched"
287
379
  : "already-patched",
288
380
  source: subagentTypes.source,
package/src/gateway.mjs CHANGED
@@ -45,6 +45,52 @@ function disableStrictFunctionTools(tools) {
45
45
  }
46
46
  }
47
47
 
48
+ function enrichSubagentModelTools(tools, catalog) {
49
+ if (!Array.isArray(tools)) return;
50
+ const aliases = catalog.map(({ alias }) => alias).filter((alias) => alias.startsWith(managedPrefix));
51
+ if (aliases.length === 0) return;
52
+ const modelList = aliases.map((alias) => `- ${alias}`).join("\n");
53
+ const modelListPattern = /(If the user explicitly asks for the model of a subagent\/task,[\s\S]*?)(?=\n\nIf the user isn't asking)/;
54
+ for (const tool of tools) {
55
+ if (!isRecord(tool) || tool.type !== "function") continue;
56
+ const definition = isRecord(tool.function) ? tool.function : tool;
57
+ if (typeof definition.name !== "string" || !/^(subagent|task)$/i.test(definition.name)) continue;
58
+ if (typeof definition.description === "string" && modelListPattern.test(definition.description)) {
59
+ definition.description = definition.description.replace(modelListPattern, `$1\n${modelList}`);
60
+ }
61
+ const model = definition.parameters?.properties?.model;
62
+ if (!isRecord(model)) continue;
63
+ if (Array.isArray(model.enum)) {
64
+ model.enum = [...new Set([...model.enum, ...aliases])];
65
+ }
66
+ if (typeof model.description === "string") {
67
+ model.description += ` Available OpenCodex model slugs: ${aliases.join(", ")}.`;
68
+ }
69
+ }
70
+ }
71
+
72
+ function restoreRoutedSubagentModels(messages, catalog) {
73
+ if (!Array.isArray(messages)) return;
74
+ const aliases = new Set(catalog.map(({ alias }) => alias));
75
+ const restore = (text) => {
76
+ if (typeof text !== "string") return text;
77
+ const requested = [...text.matchAll(/<ocx-subagent-model>(opencodex\/[^<]+)<\/ocx-subagent-model>/g)]
78
+ .map((match) => match[1])
79
+ .find((alias) => aliases.has(alias));
80
+ return requested ? text.split("composer-2.5").join(requested) : text;
81
+ };
82
+ for (const message of messages) {
83
+ if (!isRecord(message)) continue;
84
+ if (typeof message.content === "string") {
85
+ message.content = restore(message.content);
86
+ } else if (Array.isArray(message.content)) {
87
+ for (const part of message.content) {
88
+ if (isRecord(part) && typeof part.text === "string") part.text = restore(part.text);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
48
94
  export function rewriteModelAliasBody(body, catalog) {
49
95
  if (!body?.length) return body;
50
96
  let payload;
@@ -54,6 +100,8 @@ export function rewriteModelAliasBody(body, catalog) {
54
100
  return body;
55
101
  }
56
102
  if (!isRecord(payload) || typeof payload.model !== "string" || !payload.model.startsWith(managedPrefix)) return body;
103
+ restoreRoutedSubagentModels(payload.messages, catalog);
104
+ enrichSubagentModelTools(payload.tools, catalog);
57
105
 
58
106
  const variant = /^(opencodex\/.+?)\[([^\]]+)\]$/.exec(payload.model);
59
107
  let alias = variant?.[1] || payload.model;