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 +1 -1
- package/src/cursor-patch.mjs +100 -8
- package/src/gateway.mjs +48 -0
package/package.json
CHANGED
package/src/cursor-patch.mjs
CHANGED
|
@@ -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-
|
|
20
|
-
export const
|
|
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",
|
|
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
|
-
|
|
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(
|
|
228
|
+
const patched = replaceSingleMatch(restored, selectedSubagentLegacyDetails, (match) => {
|
|
184
229
|
const { options } = match.groups;
|
|
185
|
-
return `selectedSubagentModelDetails:${cursorSubagentLegacyDetailsPatchMarker}${options}.selectedSubagentModelsLegacy
|
|
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
|
|
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;
|