diff --git a/engine/baml-schema-wasm/src/runtime_wasm/mod.rs b/engine/baml-schema-wasm/src/runtime_wasm/mod.rs index 7978b21cd..e338ae698 100644 --- a/engine/baml-schema-wasm/src/runtime_wasm/mod.rs +++ b/engine/baml-schema-wasm/src/runtime_wasm/mod.rs @@ -916,6 +916,7 @@ impl WasmRuntime { generator_type: &str, version_check_mode: &str, generator_language: &str, + is_diagnostic: bool, ) -> Option { // Convert string parameters to enums let generator_type = match generator_type { @@ -944,6 +945,7 @@ impl WasmRuntime { generator_type, version_check_mode, generator_language, + is_diagnostic, ) .map(|error| error.msg) } diff --git a/engine/language-client-codegen/src/lib.rs b/engine/language-client-codegen/src/lib.rs index 0d5cd6334..3c97d52ab 100644 --- a/engine/language-client-codegen/src/lib.rs +++ b/engine/language-client-codegen/src/lib.rs @@ -139,11 +139,12 @@ fn version_check_with_error( client_type: GeneratorOutputType, ) -> Result<()> { let res = check_version( - runtime_version, gen_version, + runtime_version, generator_type, mode, client_type, + true, ); match res { Some(e) => Err(anyhow::anyhow!("Version mismatch: {}", e.msg)), diff --git a/engine/language-client-codegen/src/version_check.rs b/engine/language-client-codegen/src/version_check.rs index e5a4d8cf8..a2477940e 100644 --- a/engine/language-client-codegen/src/version_check.rs +++ b/engine/language-client-codegen/src/version_check.rs @@ -18,100 +18,111 @@ pub enum VersionCheckMode { Strict, None, } - + pub fn check_version( - generator_version: &str, - current_version: &str, - generator_type: GeneratorType, - version_check_mode: VersionCheckMode, - generator_language: GeneratorOutputType, -) -> Option { - if version_check_mode == VersionCheckMode::None { - return None; - } - - let gen_version = match Version::parse(generator_version) { - Ok(v) => v, - Err(_) => return Some(VersionCheckError { - msg: format!("Invalid generator version in BAML config: {}", generator_version), - }), - }; - - let runtime_version = match Version::parse(current_version) { - Ok(v) => v, - Err(_) => return Some(VersionCheckError { - msg: format!("Invalid current version: {}", current_version), - }), - }; - - if generator_version == "0.0.0" { - return Some(VersionCheckError { - msg: format!("You must now add a 'version' to the generator config. Please add 'version \"{}\"' to continue generating baml_client\n. Make sure your installed baml package dependency and VSCode are the same version. \n\nSee https://github.com/BoundaryML/baml/pull/791", current_version).to_string(), - }); - } - - if gen_version.major != runtime_version.major || gen_version.minor != runtime_version.minor { - let base_message = format!( - "Version mismatch: Generator version ({}) does not match the {} version ({}). Major and minor versions must match.", - gen_version, - match generator_type { - GeneratorType::VSCodeCLI | GeneratorType::VSCode => "VSCode extension", - GeneratorType::CLI => "installed BAML CLI", - }, - runtime_version - ); - - let (update_message, docs_link) = if runtime_version > gen_version { - ( - match generator_type { - GeneratorType::VSCodeCLI | GeneratorType::VSCode => - format!("Update the 'version' in your BAML generator config to '{}' to match the VSCode extension version.", runtime_version), - GeneratorType::CLI => - format!("Update the 'version' in your BAML generator config to '{}' to match the installed BAML CLI version.", runtime_version), - }, - "https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#troubleshooting-version-conflicts" - ) - } else { - let update_instruction = match generator_language { - GeneratorOutputType::PythonPydantic => format!("pip install --upgrade baml-py=={}", gen_version), - GeneratorOutputType::Typescript => format!("npm install --save-dev @boundaryml/baml@{}", gen_version), - GeneratorOutputType::RubySorbet => format!("gem install baml -v {}", gen_version), - }; - ( - match generator_type { - GeneratorType::VSCodeCLI | GeneratorType::VSCode => - format!("Update your VSCode extension to version '{}' to match the version in the BAML generator config. Also update your BAML package: {}", gen_version, update_instruction), - GeneratorType::CLI => - format!("Update your installed BAML CLI package to version '{}' to match the version in the BAML generator config: {}", gen_version, update_instruction), - }, - "https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#troubleshooting-version-conflicts" - ) - }; - - let formatted_link = match generator_type { - GeneratorType::VSCodeCLI | GeneratorType::VSCode => format!("[documentation]({})", docs_link), - GeneratorType::CLI => docs_link.to_string(), - }; - - let error_message = format!( - "{}\n\nAction required: {}\n\nFor more information, see: {}", - base_message, update_message, formatted_link - ); - - return Some(VersionCheckError { msg: error_message }); - } - - None + generator_version: &str, + current_version: &str, + generator_type: GeneratorType, + version_check_mode: VersionCheckMode, + generator_language: GeneratorOutputType, + is_diagnostic: bool, + ) -> Option { + if version_check_mode == VersionCheckMode::None { + return None; + } + + let gen_version = match Version::parse(generator_version) { + Ok(v) => v, + Err(_) => return Some(VersionCheckError { + msg: format!("Invalid generator version in BAML config: {}", generator_version), + }), + }; + + let runtime_version = match Version::parse(current_version) { + Ok(v) => v, + Err(_) => return Some(VersionCheckError { + msg: format!("Invalid current version: {}", current_version), + }), + }; + + if generator_version == "0.0.0" { + let error_message = format!("A 'version' is now required in generator config. Please add 'version \"{}\"' inside the generator to continue generating baml_client.\n\nMake sure your installed baml package dependency and VSCode are also version {} \n\nSee https://docs.boundaryml.com/docs/calling-baml/generate-baml-client", current_version, current_version); + return Some(VersionCheckError { + msg: if !is_diagnostic { + format!("⚠️⚠️⚠️ BAML GENERATION DISABLED: {}", error_message) + } else { + error_message + }, + }); + } + + if gen_version.major != runtime_version.major || gen_version.minor != runtime_version.minor { + let base_message = format!( + "Version mismatch: Generator version ({}) does not match the {} version ({}). Major and minor versions must match.", + gen_version, + match generator_type { + GeneratorType::VSCode => "VSCode extension", + GeneratorType::CLI | GeneratorType::VSCodeCLI => "installed baml package", + }, + runtime_version + ); + + let (update_message, docs_link) = if runtime_version > gen_version { + ( + match generator_type { + GeneratorType::VSCode => + format!("Update the 'version' in your BAML generator config to '{}' to match the VSCode extension version.", runtime_version), + GeneratorType::CLI | GeneratorType::VSCodeCLI => + format!("Update the 'version' in your BAML generator config to '{}' to match the installed baml package version.", runtime_version), + }, + "https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#troubleshooting-version-conflicts" + ) + } else { + let update_instruction = match generator_language { + GeneratorOutputType::PythonPydantic => format!("pip install --upgrade baml-py=={}", gen_version), + GeneratorOutputType::Typescript => format!("npm install --save-dev @boundaryml/baml@{}", gen_version), + GeneratorOutputType::RubySorbet => format!("gem install baml -v {}", gen_version), + }; + ( + match generator_type { + GeneratorType::VSCode => + format!("Update your VSCode extension to version '{}' to match the version in the BAML generator config. Also update your BAML package: {}", gen_version, update_instruction), + GeneratorType::VSCodeCLI | GeneratorType::CLI => + format!("Update your installed BAML CLI package to version '{}' to match the version in the BAML generator config: {}", gen_version, update_instruction), + }, + "https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#troubleshooting-version-conflicts" + ) + }; + + let formatted_link = match is_diagnostic { + false => format!("[documentation]({})", docs_link), + _ => docs_link.to_string(), + }; + + let error_message = format!( + "{}\n\nAction required: {}\n\nTo prevent this issue, see: {}", + base_message, update_message, formatted_link + ); + + return Some(VersionCheckError { + msg: if !is_diagnostic { + format!("⚠️⚠️⚠️ BAML GENERATION DISABLED: {}", error_message) + } else { + error_message + }, + }); + } + + None } - #[cfg(test)] mod tests { use super::*; #[test] fn test_vscode_link_formatting() { - let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCode, VersionCheckMode::Strict, GeneratorOutputType::Typescript); + let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCode, VersionCheckMode::Strict, GeneratorOutputType::Typescript, false); assert!(result.is_some()); let error_msg = result.unwrap().msg; assert!(error_msg.contains("[documentation](https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#updating-baml-package)")); @@ -119,7 +130,7 @@ mod tests { #[test] fn test_cli_link_formatting() { - let result = check_version("1.3.0", "1.2.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic); + let result = check_version("1.3.0", "1.2.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false); assert!(result.is_some()); let error_msg = result.unwrap().msg; assert!(error_msg.contains("https://docs.boundaryml.com/docs/calling-baml/generate-baml-client#updating-baml-package")); @@ -128,21 +139,21 @@ mod tests { #[test] fn test_version_check_none() { assert_eq!( - check_version("1.0.0", "2.0.0", GeneratorType::CLI, VersionCheckMode::None, GeneratorOutputType::PythonPydantic), + check_version("1.0.0", "2.0.0", GeneratorType::CLI, VersionCheckMode::None, GeneratorOutputType::PythonPydantic, false), None ); } #[test] fn test_invalid_generator_version() { - let result = check_version("invalid", "1.0.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic); + let result = check_version("invalid", "1.0.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false); assert!(result.is_some()); assert!(result.unwrap().msg.contains("Invalid generator version")); } #[test] fn test_invalid_current_version() { - let result = check_version("1.0.0", "invalid", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic); + let result = check_version("1.0.0", "invalid", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false); assert!(result.is_some()); assert!(result.unwrap().msg.contains("Invalid current version")); } @@ -150,14 +161,14 @@ mod tests { #[test] fn test_matching_versions() { assert_eq!( - check_version("1.2.3", "1.2.4", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic), + check_version("1.2.3", "1.2.4", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false), None ); } #[test] fn test_mismatched_major_version_cli_python() { - let result = check_version("2.0.0", "1.0.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic); + let result = check_version("2.0.0", "1.0.0", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false); assert!(result.is_some()); let error_msg = result.unwrap().msg; assert!(error_msg.contains("Version mismatch")); @@ -167,7 +178,7 @@ mod tests { #[test] fn test_mismatched_minor_version_vscode_typescript() { - let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCode, VersionCheckMode::Strict, GeneratorOutputType::Typescript); + let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCode, VersionCheckMode::Strict, GeneratorOutputType::Typescript, false); assert!(result.is_some()); let error_msg = result.unwrap().msg; assert!(error_msg.contains("Version mismatch")); @@ -177,7 +188,7 @@ mod tests { #[test] fn test_older_vscode_version_ruby() { - let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCodeCLI, VersionCheckMode::Strict, GeneratorOutputType::RubySorbet); + let result = check_version("1.3.0", "1.2.0", GeneratorType::VSCodeCLI, VersionCheckMode::Strict, GeneratorOutputType::RubySorbet, false); assert!(result.is_some()); let error_msg = result.unwrap().msg; assert!(error_msg.contains("Version mismatch")); @@ -188,7 +199,7 @@ mod tests { #[test] fn test_patch_version_difference() { assert_eq!( - check_version("1.2.3", "1.2.4", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic), + check_version("1.2.3", "1.2.4", GeneratorType::CLI, VersionCheckMode::Strict, GeneratorOutputType::PythonPydantic, false), None ); } diff --git a/typescript/playground-common/src/baml_wasm_web/EventListener.tsx b/typescript/playground-common/src/baml_wasm_web/EventListener.tsx index f8f1eff56..905021ac1 100644 --- a/typescript/playground-common/src/baml_wasm_web/EventListener.tsx +++ b/typescript/playground-common/src/baml_wasm_web/EventListener.tsx @@ -50,6 +50,7 @@ const envKeyValueStorage = atomWithStorage<[string, string][]>( defaultEnvKeyValues, vscodeLocalStorageStore, ) +export const bamlCliVersionAtom = atom(null) export const resetEnvKeyValuesAtom = atom(null, (get, set) => { set(envKeyValueStorage, []) @@ -482,6 +483,7 @@ export const EventListener: React.FC<{ children: React.ReactNode }> = ({ childre const wasm = useAtomValue(wasmAtom) const [selectedFunc, setSelectedFunction] = useAtom(selectedFunctionAtom) const envVars = useAtomValue(envVarsAtom) + const [bamlCliVersion, setBamlCliVersion] = useAtom(bamlCliVersionAtom) useEffect(() => { if (wasm) { @@ -561,6 +563,10 @@ export const EventListener: React.FC<{ children: React.ReactNode }> = ({ childre port: number } } + | { + command: 'baml_cli_version' + content: string + } >, ) => { const { command, content } = event.data @@ -589,6 +595,10 @@ export const EventListener: React.FC<{ children: React.ReactNode }> = ({ childre updateCursor(content.cursor) } break + case 'baml_cli_version': + console.log('Setting baml cli version', content) + setBamlCliVersion(content) + break case 'remove_project': removeProject((content as { root_path: string }).root_path) @@ -630,7 +640,8 @@ export const EventListener: React.FC<{ children: React.ReactNode }> = ({ childre return ( <>
- Runtime Version: {version} +
{bamlCliVersion ? 'baml-cli ' + bamlCliVersion : ''}
+ VSCode Runtime Version: {version}
{selectedProject === null ? ( availableProjects.length === 0 ? ( diff --git a/typescript/vscode-ext/packages/language-server/src/lib/baml_project_manager.ts b/typescript/vscode-ext/packages/language-server/src/lib/baml_project_manager.ts index f33233242..7a7f52b4a 100644 --- a/typescript/vscode-ext/packages/language-server/src/lib/baml_project_manager.ts +++ b/typescript/vscode-ext/packages/language-server/src/lib/baml_project_manager.ts @@ -68,15 +68,14 @@ class Project { private onSuccess: (e: WasmDiagnosticError, files: Record) => void, ) {} - private checkVersion(generator: BamlWasm.WasmGeneratorConfig) { - const current_version = BamlWasm.version() // TODO set to CLI or other thing - + private checkVersion(generator: BamlWasm.WasmGeneratorConfig, isDiagnostic: boolean) { const message = WasmRuntime.check_version( generator.version, - current_version, + this.getVSCodeGeneratorVersion(), bamlConfig?.config?.cliPath ? GeneratorType.VSCodeCLI : GeneratorType.VSCode, VersionCheckMode.Strict, generator.output_type, + isDiagnostic, ) return message } @@ -84,7 +83,7 @@ class Project { checkVersionOnSave() { let firstErrorMessage: undefined | string = undefined this.list_generators().forEach((g) => { - const message = this.checkVersion(g) + const message = this.checkVersion(g, false) if (message) { if (!firstErrorMessage) { firstErrorMessage = message @@ -96,42 +95,43 @@ class Project { } getGeneratorDiagnostics() { - if (!this.current_runtime) { - return - } - const generators = this.list_generators() // requires runtime - const diagnostics = new Map() - generators.forEach((g) => { - const message = this.checkVersion(g) - if (message) { - const diagnostic: Diagnostic = { - range: { - start: { line: g.span.start_line, character: 0 }, - end: { line: g.span.end_line, character: 0 }, - }, - message: message, - severity: DiagnosticSeverity.Error, - source: 'baml', - } - diagnostics.set(URI.file(g.span.file_path).toString(), [diagnostic]) + try { + if (!this.current_runtime) { + return } - }) - return diagnostics + const generators = this.list_generators() // requires runtime + const diagnostics = new Map() + generators.forEach((g) => { + const message = this.checkVersion(g, true) + if (message) { + const diagnostic: Diagnostic = { + range: { + start: { line: g.span.start_line, character: 0 }, + end: { line: g.span.end_line, character: 0 }, + }, + message: message, + severity: DiagnosticSeverity.Error, + source: 'baml', + } + diagnostics.set(URI.file(g.span.file_path).toString(), [diagnostic]) + } + }) + return diagnostics + } catch (e) { + console.error(`Error getting generator diagnostics: ${e}`) + return new Map() + } } private getVSCodeGeneratorVersion() { if (bamlConfig.config?.cliPath) { - const versionCommand = `${bamlConfig.config.cliPath} --version` - exec(versionCommand, (error: Error | null, stdout: string, stderr: string) => { - if (error) { - console.error(`Error running baml cli script: ${JSON.stringify(error, null, 2)}`) - - return - } else { - console.log(stdout) - } - }) + if (bamlConfig.cliVersion) { + return bamlConfig.cliVersion + } else { + throw new Error('CLI version not available') + } } + return BamlWasm.version() } update_runtime() { @@ -170,7 +170,7 @@ class Project { runtime(): BamlWasm.WasmRuntime { const rt = this.current_runtime ?? this.last_successful_runtime if (!rt) { - throw new Error(`Project is not valid.`) + throw new Error(`BAML Generate failed - Project has errors.`) } return rt @@ -297,7 +297,10 @@ class Project { } list_generators(): BamlWasm.WasmGeneratorConfig[] { - return this.runtime().list_generators() + if (this.current_runtime == undefined) { + throw new Error(`BAML Generate failed. Project has errors.`) + } + return this.current_runtime.list_generators() } rootPath(): string { @@ -475,7 +478,7 @@ class BamlProjectManager { } } - console.log('diagnostics length: ' + Array.from(diagnostics).length) + // console.log('diagnostics length: ' + Array.from(diagnostics).length) this.notifier({ errors: Array.from(diagnostics), type: 'diagnostic', @@ -542,9 +545,9 @@ class BamlProjectManager { } async upsert_file(path: URI, content: string | undefined) { - console.debug( - `Upserting file: ${path}. Current projects ${this.projects.size} ${JSON.stringify(this.projects, null, 2)}`, - ) + // console.debug( + // `Upserting file: ${path}. Current projects ${this.projects.size} ${JSON.stringify(this.projects, null, 2)}`, + // ) await this.wrapAsync(async () => { console.debug( `Upserting file: ${path}. current projects ${this.projects.size} ${JSON.stringify(this.projects, null, 2)}`, @@ -611,7 +614,7 @@ class BamlProjectManager { // Reload all files in a project // Takes in a URI to any file in the project async reload_project_files(path: URI) { - console.debug(`Reloading project files: ${path}`) + // console.debug(`Reloading project files: ${path}`) await this.wrapAsync(async () => { const rootPath = uriToRootPath(path) diff --git a/typescript/vscode-ext/packages/language-server/src/server.ts b/typescript/vscode-ext/packages/language-server/src/server.ts index 8fa1f28c0..10a9ee8a5 100644 --- a/typescript/vscode-ext/packages/language-server/src/server.ts +++ b/typescript/vscode-ext/packages/language-server/src/server.ts @@ -22,25 +22,28 @@ import { RenameParams, TextDocumentSyncKind, TextDocuments, + FormattingOptions, + TextEdit, } from 'vscode-languageserver' import { URI } from 'vscode-uri' -import debounce from 'lodash/debounce' -import { TextDocument } from 'vscode-languageserver-textdocument' -import { IPCMessageReader, IPCMessageWriter, createConnection } from 'vscode-languageserver/node' -import { getWordAtPosition } from './lib/ast' +import { exec } from 'child_process' // import { FileChangeType } from 'vscode' import fs from 'fs' // import { cliBuild, cliCheckForUpdates, cliVersion } from './baml-cli' import { type ParserDatabase, TestRequest } from '@baml/common' +import debounce from 'lodash/debounce' +import { TextDocumentIdentifier } from 'vscode-languageserver-protocol' +import { TextDocument } from 'vscode-languageserver-textdocument' +import { IPCMessageReader, IPCMessageWriter, createConnection } from 'vscode-languageserver/node' import { z } from 'zod' +import { cliBuild } from './baml-cli' +import { bamlConfig, bamlConfigSchema } from './bamlConfig' +import { getWordAtPosition } from './lib/ast' // import { getVersion, getEnginesVersion } from './lib/wasm/internals' import BamlProjectManager, { GeneratorDisabledReason, GeneratorStatus, GeneratorType } from './lib/baml_project_manager' import type { LSOptions, LSSettings } from './lib/types' import { BamlWasm } from './lib/wasm' -import { bamlConfig, bamlConfigSchema } from './bamlConfig' -import { cliBuild } from './baml-cli' -import { exec } from 'child_process' try { // only required on vscode versions 1.89 and below. @@ -73,32 +76,36 @@ export function startServer(options?: LSOptions): void { // Source code: https://github.com/microsoft/vscode-languageserver-node/blob/main/server/src/common/server.ts#L1044 const connection: Connection = getConnection(options) const bamlProjectManager = new BamlProjectManager((params) => { - switch (params.type) { - case 'runtime_updated': - // console.log(`runtime_updated today! ${Object.keys(params.files).length}: ${Object.entries(params.files).length}`) - connection.sendRequest('runtime_updated', params) - break - case 'diagnostic': - params.errors.forEach(([uri, diagnostics]) => { - connection.sendDiagnostics({ uri: uri, diagnostics: diagnostics }) - }) + try { + switch (params.type) { + case 'runtime_updated': + // console.log(`runtime_updated today! ${Object.keys(params.files).length}: ${Object.entries(params.files).length}`) + connection.sendRequest('runtime_updated', params) + break + case 'diagnostic': + params.errors.forEach(([uri, diagnostics]) => { + connection.sendDiagnostics({ uri: uri, diagnostics: diagnostics }) + }) - // Determine number of warnings and errors - const errors = params.errors.reduce((acc, [, diagnostics]) => { - return acc + diagnostics.filter((d) => d.severity === 1).length - }, 0) - const warnings = params.errors.reduce((acc, [, diagnostics]) => { - return acc + diagnostics.filter((d) => d.severity === 2).length - }, 0) - connection.sendRequest('runtime_diagnostics', { errors, warnings }) - break - case 'error': - case 'warn': - case 'info': - connection.sendNotification('baml/message', { message: params.message, type: params.type ?? 'warn' }) - break - default: - console.error(`Unknown notification type ${params}`) + // Determine number of warnings and errors + const errors = params.errors.reduce((acc, [, diagnostics]) => { + return acc + diagnostics.filter((d) => d.severity === 1).length + }, 0) + const warnings = params.errors.reduce((acc, [, diagnostics]) => { + return acc + diagnostics.filter((d) => d.severity === 2).length + }, 0) + connection.sendRequest('runtime_diagnostics', { errors, warnings }) + break + case 'error': + case 'warn': + case 'info': + connection.sendNotification('baml/message', { message: params.message, type: params.type ?? 'warn' }) + break + default: + console.error(`Unknown notification type ${params}`) + } + } catch (e) { + console.error(`Error occurred while sending runtime notification:\n${e}`) } }) @@ -233,7 +240,7 @@ export function startServer(options?: LSOptions): void { const stdout = await new Promise((resolve, reject) => { exec(versionCommand, (error, stdout, stderr) => { if (error) { - reject(`Error running baml cli script: ${error}`) + reject(`Error running baml-cli: ${error}`) } else { resolve(stdout) } @@ -245,14 +252,12 @@ export function startServer(options?: LSOptions): void { if (version) { bamlConfig.cliVersion = version } else { - throw new Error(`Error parsing baml cli version from output: ${stdout}`) + throw new Error(`Error parsing baml-cli version from output: ${stdout}`) } } catch (error) { console.error(error) - connection.window.showErrorMessage(`BAML CLI Error: ${error}`) + connection.window.showErrorMessage(`baml-cli error: ${error}`) } - } else { - throw new Error('No CLI path found in config') } } @@ -344,23 +349,25 @@ export function startServer(options?: LSOptions): void { console.log('baml config ' + JSON.stringify(bamlConfig.config, null, 2)) await loadBamlCLIVersion() - if (bamlConfig.config?.generateCodeOnSave === 'always') { + if (bamlConfig.config?.generateCodeOnSave === 'never') { return } const proj = bamlProjectManager.getProjectById(documentUri) - const error = proj.checkVersionOnSave() - - if (error) { - connection.sendNotification('baml/message', { - type: 'info', - message: error, - durationMs: 6000, - }) - } - try { + const error = proj.checkVersionOnSave() + + if (error) { + console.error('Error generating: ' + error) + connection.sendNotification('baml/message', { + type: 'info', + message: error, + durationMs: 7000, + }) + return + } + if (bamlConfig.config?.cliPath) { cliBuild( bamlConfig.config?.cliPath!, @@ -379,7 +386,7 @@ export function startServer(options?: LSOptions): void { () => { connection.sendNotification('baml/message', { type: 'info', - message: 'BAML: Client generated! (Using installed baml-cli)', + message: 'BAML: Client generated! (Using installed baml-cli ' + bamlConfig.cliVersion + ')', }) }, ) @@ -534,6 +541,17 @@ export function startServer(options?: LSOptions): void { // } // }) + // connection.onDocumentFormatting((params: DocumentFormattingParams): TextEdit[] => { + // const { textDocument, options } = params + // const document = documents.get(textDocument.uri) + + // if (!document) { + // return [] + // } + + // return formatDocument(document, options) + // }) + // connection.onCodeAction((params: CodeActionParams) => { // const doc = getDocument(params.textDocument.uri) // if (doc) { @@ -564,6 +582,10 @@ export function startServer(options?: LSOptions): void { await bamlProjectManager.requestDiagnostics() }) + connection.onRequest('bamlCliVersion', async () => { + return bamlConfig.cliVersion + }) + connection.onRequest( 'selectTestCase', ({ diff --git a/typescript/vscode-ext/packages/vscode/src/extension.ts b/typescript/vscode-ext/packages/vscode/src/extension.ts index 7cb94b5e8..eae9c7342 100644 --- a/typescript/vscode-ext/packages/vscode/src/extension.ts +++ b/typescript/vscode-ext/packages/vscode/src/extension.ts @@ -3,7 +3,7 @@ import axios from 'axios' import glooLens from './LanguageToBamlCodeLensProvider' import { WebPanelView, openPlaygroundConfig } from './panels/WebPanelView' import plugins from './plugins' -import { requestDiagnostics } from './plugins/language-server' +import { requestBamlCLIVersion, requestDiagnostics } from './plugins/language-server' import { telemetry } from './plugins/language-server' import cors from 'cors' import { createProxyMiddleware } from 'http-proxy-middleware' @@ -243,6 +243,7 @@ export function activate(context: vscode.ExtensionContext) { } // sends project files as well to webview requestDiagnostics() + openPlaygroundConfig.lastOpenedFunction = args?.functionName ?? 'default' WebPanelView.currentPanel?.postMessage('select_function', { root_path: 'default', @@ -306,6 +307,10 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.executeCommand('baml.openBamlPanel') } + setInterval(() => { + requestBamlCLIVersion() + }, 30000) + // TODO: Reactivate linter. // runDiagnostics(); } diff --git a/typescript/vscode-ext/packages/vscode/src/panels/WebPanelView.ts b/typescript/vscode-ext/packages/vscode/src/panels/WebPanelView.ts index 9789e3569..ce3162afc 100644 --- a/typescript/vscode-ext/packages/vscode/src/panels/WebPanelView.ts +++ b/typescript/vscode-ext/packages/vscode/src/panels/WebPanelView.ts @@ -6,7 +6,7 @@ import { getUri } from '../utils/getUri' import { type Config, adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names-generator' import { URI } from 'vscode-uri' -import { requestDiagnostics } from '../plugins/language-server' +import { bamlConfig, requestDiagnostics } from '../plugins/language-server' const customConfig: Config = { dictionaries: [adjectives, colors, animals], @@ -184,6 +184,7 @@ export class WebPanelView { root_path: 'default', function_name: openPlaygroundConfig.lastOpenedFunction, }) + this.postMessage('baml_cli_version', bamlConfig.cliVersion) })() return diff --git a/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts b/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts index 1a758c328..3212c9383 100644 --- a/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts +++ b/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts @@ -35,6 +35,11 @@ let serverModule: string let telemetry: TelemetryReporter const intervalTimers: NodeJS.Timeout[] = [] +export const bamlConfig: { config: BamlConfig | null; cliVersion: string | null } = { + config: null, + cliVersion: null, +} + const isDebugMode = () => process.env.VSCODE_DEBUG_MODE === 'true' const isE2ETestOnPullRequest = () => process.env.PRISMA_USE_LOCAL_LS === 'true' @@ -46,6 +51,16 @@ export const requestDiagnostics = async () => { await client?.sendRequest('requestDiagnostics') } +export const requestBamlCLIVersion = async () => { + try { + const version = (await client.sendRequest('bamlCliVersion')) as string + console.log('Got BAML CLI version', version) + bamlConfig.cliVersion = version + } catch (e) { + console.error('Failed to get BAML CLI version', e) + } +} + export const getBAMLFunctions = async (): Promise< { name: string @@ -78,34 +93,6 @@ type LatestVersions = z.infer const bamlCliPath = () => config?.path || 'baml' -const buildUpdateMessage = (latestVersions: LatestVersions): { message: string; command: string } | null => { - const shouldUpdateCli = !!latestVersions.cli.recommended_update - const shouldUpdateGenerators = latestVersions.generators.filter((g) => g.recommended_update).length > 0 - - if (shouldUpdateCli && shouldUpdateGenerators) { - return { - message: 'Please update BAML and its client libraries', - command: `${bamlCliPath()} update && ${bamlCliPath()} update-client`, - } - } - - if (shouldUpdateCli) { - return { - message: 'Please update BAML', - command: `${bamlCliPath()} update`, - } - } - - if (shouldUpdateGenerators) { - return { - message: 'Please update the BAML client libraries', - command: `${bamlCliPath()} update-client`, - } - } - - return null -} - const checkForUpdates = async ({ showIfNoUpdates }: { showIfNoUpdates: boolean }) => { try { if (telemetry) { @@ -194,13 +181,13 @@ const activateClient = ( customCancellationToken?.dispose() customCancellationToken = null - vscode.window.showInformationMessage('Cancelled the progress') + // vscode.window.showInformationMessage('Cancelled the progress') resolve(null) return }) const totalMs = message.durationMs || 1500 // Total duration in milliseconds (2 seconds) - const updateCount = 20 // Number of updates + const updateCount = 50 // Number of updates const intervalMs = totalMs / updateCount // Interval between updates for (let i = 0; i < updateCount; i++) { @@ -225,12 +212,16 @@ const activateClient = ( }) client.onRequest('runtime_diagnostics', ({ errors, warnings }: { errors: number; warnings: number }) => { - if (errors > 0) { - StatusBarPanel.instance.setStatus({ status: 'fail', count: errors }) - } else if (warnings > 0) { - StatusBarPanel.instance.setStatus({ status: 'warn', count: warnings }) - } else { - StatusBarPanel.instance.setStatus('pass') + try { + if (errors > 0) { + StatusBarPanel.instance.setStatus({ status: 'fail', count: errors }) + } else if (warnings > 0) { + StatusBarPanel.instance.setStatus({ status: 'warn', count: warnings }) + } else { + StatusBarPanel.instance.setStatus('pass') + } + } catch (e) { + console.error('Error updating status bar', e) } })