@botpress/adk-cli 1.11.8 → 1.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -348574,7 +348574,7 @@ var init_internal = __esm(() => {
348574
348574
  });
348575
348575
  init_define_PACKAGE_VERSIONS = __esm2({
348576
348576
  "<define:__PACKAGE_VERSIONS__>"() {
348577
- define_PACKAGE_VERSIONS_default = { runtime: "1.11.8", adk: "1.11.8", sdk: "4.20.2", llmz: "0.0.33", zai: "2.5.0", cognitive: "0.2.0" };
348577
+ define_PACKAGE_VERSIONS_default = { runtime: "1.11.9", adk: "1.11.9", sdk: "4.20.2", llmz: "0.0.33", zai: "2.5.0", cognitive: "0.2.0" };
348578
348578
  }
348579
348579
  });
348580
348580
  init_asset = __esm2({
@@ -654980,7 +654980,7 @@ var init_library2 = __esm(() => {
654980
654980
  });
654981
654981
  init_define_PACKAGE_VERSIONS2 = __esm4({
654982
654982
  "<define:__PACKAGE_VERSIONS__>"() {
654983
- define_PACKAGE_VERSIONS_default2 = { runtime: "1.11.8", adk: "1.11.8", sdk: "4.20.2", llmz: "0.0.33", zai: "2.5.0", cognitive: "0.2.0" };
654983
+ define_PACKAGE_VERSIONS_default2 = { runtime: "1.11.9", adk: "1.11.9", sdk: "4.20.2", llmz: "0.0.33", zai: "2.5.0", cognitive: "0.2.0" };
654984
654984
  }
654985
654985
  });
654986
654986
  init_assets2 = __esm4({
@@ -696621,7 +696621,6 @@ import { EventEmitter as EventEmitter24 } from "events";
696621
696621
  import path14 from "path";
696622
696622
  import * as fs11 from "fs";
696623
696623
  import * as path15 from "path";
696624
- import { fileURLToPath as fileURLToPath7 } from "url";
696625
696624
  import path16 from "path";
696626
696625
  import crypto24 from "crypto";
696627
696626
  import path17 from "path";
@@ -696650,14 +696649,14 @@ import { existsSync as existsSync52 } from "fs";
696650
696649
  import crypto42 from "crypto";
696651
696650
  import path332 from "path";
696652
696651
  import fs16 from "fs/promises";
696653
- import { readFileSync as readFileSync22 } from "fs";
696652
+ import { readFileSync as readFileSync6 } from "fs";
696654
696653
  import { join as join72 } from "path";
696655
696654
  import { watch as watch2, readdirSync as readdirSync22 } from "fs";
696656
696655
  import { EventEmitter as EventEmitter32 } from "events";
696657
696656
  import { join as join82, relative as relative3 } from "path";
696658
696657
  import { existsSync as existsSync7 } from "fs";
696659
696658
  import path342 from "path";
696660
- import { readFileSync as readFileSync32 } from "fs";
696659
+ import { readFileSync as readFileSync22 } from "fs";
696661
696660
  import { join as join9 } from "path";
696662
696661
 
696663
696662
  class ValidationErrors {
@@ -699802,7 +699801,7 @@ class AgentProjectGenerator {
699802
699801
  deploy: "adk deploy"
699803
699802
  },
699804
699803
  dependencies: {
699805
- "@botpress/runtime": "^1.11.8"
699804
+ "@botpress/runtime": "^1.11.9"
699806
699805
  },
699807
699806
  devDependencies: {
699808
699807
  typescript: "^5.9.3"
@@ -699966,9 +699965,7 @@ A Botpress Agent built with the ADK.
699966
699965
  await this.writeFormattedFile("README.md", readme);
699967
699966
  }
699968
699967
  createClaudeMd() {
699969
- const templatePath = path15.join(__dirname2, "CLAUDE.template.md");
699970
- const claudeMd = fs11.readFileSync(templatePath, "utf-8");
699971
- this.writeFile("CLAUDE.md", claudeMd);
699968
+ this.writeFile("CLAUDE.md", CLAUDE_template_default);
699972
699969
  }
699973
699970
  async createSourceStructure() {
699974
699971
  const srcPath = path15.join(this.projectPath, "src");
@@ -704057,11 +704054,1271 @@ var import_ts_morph, __defProp11, __commonJS7 = (cb4, mod) => () => (mod || cb4(
704057
704054
  `));
704058
704055
  return code;
704059
704056
  }
704060
- }, ADK_VERSION = "1.11.8", relative22 = (from, to3) => {
704057
+ }, ADK_VERSION = "1.11.9", relative22 = (from, to3) => {
704061
704058
  const fromDir = path102.dirname(from);
704062
704059
  const relative32 = path102.relative(fromDir, to3);
704063
704060
  return relative32.startsWith(".") ? relative32 : `./${relative32}`;
704064
- }, init_utils8, exports_action_types, init_action_types, exports_integration_action_types, init_integration_action_types, require_package3, bpCliImporter, auth, BP_CLI_VERSION = "4.27.3", BP_CLI_INSTALL_ALL, BP_CLI_INSTALL_DIR, BP_CLI_BIN_PATH, BpAddCommand, BpBuildCommand, BpDeployCommand, BpDevCommand, BpChatCommand, workspaceCache, agentInfoKeyOrder, dependenciesKeyOrder, integrationKeyOrder, defaultAdkFolder = ".adk", integrationRefSchema, versionSchema, HubCache, AgentProject, FileWatcher, __filename2, __dirname2, getIntegrationHash = (integration) => {
704061
+ }, init_utils8, exports_action_types, init_action_types, exports_integration_action_types, init_integration_action_types, require_package3, bpCliImporter, auth, BP_CLI_VERSION = "4.27.3", BP_CLI_INSTALL_ALL, BP_CLI_INSTALL_DIR, BP_CLI_BIN_PATH, BpAddCommand, BpBuildCommand, BpDeployCommand, BpDevCommand, BpChatCommand, workspaceCache, agentInfoKeyOrder, dependenciesKeyOrder, integrationKeyOrder, defaultAdkFolder = ".adk", integrationRefSchema, versionSchema, HubCache, AgentProject, FileWatcher, CLAUDE_template_default = `# Botpress ADK Project Context
704062
+
704063
+ This project is built with the **Botpress Agent Development Kit (ADK)** - a TypeScript-first framework for building AI agents.
704064
+
704065
+ ## Table of Contents
704066
+
704067
+ - [Quick Reference: Use the Botpress MCP Server](#quick-reference-use-the-botpress-mcp-server)
704068
+ - [What is the ADK?](#what-is-the-adk)
704069
+ - [ADK CLI](#adk-cli)
704070
+ - [Core Concepts](#core-concepts)
704071
+ - [1. Agent Configuration](#1-agent-configuration-agentconfigts)
704072
+ - [2. Conversations](#2-conversations-srcconversations)
704073
+ - [3. Workflows](#3-workflows-srcworkflows)
704074
+ - [4. Tools](#4-tools-srctools)
704075
+ - [5. Knowledge Bases](#5-knowledge-bases-srcknowledge)
704076
+ - [6. Actions](#6-actions-srcactions)
704077
+ - [7. Zai Library](#7-zai-library)
704078
+ - [Project Structure](#project-structure)
704079
+ - [Development Workflow](#development-workflow)
704080
+ - [Examples](#examples)
704081
+ - [Best Practices](#best-practices)
704082
+ - [Common APIs](#common-apis)
704083
+ - [Advanced Autonomous Execution](#advanced-autonomous-execution)
704084
+ - [State and Metadata Management](#state-and-metadata-management)
704085
+ - [Advanced Table Operations](#advanced-table-operations)
704086
+ - [Knowledge Base Operations](#knowledge-base-operations)
704087
+ - [Advanced Conversation Patterns](#advanced-conversation-patterns)
704088
+ - [Citations System](#citations-system)
704089
+ - [When Making Changes](#when-making-changes)
704090
+ - [Resources](#resources)
704091
+
704092
+ ## Quick Reference: Use the Botpress MCP Server
704093
+
704094
+ **IMPORTANT**: When working on this project, always search the Botpress documentation using the \`mcp__botpress-docs__SearchBotpress\` tool before making changes. The ADK has specific patterns and APIs that are well-documented.
704095
+
704096
+ ## What is the ADK?
704097
+
704098
+ The ADK allows developers to build Botpress agents using **code instead of the Studio interface**. It provides:
704099
+
704100
+ - Project scaffolding with TypeScript
704101
+ - Hot reloading development server (\`adk dev\`)
704102
+ - Type-safe APIs and auto-generated types
704103
+ - Build and deploy to Botpress Cloud
704104
+
704105
+ ## ADK CLI
704106
+
704107
+ The ADK CLI is installed globally. You can run it using \`adk <command>\`.
704108
+ Always use bash to run ADK. (\`Bash(adk)\`)
704109
+ To install an integration: \`adk install <integration>\`
704110
+ To generate types without running in dev mode: \`adk build\`
704111
+
704112
+ ## Core Concepts
704113
+
704114
+ ### 1. Agent Configuration (\`agent.config.ts\`)
704115
+
704116
+ The main configuration file defines:
704117
+
704118
+ - **Agent name and description**
704119
+ - **Default models** for autonomous and zai operations
704120
+ - **State schemas** (bot-level and user-level state using Zod)
704121
+ - **Configuration variables** (encrypted, secure storage for API keys)
704122
+ - **Integration dependencies** (webchat, chat, etc.)
704123
+
704124
+ \`\`\`typescript
704125
+ export default defineConfig({
704126
+ name: "my-agent",
704127
+ defaultModels: {
704128
+ autonomous: "cerebras:gpt-oss-120b",
704129
+ zai: "cerebras:gpt-oss-120b",
704130
+ },
704131
+ bot: { state: z.object({}) },
704132
+ user: { state: z.object({}) },
704133
+ dependencies: {
704134
+ integrations: {
704135
+ webchat: { version: "webchat@0.3.0", enabled: true },
704136
+ },
704137
+ },
704138
+ });
704139
+ \`\`\`
704140
+
704141
+ ### 2. Conversations (\`src/conversations/\`)
704142
+
704143
+ **Primary way agents handle user messages**. Each conversation handler:
704144
+
704145
+ - Responds to messages from specific channels
704146
+ - Uses \`execute()\` to run autonomous AI logic
704147
+ - Can access conversation state, send messages, and call tools
704148
+
704149
+ **Key Pattern**: The \`execute()\` function runs the agent's AI loop:
704150
+
704151
+ \`\`\`typescript
704152
+ export default new Conversation({
704153
+ channel: "webchat.channel",
704154
+ handler: async ({ execute, conversation, state }) => {
704155
+ await execute({
704156
+ instructions: "Your agent's instructions here",
704157
+ tools: [myTool1, myTool2],
704158
+ knowledge: [myKnowledgeBase],
704159
+ });
704160
+ },
704161
+ });
704162
+ \`\`\`
704163
+
704164
+ ### 3. Workflows (\`src/workflows/\`)
704165
+
704166
+ **Long-running processes** for complex, multi-step operations:
704167
+
704168
+ - Can run on schedules (cron syntax)
704169
+ - Run independently or triggered by events
704170
+ - NOT the same as Studio Workflows
704171
+ - Use \`step()\` for durable execution (survives restarts)
704172
+
704173
+ \`\`\`typescript
704174
+ export default new Workflow({
704175
+ name: "periodic-indexing",
704176
+ schedule: "0 */6 * * *",
704177
+ handler: async ({ step }) => {
704178
+ await step("task-name", async () => {
704179
+ // Your logic here
704180
+ });
704181
+ },
704182
+ });
704183
+ \`\`\`
704184
+
704185
+ #### Advanced Workflow Step Methods
704186
+
704187
+ Beyond basic \`step()\`, workflows have powerful methods for complex orchestration:
704188
+
704189
+ **Parallel Processing:**
704190
+
704191
+ - \`step.map()\` - Process array items in parallel with concurrency control
704192
+ - \`step.forEach()\` - Like map but for side effects (returns void)
704193
+ - \`step.batch()\` - Process in sequential batches
704194
+
704195
+ \`\`\`typescript
704196
+ // Process items in parallel
704197
+ const results = await step.map(
704198
+ 'process-items',
704199
+ items,
704200
+ async (item, { i }) => processItem(item),
704201
+ { concurrency: 5, maxAttempts: 3 }
704202
+ )
704203
+
704204
+ // Batch processing
704205
+ await step.batch(
704206
+ 'bulk-insert',
704207
+ records,
704208
+ async (batch) => database.bulkInsert(batch),
704209
+ { batchSize: 100 }
704210
+ )
704211
+ \`\`\`
704212
+
704213
+ **Workflow Coordination:**
704214
+
704215
+ - \`step.waitForWorkflow()\` - Wait for another workflow to complete
704216
+ - \`step.executeWorkflow()\` - Start and wait in one call
704217
+
704218
+ \`\`\`typescript
704219
+ const result = await step.executeWorkflow('run-child', ChildWorkflow, { input })
704220
+ \`\`\`
704221
+
704222
+ **Timing Control:**
704223
+
704224
+ - \`step.sleep()\` - Pause execution (< 10s in-memory, >= 10s uses listening mode)
704225
+ - \`step.sleepUntil()\` - Sleep until specific time
704226
+ - \`step.listen()\` - Pause and wait for external event
704227
+
704228
+ \`\`\`typescript
704229
+ await step.sleep('wait-5s', 5000)
704230
+ await step.sleepUntil('wait-until-noon', new Date('2025-01-15T12:00:00Z'))
704231
+ \`\`\`
704232
+
704233
+ **Request Data from Conversation:**
704234
+
704235
+ \`\`\`typescript
704236
+ // In workflow
704237
+ const { topic } = await step.request('topic', 'What topic should I research?')
704238
+
704239
+ // In conversation
704240
+ if (isWorkflowDataRequest(event)) {
704241
+ await workflow.provide(event, { topic: userInput })
704242
+ }
704243
+ \`\`\`
704244
+
704245
+ **Execution Control:**
704246
+
704247
+ - \`step.fail()\` - Mark workflow as failed
704248
+ - \`step.abort()\` - Abort without failing
704249
+ - \`step.progress()\` - Record progress checkpoint
704250
+
704251
+ ### 4. Tools (\`src/tools/\`)
704252
+
704253
+ **AI-callable functions** that enable agents to perform actions:
704254
+
704255
+ - Must have clear name and description
704256
+ - Use Zod schemas for input/output
704257
+ - Can be passed to \`execute()\`
704258
+
704259
+ \`\`\`typescript
704260
+ export default new Autonomous.Tool({
704261
+ name: "searchDatabase",
704262
+ description: "Search the database",
704263
+ input: z.object({ query: z.string() }),
704264
+ output: z.object({ results: z.array(z.any()) }),
704265
+ handler: async ({ query }) => {
704266
+ // Tool logic
704267
+ return { results: [] };
704268
+ },
704269
+ });
704270
+ \`\`\`
704271
+
704272
+ ### 5. Knowledge Bases (\`src/knowledge/\`)
704273
+
704274
+ **RAG (Retrieval-Augmented Generation)** for providing context:
704275
+
704276
+ - Website scraping
704277
+ - Document ingestion
704278
+ - Can be passed to \`execute()\` via \`knowledge\` parameter
704279
+
704280
+ ### 6. Actions (\`src/actions/\`)
704281
+
704282
+ **Reusable business logic** that can:
704283
+
704284
+ - Be called from anywhere (import \`actions\` from \`@botpress/runtime\`)
704285
+ - Be converted to tools with \`.asTool()\`
704286
+ - Encapsulate logic not tied to conversational flow
704287
+
704288
+ ### 7. Zai Library
704289
+
704290
+ **Zai** is an LLM utility library that provides a clean, type-safe API for common AI operations. It's designed to work seamlessly with the ADK and SDK to process LLM inputs and outputs programmatically.
704291
+
704292
+ #### Importing Zai in ADK
704293
+
704294
+ In the ADK, Zai is available from \`@botpress/runtime\`:
704295
+
704296
+ \`\`\`typescript
704297
+ import { adk } from '@botpress/runtime'
704298
+ // then adk.zai.<method_name>
704299
+ \`\`\`
704300
+
704301
+ The default model for Zai operations is configured in \`agent.config.ts\`:
704302
+
704303
+ \`\`\`typescript
704304
+ export default defineConfig({
704305
+ defaultModels: {
704306
+ autonomous: "cerebras:gpt-oss-120b",
704307
+ zai: "cerebras:gpt-oss-120b", // Model used for Zai operations
704308
+ },
704309
+ })
704310
+ \`\`\`
704311
+
704312
+ #### When to Use Zai
704313
+
704314
+ Use Zai when you need to:
704315
+ - Extract structured data from unstructured text
704316
+ - Answer questions from documents with source citations
704317
+ - Verify Boolean conditions in content
704318
+ - Summarize long text into concise summaries
704319
+ - Generate text programmatically based on prompts
704320
+
704321
+ **Use Zai instead of \`execute()\` when**: You need deterministic, structured outputs for specific AI tasks (extraction, validation, summarization) rather than conversational interactions.
704322
+
704323
+ #### Zai Methods
704324
+
704325
+ **1. \`answer()\` - Answer Questions with Citations**
704326
+
704327
+ Answers questions from documents with intelligent source citations.
704328
+
704329
+ \`\`\`typescript
704330
+ const documents = [
704331
+ 'Botpress was founded in 2016.',
704332
+ 'The company is based in Quebec, Canada.',
704333
+ ]
704334
+
704335
+ const result = await zai.answer(documents, 'When was Botpress founded?')
704336
+
704337
+ if (result.type === 'answer') {
704338
+ console.log(result.answer) // "Botpress was founded in 2016."
704339
+ console.log(result.citations) // Array of citations with source references
704340
+ }
704341
+ \`\`\`
704342
+
704343
+ **When to use**: When you need to answer questions from a set of documents with traceable sources (e.g., custom RAG implementations, document Q&A).
704344
+
704345
+ **2. \`extract()\` - Extract Structured Data**
704346
+
704347
+ Extracts structured data from unstructured input using Zod schemas.
704348
+
704349
+ \`\`\`typescript
704350
+ import { z, adk } from '@botpress/runtime'
704351
+
704352
+ const userSchema = z.object({
704353
+ name: z.string(),
704354
+ email: z.string().email(),
704355
+ age: z.number()
704356
+ })
704357
+
704358
+ const input = "My name is John Doe, I'm 30 years old and my email is john@example.com"
704359
+ // zai.extract returns the extracted data DIRECTLY (not wrapped in { output: ... })
704360
+ const result = await adk.zai.extract(input, userSchema)
704361
+
704362
+ console.log(result)
704363
+ // { name: "John Doe", email: "john@example.com", age: 30 }
704364
+ \`\`\`
704365
+
704366
+ **When to use**: When you need to parse unstructured user input into structured data (e.g., form extraction from natural language, parsing contact information).
704367
+
704368
+ **3. \`check()\` - Verify Boolean Conditions**
704369
+
704370
+ Verifies a condition against some input and returns a boolean with explanation.
704371
+
704372
+ \`\`\`typescript
704373
+ const email = "Get rich quick! Click here now!!!"
704374
+ const { output } = await zai.check(email, 'is spam').result()
704375
+
704376
+ console.log(output.value) // true
704377
+ console.log(output.explanation) // "This email contains typical spam indicators..."
704378
+ \`\`\`
704379
+
704380
+ **When to use**: When you need to validate content or make binary decisions (e.g., content moderation, intent verification, condition checking).
704381
+
704382
+ **4. \`summarize()\` - Summarize Text**
704383
+
704384
+ Creates concise summaries of lengthy text to a desired length.
704385
+
704386
+ \`\`\`typescript
704387
+ const longArticle = "..." // Long article content
704388
+
704389
+ const summary = await zai.summarize(longArticle, {
704390
+ length: 100, // tokens
704391
+ prompt: 'key findings and main conclusions'
704392
+ })
704393
+ \`\`\`
704394
+
704395
+ **When to use**: When you need to condense long content (e.g., article summaries, transcript summaries, document overviews).
704396
+
704397
+ **5. \`text()\` - Generate Text**
704398
+
704399
+ Generates text of the desired length according to a prompt.
704400
+
704401
+ \`\`\`typescript
704402
+ const generated = await zai.text('Write a welcome message for new users', {
704403
+ length: 50 // tokens
704404
+ })
704405
+ \`\`\`
704406
+
704407
+ **When to use**: When you need to generate specific text content programmatically (e.g., dynamic content generation, templated responses).
704408
+
704409
+ #### Response Methods
704410
+
704411
+ All Zai operations return a Response object with promise-like behavior and additional functionality:
704412
+
704413
+ \`\`\`typescript
704414
+ // Await the result directly
704415
+ const result = await zai.extract(input, schema)
704416
+
704417
+ // Or use .result() for explicit promise handling
704418
+ const { output } = await zai.check(content, 'is valid').result()
704419
+ \`\`\`
704420
+
704421
+ ## Project Structure
704422
+
704423
+ \`\`\`
704424
+ agent.config.ts # Main configuration
704425
+ src/
704426
+ conversations/ # Message handlers (primary user interaction)
704427
+ workflows/ # Long-running processes
704428
+ tools/ # AI-callable functions
704429
+ actions/ # Reusable business logic
704430
+ knowledge/ # Knowledge bases for RAG
704431
+ triggers/ # Event-based triggers
704432
+ tables/ # Database tables
704433
+ .botpress/ # Auto-generated types (DO NOT EDIT)
704434
+ \`\`\`
704435
+
704436
+ ## Development Workflow
704437
+
704438
+ 1. **Start dev server**: \`adk dev\` (http://localhost:3001 for console)
704439
+ 2. **Add integrations**: \`adk add webchat@latest\`
704440
+ 3. **Build**: \`adk build\`
704441
+ 4. **Deploy**: \`adk deploy\`
704442
+ 5. **Chat in CLI**: \`adk chat\`
704443
+
704444
+ ## Examples
704445
+
704446
+ Official examples: https://github.com/botpress/adk/tree/main/examples
704447
+
704448
+ ### subagents
704449
+
704450
+ **What you'll learn:** How to build a multi-agent system where an orchestrator delegates to specialists.
704451
+
704452
+ Shows the \`SubAgent\` pattern where each specialist (HR, IT, Sales, etc.) runs in its own context with \`mode: "worker"\`, returns structured results via custom exits, and reports progress through \`onTrace\` hooks.
704453
+
704454
+ ### webchat-rag
704455
+
704456
+ **What you'll learn:** How to build a RAG assistant with scheduled indexing, guardrails, and admin features.
704457
+
704458
+ Shows \`Autonomous.Object\` for dynamic tool grouping, \`onBeforeTool\` hooks to enforce knowledge search before answering, scheduled workflows for KB refresh, and \`ThinkSignal\` for interrupting execution.
704459
+
704460
+ ### deep-research
704461
+
704462
+ **What you'll learn:** How to build complex, long-running workflows with progress tracking.
704463
+
704464
+ Shows \`step()\` and \`step.map()\` for workflow phases, \`Reference.Workflow\` for conversation-workflow linking, Tables for activity tracking, and extensive Zai usage (\`extract\`, \`answer\`, \`filter\`, \`text\`).
704465
+
704466
+ ## Best Practices
704467
+
704468
+ 1. **Search Botpress docs first** - Use the MCP tool before implementing
704469
+ 2. **Keep tools focused** - Single responsibility per tool
704470
+ 3. **Use Zod schemas** with \`.describe()\` for clarity
704471
+ 4. **State management** - Minimize large variables in main workflow
704472
+ 5. **Type safety** - Run \`adk dev\` or \`adk build\` to regenerate types after config changes
704473
+ 6. **Conversations vs Workflows**:
704474
+ - Conversations: User interactions, real-time responses
704475
+ - Workflows: Background tasks, scheduled jobs, long-running processes
704476
+
704477
+ ## Common APIs
704478
+
704479
+ ### Conversation Handler
704480
+
704481
+ \`\`\`typescript
704482
+ handler: async ({
704483
+ execute, // Run autonomous AI loop
704484
+ conversation, // Send messages, manage conversation
704485
+ state, // Conversation state (persisted)
704486
+ message, // Incoming message
704487
+ client, // Botpress API client
704488
+ }) => {};
704489
+ \`\`\`
704490
+
704491
+ ### Execute Function
704492
+
704493
+ \`\`\`typescript
704494
+ await execute({
704495
+ instructions: "String or function returning instructions",
704496
+ tools: [tool1, tool2], // Optional tools
704497
+ knowledge: [kb1, kb2], // Optional knowledge bases
704498
+ exits: [customExit], // Optional custom exits
704499
+ hooks: { onTrace, onBeforeTool }, // Optional hooks
704500
+ mode: "worker", // Optional: autonomous until exit
704501
+ iterations: 10, // Max loops (default 10)
704502
+ });
704503
+ \`\`\`
704504
+
704505
+ ## Advanced Autonomous Execution
704506
+
704507
+ ### Autonomous Namespace
704508
+
704509
+ The \`Autonomous\` namespace provides powerful primitives for controlling LLM behavior:
704510
+
704511
+ #### Autonomous.Exit - Custom Exit Conditions
704512
+
704513
+ Define custom exits for autonomous execution loops:
704514
+
704515
+ \`\`\`typescript
704516
+ import { Autonomous, z } from '@botpress/runtime'
704517
+
704518
+ const AnswerExit = new Autonomous.Exit({
704519
+ name: 'answer',
704520
+ description: 'Return when you have the final answer',
704521
+ schema: z.object({
704522
+ answer: z.string(),
704523
+ confidence: z.number()
704524
+ })
704525
+ })
704526
+
704527
+ const NoAnswerExit = new Autonomous.Exit({
704528
+ name: 'no_answer',
704529
+ description: 'No answer could be found'
704530
+ })
704531
+
704532
+ const result = await execute({
704533
+ instructions: 'Research and answer the question',
704534
+ exits: [AnswerExit, NoAnswerExit],
704535
+ mode: 'worker' // Run until exit triggered
704536
+ })
704537
+
704538
+ // \u2705 CORRECT - Use result.is() and result.output
704539
+ if (result.is(AnswerExit)) {
704540
+ console.log(result.output.answer) // Type-safe access
704541
+ console.log(result.output.confidence)
704542
+ } else if (result.is(NoAnswerExit)) {
704543
+ console.log('No answer found')
704544
+ }
704545
+
704546
+ // \u274C WRONG - Don't use result.exit.name or result.exit.value
704547
+ // if (result.exit?.name === 'answer') { ... }
704548
+ \`\`\`
704549
+
704550
+ #### Autonomous.ThinkSignal - Inject Context
704551
+
704552
+ Provide context to the LLM without continuing execution:
704553
+
704554
+ \`\`\`typescript
704555
+ const results = await fetchData()
704556
+
704557
+ if (!results.length) {
704558
+ throw new ThinkSignal('error', 'No results found')
704559
+ }
704560
+
704561
+ // Inject formatted results into LLM context
704562
+ throw new ThinkSignal('results ready', formatResults(results))
704563
+ \`\`\`
704564
+
704565
+ #### Autonomous.Object - Dynamic Tool Grouping
704566
+
704567
+ Group tools dynamically based on state:
704568
+
704569
+ \`\`\`typescript
704570
+ const adminTools = new Autonomous.Object({
704571
+ name: 'admin',
704572
+ description: user.isAdmin ? 'Admin tools available' : 'Login required',
704573
+ tools: user.isAdmin ? [refreshKB, manageBots] : [generateLoginCode]
704574
+ })
704575
+
704576
+ await execute({
704577
+ objects: [adminTools]
704578
+ })
704579
+ \`\`\`
704580
+
704581
+ ### Execution Hooks
704582
+
704583
+ Full control over the autonomous execution loop:
704584
+
704585
+ \`\`\`typescript
704586
+ await execute({
704587
+ instructions: '...',
704588
+ hooks: {
704589
+ // Before tool execution - can modify input
704590
+ onBeforeTool: async ({ iteration, tool, input, controller }) => {
704591
+ console.log(\`About to call \${tool.name}\`)
704592
+ return { input: modifiedInput } // Optional: transform input
704593
+ },
704594
+
704595
+ // After tool execution - can modify output
704596
+ onAfterTool: async ({ iteration, tool, input, output, controller }) => {
704597
+ console.log(\`\${tool.name} returned:\`, output)
704598
+ return { output: modifiedOutput } // Optional: transform output
704599
+ },
704600
+
704601
+ // Before code execution in iteration
704602
+ onBeforeExecution: async (iteration, controller) => {
704603
+ return { code: modifiedCode } // Optional: transform generated code
704604
+ },
704605
+
704606
+ // When exit is triggered
704607
+ onExit: async (result) => {
704608
+ console.log('Exited with:', result)
704609
+ },
704610
+
704611
+ // After each iteration completes
704612
+ onIterationEnd: async (iteration, controller) => {
704613
+ if (iteration > 5) {
704614
+ controller.abort() // Stop execution
704615
+ }
704616
+ },
704617
+
704618
+ // On trace events (synchronous, non-blocking)
704619
+ onTrace: ({ trace, iteration }) => {
704620
+ if (trace.type === 'comment') {
704621
+ console.log('LLM thinking:', trace.comment)
704622
+ }
704623
+ if (trace.type === 'tool_call') {
704624
+ console.log('Calling:', trace.tool_name)
704625
+ }
704626
+ }
704627
+ }
704628
+ })
704629
+ \`\`\`
704630
+
704631
+ **Hook use cases:**
704632
+ - Logging and debugging
704633
+ - Input/output validation and transformation
704634
+ - Rate limiting tool calls
704635
+ - Custom abort conditions
704636
+ - Injecting dynamic context
704637
+
704638
+ ## State and Metadata Management
704639
+
704640
+ ### Tags - Key-Value Metadata
704641
+
704642
+ Track metadata for any entity (bot, user, conversation, workflow):
704643
+
704644
+ \`\`\`typescript
704645
+ import { TrackedTags } from '@botpress/runtime'
704646
+
704647
+ // Create tags instance
704648
+ const tags = TrackedTags.create({
704649
+ type: 'bot', // or 'user' | 'conversation' | 'workflow'
704650
+ id: entityId,
704651
+ client: botClient,
704652
+ initialTags: { status: 'active' }
704653
+ })
704654
+
704655
+ // Load from server
704656
+ await tags.load()
704657
+
704658
+ // Modify tags
704659
+ tags.tags = {
704660
+ ...tags.tags,
704661
+ lastSync: new Date().toISOString()
704662
+ }
704663
+
704664
+ // Check if modified
704665
+ if (tags.isDirty()) {
704666
+ await tags.save()
704667
+ }
704668
+
704669
+ // Batch operations
704670
+ await TrackedTags.saveAllDirty()
704671
+ await TrackedTags.loadAll()
704672
+ \`\`\`
704673
+
704674
+ **Access via workflow instance:**
704675
+
704676
+ \`\`\`typescript
704677
+ workflow.tags = { status: 'processing' }
704678
+ await workflow.save()
704679
+ \`\`\`
704680
+
704681
+ ### Reference.Workflow - Typed Workflow References
704682
+
704683
+ Serialize workflow references in state that auto-hydrate on access:
704684
+
704685
+ \`\`\`typescript
704686
+ import { Reference, z } from '@botpress/runtime'
704687
+
704688
+ // In conversation state schema
704689
+ state: z.object({
704690
+ research: Reference.Workflow('deep_research').optional()
704691
+ // or untyped: Reference.Workflow().optional()
704692
+ })
704693
+
704694
+ // In handler - always a WorkflowInstance
704695
+ handler: async ({ state }) => {
704696
+ if (state.research) {
704697
+ // state.research is typed WorkflowInstance
704698
+ console.log(state.research.status) // 'running' | 'completed' | etc
704699
+ console.log(state.research.output) // Typed output
704700
+
704701
+ if (state.research.status === 'completed') {
704702
+ // Access completed workflow data
704703
+ }
704704
+ }
704705
+ }
704706
+ \`\`\`
704707
+
704708
+ ### Context Object - Runtime Access
704709
+
704710
+ Global context for accessing runtime information:
704711
+
704712
+ \`\`\`typescript
704713
+ import { context } from '@botpress/runtime'
704714
+
704715
+ // Get specific context
704716
+ const client = context.get('client')
704717
+ const citations = context.get('citations')
704718
+ const logger = context.get('logger')
704719
+
704720
+ // Get all context
704721
+ const { client, cognitive, logger, operation } = context.getAll()
704722
+ \`\`\`
704723
+
704724
+ **Available context properties:**
704725
+ - \`client\` - Botpress API client
704726
+ - \`cognitive\` - LLM access
704727
+ - \`logger\` - Logging
704728
+ - \`operation\` - Current operation info
704729
+ - \`citations\` - Citation tracking
704730
+ - \`chat\` - Chat interface
704731
+ - \`bot\` - Bot tags and metadata
704732
+ - \`user\` - User information
704733
+ - \`conversation\` - Current conversation
704734
+ - \`message\` - Incoming message
704735
+ - \`event\` - Current event
704736
+ - \`workflow\` - Current workflow
704737
+ - \`workflowControlContext\` - Workflow control (abort, fail, restart)
704738
+
704739
+ ### State Management
704740
+
704741
+ Access and modify tracked state:
704742
+
704743
+ \`\`\`typescript
704744
+ import { bot, user } from '@botpress/runtime'
704745
+
704746
+ // Bot state
704747
+ bot.state.lastIndexed = new Date().toISOString()
704748
+ bot.state.config = { theme: 'dark' }
704749
+
704750
+ // User state
704751
+ user.state.preferences = { notifications: true }
704752
+ user.state.lastActive = Date.now()
704753
+ \`\`\`
704754
+
704755
+ State persists automatically across executions.
704756
+
704757
+ ## Advanced Table Operations
704758
+
704759
+ ### Table Naming Rules
704760
+
704761
+ **IMPORTANT**: Tables have strict naming requirements:
704762
+
704763
+ \`\`\`typescript
704764
+ // \u2705 CORRECT - Name must end with "Table"
704765
+ export const MyDataTable = new Table({
704766
+ name: "mydataTable", // Must end with "Table"
704767
+ columns: { ... }
704768
+ });
704769
+
704770
+ // \u274C WRONG - Missing "Table" suffix
704771
+ name: "mydata"
704772
+ name: "my_data"
704773
+ \`\`\`
704774
+
704775
+ **Reserved column names** - Cannot use these as column names:
704776
+ - \`id\` (auto-generated)
704777
+ - \`createdAt\` (auto-generated)
704778
+ - \`updatedAt\` (auto-generated)
704779
+ - \`computed\`
704780
+ - \`stale\`
704781
+
704782
+ \`\`\`typescript
704783
+ // \u274C WRONG - Using reserved column name
704784
+ columns: {
704785
+ createdAt: z.string() // Reserved!
704786
+ }
704787
+
704788
+ // \u2705 CORRECT - Use alternative name
704789
+ columns: {
704790
+ savedAt: z.string()
704791
+ }
704792
+ \`\`\`
704793
+
704794
+ ### Auto-Registration
704795
+
704796
+ Files in \`src/tables/\` are **auto-registered** by the ADK. Do NOT re-export from index.ts:
704797
+
704798
+ \`\`\`typescript
704799
+ // src/tables/index.ts
704800
+ // \u274C WRONG - Causes duplicate registration errors
704801
+ export { MyTable } from "./myTable";
704802
+
704803
+ // \u2705 CORRECT - Leave empty or add comment
704804
+ // Tables are auto-registered from src/tables/*.ts files
704805
+ \`\`\`
704806
+
704807
+ Same applies to \`src/conversations/\`, \`src/workflows/\`, \`src/triggers/\`, etc.
704808
+
704809
+ Beyond basic CRUD, Tables support powerful query and manipulation features:
704810
+
704811
+ ### Complex Filtering
704812
+
704813
+ Use logical operators and conditions:
704814
+
704815
+ \`\`\`typescript
704816
+ await MyTable.findRows({
704817
+ filter: {
704818
+ $and: [
704819
+ { status: 'open' },
704820
+ { priority: { $in: ['high', 'urgent'] } }
704821
+ ],
704822
+ $or: [
704823
+ { assignee: userId },
704824
+ { reporter: userId }
704825
+ ],
704826
+ title: { $regex: 'bug|error', $options: 'i' }
704827
+ }
704828
+ })
704829
+ \`\`\`
704830
+
704831
+ **Filter operators:**
704832
+ - \`$eq\`, \`$ne\` - Equal, not equal
704833
+ - \`$gt\`, \`$gte\`, \`$lt\`, \`$lte\` - Comparisons
704834
+ - \`$in\`, \`$nin\` - In array, not in array
704835
+ - \`$exists\` - Field exists
704836
+ - \`$regex\` - Regular expression match
704837
+ - \`$options\` - Regex options (e.g., 'i' for case-insensitive)
704838
+ - \`$and\`, \`$or\` - Logical operators
704839
+
704840
+ ### Full-Text Search
704841
+
704842
+ Search across searchable columns:
704843
+
704844
+ \`\`\`typescript
704845
+ await MyTable.findRows({
704846
+ search: 'query string',
704847
+ filter: { status: 'active' }
704848
+ })
704849
+ \`\`\`
704850
+
704851
+ Mark columns as searchable in schema:
704852
+
704853
+ \`\`\`typescript
704854
+ columns: {
704855
+ title: z.string().searchable(),
704856
+ description: z.string().searchable()
704857
+ }
704858
+ \`\`\`
704859
+
704860
+ ### Aggregation and Grouping
704861
+
704862
+ Group and aggregate data:
704863
+
704864
+ \`\`\`typescript
704865
+ await MyTable.findRows({
704866
+ group: {
704867
+ status: 'count',
704868
+ priority: ['sum', 'avg'],
704869
+ complexity: ['max', 'min']
704870
+ }
704871
+ })
704872
+ \`\`\`
704873
+
704874
+ **Aggregation operations:** \`key\`, \`count\`, \`sum\`, \`avg\`, \`max\`, \`min\`, \`unique\`
704875
+
704876
+ ### Computed Columns
704877
+
704878
+ Columns with values computed from row data:
704879
+
704880
+ \`\`\`typescript
704881
+ columns: {
704882
+ fullName: {
704883
+ computed: true,
704884
+ schema: z.string(),
704885
+ dependencies: ['firstName', 'lastName'],
704886
+ value: async (row) => \`\${row.firstName} \${row.lastName}\`
704887
+ },
704888
+ age: {
704889
+ computed: true,
704890
+ schema: z.number(),
704891
+ dependencies: ['birthDate'],
704892
+ value: async (row) => {
704893
+ const today = new Date()
704894
+ const birth = new Date(row.birthDate)
704895
+ return today.getFullYear() - birth.getFullYear()
704896
+ }
704897
+ }
704898
+ }
704899
+ \`\`\`
704900
+
704901
+ ### Upsert Operations
704902
+
704903
+ Insert or update based on key column:
704904
+
704905
+ \`\`\`typescript
704906
+ await MyTable.upsertRows({
704907
+ rows: [
704908
+ { externalId: '123', name: 'Item 1' },
704909
+ { externalId: '456', name: 'Item 2' }
704910
+ ],
704911
+ keyColumn: 'externalId', // Update if exists, insert if not
704912
+ waitComputed: true // Wait for computed columns to update
704913
+ })
704914
+ \`\`\`
704915
+
704916
+ ### Bulk Operations
704917
+
704918
+ Efficient batch operations:
704919
+
704920
+ \`\`\`typescript
704921
+ // Delete by filter
704922
+ await MyTable.deleteRows({
704923
+ filter: { status: 'archived', createdAt: { $lt: '2024-01-01' } }
704924
+ })
704925
+
704926
+ // Delete by IDs
704927
+ await MyTable.deleteRowIds([1, 2, 3])
704928
+
704929
+ // Delete all
704930
+ await MyTable.deleteAllRows()
704931
+
704932
+ // Update multiple
704933
+ await MyTable.updateRows({
704934
+ rows: [
704935
+ { id: 1, status: 'active' },
704936
+ { id: 2, status: 'inactive' }
704937
+ ],
704938
+ waitComputed: true
704939
+ })
704940
+ \`\`\`
704941
+
704942
+ ### Error Handling
704943
+
704944
+ Collect errors and warnings from bulk operations:
704945
+
704946
+ \`\`\`typescript
704947
+ const { errors, warnings } = await MyTable.createRows({
704948
+ rows: data,
704949
+ waitComputed: true
704950
+ })
704951
+
704952
+ if (errors?.length) {
704953
+ console.error('Failed rows:', errors)
704954
+ }
704955
+ if (warnings?.length) {
704956
+ console.warn('Warnings:', warnings)
704957
+ }
704958
+ \`\`\`
704959
+
704960
+ ## Knowledge Base Operations
704961
+
704962
+ ### Data Sources
704963
+
704964
+ Multiple source types for knowledge bases:
704965
+
704966
+ #### Directory Source
704967
+
704968
+ \`\`\`typescript
704969
+ import { DataSource } from '@botpress/runtime'
704970
+
704971
+ const docs = DataSource.Directory.fromPath('src/knowledge', {
704972
+ id: 'docs',
704973
+ filter: (path) => path.endsWith('.md') || path.endsWith('.txt')
704974
+ })
704975
+ \`\`\`
704976
+
704977
+ #### Website Source
704978
+
704979
+ \`\`\`typescript
704980
+ const siteDocs = DataSource.Website.fromSitemap('https://example.com/sitemap.xml', {
704981
+ id: 'website',
704982
+ maxPages: 500,
704983
+ fetch: 'node:fetch' // or custom fetch implementation
704984
+ })
704985
+ \`\`\`
704986
+
704987
+ ### Knowledge Base Definition
704988
+
704989
+ \`\`\`typescript
704990
+ import { Knowledge } from '@botpress/runtime'
704991
+
704992
+ export default new Knowledge({
704993
+ name: 'docs',
704994
+ description: 'Product documentation',
704995
+ sources: [docsDirectory, websiteSource]
704996
+ })
704997
+ \`\`\`
704998
+
704999
+ ### Refresh Operations
705000
+
705001
+ Manually refresh knowledge base content:
705002
+
705003
+ \`\`\`typescript
705004
+ // Refresh entire knowledge base
705005
+ await DocsKB.refresh({ force: true })
705006
+
705007
+ // Refresh specific source
705008
+ await DocsKB.refreshSource('website', { force: true })
705009
+ \`\`\`
705010
+
705011
+ **Options:**
705012
+ - \`force: true\` - Force refresh even if recently updated
705013
+ - Automatic refresh via scheduled workflows recommended
705014
+
705015
+ ### Using Knowledge in Execute
705016
+
705017
+ \`\`\`typescript
705018
+ await execute({
705019
+ instructions: 'Answer using the documentation',
705020
+ knowledge: [DocsKB, APIKB],
705021
+ tools: [searchTool]
705022
+ })
705023
+ \`\`\`
705024
+
705025
+ Knowledge bases are automatically searchable via the \`search_knowledge\` tool.
705026
+
705027
+ ## Advanced Conversation Patterns
705028
+
705029
+ ### Multiple Channel Support
705030
+
705031
+ Handle messages from multiple channels in one handler:
705032
+
705033
+ \`\`\`typescript
705034
+ export default new Conversation({
705035
+ channel: ['chat.channel', 'webchat.channel', 'slack.dm'],
705036
+ handler: async ({ channel, execute }) => {
705037
+ console.log(\`Message from: \${channel}\`)
705038
+ await execute({ instructions: '...' })
705039
+ }
705040
+ })
705041
+ \`\`\`
705042
+
705043
+ ### Event Handling
705044
+
705045
+ Subscribe to integration events:
705046
+
705047
+ \`\`\`typescript
705048
+ export default new Conversation({
705049
+ channel: 'webchat.channel',
705050
+ events: ['webchat:conversationStarted', 'webchat:conversationEnded'],
705051
+ handler: async ({ type, event, message }) => {
705052
+ if (type === 'event' && event.type === 'webchat:conversationStarted') {
705053
+ // Send welcome message
705054
+ await conversation.send({
705055
+ type: 'text',
705056
+ payload: { text: 'Welcome!' }
705057
+ })
705058
+ }
705059
+
705060
+ if (type === 'message' && message?.type === 'text') {
705061
+ // Handle regular messages
705062
+ await execute({ instructions: '...' })
705063
+ }
705064
+ }
705065
+ })
705066
+ \`\`\`
705067
+
705068
+ ### Workflow Request Handling
705069
+
705070
+ Handle data requests from workflows:
705071
+
705072
+ \`\`\`typescript
705073
+ import { isWorkflowDataRequest } from '@botpress/runtime'
705074
+
705075
+ handler: async ({ type, event, execute }) => {
705076
+ // Check if this is a workflow requesting data
705077
+ if (type === 'workflow_request' && isWorkflowDataRequest(event)) {
705078
+ const userInput = await promptUser(event.payload.message)
705079
+
705080
+ // Provide data back to workflow
705081
+ await workflow.provide(event, { topic: userInput })
705082
+ return
705083
+ }
705084
+
705085
+ // Regular message handling
705086
+ await execute({ instructions: '...' })
705087
+ }
705088
+ \`\`\`
705089
+
705090
+ ### Typed Workflow Interactions
705091
+
705092
+ Work with typed workflow instances:
705093
+
705094
+ \`\`\`typescript
705095
+ import { isWorkflow, ResearchWorkflow } from '@botpress/runtime'
705096
+
705097
+ handler: async ({ state }) => {
705098
+ if (state.research && isWorkflow(state.research, 'research')) {
705099
+ // state.research is now typed as ResearchWorkflow
705100
+ console.log(state.research.status)
705101
+ console.log(state.research.output) // Typed output
705102
+
705103
+ if (state.research.status === 'completed') {
705104
+ await conversation.send({
705105
+ type: 'text',
705106
+ payload: { text: state.research.output.result }
705107
+ })
705108
+ }
705109
+ }
705110
+ }
705111
+ \`\`\`
705112
+
705113
+ ### Dynamic Tools Based on State
705114
+
705115
+ Provide different tools based on conversation state:
705116
+
705117
+ \`\`\`typescript
705118
+ handler: async ({ state, execute }) => {
705119
+ const tools = () => {
705120
+ if (state.workflowRunning) {
705121
+ return [cancelWorkflowTool, checkStatusTool]
705122
+ } else {
705123
+ return [startWorkflowTool, browseTool, searchTool]
705124
+ }
705125
+ }
705126
+
705127
+ await execute({
705128
+ instructions: '...',
705129
+ tools: tools()
705130
+ })
705131
+ }
705132
+ \`\`\`
705133
+
705134
+ ### Message Sending
705135
+
705136
+ Send different message types:
705137
+
705138
+ \`\`\`typescript
705139
+ // Text message
705140
+ await conversation.send({
705141
+ type: 'text',
705142
+ payload: { text: 'Hello!' }
705143
+ })
705144
+
705145
+ // Custom message type (integration-specific)
705146
+ await conversation.send({
705147
+ type: 'custom:messageType',
705148
+ payload: { data: 'custom payload' }
705149
+ })
705150
+ \`\`\`
705151
+
705152
+ ## Citations System
705153
+
705154
+ Track and manage source citations for LLM responses:
705155
+
705156
+ ### CitationsManager
705157
+
705158
+ Access via context:
705159
+
705160
+ \`\`\`typescript
705161
+ import { context } from '@botpress/runtime'
705162
+
705163
+ const citations = context.get('citations')
705164
+ \`\`\`
705165
+
705166
+ ### Registering Sources
705167
+
705168
+ Register sources that can be cited:
705169
+
705170
+ \`\`\`typescript
705171
+ // Register with URL
705172
+ const { tag } = citations.registerSource({
705173
+ url: 'https://example.com/doc',
705174
+ title: 'Documentation Page'
705175
+ })
705176
+
705177
+ // Register with file reference
705178
+ const { tag } = citations.registerSource({
705179
+ file: fileKey,
705180
+ title: 'Internal Document'
705181
+ })
705182
+ \`\`\`
705183
+
705184
+ ### Using Citation Tags
705185
+
705186
+ Inject citation tags into LLM content:
705187
+
705188
+ \`\`\`typescript
705189
+ const results = await searchKnowledgeBase(query)
705190
+
705191
+ for (const result of results) {
705192
+ const { tag } = citations.registerSource({
705193
+ file: result.file.key,
705194
+ title: result.file.name
705195
+ })
705196
+
705197
+ content += \`\${result.content} \${tag}\\n\`
705198
+ }
705199
+
705200
+ // Return cited content
705201
+ throw new ThinkSignal('results', content)
705202
+ \`\`\`
705203
+
705204
+ ### Citation Format
705205
+
705206
+ Citations are automatically formatted with tags like \`[1]\`, \`[2]\`, etc., and tracked by the system for reference.
705207
+
705208
+ ### Example: Tool with Citations
705209
+
705210
+ \`\`\`typescript
705211
+ export default new Autonomous.Tool({
705212
+ name: 'search_docs',
705213
+ description: 'Search documentation',
705214
+ handler: async ({ query }) => {
705215
+ const citations = context.get('citations')
705216
+ const results = await searchDocs(query)
705217
+
705218
+ let response = ''
705219
+ for (const doc of results) {
705220
+ const { tag } = citations.registerSource({
705221
+ url: doc.url,
705222
+ title: doc.title
705223
+ })
705224
+ response += \`\${doc.content} \${tag}\\n\\n\`
705225
+ }
705226
+
705227
+ return response
705228
+ }
705229
+ })
705230
+ \`\`\`
705231
+
705232
+ ## Common Mistakes to Avoid
705233
+
705234
+ ### 1. Wrong Zai Import
705235
+ \`\`\`typescript
705236
+ // \u274C WRONG
705237
+ import { zai } from '@botpress/runtime'
705238
+ const result = await zai.extract(...)
705239
+
705240
+ // \u2705 CORRECT
705241
+ import { adk } from '@botpress/runtime'
705242
+ const result = await adk.zai.extract(...)
705243
+ \`\`\`
705244
+
705245
+ ### 2. Expecting \`.output\` from zai.extract
705246
+ \`\`\`typescript
705247
+ // \u274C WRONG - zai.extract returns data directly
705248
+ const result = await adk.zai.extract(input, schema)
705249
+ console.log(result.output) // undefined!
705250
+
705251
+ // \u2705 CORRECT
705252
+ const result = await adk.zai.extract(input, schema)
705253
+ console.log(result) // { name: "John", age: 30 }
705254
+ \`\`\`
705255
+
705256
+ ### 3. Wrong Exit Result Handling
705257
+ \`\`\`typescript
705258
+ // \u274C WRONG
705259
+ if (result.exit?.name === 'my_exit') {
705260
+ const data = result.exit.value
705261
+ }
705262
+
705263
+ // \u2705 CORRECT
705264
+ if (result.is(MyExit)) {
705265
+ const data = result.output // Type-safe!
705266
+ }
705267
+ \`\`\`
705268
+
705269
+ ### 4. Reserved Table Column Names
705270
+ \`\`\`typescript
705271
+ // \u274C WRONG - These are reserved
705272
+ columns: {
705273
+ id: z.string(),
705274
+ createdAt: z.string(),
705275
+ updatedAt: z.string()
705276
+ }
705277
+
705278
+ // \u2705 CORRECT - Use alternatives
705279
+ columns: {
705280
+ visibleId: z.string(),
705281
+ savedAt: z.string(),
705282
+ modifiedAt: z.string()
705283
+ }
705284
+ \`\`\`
705285
+
705286
+ ### 5. Re-exporting Auto-Registered Files
705287
+ \`\`\`typescript
705288
+ // \u274C WRONG - src/tables/index.ts
705289
+ export { MyTable } from "./myTable" // Causes duplicates!
705290
+
705291
+ // \u2705 CORRECT - Leave index.ts empty
705292
+ // Files in src/tables/, src/conversations/, etc. are auto-registered
705293
+ \`\`\`
705294
+
705295
+ ### 6. Table Name Missing "Table" Suffix
705296
+ \`\`\`typescript
705297
+ // \u274C WRONG
705298
+ name: "users"
705299
+ name: "user_data"
705300
+
705301
+ // \u2705 CORRECT
705302
+ name: "usersTable"
705303
+ name: "userdataTable"
705304
+ \`\`\`
705305
+
705306
+ ## When Making Changes
705307
+
705308
+ 1. **Always search Botpress docs** using \`mcp__botpress-docs__SearchBotpress\`
705309
+ 2. **Check examples** for patterns
705310
+ 3. **Regenerate types** after changing \`agent.config.ts\` (run \`adk dev\`)
705311
+ 4. **Test in dev mode** with hot reloading (\`adk dev\`)
705312
+ 5. **Follow TypeScript types** - They're auto-generated from integrations
705313
+
705314
+ ## Resources
705315
+
705316
+ - [ADK Overview](https://botpress.com/docs/for-developers/adk/overview)
705317
+ - [ADK Getting Started](https://botpress.com/docs/for-developers/adk/getting-started)
705318
+ - [Project Structure](https://botpress.com/docs/for-developers/adk/project-structure)
705319
+ - [Conversations](https://botpress.com/docs/for-developers/adk/concepts/conversations)
705320
+ - [Workflows](https://botpress.com/docs/for-developers/adk/concepts/workflows)
705321
+ `, getIntegrationHash = (integration) => {
704065
705322
  return crypto24.createHash("sha256").update(`${integration.alias}|${integration.definition?.id}|${integration.definition?.version}|${integration.definition?.updatedAt}`).digest("hex");
704066
705323
  }, getPascalAlias = (integration) => pascalCase(getIntegrationAlias(integration.alias)), getIntegrationNames = (integration) => ({
704067
705324
  typings: {
@@ -704106,7 +705363,7 @@ var import_ts_morph, __defProp11, __commonJS7 = (cb4, mod) => () => (mod || cb4(
704106
705363
  } catch {
704107
705364
  try {
704108
705365
  const adkPackagePath = join72(process.cwd(), "node_modules/@botpress/adk/package.json");
704109
- const pkg = JSON.parse(readFileSync22(adkPackagePath, "utf-8"));
705366
+ const pkg = JSON.parse(readFileSync6(adkPackagePath, "utf-8"));
704110
705367
  return pkg.version;
704111
705368
  } catch {
704112
705369
  return "unknown";
@@ -704119,7 +705376,7 @@ var import_ts_morph, __defProp11, __commonJS7 = (cb4, mod) => () => (mod || cb4(
704119
705376
  } catch {
704120
705377
  try {
704121
705378
  const adkPackagePath = join9(process.cwd(), "node_modules/@botpress/adk/package.json");
704122
- const pkg = JSON.parse(readFileSync32(adkPackagePath, "utf-8"));
705379
+ const pkg = JSON.parse(readFileSync22(adkPackagePath, "utf-8"));
704123
705380
  return pkg.version;
704124
705381
  } catch {
704125
705382
  return "unknown";
@@ -704273,7 +705530,7 @@ var init_dist17 = __esm(() => {
704273
705530
  require_package3 = __commonJS7((exports7, module) => {
704274
705531
  module.exports = {
704275
705532
  name: "@botpress/adk",
704276
- version: "1.11.8",
705533
+ version: "1.11.9",
704277
705534
  description: "Core ADK library for building AI agents on Botpress",
704278
705535
  type: "module",
704279
705536
  main: "dist/index.js",
@@ -704320,7 +705577,7 @@ var init_dist17 = __esm(() => {
704320
705577
  "@botpress/cli": "^4.27.3",
704321
705578
  "@botpress/client": "^1.27.2",
704322
705579
  "@botpress/cognitive": "^0.2.0",
704323
- "@botpress/runtime": "^1.11.8",
705580
+ "@botpress/runtime": "^1.11.9",
704324
705581
  "@botpress/sdk": "^4.18.1",
704325
705582
  "@bpinternal/jex": "^1.2.4",
704326
705583
  "@bpinternal/yargs-extra": "^0.0.21",
@@ -705679,8 +706936,6 @@ ${this.stderrLines.join(`
705679
706936
  init_agent_resolver();
705680
706937
  init_types6();
705681
706938
  init_utils8();
705682
- __filename2 = fileURLToPath7(import.meta.url);
705683
- __dirname2 = path15.dirname(__filename2);
705684
706939
  init_fs();
705685
706940
  init_utils8();
705686
706941
  init_utils8();
@@ -706086,7 +707341,7 @@ function pathKey2(options = {}) {
706086
707341
  // ../../node_modules/clipboardy/node_modules/execa/node_modules/npm-run-path/index.js
706087
707342
  import process26 from "process";
706088
707343
  import path35 from "path";
706089
- import { fileURLToPath as fileURLToPath8 } from "url";
707344
+ import { fileURLToPath as fileURLToPath7 } from "url";
706090
707345
  var npmRunPath2 = ({
706091
707346
  cwd: cwd4 = process26.cwd(),
706092
707347
  path: pathOption = process26.env[pathKey2()],
@@ -706094,7 +707349,7 @@ var npmRunPath2 = ({
706094
707349
  execPath: execPath3 = process26.execPath,
706095
707350
  addExecPath = true
706096
707351
  } = {}) => {
706097
- const cwdString = cwd4 instanceof URL ? fileURLToPath8(cwd4) : cwd4;
707352
+ const cwdString = cwd4 instanceof URL ? fileURLToPath7(cwd4) : cwd4;
706098
707353
  const cwdPath = path35.resolve(cwdString);
706099
707354
  const result = [];
706100
707355
  if (preferLocal) {
@@ -706112,7 +707367,7 @@ var npmRunPath2 = ({
706112
707367
  cwdPath = path35.resolve(cwdPath, "..");
706113
707368
  }
706114
707369
  }, applyExecPath2 = (result, execPath3, cwdPath) => {
706115
- const execPathString = execPath3 instanceof URL ? fileURLToPath8(execPath3) : execPath3;
707370
+ const execPathString = execPath3 instanceof URL ? fileURLToPath7(execPath3) : execPath3;
706116
707371
  result.push(path35.resolve(cwdPath, execPathString, ".."));
706117
707372
  }, npmRunPathEnv2 = ({ env: env6 = process26.env, ...options } = {}) => {
706118
707373
  env6 = { ...env6 };
@@ -707447,8 +708702,8 @@ var init_termux = __esm(() => {
707447
708702
 
707448
708703
  // ../../node_modules/clipboardy/lib/linux.js
707449
708704
  import path38 from "path";
707450
- import { fileURLToPath as fileURLToPath9 } from "url";
707451
- var __dirname3, xsel = "xsel", xselFallback, copyArguments, pasteArguments, makeError3 = (xselError, fallbackError) => {
708705
+ import { fileURLToPath as fileURLToPath8 } from "url";
708706
+ var __dirname2, xsel = "xsel", xselFallback, copyArguments, pasteArguments, makeError3 = (xselError, fallbackError) => {
707452
708707
  let error;
707453
708708
  if (xselError.code === "ENOENT") {
707454
708709
  error = new Error("Couldn't find the `xsel` binary and fallback didn't work. On Debian/Ubuntu you can install xsel with: sudo apt install xsel");
@@ -707483,8 +708738,8 @@ var __dirname3, xsel = "xsel", xselFallback, copyArguments, pasteArguments, make
707483
708738
  }, clipboard2, linux_default;
707484
708739
  var init_linux = __esm(() => {
707485
708740
  init_execa2();
707486
- __dirname3 = path38.dirname(fileURLToPath9(import.meta.url));
707487
- xselFallback = path38.join(__dirname3, "../fallbacks/linux/xsel");
708741
+ __dirname2 = path38.dirname(fileURLToPath8(import.meta.url));
708742
+ xselFallback = path38.join(__dirname2, "../fallbacks/linux/xsel");
707488
708743
  copyArguments = ["--clipboard", "--input"];
707489
708744
  pasteArguments = ["--clipboard", "--output"];
707490
708745
  clipboard2 = {
@@ -707565,14 +708820,14 @@ var init_is64bit = __esm(() => {
707565
708820
 
707566
708821
  // ../../node_modules/clipboardy/lib/windows.js
707567
708822
  import path39 from "path";
707568
- import { fileURLToPath as fileURLToPath10 } from "url";
707569
- var __dirname5, binarySuffix, windowBinaryPath, clipboard4, windows_default;
708823
+ import { fileURLToPath as fileURLToPath9 } from "url";
708824
+ var __dirname3, binarySuffix, windowBinaryPath, clipboard4, windows_default;
707570
708825
  var init_windows = __esm(() => {
707571
708826
  init_execa2();
707572
708827
  init_is64bit();
707573
- __dirname5 = path39.dirname(fileURLToPath10(import.meta.url));
708828
+ __dirname3 = path39.dirname(fileURLToPath9(import.meta.url));
707574
708829
  binarySuffix = is64bitSync() ? "x86_64" : "i686";
707575
- windowBinaryPath = path39.join(__dirname5, `../fallbacks/windows/clipboard_${binarySuffix}.exe`);
708830
+ windowBinaryPath = path39.join(__dirname3, `../fallbacks/windows/clipboard_${binarySuffix}.exe`);
707576
708831
  clipboard4 = {
707577
708832
  copy: async (options) => execa2(windowBinaryPath, ["--copy"], options),
707578
708833
  async paste(options) {
@@ -709284,7 +710539,7 @@ var init_default_browser = __esm(() => {
709284
710539
  import process36 from "process";
709285
710540
  import { Buffer as Buffer8 } from "buffer";
709286
710541
  import path40 from "path";
709287
- import { fileURLToPath as fileURLToPath11 } from "url";
710542
+ import { fileURLToPath as fileURLToPath10 } from "url";
709288
710543
  import { promisify as promisify9 } from "util";
709289
710544
  import childProcess3 from "child_process";
709290
710545
  import fs25, { constants as fsConstants2 } from "fs/promises";
@@ -709328,7 +710583,7 @@ function detectPlatformBinary({ [platform4]: platformBinary }, { wsl }) {
709328
710583
  }
709329
710584
  return detectArchBinary(platformBinary);
709330
710585
  }
709331
- var execFile5, __dirname6, localXdgOpenPath, platform4, arch3, pTryEach = async (array, mapper) => {
710586
+ var execFile5, __dirname4, localXdgOpenPath, platform4, arch3, pTryEach = async (array, mapper) => {
709332
710587
  let latestError;
709333
710588
  for (const item of array) {
709334
710589
  try {
@@ -709441,7 +710696,7 @@ var execFile5, __dirname6, localXdgOpenPath, platform4, arch3, pTryEach = async
709441
710696
  if (app) {
709442
710697
  command = app;
709443
710698
  } else {
709444
- const isBundled = !__dirname6 || __dirname6 === "/";
710699
+ const isBundled = !__dirname4 || __dirname4 === "/";
709445
710700
  let exeLocalXdgOpen = false;
709446
710701
  try {
709447
710702
  await fs25.access(localXdgOpenPath, fsConstants2.X_OK);
@@ -709493,8 +710748,8 @@ var init_open = __esm(() => {
709493
710748
  init_default_browser();
709494
710749
  init_is_inside_container();
709495
710750
  execFile5 = promisify9(childProcess3.execFile);
709496
- __dirname6 = path40.dirname(fileURLToPath11(import.meta.url));
709497
- localXdgOpenPath = path40.join(__dirname6, "xdg-open");
710751
+ __dirname4 = path40.dirname(fileURLToPath10(import.meta.url));
710752
+ localXdgOpenPath = path40.join(__dirname4, "xdg-open");
709498
710753
  ({ platform: platform4, arch: arch3 } = process36);
709499
710754
  apps = {};
709500
710755
  defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
@@ -710869,7 +712124,7 @@ var init_Separator = __esm(async () => {
710869
712124
  var require_package4 = __commonJS((exports7, module) => {
710870
712125
  module.exports = {
710871
712126
  name: "@botpress/adk",
710872
- version: "1.11.8",
712127
+ version: "1.11.9",
710873
712128
  description: "Core ADK library for building AI agents on Botpress",
710874
712129
  type: "module",
710875
712130
  main: "dist/index.js",
@@ -710916,7 +712171,7 @@ var require_package4 = __commonJS((exports7, module) => {
710916
712171
  "@botpress/cli": "^4.27.3",
710917
712172
  "@botpress/client": "^1.27.2",
710918
712173
  "@botpress/cognitive": "^0.2.0",
710919
- "@botpress/runtime": "^1.11.8",
712174
+ "@botpress/runtime": "^1.11.9",
710920
712175
  "@botpress/sdk": "^4.18.1",
710921
712176
  "@bpinternal/jex": "^1.2.4",
710922
712177
  "@bpinternal/yargs-extra": "^0.0.21",
@@ -712856,7 +714111,7 @@ function checkRuntimeVersion(agentRoot) {
712856
714111
  `));
712857
714112
  }
712858
714113
  }
712859
- var semver2, EXPECTED_RUNTIME_VERSION = "1.11.8", SUPPORTED_RUNTIME_RANGE = ">=1.11.0";
714114
+ var semver2, EXPECTED_RUNTIME_VERSION = "1.11.9", SUPPORTED_RUNTIME_RANGE = ">=1.11.0";
712860
714115
  var init_runtime_version_check = __esm(() => {
712861
714116
  init_source();
712862
714117
  semver2 = __toESM(require_semver2(), 1);
@@ -716634,17 +717889,17 @@ function getContentType(pathname) {
716634
717889
  import { readFileSync as readFileSync14, existsSync as existsSync15 } from "fs";
716635
717890
  import { join as join16, resolve as resolve5 } from "path";
716636
717891
  import path41 from "path";
716637
- import { fileURLToPath as fileURLToPath12 } from "url";
717892
+ import { fileURLToPath as fileURLToPath11 } from "url";
716638
717893
  function getUIDistPath() {
716639
- const __filename3 = fileURLToPath12(import.meta.url);
716640
- const __dirname4 = path41.dirname(__filename3);
716641
- const isBinary = !__filename3.endsWith(".js") && !__filename3.endsWith(".ts");
717894
+ const __filename2 = fileURLToPath11(import.meta.url);
717895
+ const __dirname5 = path41.dirname(__filename2);
717896
+ const isBinary = !__filename2.endsWith(".js") && !__filename2.endsWith(".ts");
716642
717897
  if (isBinary) {
716643
717898
  const execDir = path41.dirname(process.execPath);
716644
717899
  return resolve5(execDir, "assets/ui-dist");
716645
717900
  } else {
716646
- const isCompiledDist = __filename3.includes("/dist/");
716647
- return isCompiledDist ? resolve5(__dirname4, "../assets/ui-dist") : resolve5(__dirname4, "../../assets/ui-dist");
717901
+ const isCompiledDist = __filename2.includes("/dist/");
717902
+ return isCompiledDist ? resolve5(__dirname5, "../assets/ui-dist") : resolve5(__dirname5, "../../assets/ui-dist");
716648
717903
  }
716649
717904
  }
716650
717905
  function serveStaticFile(pathname, uiDistPath) {
@@ -722736,7 +723991,7 @@ var stripTrailingSlashes = (str) => {
722736
723991
 
722737
723992
  // ../../node_modules/tar/dist/esm/list.js
722738
723993
  import fs28 from "fs";
722739
- import { dirname as dirname5, parse as parse9 } from "path";
723994
+ import { dirname as dirname4, parse as parse9 } from "path";
722740
723995
  var onReadEntryFunction = (opt) => {
722741
723996
  const onReadEntry = opt.onReadEntry;
722742
723997
  opt.onReadEntry = onReadEntry ? (e6) => {
@@ -722756,7 +724011,7 @@ var onReadEntryFunction = (opt) => {
722756
724011
  if (m2 !== undefined) {
722757
724012
  ret = m2;
722758
724013
  } else {
722759
- ret = mapHas(dirname5(file), root5);
724014
+ ret = mapHas(dirname4(file), root5);
722760
724015
  }
722761
724016
  }
722762
724017
  map.set(file, ret);
@@ -727969,7 +729224,7 @@ __export(exports_upgrade, {
727969
729224
  adkSelfUpgrade: () => adkSelfUpgrade
727970
729225
  });
727971
729226
  import { existsSync as existsSync17, writeFileSync as writeFileSync6, chmodSync, renameSync, unlinkSync, readFileSync as readFileSync16, mkdirSync as mkdirSync5, rmdirSync, accessSync, constants as constants8 } from "fs";
727972
- import { join as join19, dirname as dirname6 } from "path";
729227
+ import { join as join19, dirname as dirname5 } from "path";
727973
729228
  import { tmpdir } from "os";
727974
729229
  import { execSync as execSync4 } from "child_process";
727975
729230
  function getPlatformInfo() {
@@ -728057,7 +729312,7 @@ function getCurrentBinaryPath() {
728057
729312
  }
728058
729313
  function checkWritePermissions(path36) {
728059
729314
  try {
728060
- const dir = dirname6(path36);
729315
+ const dir = dirname5(path36);
728061
729316
  accessSync(dir, constants8.W_OK);
728062
729317
  if (existsSync17(path36)) {
728063
729318
  accessSync(path36, constants8.W_OK);
@@ -872045,7 +873300,7 @@ function dew18() {
872045
873300
  exports$114.Url = Url2;
872046
873301
  return exports$114;
872047
873302
  }
872048
- function fileURLToPath13(path210) {
873303
+ function fileURLToPath12(path210) {
872049
873304
  if (typeof path210 === "string")
872050
873305
  path210 = new URL(path210);
872051
873306
  else if (!(path210 instanceof URL)) {
@@ -896753,7 +898008,7 @@ Use Chrome, Firefox or Internet Explorer 11`);
896753
898008
  URL: () => _URL,
896754
898009
  Url: () => Url,
896755
898010
  default: () => exports19,
896756
- fileURLToPath: () => fileURLToPath13,
898011
+ fileURLToPath: () => fileURLToPath12,
896757
898012
  format: () => format23,
896758
898013
  parse: () => parse17,
896759
898014
  pathToFileURL: () => pathToFileURL,
@@ -896796,7 +898051,7 @@ Use Chrome, Firefox or Internet Explorer 11`);
896796
898051
  processPlatform = typeof Deno !== "undefined" ? Deno.build.os === "windows" ? "win32" : Deno.build.os : undefined;
896797
898052
  exports19.URL = typeof URL !== "undefined" ? URL : null;
896798
898053
  exports19.pathToFileURL = pathToFileURL;
896799
- exports19.fileURLToPath = fileURLToPath13;
898054
+ exports19.fileURLToPath = fileURLToPath12;
896800
898055
  Url = exports19.Url;
896801
898056
  format23 = exports19.format;
896802
898057
  resolve7 = exports19.resolve;
@@ -905193,14 +906448,14 @@ var init_tools = __esm(() => {
905193
906448
  });
905194
906449
 
905195
906450
  // src/mcp/server.ts
905196
- import { fileURLToPath as fileURLToPath14 } from "url";
905197
- import { dirname as dirname7, join as join25 } from "path";
906451
+ import { fileURLToPath as fileURLToPath13 } from "url";
906452
+ import { dirname as dirname6, join as join25 } from "path";
905198
906453
  import { readFileSync as readFileSync18 } from "fs";
905199
906454
  function getMcpServerVersion() {
905200
906455
  try {
905201
- const __filename3 = fileURLToPath14(import.meta.url);
905202
- const __dirname4 = dirname7(__filename3);
905203
- const packageJsonPath = join25(__dirname4, "../../package.json");
906456
+ const __filename2 = fileURLToPath13(import.meta.url);
906457
+ const __dirname5 = dirname6(__filename2);
906458
+ const packageJsonPath = join25(__dirname5, "../../package.json");
905204
906459
  const packageJson = JSON.parse(readFileSync18(packageJsonPath, "utf-8"));
905205
906460
  return packageJson.version ?? "0.0.0";
905206
906461
  } catch {
@@ -905267,7 +906522,7 @@ var init_adk_mcp = __esm(() => {
905267
906522
 
905268
906523
  // src/mcp/config-generator.ts
905269
906524
  import { existsSync as existsSync22, mkdirSync as mkdirSync6, writeFileSync as writeFileSync7, readFileSync as readFileSync19 } from "fs";
905270
- import { dirname as dirname8, resolve as resolve9 } from "path";
906525
+ import { dirname as dirname7, resolve as resolve9 } from "path";
905271
906526
  function validatePath(basePath, relativePath) {
905272
906527
  const resolvedBase = resolve9(basePath);
905273
906528
  const resolvedPath = resolve9(basePath, relativePath);
@@ -905360,7 +906615,7 @@ function generateConfig(tool, cwd5, options = {}) {
905360
906615
  };
905361
906616
  }
905362
906617
  try {
905363
- const dir = dirname8(configPath);
906618
+ const dir = dirname7(configPath);
905364
906619
  if (!existsSync22(dir)) {
905365
906620
  mkdirSync6(dir, { recursive: true });
905366
906621
  }
@@ -906116,8 +907371,8 @@ var {
906116
907371
 
906117
907372
  // src/cli.ts
906118
907373
  import { readFileSync as readFileSync20 } from "fs";
906119
- import { join as join28, dirname as dirname9 } from "path";
906120
- import { fileURLToPath as fileURLToPath15 } from "url";
907374
+ import { join as join28, dirname as dirname8 } from "path";
907375
+ import { fileURLToPath as fileURLToPath14 } from "url";
906121
907376
 
906122
907377
  // src/utils/version-check.tsx
906123
907378
  await init_build2();
@@ -906547,12 +907802,12 @@ if (!checkNodeVersion(true)) {
906547
907802
  checkNodeVersion(false);
906548
907803
  process.exit(1);
906549
907804
  }
906550
- var CLI_VERSION = "1.11.8";
907805
+ var CLI_VERSION = "1.11.9";
906551
907806
  if (CLI_VERSION.startsWith("<<") && CLI_VERSION.endsWith(">>")) {
906552
907807
  try {
906553
- const __filename3 = fileURLToPath15(import.meta.url);
906554
- const __dirname4 = dirname9(__filename3);
906555
- const packageJson = JSON.parse(readFileSync20(join28(__dirname4, "../package.json"), "utf-8"));
907808
+ const __filename2 = fileURLToPath14(import.meta.url);
907809
+ const __dirname5 = dirname8(__filename2);
907810
+ const packageJson = JSON.parse(readFileSync20(join28(__dirname5, "../package.json"), "utf-8"));
906556
907811
  CLI_VERSION = packageJson.version;
906557
907812
  } catch {}
906558
907813
  }