diff --git a/web/packages/sdk/generateAll.ts b/web/packages/sdk/generateAll.ts index d815aabc68..529473ded6 100644 --- a/web/packages/sdk/generateAll.ts +++ b/web/packages/sdk/generateAll.ts @@ -76,9 +76,12 @@ const computeInputHash = (): string => { hash.update(`orval:${readOrvalVersion()}\n`); const generatorSources = [ + path.join(__dirname, 'orval.config.ts'), path.join(ORVAL_DIR, 'generate.ts'), path.join(ORVAL_DIR, 'constants.ts'), + path.join(ORVAL_DIR, 'format-generated.ts'), path.join(ORVAL_DIR, 'generateCustomFetcher.ts'), + path.join(ORVAL_DIR, 'operationNameOverride.ts'), path.join(__dirname, 'generateAll.ts'), ]; for (const file of generatorSources) { diff --git a/web/packages/sdk/orval/operationNameOverride.test.ts b/web/packages/sdk/orval/operationNameOverride.test.ts index 9697bd461a..cdd0125470 100644 --- a/web/packages/sdk/orval/operationNameOverride.test.ts +++ b/web/packages/sdk/orval/operationNameOverride.test.ts @@ -48,6 +48,14 @@ describe('operationNameOverride', () => { ).toBe('dataDesignerCreateJob'); }); + it('create data designer job with create path segment', () => { + expect( + operationNameOverride({ + operationId: 'create_job_apis_data_designer_v2_workspaces__workspace__jobs_create_post', + }) + ).toBe('dataDesignerCreateJob'); + }); + it('list workspaces', () => { expect( operationNameOverride({ @@ -60,6 +68,42 @@ describe('operationNameOverride', () => { expect(operationNameOverride({ operationId: 'gateway_proxy_get' })).toBe('gatewayProxyGet'); }); + // --- Job subtype routes --- + + it('create agent analyze job', () => { + expect( + operationNameOverride({ + operationId: 'create_job_apis_agents_v2_workspaces__workspace__jobs_analyze_post', + }) + ).toBe('agentsCreateAnalyzeJob'); + }); + + it('list agent evaluate suite jobs', () => { + expect( + operationNameOverride({ + operationId: 'list_jobs_apis_agents_v2_workspaces__workspace__jobs_evaluate_suite_get', + }) + ).toBe('agentsListEvaluateSuiteJobs'); + }); + + it('get agent optimize job logs', () => { + expect( + operationNameOverride({ + operationId: + 'get_job_logs_apis_agents_v2_workspaces__workspace__jobs_optimize__name__logs_get', + }) + ).toBe('agentsGetOptimizeJobLogs'); + }); + + it('list agent optimize skills job results', () => { + expect( + operationNameOverride({ + operationId: + 'list_job_results_apis_agents_v2_workspaces__workspace__jobs_optimize_skills__name__results_get', + }) + ).toBe('agentsListOptimizeSkillsJobResults'); + }); + // --- Flat collection endpoints (should keep original names) --- it('list metric job results (flat)', () => { diff --git a/web/packages/sdk/orval/operationNameOverride.ts b/web/packages/sdk/orval/operationNameOverride.ts index d0ea675ac9..db206880ed 100644 --- a/web/packages/sdk/orval/operationNameOverride.ts +++ b/web/packages/sdk/orval/operationNameOverride.ts @@ -9,6 +9,8 @@ // - list_jobs_apis_customization_v2_workspaces__workspace__jobs_get -> customizationListJobs // - create_job_apis_data_designer_v2_workspaces__workspace__jobs_post -> dataDesignerCreateJob // - list_workspaces_apis_entities_v2_workspaces_get -> entitiesListWorkspaces +// - create_job_apis_agents_v2_workspaces__workspace__jobs_analyze_post -> agentsCreateAnalyzeJob +// - list_jobs_apis_agents_v2_workspaces__workspace__jobs_evaluate_suite_get -> agentsListEvaluateSuiteJobs // // Non-apis_ routes (unchanged): // - gateway_proxy_get -> gatewayProxyGet @@ -84,6 +86,37 @@ const extractAllPathResources = (pathPart: string): string[] => { return segments.filter((_, i) => i % 2 === 0); }; +/** + * Qualifies generic job actions using job subtype routes. + * + * e.g., actionResource="job", pathResource="jobs_analyze" -> "analyze_job" + * e.g., actionResource="jobs", pathResource="jobs_evaluate_suite" -> "evaluate_suite_jobs" + * e.g., actionResource="job_logs", pathResource="jobs_optimize" -> "optimize_job_logs" + */ +const qualifyJobSubtypeResource = ( + service: string, + actionResource: string, + pathResource: string +): string | undefined => { + if (service !== 'agents') { + return undefined; + } + + const actionWords = actionResource.split('_'); + const pathWords = pathResource.split('_'); + + if (pathWords.length < 2 || singularize(pathWords[0]) !== 'job') { + return undefined; + } + + if (actionWords.length === 0 || singularize(actionWords[0]) !== 'job') { + return undefined; + } + + const subtypeWords = pathWords.slice(1); + return [...subtypeWords, actionWords[0], ...actionWords.slice(1)].join('_'); +}; + /** * Qualifies the action resource using path information for disambiguation. * When the path is more specific than the action, the path qualifier is prepended. @@ -93,9 +126,12 @@ const extractAllPathResources = (pathPart: string): string[] => { * e.g., actionResource="job_result_aggregate_scores", pathResource="benchmark_jobs" * -> "benchmark_job_result_aggregate_scores" */ -const qualifyResource = (actionResource: string, pathResource: string): string => { +const qualifyResource = (service: string, actionResource: string, pathResource: string): string => { if (!actionResource || !pathResource) return actionResource; + const jobSubtypeResource = qualifyJobSubtypeResource(service, actionResource, pathResource); + if (jobSubtypeResource) return jobSubtypeResource; + const actionWords = actionResource.split('_'); const pathWords = pathResource.split('_'); @@ -177,7 +213,7 @@ export const operationNameOverride = (operation: { operationId?: string }) => { const pathResource = extractPrimaryResource(pathPart); // Qualify the action resource using path context - const qualifiedResource = qualifyResource(actionResource, pathResource); + const qualifiedResource = qualifyResource(service, actionResource, pathResource); // Build: {service}_{verb}_{qualifiedResource} let name = normalizeOperationName(service, buildOperationName(service, verb, qualifiedResource));