diff --git a/docs/core_docs/docs/integrations/toolkits/sql.ipynb b/docs/core_docs/docs/integrations/toolkits/sql.ipynb new file mode 100644 index 000000000000..fa21ffd3df35 --- /dev/null +++ b/docs/core_docs/docs/integrations/toolkits/sql.ipynb @@ -0,0 +1,316 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "afaf8039", + "metadata": { + "vscode": { + "languageId": "raw" + } + }, + "source": [ + "---\n", + "sidebar_label: Sql Toolkit\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "e49f1e0d", + "metadata": {}, + "source": [ + "# SqlToolkit\n", + "\n", + "This will help you getting started with the [SqlToolkit](/docs/concepts/#toolkits). For detailed documentation of all SqlToolkit features and configurations head to the [API reference](https://api.js.langchain.com/classes/langchain_agents_toolkits_sql.SqlToolkit.html). You can also find the documentation for the Python equivalent [here](https://python.langchain.com/docs/integrations/toolkits/sql_database/).\n", + "\n", + "This toolkit contains a the following tools:\n", + "\n", + "| Name | Description |\n", + "|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n", + "| `query-sql` | Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. |\n", + "| `info-sql` | Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables. Be sure that the tables actually exist by calling list-tables-sql first! Example Input: \"table1, table2, table3\". |\n", + "| `list-tables-sql` | Input is an empty string, output is a comma-separated list of tables in the database. |\n", + "| `query-checker` | Use this tool to double check if your query is correct before executing it. Always use this tool before executing a query with query-sql! |\n", + "\n", + "This toolkit is useful for asking questions, performing queries, validating queries and more on a SQL database.\n", + "\n", + "## Setup\n", + "\n", + "This example uses Chinook database, which is a sample database available for SQL Server, Oracle, MySQL, etc. To set it up, follow [these instructions](https://database.guide/2-sample-databases-sqlite/), placing the `.db` file in the directory where your code lives.\n", + "\n", + "If you want to get automated tracing from runs of individual tools, you can also set your [LangSmith](https://docs.smith.langchain.com/) API key by uncommenting below:\n", + "\n", + "```typescript\n", + "process.env.LANGCHAIN_TRACING_V2=\"true\"\n", + "process.env.LANGCHAIN_API_KEY=\"your-api-key\"\n", + "```\n", + "\n", + "### Installation\n", + "\n", + "This toolkit lives in the `langchain` package. You'll also need to install the `typeorm` peer dependency.\n", + "\n", + "```{=mdx}\n", + "import IntegrationInstallTooltip from \"@mdx_components/integration_install_tooltip.mdx\";\n", + "import Npm2Yarn from \"@theme/Npm2Yarn\";\n", + "\n", + "\n", + "\n", + "\n", + " langchain typeorm\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "a38cde65-254d-4219-a441-068766c0d4b5", + "metadata": {}, + "source": [ + "## Instantiation\n", + "\n", + "First, we need to define our LLM to be used in the toolkit.\n", + "\n", + "```{=mdx}\n", + "import ChatModelTabs from \"@theme/ChatModelTabs\";\n", + "\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d1002b65", + "metadata": {}, + "outputs": [], + "source": [ + "// @lc-docs-hide-cell\n", + "\n", + "import { ChatOpenAI } from \"@langchain/openai\";\n", + "\n", + "const llm = new ChatOpenAI({\n", + " model: \"gpt-4o-mini\",\n", + " temperature: 0,\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae", + "metadata": {}, + "outputs": [], + "source": [ + "import { SqlToolkit } from \"langchain/agents/toolkits/sql\"\n", + "import { DataSource } from \"typeorm\";\n", + "import { SqlDatabase } from \"langchain/sql_db\";\n", + "\n", + "const datasource = new DataSource({\n", + " type: \"sqlite\",\n", + " database: \"../../../../../../Chinook.db\", // Replace with the link to your database\n", + "});\n", + "const db = await SqlDatabase.fromDataSourceParams({\n", + " appDataSource: datasource,\n", + "});\n", + "\n", + "const toolkit = new SqlToolkit(db, llm);" + ] + }, + { + "cell_type": "markdown", + "id": "5c5f2839-4020-424e-9fc9-07777eede442", + "metadata": {}, + "source": [ + "## Tools\n", + "\n", + "View available tools:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "51a60dbe-9f2e-4e04-bb62-23968f17164a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\n", + " {\n", + " name: 'query-sql',\n", + " description: 'Input to this tool is a detailed and correct SQL query, output is a result from the database.\\n' +\n", + " ' If the query is not correct, an error message will be returned.\\n' +\n", + " ' If an error is returned, rewrite the query, check the query, and try again.'\n", + " },\n", + " {\n", + " name: 'info-sql',\n", + " description: 'Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables.\\n' +\n", + " ' Be sure that the tables actually exist by calling list-tables-sql first!\\n' +\n", + " '\\n' +\n", + " ' Example Input: \"table1, table2, table3.'\n", + " },\n", + " {\n", + " name: 'list-tables-sql',\n", + " description: 'Input is an empty string, output is a comma-separated list of tables in the database.'\n", + " },\n", + " {\n", + " name: 'query-checker',\n", + " description: 'Use this tool to double check if your query is correct before executing it.\\n' +\n", + " ' Always use this tool before executing a query with query-sql!'\n", + " }\n", + "]\n" + ] + } + ], + "source": [ + "const tools = toolkit.getTools();\n", + "\n", + "console.log(tools.map((tool) => ({\n", + " name: tool.name,\n", + " description: tool.description,\n", + "})))" + ] + }, + { + "cell_type": "markdown", + "id": "dfe8aad4-8626-4330-98a9-7ea1ca5d2e0e", + "metadata": {}, + "source": [ + "## Use within an agent\n", + "\n", + "First, ensure you have LangGraph installed:\n", + "\n", + "```{=mdx}\n", + "\n", + " @langchain/langgraph\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "310bf18e-6c9a-4072-b86e-47bc1fcca29d", + "metadata": {}, + "outputs": [], + "source": [ + "import { createReactAgent } from \"@langchain/langgraph/prebuilt\"\n", + "\n", + "const agentExecutor = createReactAgent({ llm, tools });" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "23e11cc9-abd6-4855-a7eb-799f45ca01ae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\n", + " {\n", + " name: 'list-tables-sql',\n", + " args: {},\n", + " type: 'tool_call',\n", + " id: 'call_LqsRA86SsKmzhRfSRekIQtff'\n", + " }\n", + "]\n", + "Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\n", + "[\n", + " {\n", + " name: 'query-checker',\n", + " args: { input: 'SELECT * FROM Artist LIMIT 10;' },\n", + " type: 'tool_call',\n", + " id: 'call_MKBCjt4gKhl5UpnjsMHmDrBH'\n", + " }\n", + "]\n", + "The SQL query you provided is:\n", + "\n", + "```sql\n", + "SELECT * FROM Artist LIMIT 10;\n", + "```\n", + "\n", + "This query is straightforward and does not contain any of the common mistakes listed. It simply selects all columns from the `Artist` table and limits the result to 10 rows. \n", + "\n", + "Therefore, there are no mistakes to correct, and the original query can be reproduced as is:\n", + "\n", + "```sql\n", + "SELECT * FROM Artist LIMIT 10;\n", + "```\n", + "[\n", + " {\n", + " name: 'query-sql',\n", + " args: { input: 'SELECT * FROM Artist LIMIT 10;' },\n", + " type: 'tool_call',\n", + " id: 'call_a8MPiqXPMaN6yjN9i7rJctJo'\n", + " }\n", + "]\n", + "[{\"ArtistId\":1,\"Name\":\"AC/DC\"},{\"ArtistId\":2,\"Name\":\"Accept\"},{\"ArtistId\":3,\"Name\":\"Aerosmith\"},{\"ArtistId\":4,\"Name\":\"Alanis Morissette\"},{\"ArtistId\":5,\"Name\":\"Alice In Chains\"},{\"ArtistId\":6,\"Name\":\"Antônio Carlos Jobim\"},{\"ArtistId\":7,\"Name\":\"Apocalyptica\"},{\"ArtistId\":8,\"Name\":\"Audioslave\"},{\"ArtistId\":9,\"Name\":\"BackBeat\"},{\"ArtistId\":10,\"Name\":\"Billy Cobham\"}]\n", + "Here are 10 artists from your database:\n", + "\n", + "1. AC/DC\n", + "2. Accept\n", + "3. Aerosmith\n", + "4. Alanis Morissette\n", + "5. Alice In Chains\n", + "6. Antônio Carlos Jobim\n", + "7. Apocalyptica\n", + "8. Audioslave\n", + "9. BackBeat\n", + "10. Billy Cobham\n" + ] + } + ], + "source": [ + "const exampleQuery = \"Can you list 10 artists from my database?\"\n", + "\n", + "const events = await agentExecutor.stream(\n", + " { messages: [[\"user\", exampleQuery]]},\n", + " { streamMode: \"values\", }\n", + ")\n", + "\n", + "for await (const event of events) {\n", + " const lastMsg = event.messages[event.messages.length - 1];\n", + " if (lastMsg.tool_calls?.length) {\n", + " console.dir(lastMsg.tool_calls, { depth: null });\n", + " } else if (lastMsg.content) {\n", + " console.log(lastMsg.content);\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "3a5bb5ca-c3ae-4a58-be67-2cd18574b9a3", + "metadata": {}, + "source": [ + "## API reference\n", + "\n", + "For detailed documentation of all SqlToolkit features and configurations head to the [API reference](https://api.js.langchain.com/classes/langchain_agents_toolkits_sql.SqlToolkit.html)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "TypeScript", + "language": "typescript", + "name": "tslab" + }, + "language_info": { + "codemirror_mode": { + "mode": "typescript", + "name": "javascript", + "typescript": true + }, + "file_extension": ".ts", + "mimetype": "text/typescript", + "name": "typescript", + "version": "3.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/core_docs/docs/integrations/toolkits/sql.mdx b/docs/core_docs/docs/integrations/toolkits/sql.mdx deleted file mode 100644 index 3828554b20e2..000000000000 --- a/docs/core_docs/docs/integrations/toolkits/sql.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -hide_table_of_contents: true ---- - -# SQL Agent Toolkit - -This example shows how to load and use an agent with a SQL toolkit. - -## Setup - -You'll need to first install `typeorm`: - -```bash npm2yarn -npm install typeorm -``` - -## Usage - -import CodeBlock from "@theme/CodeBlock"; -import Example from "@examples/agents/sql.ts"; - -import IntegrationInstallTooltip from "@mdx_components/integration_install_tooltip.mdx"; - - - -```bash npm2yarn -npm install @langchain/openai -``` - -{Example} diff --git a/libs/langchain-scripts/src/cli/docs/index.ts b/libs/langchain-scripts/src/cli/docs/index.ts index a4ab18784d36..71e47e471de4 100644 --- a/libs/langchain-scripts/src/cli/docs/index.ts +++ b/libs/langchain-scripts/src/cli/docs/index.ts @@ -7,13 +7,22 @@ import { fillDocLoaderIntegrationDocTemplate } from "./document_loaders.js"; import { fillLLMIntegrationDocTemplate } from "./llms.js"; import { fillRetrieverIntegrationDocTemplate } from "./retrievers.js"; import { fillEmbeddingsIntegrationDocTemplate } from "./embeddings.js"; +import { fillToolkitIntegrationDocTemplate } from "./toolkits.js"; type CLIInput = { type: string; - community: boolean; classname: string; }; +const ALLOWED_TYPES = [ + "chat", + "llm", + "retriever", + "embeddings", + "doc_loader", + "toolkit", +]; + async function main() { const program = new Command(); program @@ -22,7 +31,10 @@ async function main() { "--classname ", "Class name of the integration. e.g ChatOpenAI" ) - .option("--type ", "Type of integration, e.g. 'chat'"); + .option( + "--type ", + `Type of integration.\nMust be one of:\n - ${ALLOWED_TYPES.join("\n - ")}` + ); program.parse(); @@ -56,9 +68,16 @@ async function main() { className, }); break; + case "toolkit": + await fillToolkitIntegrationDocTemplate({ + className, + }); + break; default: console.error( - `Invalid type: ${type}.\nOnly 'chat', 'llm', 'retriever', 'embeddings' and 'doc_loader' are supported at this time.` + `Invalid type: '${type}'.\nMust be one of:\n - ${ALLOWED_TYPES.join( + "\n - " + )}` ); process.exit(1); } diff --git a/libs/langchain-scripts/src/cli/docs/templates/toolkits.ipynb b/libs/langchain-scripts/src/cli/docs/templates/toolkits.ipynb new file mode 100644 index 000000000000..aec1b7cb026c --- /dev/null +++ b/libs/langchain-scripts/src/cli/docs/templates/toolkits.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "afaf8039", + "metadata": { + "vscode": { + "languageId": "raw" + } + }, + "source": [ + "---\n", + "sidebar_label: __sidebar_label__ Toolkit\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "e49f1e0d", + "metadata": {}, + "source": [ + "# __module_name__\n", + "\n", + "- TODO: Make sure API reference link is correct.\n", + "\n", + "This will help you getting started with the [__module_name__](/docs/concepts/#toolkits). For detailed documentation of all __module_name__ features and configurations head to the [API reference](__api_ref_module__).\n", + "\n", + "## Setup\n", + "\n", + "- TODO: Update with relevant info.\n", + "\n", + "If you want to get automated tracing from runs of individual tools, you can also set your [LangSmith](https://docs.smith.langchain.com/) API key by uncommenting below:\n", + "\n", + "```typescript\n", + "process.env.LANGCHAIN_TRACING_V2=\"true\"\n", + "process.env.LANGCHAIN_API_KEY=\"your-api-key\"\n", + "```\n", + "\n", + "### Installation\n", + "\n", + "This toolkit lives in the `__package_name__` package:\n", + "\n", + "```{=mdx}\n", + "import IntegrationInstallTooltip from \"@mdx_components/integration_install_tooltip.mdx\";\n", + "import Npm2Yarn from \"@theme/Npm2Yarn\";\n", + "\n", + "\n", + "\n", + "\n", + " __package_name__\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "a38cde65-254d-4219-a441-068766c0d4b5", + "metadata": {}, + "source": [ + "## Instantiation\n", + "\n", + "Now we can instantiate our toolkit:\n", + "\n", + "- TODO: Update model instantiation with relevant params." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae", + "metadata": { + "vscode": { + "languageId": "typescript" + } + }, + "outputs": [], + "source": [ + "import { __module_name__ } from \"__full_import_path__\"\n", + "\n", + "const toolkit = new __module_name__({\n", + " // ...\n", + "})" + ] + }, + { + "cell_type": "markdown", + "id": "5c5f2839-4020-424e-9fc9-07777eede442", + "metadata": {}, + "source": [ + "## Tools\n", + "\n", + "View available tools:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51a60dbe-9f2e-4e04-bb62-23968f17164a", + "metadata": { + "vscode": { + "languageId": "typescript" + } + }, + "outputs": [], + "source": [ + "toolkit.getTools()" + ] + }, + { + "cell_type": "markdown", + "id": "d11245ad-3661-4405-8558-1188896347ec", + "metadata": {}, + "source": [ + "TODO: list API reference pages for individual tools." + ] + }, + { + "cell_type": "markdown", + "id": "dfe8aad4-8626-4330-98a9-7ea1ca5d2e0e", + "metadata": {}, + "source": [ + "## Use within an agent\n", + "\n", + "First, ensure you have LangGraph installed:\n", + "\n", + "```{=mdx}\n", + "\n", + " @langchain/langgraph\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "c6d2ca9c", + "metadata": {}, + "source": [ + "Then, instanciate your LLM to be used in the React agent:\n", + "\n", + "```{=mdx}\n", + "import ChatModelTabs from \"@theme/ChatModelTabs\";\n", + "\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5af22142", + "metadata": { + "vscode": { + "languageId": "typescript" + } + }, + "outputs": [], + "source": [ + "// @lc-docs-hide-cell\n", + "\n", + "import { ChatOpenAI } from \"@langchain/openai\";\n", + "\n", + "const llm = new ChatOpenAI({\n", + " model: \"gpt-4o-mini\",\n", + " temperature: 0,\n", + "})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "310bf18e-6c9a-4072-b86e-47bc1fcca29d", + "metadata": { + "vscode": { + "languageId": "typescript" + } + }, + "outputs": [], + "source": [ + "import { createReactAgent } from \"@langchain/langgraph/prebuilt\"\n", + "\n", + "const agentExecutor = createReactAgent({ llm, tools });" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23e11cc9-abd6-4855-a7eb-799f45ca01ae", + "metadata": { + "vscode": { + "languageId": "typescript" + } + }, + "outputs": [], + "source": [ + "const exampleQuery = \"...\"\n", + "\n", + "const events = await agentExecutor.stream(\n", + " { messages: [[\"user\", exampleQuery]]},\n", + " { streamMode: \"values\", }\n", + ")\n", + "for await (const event of events) {\n", + " console.log(event.messages[event.messages.length - 1])\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "d1ee55bc-ffc8-4cfa-801c-993953a08cfd", + "metadata": {}, + "source": [ + "## TODO: Any functionality or considerations specific to this toolkit\n", + "\n", + "Fill in or delete if not relevant." + ] + }, + { + "cell_type": "markdown", + "id": "3a5bb5ca-c3ae-4a58-be67-2cd18574b9a3", + "metadata": {}, + "source": [ + "## API reference\n", + "\n", + "For detailed documentation of all __module_name__ features and configurations head to the [API reference](__api_ref_module__)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/libs/langchain-scripts/src/cli/docs/toolkits.ts b/libs/langchain-scripts/src/cli/docs/toolkits.ts new file mode 100644 index 000000000000..b29e43f8d487 --- /dev/null +++ b/libs/langchain-scripts/src/cli/docs/toolkits.ts @@ -0,0 +1,117 @@ +import * as path from "node:path"; +import * as fs from "node:fs"; +import { + boldText, + getUserInput, + greenText, + redBackground, +} from "../utils/get-input.js"; +import { fetchURLStatus } from "../utils/fetch-url-status.js"; +import { + SIDEBAR_LABEL_PLACEHOLDER, + MODULE_NAME_PLACEHOLDER, + PACKAGE_NAME_PLACEHOLDER, + FULL_IMPORT_PATH_PLACEHOLDER, + PYTHON_DOC_URL_PLACEHOLDER, + API_REF_MODULE_PLACEHOLDER, + PY_SUPPORT_PLACEHOLDER, +} from "../constants.js"; + +const TEMPLATE_PATH = path.resolve("./src/cli/docs/templates/toolkits.ipynb"); +const INTEGRATIONS_DOCS_PATH = path.resolve( + "../../docs/core_docs/docs/integrations/toolkits" +); + +type ExtraFields = { + pySupport: boolean; + fullImportPath: string; + packageName: string; +}; + +async function promptExtraFields(): Promise { + const hasPySupport = await getUserInput( + "Does this integration have Python support? (y/n) ", + undefined, + true + ); + const importPath = await getUserInput( + "What is the full import path of the integration? (e.g @langchain/community/llms/togetherai) ", + undefined, + true + ); + + let packageName = ""; + if (importPath.startsWith("langchain/")) { + packageName = "langchain"; + } else { + packageName = importPath.split("/").slice(0, 2).join("/"); + } + + const verifyPackageName = await getUserInput( + `Is ${packageName} the correct package name? (y/n) `, + undefined, + true + ); + if (verifyPackageName.toLowerCase() === "n") { + packageName = await getUserInput( + "Please enter the full package name (e.g @langchain/community) ", + undefined, + true + ); + } + + return { + pySupport: hasPySupport.toLowerCase() === "y", + fullImportPath: importPath, + packageName, + }; +} + +export async function fillToolkitIntegrationDocTemplate(fields: { + className: string; +}) { + const sidebarLabel = fields.className.replace("Toolkit", ""); + const pyDocUrl = `https://python.langchain.com/docs/integrations/toolkits/${sidebarLabel.toLowerCase()}/`; + const extraFields = await promptExtraFields(); + const importPathEnding = extraFields.fullImportPath.split("/").pop() ?? ""; + const apiRefModuleUrl = `https://api.js.langchain.com/classes/${extraFields.fullImportPath + .replace("@", "") + .replaceAll("/", "_") + .replaceAll("-", "_")}_${importPathEnding}.${fields.className}.html`; + + const apiRefUrlSuccess = await fetchURLStatus(apiRefModuleUrl); + if (apiRefUrlSuccess === false) { + console.warn( + "API ref URL is invalid. Please manually ensure it is correct." + ); + } + + const docTemplate = (await fs.promises.readFile(TEMPLATE_PATH, "utf-8")) + .replaceAll(SIDEBAR_LABEL_PLACEHOLDER, sidebarLabel) + .replaceAll(MODULE_NAME_PLACEHOLDER, fields.className) + .replaceAll(PACKAGE_NAME_PLACEHOLDER, extraFields.packageName) + .replaceAll(FULL_IMPORT_PATH_PLACEHOLDER, extraFields.fullImportPath) + .replaceAll(PYTHON_DOC_URL_PLACEHOLDER, pyDocUrl) + .replaceAll(API_REF_MODULE_PLACEHOLDER, apiRefModuleUrl) + .replaceAll(PY_SUPPORT_PLACEHOLDER, extraFields?.pySupport ? "✅" : "❌"); + + const docPath = path.join( + INTEGRATIONS_DOCS_PATH, + `${importPathEnding}.ipynb` + ); + await fs.promises.writeFile(docPath, docTemplate); + const prettyDocPath = docPath.split("docs/core_docs/")[1]; + + const updatePythonDocUrlText = ` ${redBackground( + "- Update the Python documentation URL with the proper URL." + )}`; + const successText = `\nSuccessfully created new document loader integration doc at ${prettyDocPath}.`; + + console.log( + `${greenText(successText)}\n +${boldText("Next steps:")} +${extraFields?.pySupport ? updatePythonDocUrlText : ""} + - Run all code cells in the generated doc to record the outputs. + - Add extra sections on integration specific features.\n` + ); +}