diff --git a/packages/salesforcedx-vscode-apex/src/commands/apexActionController.ts b/packages/salesforcedx-vscode-apex/src/commands/apexActionController.ts index 66e0bfb57d..fae9741ca5 100644 --- a/packages/salesforcedx-vscode-apex/src/commands/apexActionController.ts +++ b/packages/salesforcedx-vscode-apex/src/commands/apexActionController.ts @@ -343,7 +343,7 @@ export class ApexActionController { let jsonObj; // Ensure namedCredential is provided and not blank - if (!namedCredential || namedCredential.trim() === '') { + if (!this.isVersionGte(orgVersion, '63.0') && (!namedCredential || namedCredential.trim() === '')) { throw new Error(nls.localize('invalid_named_credential')); } diff --git a/packages/salesforcedx-vscode-apex/src/oas/documentProcessorPipeline/oasValidationStep.ts b/packages/salesforcedx-vscode-apex/src/oas/documentProcessorPipeline/oasValidationStep.ts index 91a0112a83..d8a76a774d 100644 --- a/packages/salesforcedx-vscode-apex/src/oas/documentProcessorPipeline/oasValidationStep.ts +++ b/packages/salesforcedx-vscode-apex/src/oas/documentProcessorPipeline/oasValidationStep.ts @@ -12,12 +12,12 @@ import { ProcessorInputOutput, ProcessorStep } from './processorStep'; import ruleset from './ruleset.spectral'; export class OasValidationStep implements ProcessorStep { - private diagnosticCollection: vscode.DiagnosticCollection; + public static diagnosticCollection: vscode.DiagnosticCollection = + vscode.languages.createDiagnosticCollection('OAS Validations'); private className: string; constructor(className: string) { // Initialize a diagnostic collection for in-memory YAML validation - this.diagnosticCollection = vscode.languages.createDiagnosticCollection('OAS Validations'); this.className = className; } @@ -27,7 +27,7 @@ export class OasValidationStep implements ProcessorStep { // Create a virtual URI to represent the YAML const virtualUri = vscode.Uri.parse(`untitled:${this.className}_OAS_temp.yaml`); - this.diagnosticCollection.clear(); + OasValidationStep.diagnosticCollection.clear(); // Run validation using Spectral await spectral.run(stringify(input.yaml)).then(results => { @@ -43,7 +43,7 @@ export class OasValidationStep implements ProcessorStep { }); // Add diagnostics to the Problems tab for the virtual document - this.diagnosticCollection.set(virtualUri, diagnostics); + OasValidationStep.diagnosticCollection.set(virtualUri, diagnostics); input.errors = results; }); diff --git a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/methodByMethodStrategy.ts b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/methodByMethodStrategy.ts index e09f395077..2ff53536b4 100644 --- a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/methodByMethodStrategy.ts +++ b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/methodByMethodStrategy.ts @@ -6,6 +6,7 @@ */ import * as fs from 'fs'; +import { OpenAPIV3 } from 'openapi-types'; import { DocumentSymbol } from 'vscode'; import { parse, stringify } from 'yaml'; import { @@ -19,7 +20,7 @@ import { } from '../schemas'; import { IMPOSED_FACTOR, PROMPT_TOKEN_MAX_LIMIT, SUM_TOKEN_MAX_LIMIT } from '.'; import { GenerationStrategy } from './generationStrategy'; -import { prompts } from './prompts'; +import { getPrompts } from './promptsHandler'; export const METHOD_BY_METHOD_STRATEGY_NAME = 'MethodByMethod'; export class MethodByMethodStrategy extends GenerationStrategy { @@ -84,13 +85,15 @@ export class MethodByMethodStrategy extends GenerationStrategy { for (const doc of docs) { const yamlCleanDoc = this.cleanYamlString(doc); - const parsed = parse(yamlCleanDoc) as OpenAPIDoc; + const parsed = parse(yamlCleanDoc) as OpenAPIV3.Document; // Merge paths - for (const [path, methods] of Object.entries(parsed.paths)) { - if (!combined.paths[path]) { - combined.paths[path] = {}; + if (parsed.paths) { + for (const [path, methods] of Object.entries(parsed.paths)) { + if (!combined.paths[path]) { + combined.paths[path] = {}; + } + Object.assign(combined.paths[path], methods); } - Object.assign(combined.paths[path], methods); } // Merge components if (parsed.components?.schemas) { @@ -197,6 +200,7 @@ export class MethodByMethodStrategy extends GenerationStrategy { } generatePromptForMethod(methodName: string): string { + const prompts = getPrompts(); let input = ''; const methodContext = this.methodsContextMap.get(methodName); input += `${prompts.SYSTEM_TAG}\n${prompts.METHOD_BY_METHOD.systemPrompt}\n${prompts.END_OF_PROMPT_TAG}\n`; diff --git a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts index 1fdb897e12..2f1640f2aa 100644 --- a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts +++ b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts @@ -4,7 +4,9 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -export const prompts = { +import { Prompts } from '../schemas'; + +export const sourcePrompts: Prompts = { SYSTEM_TAG: '<|system|>', END_OF_PROMPT_TAG: '<|endofprompt|>', USER_TAG: '<|user|>', diff --git a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/promptsHandler.ts b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/promptsHandler.ts new file mode 100644 index 0000000000..41867118a9 --- /dev/null +++ b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/promptsHandler.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import { parse, stringify } from 'yaml'; +import { Prompts } from '../schemas'; +import { sourcePrompts } from './prompts'; + +const PROMPTS_DIR = path.join('.sfdx', 'oas_prompts'); +const PROMPTS_FILE = path.join(PROMPTS_DIR, 'prompts.yaml'); + +const getPromptsFromSource = (): Record => { + return sourcePrompts; +}; + +export const ensurePromptsExist = (): void => { + if (!fs.existsSync(PROMPTS_DIR)) { + fs.mkdirSync(PROMPTS_DIR, { recursive: true }); + } + + if (!fs.existsSync(PROMPTS_FILE)) { + const extractedPrompts = getPromptsFromSource(); + fs.writeFileSync(PROMPTS_FILE, stringify(extractedPrompts), 'utf8'); + } +}; + +export const getPrompts = (): Prompts => { + ensurePromptsExist(); + const data = fs.readFileSync(PROMPTS_FILE, 'utf8'); + return parse(data) as Prompts; +}; + +// For future use cases (if needed) +export const updatePrompts = (newPrompts: Record): void => { + fs.writeFileSync(PROMPTS_FILE, stringify(newPrompts, null, 2), 'utf8'); +}; diff --git a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/wholeClassStrategy.ts b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/wholeClassStrategy.ts index 63248861d2..5c0b72c651 100644 --- a/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/wholeClassStrategy.ts +++ b/packages/salesforcedx-vscode-apex/src/oas/generationStrategy/wholeClassStrategy.ts @@ -15,7 +15,7 @@ import { } from '../schemas'; import { IMPOSED_FACTOR, PROMPT_TOKEN_MAX_LIMIT, SUM_TOKEN_MAX_LIMIT } from '.'; import { GenerationStrategy } from './generationStrategy'; -import { prompts } from './prompts'; +import { getPrompts } from './promptsHandler'; export const WHOLE_CLASS_STRATEGY_NAME = 'WholeClass'; export class WholeClassStrategy extends GenerationStrategy { metadata: ApexClassOASEligibleResponse; @@ -45,6 +45,7 @@ export class WholeClassStrategy extends GenerationStrategy { } public generate(): PromptGenerationResult { + const prompts = getPrompts(); const documentText = fs.readFileSync(new URL(this.metadata.resourceUri.toString()), 'utf8'); const input = `${prompts.SYSTEM_TAG}\n${prompts.systemPrompt}\n${prompts.END_OF_PROMPT_TAG}\n${prompts.USER_TAG}\n` + diff --git a/packages/salesforcedx-vscode-apex/src/oas/schemas.ts b/packages/salesforcedx-vscode-apex/src/oas/schemas.ts index 7665606a2e..ee650abcac 100644 --- a/packages/salesforcedx-vscode-apex/src/oas/schemas.ts +++ b/packages/salesforcedx-vscode-apex/src/oas/schemas.ts @@ -107,3 +107,18 @@ export interface OpenAPIDoc { paths: Record; components?: { schemas?: Record }; } + +export interface Prompts { + SYSTEM_TAG: string; + END_OF_PROMPT_TAG: string; + USER_TAG: string; + ASSISTANT_TAG: string; + systemPrompt: string; + METHOD_BY_METHOD: { + systemPrompt: string; + USER_PROMPT: string; + }; + wholeClass: { + userPrompt: string; + }; +}