Spaces:
Build error
Build error
| ; | |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | |
| if (k2 === undefined) k2 = k; | |
| var desc = Object.getOwnPropertyDescriptor(m, k); | |
| if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | |
| desc = { enumerable: true, get: function() { return m[k]; } }; | |
| } | |
| Object.defineProperty(o, k2, desc); | |
| }) : (function(o, m, k, k2) { | |
| if (k2 === undefined) k2 = k; | |
| o[k2] = m[k]; | |
| })); | |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | |
| Object.defineProperty(o, "default", { enumerable: true, value: v }); | |
| }) : function(o, v) { | |
| o["default"] = v; | |
| }); | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | |
| __setModuleDefault(result, mod); | |
| return result; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| const child_process = __importStar(require("child_process")); | |
| const fs = __importStar(require("fs")); | |
| const path = __importStar(require("path")); | |
| const util = __importStar(require("util")); | |
| const env_js_1 = require("../utils/env.cjs"); | |
| const commander_1 = require("commander"); | |
| const child_process_1 = require("child_process"); | |
| const currentFileName = __filename; | |
| const currentDirName = __dirname; | |
| const program = new commander_1.Command(); | |
| async function getDockerComposeCommand() { | |
| const exec = util.promisify(child_process.exec); | |
| try { | |
| await exec("docker compose --version"); | |
| return ["docker", "compose"]; | |
| } | |
| catch { | |
| try { | |
| await exec("docker-compose --version"); | |
| return ["docker-compose"]; | |
| } | |
| catch { | |
| throw new Error("Neither 'docker compose' nor 'docker-compose' commands are available. Please install the Docker server following the instructions for your operating system at https://docs.docker.com/engine/install/"); | |
| } | |
| } | |
| } | |
| async function pprintServices(servicesStatus) { | |
| const services = []; | |
| for (const service of servicesStatus) { | |
| const serviceStatus = { | |
| Service: String(service["Service"]), | |
| Status: String(service["Status"]), | |
| }; | |
| const publishers = service["Publishers"] || []; | |
| if (publishers) { | |
| serviceStatus["PublishedPorts"] = publishers | |
| .map((publisher) => String(publisher["PublishedPort"])) | |
| .join(", "); | |
| } | |
| services.push(serviceStatus); | |
| } | |
| const maxServiceLen = Math.max(...services.map((service) => service["Service"].length)); | |
| const maxStateLen = Math.max(...services.map((service) => service["Status"].length)); | |
| const serviceMessage = [ | |
| "\n" + | |
| "Service".padEnd(maxServiceLen + 2) + | |
| "Status".padEnd(maxStateLen + 2) + | |
| "Published Ports", | |
| ]; | |
| for (const service of services) { | |
| const serviceStr = service["Service"].padEnd(maxServiceLen + 2); | |
| const stateStr = service["Status"].padEnd(maxStateLen + 2); | |
| const portsStr = service["PublishedPorts"] || ""; | |
| serviceMessage.push(serviceStr + stateStr + portsStr); | |
| } | |
| let langchainEndpoint = "http://localhost:1984"; | |
| const usedNgrok = services.some((service) => service["Service"].includes("ngrok")); | |
| if (usedNgrok) { | |
| langchainEndpoint = await getNgrokUrl(); | |
| } | |
| serviceMessage.push("\nTo connect, set the following environment variables" + | |
| " in your LangChain application:" + | |
| "\nLANGCHAIN_TRACING_V2=true" + | |
| `\nLANGCHAIN_ENDPOINT=${langchainEndpoint}`); | |
| console.info(serviceMessage.join("\n")); | |
| } | |
| async function getNgrokUrl() { | |
| const ngrokUrl = "http://localhost:4040/api/tunnels"; | |
| try { | |
| // const response = await axios.get(ngrokUrl); | |
| const response = await fetch(ngrokUrl); | |
| if (response.status !== 200) { | |
| throw new Error(`Could not connect to ngrok console. ${response.status}, ${response.statusText}`); | |
| } | |
| const result = await response.json(); | |
| const exposedUrl = result["tunnels"][0]["public_url"]; | |
| return exposedUrl; | |
| } | |
| catch (error) { | |
| throw new Error(`Could not connect to ngrok console. ${error}`); | |
| } | |
| } | |
| async function createNgrokConfig(authToken) { | |
| const configPath = path.join(currentDirName, "ngrok_config.yaml"); | |
| // Check if is a directory | |
| if (fs.existsSync(configPath) && fs.lstatSync(configPath).isDirectory()) { | |
| fs.rmdirSync(configPath, { recursive: true }); | |
| } | |
| else if (fs.existsSync(configPath)) { | |
| fs.unlinkSync(configPath); | |
| } | |
| let ngrokConfig = ` | |
| region: us | |
| tunnels: | |
| langchain: | |
| addr: langchain-backend:1984 | |
| proto: http | |
| version: '2' | |
| `; | |
| if (authToken !== null) { | |
| ngrokConfig += `authtoken: ${authToken}`; | |
| } | |
| fs.writeFileSync(configPath, ngrokConfig); | |
| return configPath; | |
| } | |
| class SmithCommand { | |
| constructor({ dockerComposeCommand }) { | |
| Object.defineProperty(this, "dockerComposeCommand", { | |
| enumerable: true, | |
| configurable: true, | |
| writable: true, | |
| value: [] | |
| }); | |
| Object.defineProperty(this, "dockerComposeFile", { | |
| enumerable: true, | |
| configurable: true, | |
| writable: true, | |
| value: "" | |
| }); | |
| Object.defineProperty(this, "dockerComposeDevFile", { | |
| enumerable: true, | |
| configurable: true, | |
| writable: true, | |
| value: "" | |
| }); | |
| Object.defineProperty(this, "dockerComposeBetaFile", { | |
| enumerable: true, | |
| configurable: true, | |
| writable: true, | |
| value: "" | |
| }); | |
| Object.defineProperty(this, "ngrokPath", { | |
| enumerable: true, | |
| configurable: true, | |
| writable: true, | |
| value: "" | |
| }); | |
| this.dockerComposeCommand = dockerComposeCommand; | |
| this.dockerComposeFile = path.join(path.dirname(currentFileName), "docker-compose.yaml"); | |
| this.dockerComposeDevFile = path.join(path.dirname(currentFileName), "docker-compose.dev.yaml"); | |
| this.dockerComposeBetaFile = path.join(path.dirname(currentFileName), "docker-compose.beta.yaml"); | |
| this.ngrokPath = path.join(path.dirname(currentFileName), "docker-compose.ngrok.yaml"); | |
| } | |
| async executeCommand(command) { | |
| return new Promise((resolve, reject) => { | |
| const child = (0, child_process_1.spawn)(command[0], command.slice(1), { stdio: "inherit" }); | |
| child.on("error", (error) => { | |
| console.error(`error: ${error.message}`); | |
| reject(error); | |
| }); | |
| child.on("close", (code) => { | |
| if (code !== 0) { | |
| reject(new Error(`Process exited with code ${code}`)); | |
| } | |
| else { | |
| resolve(); | |
| } | |
| }); | |
| }); | |
| } | |
| static async create() { | |
| console.info("BY USING THIS SOFTWARE YOU AGREE TO THE TERMS OF SERVICE AT:"); | |
| console.info("https://smith.langchain.com/terms-of-service.pdf"); | |
| const dockerComposeCommand = await getDockerComposeCommand(); | |
| return new SmithCommand({ dockerComposeCommand }); | |
| } | |
| async pull({ stage = "prod" }) { | |
| if (stage === "dev") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "dev-"); | |
| } | |
| else if (stage === "beta") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-"); | |
| } | |
| const command = [ | |
| ...this.dockerComposeCommand, | |
| "-f", | |
| this.dockerComposeFile, | |
| "pull", | |
| ]; | |
| await this.executeCommand(command); | |
| } | |
| async startLocal(stage = "prod") { | |
| const command = [ | |
| ...this.dockerComposeCommand, | |
| "-f", | |
| this.dockerComposeFile, | |
| ]; | |
| if (stage === "dev") { | |
| command.push("-f", this.dockerComposeDevFile); | |
| } | |
| else if (stage === "beta") { | |
| command.push("-f", this.dockerComposeBetaFile); | |
| } | |
| command.push("up", "--quiet-pull", "--wait"); | |
| await this.executeCommand(command); | |
| console.info("LangSmith server is running at http://localhost:1984.\n" + | |
| "To view the app, navigate your browser to http://localhost:80" + | |
| "\n\nTo connect your LangChain application to the server" + | |
| " locally, set the following environment variable" + | |
| " when running your LangChain application."); | |
| console.info("\tLANGCHAIN_TRACING_V2=true"); | |
| } | |
| async startAndExpose(ngrokAuthToken, stage = "prod") { | |
| const configPath = await createNgrokConfig(ngrokAuthToken); | |
| const command = [ | |
| ...this.dockerComposeCommand, | |
| "-f", | |
| this.dockerComposeFile, | |
| "-f", | |
| this.ngrokPath, | |
| ]; | |
| if (stage === "dev") { | |
| command.push("-f", this.dockerComposeDevFile); | |
| } | |
| else if (stage === "beta") { | |
| command.push("-f", this.dockerComposeBetaFile); | |
| } | |
| command.push("up", "--quiet-pull", "--wait"); | |
| await this.executeCommand(command); | |
| console.info("ngrok is running. You can view the dashboard at http://0.0.0.0:4040"); | |
| const ngrokUrl = await getNgrokUrl(); | |
| console.info("LangSmith server is running at http://localhost:1984." + | |
| "To view the app, navigate your browser to http://localhost:80" + | |
| "\n\nTo connect your LangChain application to the server" + | |
| " remotely, set the following environment variable" + | |
| " when running your LangChain application."); | |
| console.info("\tLANGCHAIN_TRACING_V2=true"); | |
| console.info(`\tLANGCHAIN_ENDPOINT=${ngrokUrl}`); | |
| fs.unlinkSync(configPath); | |
| } | |
| async stop() { | |
| const command = [ | |
| ...this.dockerComposeCommand, | |
| "-f", | |
| this.dockerComposeFile, | |
| "-f", | |
| this.ngrokPath, | |
| "down", | |
| ]; | |
| await this.executeCommand(command); | |
| } | |
| async status() { | |
| const command = [ | |
| ...this.dockerComposeCommand, | |
| "-f", | |
| this.dockerComposeFile, | |
| "ps", | |
| "--format", | |
| "json", | |
| ]; | |
| const exec = util.promisify(child_process.exec); | |
| const result = await exec(command.join(" ")); | |
| const servicesStatus = JSON.parse(result.stdout); | |
| if (servicesStatus) { | |
| console.info("The LangSmith server is currently running."); | |
| await pprintServices(servicesStatus); | |
| } | |
| else { | |
| console.info("The LangSmith server is not running."); | |
| } | |
| } | |
| async env() { | |
| const env = await (0, env_js_1.getRuntimeEnvironment)(); | |
| const envVars = await (0, env_js_1.getLangChainEnvVars)(); | |
| const envDict = { | |
| ...env, | |
| ...envVars, | |
| }; | |
| // Pretty print | |
| const maxKeyLength = Math.max(...Object.keys(envDict).map((key) => key.length)); | |
| console.info("LangChain Environment:"); | |
| for (const [key, value] of Object.entries(envDict)) { | |
| console.info(`${key.padEnd(maxKeyLength)}: ${value}`); | |
| } | |
| } | |
| } | |
| const startCommand = new commander_1.Command("start") | |
| .description("Start the LangSmith server") | |
| .option("--expose", "Expose the server to the internet via ngrok (requires ngrok to be installed)") | |
| .option("--ngrok-authtoken <ngrokAuthtoken>", "Your ngrok auth token. If this is set, --expose is implied.") | |
| .option("--stage <stage>", "Which version of LangSmith to run. Options: prod, dev, beta (default: prod)") | |
| .option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If not provided, the OpenAI API Key will be read" + | |
| " from the OPENAI_API_KEY environment variable. If neither are provided," + | |
| " some features of LangSmith will not be available.") | |
| .option("--langsmith-license-key <langsmithLicenseKey>", "The LangSmith license key to use for LangSmith. If not provided, the LangSmith" + | |
| " License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." + | |
| " If neither are provided, the Langsmith application will not spin up.") | |
| .action(async (args) => { | |
| const smith = await SmithCommand.create(); | |
| if (args.stage === "dev") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "dev-"); | |
| } | |
| else if (args.stage === "beta") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-"); | |
| } | |
| if (args.openaiApiKey) { | |
| (0, env_js_1.setEnvironmentVariable)("OPENAI_API_KEY", args.openaiApiKey); | |
| } | |
| if (args.langsmithLicenseKey) { | |
| (0, env_js_1.setEnvironmentVariable)("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey); | |
| } | |
| await smith.pull({ stage: args.stage }); | |
| if (args.expose) { | |
| await smith.startAndExpose(args.ngrokAuthtoken, args.stage); | |
| } | |
| else { | |
| await smith.startLocal(args.stage); | |
| } | |
| }); | |
| const stopCommand = new commander_1.Command("stop") | |
| .description("Stop the LangSmith server") | |
| .action(async () => { | |
| const smith = await SmithCommand.create(); | |
| await smith.stop(); | |
| }); | |
| const pullCommand = new commander_1.Command("pull") | |
| .description("Pull the latest version of the LangSmith server") | |
| .option("--stage <stage>", "Which version of LangSmith to pull. Options: prod, dev, beta (default: prod)") | |
| .action(async (args) => { | |
| const smith = await SmithCommand.create(); | |
| if (args.stage === "dev") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "dev-"); | |
| } | |
| else if (args.stage === "beta") { | |
| (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-"); | |
| } | |
| await smith.pull({ stage: args.stage }); | |
| }); | |
| const statusCommand = new commander_1.Command("status") | |
| .description("Get the status of the LangSmith server") | |
| .action(async () => { | |
| const smith = await SmithCommand.create(); | |
| await smith.status(); | |
| }); | |
| const envCommand = new commander_1.Command("env") | |
| .description("Get relevant environment information for the LangSmith server") | |
| .action(async () => { | |
| const smith = await SmithCommand.create(); | |
| await smith.env(); | |
| }); | |
| program | |
| .description("Manage the LangSmith server") | |
| .addCommand(startCommand) | |
| .addCommand(stopCommand) | |
| .addCommand(pullCommand) | |
| .addCommand(statusCommand) | |
| .addCommand(envCommand); | |
| program.parse(process.argv); | |