@carto-knowledge/runner 0.2.4 → 0.2.5

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/index.cjs CHANGED
@@ -143,6 +143,7 @@ var WRITE_ALLOWLIST = {
143
143
  "item update content",
144
144
  "item upload",
145
145
  "item assign",
146
+ "item move",
146
147
  // Edge writes
147
148
  "edge create",
148
149
  "edge update",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/runner.ts","../src/tokenizer.ts","../src/allowlist.ts","../src/envelope.ts","../src/runtime.ts"],"sourcesContent":["// ABOUTME: Public API for @carto/runner package\n// ABOUTME: Exports in-process runner and supporting utilities\n\nexport { runInProcess } from './runner';\nexport type { RunOptions } from './runner';\nexport type { CommandOutput } from './envelope';\nexport { successEnvelope, errorEnvelope, ErrorCodes } from './envelope';\nexport { tokenize, extractCommandPath } from './tokenizer';\nexport { checkAllowlist, DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport { WorkerRuntime, CliRuntime } from './runtime';\nexport type { CartoRuntime } from './runtime';\n","// ABOUTME: Executes CLI commands in-process without subprocess spawning\n// ABOUTME: Designed for Cloudflare Worker compatibility\n\nimport { Cli } from 'clipanion';\nimport { tokenize, extractCommandPath } from './tokenizer';\nimport { checkAllowlist, AllowlistConfig, DEFAULT_ALLOWLIST } from './allowlist';\nimport { successEnvelope, errorEnvelope, CommandOutput, ErrorCodes } from './envelope';\nimport { WorkerRuntime } from './runtime';\nimport { allCommands } from '@carto-knowledge/commands';\nimport { CartoClient } from '@carto-knowledge/core';\n\nexport interface RunOptions {\n /** Correlation ID for tracing */\n requestId?: string;\n\n /** Auth token for API calls */\n authToken: string;\n\n /** Base URL for Carto API */\n apiBaseUrl: string;\n\n /** Command allowlist (defaults to read-only operations) */\n allowlist?: AllowlistConfig;\n}\n\n/**\n * Executes a CLI command in-process.\n *\n * Designed for Worker runtime:\n * - No subprocess spawning\n * - Captures output to memory streams\n * - Forces JSON output and non-interactive mode\n * - Validates against allowlist\n *\n * @param commandLine - Command string, e.g., \"folder tree --library my-lib\"\n * @param options - Execution options including auth and allowlist\n * @returns Structured command output envelope\n */\nexport async function runInProcess(\n commandLine: string,\n options: RunOptions\n): Promise<CommandOutput> {\n const { requestId, authToken, apiBaseUrl, allowlist = DEFAULT_ALLOWLIST } = options;\n\n // Defensive: Validate inputs\n if (!commandLine || typeof commandLine !== 'string') {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'commandLine must be a non-empty string',\n }, requestId);\n }\n\n if (!authToken) {\n return errorEnvelope('', {\n code: ErrorCodes.AUTH_ERROR,\n message: 'authToken is required',\n }, requestId);\n }\n\n // Parse command line\n const tokens = tokenize(commandLine.trim());\n\n if (tokens.length === 0) {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'Empty command line',\n }, requestId);\n }\n\n const commandPath = extractCommandPath(tokens);\n\n // Check allowlist\n const allowlistResult = checkAllowlist(commandPath, allowlist);\n if (!allowlistResult.allowed) {\n return errorEnvelope(commandPath, allowlistResult.error!, requestId);\n }\n\n // Force tool-mode flags\n const augmentedTokens = [\n ...tokens,\n '--format', 'json',\n ];\n\n // Create CLI instance\n const cli = new Cli({\n binaryName: 'carto',\n enableCapture: true,\n });\n\n // Register all commands\n for (const CommandClass of allCommands) {\n cli.register(CommandClass);\n }\n\n // Capture output to memory using simple buffers (Worker-compatible)\n let stdoutData = '';\n let stderrData = '';\n\n const stdout = {\n write(chunk: string | Uint8Array): boolean {\n stdoutData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n const stderr = {\n write(chunk: string | Uint8Array): boolean {\n stderrData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n // Create runtime and client\n const runtime = new WorkerRuntime(authToken, apiBaseUrl);\n const client = new CartoClient({\n baseUrl: apiBaseUrl,\n getAuthToken: async () => authToken,\n });\n\n // Create context matching CartoCommandContext\n // Type assertion needed because we use minimal stream stubs for Worker compatibility\n // Clipanion only uses the write() method at runtime\n const context = {\n stdin: process.stdin,\n stdout,\n stderr,\n env: {},\n colorDepth: 1,\n client,\n runtime,\n } as unknown as Parameters<typeof cli.run>[1];\n\n try {\n const exitCode = await cli.run(augmentedTokens, context);\n const output = stdoutData.trim();\n const errorOutput = stderrData.trim();\n\n if (exitCode === 0) {\n // Parse JSON output from command\n try {\n const result = output ? JSON.parse(output) : null;\n return successEnvelope(commandPath, result, requestId);\n } catch {\n // Command succeeded but output wasn't JSON (shouldn't happen in tool mode)\n return successEnvelope(commandPath, { text: output }, requestId);\n }\n } else {\n // Command failed\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message: errorOutput || output || `Command exited with code ${exitCode}`,\n }, requestId);\n }\n } catch (error) {\n // Unexpected error during execution\n const message = error instanceof Error ? error.message : String(error);\n console.error(`[carto-cli] Execution error for '${commandPath}':`, error);\n\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message,\n }, requestId);\n }\n}\n\n// Re-export for convenience\nexport { DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport type { CommandOutput } from './envelope';\n","// ABOUTME: Tokenizes command line strings for in-process CLI execution\n// ABOUTME: Handles quoted strings and shell-like argument parsing\n\n/**\n * Tokenizes a command line string, handling quoted strings.\n *\n * Examples:\n * - \"folder tree\" => ['folder', 'tree']\n * - \"--name 'My Folder'\" => ['--name', 'My Folder']\n * - '--name \"My Folder\"' => ['--name', 'My Folder']\n * - \"folder create --name 'Test's Folder'\" => handles escaped quotes\n */\nexport function tokenize(commandLine: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let inQuote: string | null = null;\n let escaped = false;\n\n for (let i = 0; i < commandLine.length; i++) {\n const char = commandLine[i];\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inQuote) {\n if (char === inQuote) {\n // Empty quoted string should still produce a token\n tokens.push(current);\n current = '';\n inQuote = null;\n } else {\n current += char;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current);\n current = '';\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n tokens.push(current);\n }\n\n return tokens;\n}\n\n/**\n * Extracts the command path from tokens (before any options).\n *\n * Examples:\n * - ['folder', 'tree', '--library', 'x'] => 'folder tree'\n * - ['item', 'search', '-q', 'hello'] => 'item search'\n */\nexport function extractCommandPath(tokens: string[]): string {\n const path: string[] = [];\n for (const token of tokens) {\n if (token.startsWith('-')) break;\n path.push(token);\n }\n return path.join(' ');\n}\n","// ABOUTME: Validates commands against an allowlist for tool-mode execution\n// ABOUTME: Prevents unauthorized command execution in Worker context\n\nexport interface AllowlistConfig {\n commands: string[]; // e.g., ['folder tree', 'item search']\n}\n\nexport interface AllowlistResult {\n allowed: boolean;\n error?: {\n code: 'COMMAND_NOT_ALLOWED';\n message: string;\n };\n}\n\n/**\n * Checks if a command matches the allowlist.\n *\n * Defensive validation:\n * - Normalizes command path (lowercase, trim)\n * - Supports prefix matching for subcommands\n */\nexport function checkAllowlist(\n commandPath: string,\n config: AllowlistConfig\n): AllowlistResult {\n const normalizedPath = commandPath.toLowerCase().trim();\n\n // Check exact match\n if (config.commands.some(cmd => cmd.toLowerCase() === normalizedPath)) {\n return { allowed: true };\n }\n\n // Check prefix match (e.g., 'folder' allows 'folder tree', 'folder create')\n if (config.commands.some(cmd => normalizedPath.startsWith(cmd.toLowerCase() + ' '))) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n error: {\n code: 'COMMAND_NOT_ALLOWED',\n message: `Command '${commandPath}' is not in the allowlist. ` +\n `Allowed commands: ${config.commands.join(', ')}`,\n },\n };\n}\n\n/**\n * Default allowlist for Worker tool mode.\n * Read-only operations by default.\n */\nexport const DEFAULT_ALLOWLIST: AllowlistConfig = {\n commands: [\n // Folder reads\n 'folder tree',\n 'folder list',\n 'folder get',\n // Item reads\n 'item search',\n 'item get',\n 'item list',\n 'item get-by-uri',\n 'item segments',\n // Edge reads\n 'edge list',\n 'edge get',\n // Share link reads\n 'share-link list',\n 'share-link analytics',\n // Librarian\n 'librarian chat',\n ],\n};\n\n/**\n * Extended allowlist including write operations.\n * Use when agent needs to modify data.\n */\nexport const WRITE_ALLOWLIST: AllowlistConfig = {\n commands: [\n ...DEFAULT_ALLOWLIST.commands,\n // Folder writes\n 'folder create',\n 'folder update',\n 'folder delete',\n 'folder move',\n 'folder restructure',\n 'folder create-tree',\n // Item writes\n 'item create',\n 'item update',\n 'item delete',\n 'item update content',\n 'item upload',\n 'item assign',\n // Edge writes\n 'edge create',\n 'edge update',\n 'edge delete',\n // Share link writes\n 'share-link create',\n 'share-link delete',\n ],\n};\n","// ABOUTME: Wraps CLI command outputs in structured JSON envelopes\n// ABOUTME: Provides consistent response format for Mastra tool integration\n\nexport interface CommandError {\n code: string;\n message: string;\n}\n\nexport interface CommandOutput<T = unknown> {\n ok: boolean;\n command: string;\n result?: T;\n error?: CommandError;\n requestId?: string;\n schemaVersion: 1;\n}\n\n/**\n * Creates a successful output envelope.\n */\nexport function successEnvelope<T>(\n command: string,\n result: T,\n requestId?: string\n): CommandOutput<T> {\n return {\n ok: true,\n command,\n result,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Creates an error output envelope.\n */\nexport function errorEnvelope(\n command: string,\n error: CommandError,\n requestId?: string\n): CommandOutput<never> {\n return {\n ok: false,\n command,\n error,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Common error codes for CLI operations.\n */\nexport const ErrorCodes = {\n COMMAND_NOT_ALLOWED: 'COMMAND_NOT_ALLOWED',\n COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',\n INVALID_ARGUMENTS: 'INVALID_ARGUMENTS',\n AUTH_ERROR: 'AUTH_ERROR',\n EXECUTION_ERROR: 'EXECUTION_ERROR',\n PARSE_ERROR: 'PARSE_ERROR',\n} as const;\n","// ABOUTME: Abstracts runtime differences between CLI and Worker execution\n// ABOUTME: Provides consistent interface for auth, logging, and config\n\nexport interface CartoRuntime {\n // Authentication\n getAuthToken(): Promise<string>;\n\n // API access\n apiBaseUrl: string;\n\n // Environment flags\n isInteractive: boolean;\n isToolMode: boolean;\n\n // Logging (respects --quiet, routes to correct streams)\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\n/**\n * Worker runtime - receives auth from request context.\n * Non-interactive, always tool mode.\n */\nexport class WorkerRuntime implements CartoRuntime {\n isInteractive = false;\n isToolMode = true;\n\n constructor(\n private authToken: string,\n public apiBaseUrl: string,\n ) {}\n\n async getAuthToken(): Promise<string> {\n return this.authToken;\n }\n\n log(message: string): void {\n console.log(`[carto-cli] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[carto-cli] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[carto-cli] ${message}`);\n }\n}\n\n/**\n * CLI runtime - reads from config file or env vars.\n * Interactive when terminal attached.\n *\n * Compatible with both Bun and Node.js runtimes.\n */\nexport class CliRuntime implements CartoRuntime {\n isInteractive: boolean;\n isToolMode = false;\n\n constructor(\n private config: { apiBaseUrl: string; authToken?: string },\n ) {\n // Works in both Bun and Node.js\n this.isInteractive = process.stdout.isTTY ?? false;\n }\n\n get apiBaseUrl(): string {\n return this.config.apiBaseUrl;\n }\n\n async getAuthToken(): Promise<string> {\n if (!this.config.authToken) {\n throw new Error('Not authenticated. Run `carto auth login` first.');\n }\n return this.config.authToken;\n }\n\n log(message: string): void {\n console.log(message);\n }\n\n warn(message: string): void {\n console.warn(message);\n }\n\n error(message: string): void {\n console.error(message);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/runner.ts","../src/tokenizer.ts","../src/allowlist.ts","../src/envelope.ts","../src/runtime.ts"],"sourcesContent":["// ABOUTME: Public API for @carto/runner package\n// ABOUTME: Exports in-process runner and supporting utilities\n\nexport { runInProcess } from './runner';\nexport type { RunOptions } from './runner';\nexport type { CommandOutput } from './envelope';\nexport { successEnvelope, errorEnvelope, ErrorCodes } from './envelope';\nexport { tokenize, extractCommandPath } from './tokenizer';\nexport { checkAllowlist, DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport { WorkerRuntime, CliRuntime } from './runtime';\nexport type { CartoRuntime } from './runtime';\n","// ABOUTME: Executes CLI commands in-process without subprocess spawning\n// ABOUTME: Designed for Cloudflare Worker compatibility\n\nimport { Cli } from 'clipanion';\nimport { tokenize, extractCommandPath } from './tokenizer';\nimport { checkAllowlist, AllowlistConfig, DEFAULT_ALLOWLIST } from './allowlist';\nimport { successEnvelope, errorEnvelope, CommandOutput, ErrorCodes } from './envelope';\nimport { WorkerRuntime } from './runtime';\nimport { allCommands } from '@carto-knowledge/commands';\nimport { CartoClient } from '@carto-knowledge/core';\n\nexport interface RunOptions {\n /** Correlation ID for tracing */\n requestId?: string;\n\n /** Auth token for API calls */\n authToken: string;\n\n /** Base URL for Carto API */\n apiBaseUrl: string;\n\n /** Command allowlist (defaults to read-only operations) */\n allowlist?: AllowlistConfig;\n}\n\n/**\n * Executes a CLI command in-process.\n *\n * Designed for Worker runtime:\n * - No subprocess spawning\n * - Captures output to memory streams\n * - Forces JSON output and non-interactive mode\n * - Validates against allowlist\n *\n * @param commandLine - Command string, e.g., \"folder tree --library my-lib\"\n * @param options - Execution options including auth and allowlist\n * @returns Structured command output envelope\n */\nexport async function runInProcess(\n commandLine: string,\n options: RunOptions\n): Promise<CommandOutput> {\n const { requestId, authToken, apiBaseUrl, allowlist = DEFAULT_ALLOWLIST } = options;\n\n // Defensive: Validate inputs\n if (!commandLine || typeof commandLine !== 'string') {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'commandLine must be a non-empty string',\n }, requestId);\n }\n\n if (!authToken) {\n return errorEnvelope('', {\n code: ErrorCodes.AUTH_ERROR,\n message: 'authToken is required',\n }, requestId);\n }\n\n // Parse command line\n const tokens = tokenize(commandLine.trim());\n\n if (tokens.length === 0) {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'Empty command line',\n }, requestId);\n }\n\n const commandPath = extractCommandPath(tokens);\n\n // Check allowlist\n const allowlistResult = checkAllowlist(commandPath, allowlist);\n if (!allowlistResult.allowed) {\n return errorEnvelope(commandPath, allowlistResult.error!, requestId);\n }\n\n // Force tool-mode flags\n const augmentedTokens = [\n ...tokens,\n '--format', 'json',\n ];\n\n // Create CLI instance\n const cli = new Cli({\n binaryName: 'carto',\n enableCapture: true,\n });\n\n // Register all commands\n for (const CommandClass of allCommands) {\n cli.register(CommandClass);\n }\n\n // Capture output to memory using simple buffers (Worker-compatible)\n let stdoutData = '';\n let stderrData = '';\n\n const stdout = {\n write(chunk: string | Uint8Array): boolean {\n stdoutData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n const stderr = {\n write(chunk: string | Uint8Array): boolean {\n stderrData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n // Create runtime and client\n const runtime = new WorkerRuntime(authToken, apiBaseUrl);\n const client = new CartoClient({\n baseUrl: apiBaseUrl,\n getAuthToken: async () => authToken,\n });\n\n // Create context matching CartoCommandContext\n // Type assertion needed because we use minimal stream stubs for Worker compatibility\n // Clipanion only uses the write() method at runtime\n const context = {\n stdin: process.stdin,\n stdout,\n stderr,\n env: {},\n colorDepth: 1,\n client,\n runtime,\n } as unknown as Parameters<typeof cli.run>[1];\n\n try {\n const exitCode = await cli.run(augmentedTokens, context);\n const output = stdoutData.trim();\n const errorOutput = stderrData.trim();\n\n if (exitCode === 0) {\n // Parse JSON output from command\n try {\n const result = output ? JSON.parse(output) : null;\n return successEnvelope(commandPath, result, requestId);\n } catch {\n // Command succeeded but output wasn't JSON (shouldn't happen in tool mode)\n return successEnvelope(commandPath, { text: output }, requestId);\n }\n } else {\n // Command failed\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message: errorOutput || output || `Command exited with code ${exitCode}`,\n }, requestId);\n }\n } catch (error) {\n // Unexpected error during execution\n const message = error instanceof Error ? error.message : String(error);\n console.error(`[carto-cli] Execution error for '${commandPath}':`, error);\n\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message,\n }, requestId);\n }\n}\n\n// Re-export for convenience\nexport { DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport type { CommandOutput } from './envelope';\n","// ABOUTME: Tokenizes command line strings for in-process CLI execution\n// ABOUTME: Handles quoted strings and shell-like argument parsing\n\n/**\n * Tokenizes a command line string, handling quoted strings.\n *\n * Examples:\n * - \"folder tree\" => ['folder', 'tree']\n * - \"--name 'My Folder'\" => ['--name', 'My Folder']\n * - '--name \"My Folder\"' => ['--name', 'My Folder']\n * - \"folder create --name 'Test's Folder'\" => handles escaped quotes\n */\nexport function tokenize(commandLine: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let inQuote: string | null = null;\n let escaped = false;\n\n for (let i = 0; i < commandLine.length; i++) {\n const char = commandLine[i];\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inQuote) {\n if (char === inQuote) {\n // Empty quoted string should still produce a token\n tokens.push(current);\n current = '';\n inQuote = null;\n } else {\n current += char;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current);\n current = '';\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n tokens.push(current);\n }\n\n return tokens;\n}\n\n/**\n * Extracts the command path from tokens (before any options).\n *\n * Examples:\n * - ['folder', 'tree', '--library', 'x'] => 'folder tree'\n * - ['item', 'search', '-q', 'hello'] => 'item search'\n */\nexport function extractCommandPath(tokens: string[]): string {\n const path: string[] = [];\n for (const token of tokens) {\n if (token.startsWith('-')) break;\n path.push(token);\n }\n return path.join(' ');\n}\n","// ABOUTME: Validates commands against an allowlist for tool-mode execution\n// ABOUTME: Prevents unauthorized command execution in Worker context\n\nexport interface AllowlistConfig {\n commands: string[]; // e.g., ['folder tree', 'item search']\n}\n\nexport interface AllowlistResult {\n allowed: boolean;\n error?: {\n code: 'COMMAND_NOT_ALLOWED';\n message: string;\n };\n}\n\n/**\n * Checks if a command matches the allowlist.\n *\n * Defensive validation:\n * - Normalizes command path (lowercase, trim)\n * - Supports prefix matching for subcommands\n */\nexport function checkAllowlist(\n commandPath: string,\n config: AllowlistConfig\n): AllowlistResult {\n const normalizedPath = commandPath.toLowerCase().trim();\n\n // Check exact match\n if (config.commands.some(cmd => cmd.toLowerCase() === normalizedPath)) {\n return { allowed: true };\n }\n\n // Check prefix match (e.g., 'folder' allows 'folder tree', 'folder create')\n if (config.commands.some(cmd => normalizedPath.startsWith(cmd.toLowerCase() + ' '))) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n error: {\n code: 'COMMAND_NOT_ALLOWED',\n message: `Command '${commandPath}' is not in the allowlist. ` +\n `Allowed commands: ${config.commands.join(', ')}`,\n },\n };\n}\n\n/**\n * Default allowlist for Worker tool mode.\n * Read-only operations by default.\n */\nexport const DEFAULT_ALLOWLIST: AllowlistConfig = {\n commands: [\n // Folder reads\n 'folder tree',\n 'folder list',\n 'folder get',\n // Item reads\n 'item search',\n 'item get',\n 'item list',\n 'item get-by-uri',\n 'item segments',\n // Edge reads\n 'edge list',\n 'edge get',\n // Share link reads\n 'share-link list',\n 'share-link analytics',\n // Librarian\n 'librarian chat',\n ],\n};\n\n/**\n * Extended allowlist including write operations.\n * Use when agent needs to modify data.\n */\nexport const WRITE_ALLOWLIST: AllowlistConfig = {\n commands: [\n ...DEFAULT_ALLOWLIST.commands,\n // Folder writes\n 'folder create',\n 'folder update',\n 'folder delete',\n 'folder move',\n 'folder restructure',\n 'folder create-tree',\n // Item writes\n 'item create',\n 'item update',\n 'item delete',\n 'item update content',\n 'item upload',\n 'item assign',\n 'item move',\n // Edge writes\n 'edge create',\n 'edge update',\n 'edge delete',\n // Share link writes\n 'share-link create',\n 'share-link delete',\n ],\n};\n","// ABOUTME: Wraps CLI command outputs in structured JSON envelopes\n// ABOUTME: Provides consistent response format for Mastra tool integration\n\nexport interface CommandError {\n code: string;\n message: string;\n}\n\nexport interface CommandOutput<T = unknown> {\n ok: boolean;\n command: string;\n result?: T;\n error?: CommandError;\n requestId?: string;\n schemaVersion: 1;\n}\n\n/**\n * Creates a successful output envelope.\n */\nexport function successEnvelope<T>(\n command: string,\n result: T,\n requestId?: string\n): CommandOutput<T> {\n return {\n ok: true,\n command,\n result,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Creates an error output envelope.\n */\nexport function errorEnvelope(\n command: string,\n error: CommandError,\n requestId?: string\n): CommandOutput<never> {\n return {\n ok: false,\n command,\n error,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Common error codes for CLI operations.\n */\nexport const ErrorCodes = {\n COMMAND_NOT_ALLOWED: 'COMMAND_NOT_ALLOWED',\n COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',\n INVALID_ARGUMENTS: 'INVALID_ARGUMENTS',\n AUTH_ERROR: 'AUTH_ERROR',\n EXECUTION_ERROR: 'EXECUTION_ERROR',\n PARSE_ERROR: 'PARSE_ERROR',\n} as const;\n","// ABOUTME: Abstracts runtime differences between CLI and Worker execution\n// ABOUTME: Provides consistent interface for auth, logging, and config\n\nexport interface CartoRuntime {\n // Authentication\n getAuthToken(): Promise<string>;\n\n // API access\n apiBaseUrl: string;\n\n // Environment flags\n isInteractive: boolean;\n isToolMode: boolean;\n\n // Logging (respects --quiet, routes to correct streams)\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\n/**\n * Worker runtime - receives auth from request context.\n * Non-interactive, always tool mode.\n */\nexport class WorkerRuntime implements CartoRuntime {\n isInteractive = false;\n isToolMode = true;\n\n constructor(\n private authToken: string,\n public apiBaseUrl: string,\n ) {}\n\n async getAuthToken(): Promise<string> {\n return this.authToken;\n }\n\n log(message: string): void {\n console.log(`[carto-cli] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[carto-cli] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[carto-cli] ${message}`);\n }\n}\n\n/**\n * CLI runtime - reads from config file or env vars.\n * Interactive when terminal attached.\n *\n * Compatible with both Bun and Node.js runtimes.\n */\nexport class CliRuntime implements CartoRuntime {\n isInteractive: boolean;\n isToolMode = false;\n\n constructor(\n private config: { apiBaseUrl: string; authToken?: string },\n ) {\n // Works in both Bun and Node.js\n this.isInteractive = process.stdout.isTTY ?? false;\n }\n\n get apiBaseUrl(): string {\n return this.config.apiBaseUrl;\n }\n\n async getAuthToken(): Promise<string> {\n if (!this.config.authToken) {\n throw new Error('Not authenticated. Run `carto auth login` first.');\n }\n return this.config.authToken;\n }\n\n log(message: string): void {\n console.log(message);\n }\n\n warn(message: string): void {\n console.warn(message);\n }\n\n error(message: string): void {\n console.error(message);\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -107,6 +107,7 @@ var WRITE_ALLOWLIST = {
107
107
  "item update content",
108
108
  "item upload",
109
109
  "item assign",
110
+ "item move",
110
111
  // Edge writes
111
112
  "edge create",
112
113
  "edge update",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runner.ts","../src/tokenizer.ts","../src/allowlist.ts","../src/envelope.ts","../src/runtime.ts"],"sourcesContent":["// ABOUTME: Executes CLI commands in-process without subprocess spawning\n// ABOUTME: Designed for Cloudflare Worker compatibility\n\nimport { Cli } from 'clipanion';\nimport { tokenize, extractCommandPath } from './tokenizer';\nimport { checkAllowlist, AllowlistConfig, DEFAULT_ALLOWLIST } from './allowlist';\nimport { successEnvelope, errorEnvelope, CommandOutput, ErrorCodes } from './envelope';\nimport { WorkerRuntime } from './runtime';\nimport { allCommands } from '@carto-knowledge/commands';\nimport { CartoClient } from '@carto-knowledge/core';\n\nexport interface RunOptions {\n /** Correlation ID for tracing */\n requestId?: string;\n\n /** Auth token for API calls */\n authToken: string;\n\n /** Base URL for Carto API */\n apiBaseUrl: string;\n\n /** Command allowlist (defaults to read-only operations) */\n allowlist?: AllowlistConfig;\n}\n\n/**\n * Executes a CLI command in-process.\n *\n * Designed for Worker runtime:\n * - No subprocess spawning\n * - Captures output to memory streams\n * - Forces JSON output and non-interactive mode\n * - Validates against allowlist\n *\n * @param commandLine - Command string, e.g., \"folder tree --library my-lib\"\n * @param options - Execution options including auth and allowlist\n * @returns Structured command output envelope\n */\nexport async function runInProcess(\n commandLine: string,\n options: RunOptions\n): Promise<CommandOutput> {\n const { requestId, authToken, apiBaseUrl, allowlist = DEFAULT_ALLOWLIST } = options;\n\n // Defensive: Validate inputs\n if (!commandLine || typeof commandLine !== 'string') {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'commandLine must be a non-empty string',\n }, requestId);\n }\n\n if (!authToken) {\n return errorEnvelope('', {\n code: ErrorCodes.AUTH_ERROR,\n message: 'authToken is required',\n }, requestId);\n }\n\n // Parse command line\n const tokens = tokenize(commandLine.trim());\n\n if (tokens.length === 0) {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'Empty command line',\n }, requestId);\n }\n\n const commandPath = extractCommandPath(tokens);\n\n // Check allowlist\n const allowlistResult = checkAllowlist(commandPath, allowlist);\n if (!allowlistResult.allowed) {\n return errorEnvelope(commandPath, allowlistResult.error!, requestId);\n }\n\n // Force tool-mode flags\n const augmentedTokens = [\n ...tokens,\n '--format', 'json',\n ];\n\n // Create CLI instance\n const cli = new Cli({\n binaryName: 'carto',\n enableCapture: true,\n });\n\n // Register all commands\n for (const CommandClass of allCommands) {\n cli.register(CommandClass);\n }\n\n // Capture output to memory using simple buffers (Worker-compatible)\n let stdoutData = '';\n let stderrData = '';\n\n const stdout = {\n write(chunk: string | Uint8Array): boolean {\n stdoutData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n const stderr = {\n write(chunk: string | Uint8Array): boolean {\n stderrData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n // Create runtime and client\n const runtime = new WorkerRuntime(authToken, apiBaseUrl);\n const client = new CartoClient({\n baseUrl: apiBaseUrl,\n getAuthToken: async () => authToken,\n });\n\n // Create context matching CartoCommandContext\n // Type assertion needed because we use minimal stream stubs for Worker compatibility\n // Clipanion only uses the write() method at runtime\n const context = {\n stdin: process.stdin,\n stdout,\n stderr,\n env: {},\n colorDepth: 1,\n client,\n runtime,\n } as unknown as Parameters<typeof cli.run>[1];\n\n try {\n const exitCode = await cli.run(augmentedTokens, context);\n const output = stdoutData.trim();\n const errorOutput = stderrData.trim();\n\n if (exitCode === 0) {\n // Parse JSON output from command\n try {\n const result = output ? JSON.parse(output) : null;\n return successEnvelope(commandPath, result, requestId);\n } catch {\n // Command succeeded but output wasn't JSON (shouldn't happen in tool mode)\n return successEnvelope(commandPath, { text: output }, requestId);\n }\n } else {\n // Command failed\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message: errorOutput || output || `Command exited with code ${exitCode}`,\n }, requestId);\n }\n } catch (error) {\n // Unexpected error during execution\n const message = error instanceof Error ? error.message : String(error);\n console.error(`[carto-cli] Execution error for '${commandPath}':`, error);\n\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message,\n }, requestId);\n }\n}\n\n// Re-export for convenience\nexport { DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport type { CommandOutput } from './envelope';\n","// ABOUTME: Tokenizes command line strings for in-process CLI execution\n// ABOUTME: Handles quoted strings and shell-like argument parsing\n\n/**\n * Tokenizes a command line string, handling quoted strings.\n *\n * Examples:\n * - \"folder tree\" => ['folder', 'tree']\n * - \"--name 'My Folder'\" => ['--name', 'My Folder']\n * - '--name \"My Folder\"' => ['--name', 'My Folder']\n * - \"folder create --name 'Test's Folder'\" => handles escaped quotes\n */\nexport function tokenize(commandLine: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let inQuote: string | null = null;\n let escaped = false;\n\n for (let i = 0; i < commandLine.length; i++) {\n const char = commandLine[i];\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inQuote) {\n if (char === inQuote) {\n // Empty quoted string should still produce a token\n tokens.push(current);\n current = '';\n inQuote = null;\n } else {\n current += char;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current);\n current = '';\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n tokens.push(current);\n }\n\n return tokens;\n}\n\n/**\n * Extracts the command path from tokens (before any options).\n *\n * Examples:\n * - ['folder', 'tree', '--library', 'x'] => 'folder tree'\n * - ['item', 'search', '-q', 'hello'] => 'item search'\n */\nexport function extractCommandPath(tokens: string[]): string {\n const path: string[] = [];\n for (const token of tokens) {\n if (token.startsWith('-')) break;\n path.push(token);\n }\n return path.join(' ');\n}\n","// ABOUTME: Validates commands against an allowlist for tool-mode execution\n// ABOUTME: Prevents unauthorized command execution in Worker context\n\nexport interface AllowlistConfig {\n commands: string[]; // e.g., ['folder tree', 'item search']\n}\n\nexport interface AllowlistResult {\n allowed: boolean;\n error?: {\n code: 'COMMAND_NOT_ALLOWED';\n message: string;\n };\n}\n\n/**\n * Checks if a command matches the allowlist.\n *\n * Defensive validation:\n * - Normalizes command path (lowercase, trim)\n * - Supports prefix matching for subcommands\n */\nexport function checkAllowlist(\n commandPath: string,\n config: AllowlistConfig\n): AllowlistResult {\n const normalizedPath = commandPath.toLowerCase().trim();\n\n // Check exact match\n if (config.commands.some(cmd => cmd.toLowerCase() === normalizedPath)) {\n return { allowed: true };\n }\n\n // Check prefix match (e.g., 'folder' allows 'folder tree', 'folder create')\n if (config.commands.some(cmd => normalizedPath.startsWith(cmd.toLowerCase() + ' '))) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n error: {\n code: 'COMMAND_NOT_ALLOWED',\n message: `Command '${commandPath}' is not in the allowlist. ` +\n `Allowed commands: ${config.commands.join(', ')}`,\n },\n };\n}\n\n/**\n * Default allowlist for Worker tool mode.\n * Read-only operations by default.\n */\nexport const DEFAULT_ALLOWLIST: AllowlistConfig = {\n commands: [\n // Folder reads\n 'folder tree',\n 'folder list',\n 'folder get',\n // Item reads\n 'item search',\n 'item get',\n 'item list',\n 'item get-by-uri',\n 'item segments',\n // Edge reads\n 'edge list',\n 'edge get',\n // Share link reads\n 'share-link list',\n 'share-link analytics',\n // Librarian\n 'librarian chat',\n ],\n};\n\n/**\n * Extended allowlist including write operations.\n * Use when agent needs to modify data.\n */\nexport const WRITE_ALLOWLIST: AllowlistConfig = {\n commands: [\n ...DEFAULT_ALLOWLIST.commands,\n // Folder writes\n 'folder create',\n 'folder update',\n 'folder delete',\n 'folder move',\n 'folder restructure',\n 'folder create-tree',\n // Item writes\n 'item create',\n 'item update',\n 'item delete',\n 'item update content',\n 'item upload',\n 'item assign',\n // Edge writes\n 'edge create',\n 'edge update',\n 'edge delete',\n // Share link writes\n 'share-link create',\n 'share-link delete',\n ],\n};\n","// ABOUTME: Wraps CLI command outputs in structured JSON envelopes\n// ABOUTME: Provides consistent response format for Mastra tool integration\n\nexport interface CommandError {\n code: string;\n message: string;\n}\n\nexport interface CommandOutput<T = unknown> {\n ok: boolean;\n command: string;\n result?: T;\n error?: CommandError;\n requestId?: string;\n schemaVersion: 1;\n}\n\n/**\n * Creates a successful output envelope.\n */\nexport function successEnvelope<T>(\n command: string,\n result: T,\n requestId?: string\n): CommandOutput<T> {\n return {\n ok: true,\n command,\n result,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Creates an error output envelope.\n */\nexport function errorEnvelope(\n command: string,\n error: CommandError,\n requestId?: string\n): CommandOutput<never> {\n return {\n ok: false,\n command,\n error,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Common error codes for CLI operations.\n */\nexport const ErrorCodes = {\n COMMAND_NOT_ALLOWED: 'COMMAND_NOT_ALLOWED',\n COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',\n INVALID_ARGUMENTS: 'INVALID_ARGUMENTS',\n AUTH_ERROR: 'AUTH_ERROR',\n EXECUTION_ERROR: 'EXECUTION_ERROR',\n PARSE_ERROR: 'PARSE_ERROR',\n} as const;\n","// ABOUTME: Abstracts runtime differences between CLI and Worker execution\n// ABOUTME: Provides consistent interface for auth, logging, and config\n\nexport interface CartoRuntime {\n // Authentication\n getAuthToken(): Promise<string>;\n\n // API access\n apiBaseUrl: string;\n\n // Environment flags\n isInteractive: boolean;\n isToolMode: boolean;\n\n // Logging (respects --quiet, routes to correct streams)\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\n/**\n * Worker runtime - receives auth from request context.\n * Non-interactive, always tool mode.\n */\nexport class WorkerRuntime implements CartoRuntime {\n isInteractive = false;\n isToolMode = true;\n\n constructor(\n private authToken: string,\n public apiBaseUrl: string,\n ) {}\n\n async getAuthToken(): Promise<string> {\n return this.authToken;\n }\n\n log(message: string): void {\n console.log(`[carto-cli] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[carto-cli] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[carto-cli] ${message}`);\n }\n}\n\n/**\n * CLI runtime - reads from config file or env vars.\n * Interactive when terminal attached.\n *\n * Compatible with both Bun and Node.js runtimes.\n */\nexport class CliRuntime implements CartoRuntime {\n isInteractive: boolean;\n isToolMode = false;\n\n constructor(\n private config: { apiBaseUrl: string; authToken?: string },\n ) {\n // Works in both Bun and Node.js\n this.isInteractive = process.stdout.isTTY ?? false;\n }\n\n get apiBaseUrl(): string {\n return this.config.apiBaseUrl;\n }\n\n async getAuthToken(): Promise<string> {\n if (!this.config.authToken) {\n throw new Error('Not authenticated. Run `carto auth login` first.');\n }\n return this.config.authToken;\n }\n\n log(message: string): void {\n console.log(message);\n }\n\n warn(message: string): void {\n console.warn(message);\n }\n\n error(message: string): void {\n console.error(message);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/runner.ts","../src/tokenizer.ts","../src/allowlist.ts","../src/envelope.ts","../src/runtime.ts"],"sourcesContent":["// ABOUTME: Executes CLI commands in-process without subprocess spawning\n// ABOUTME: Designed for Cloudflare Worker compatibility\n\nimport { Cli } from 'clipanion';\nimport { tokenize, extractCommandPath } from './tokenizer';\nimport { checkAllowlist, AllowlistConfig, DEFAULT_ALLOWLIST } from './allowlist';\nimport { successEnvelope, errorEnvelope, CommandOutput, ErrorCodes } from './envelope';\nimport { WorkerRuntime } from './runtime';\nimport { allCommands } from '@carto-knowledge/commands';\nimport { CartoClient } from '@carto-knowledge/core';\n\nexport interface RunOptions {\n /** Correlation ID for tracing */\n requestId?: string;\n\n /** Auth token for API calls */\n authToken: string;\n\n /** Base URL for Carto API */\n apiBaseUrl: string;\n\n /** Command allowlist (defaults to read-only operations) */\n allowlist?: AllowlistConfig;\n}\n\n/**\n * Executes a CLI command in-process.\n *\n * Designed for Worker runtime:\n * - No subprocess spawning\n * - Captures output to memory streams\n * - Forces JSON output and non-interactive mode\n * - Validates against allowlist\n *\n * @param commandLine - Command string, e.g., \"folder tree --library my-lib\"\n * @param options - Execution options including auth and allowlist\n * @returns Structured command output envelope\n */\nexport async function runInProcess(\n commandLine: string,\n options: RunOptions\n): Promise<CommandOutput> {\n const { requestId, authToken, apiBaseUrl, allowlist = DEFAULT_ALLOWLIST } = options;\n\n // Defensive: Validate inputs\n if (!commandLine || typeof commandLine !== 'string') {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'commandLine must be a non-empty string',\n }, requestId);\n }\n\n if (!authToken) {\n return errorEnvelope('', {\n code: ErrorCodes.AUTH_ERROR,\n message: 'authToken is required',\n }, requestId);\n }\n\n // Parse command line\n const tokens = tokenize(commandLine.trim());\n\n if (tokens.length === 0) {\n return errorEnvelope('', {\n code: ErrorCodes.INVALID_ARGUMENTS,\n message: 'Empty command line',\n }, requestId);\n }\n\n const commandPath = extractCommandPath(tokens);\n\n // Check allowlist\n const allowlistResult = checkAllowlist(commandPath, allowlist);\n if (!allowlistResult.allowed) {\n return errorEnvelope(commandPath, allowlistResult.error!, requestId);\n }\n\n // Force tool-mode flags\n const augmentedTokens = [\n ...tokens,\n '--format', 'json',\n ];\n\n // Create CLI instance\n const cli = new Cli({\n binaryName: 'carto',\n enableCapture: true,\n });\n\n // Register all commands\n for (const CommandClass of allCommands) {\n cli.register(CommandClass);\n }\n\n // Capture output to memory using simple buffers (Worker-compatible)\n let stdoutData = '';\n let stderrData = '';\n\n const stdout = {\n write(chunk: string | Uint8Array): boolean {\n stdoutData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n const stderr = {\n write(chunk: string | Uint8Array): boolean {\n stderrData += typeof chunk === 'string' ? chunk : new TextDecoder().decode(chunk);\n return true;\n },\n };\n\n // Create runtime and client\n const runtime = new WorkerRuntime(authToken, apiBaseUrl);\n const client = new CartoClient({\n baseUrl: apiBaseUrl,\n getAuthToken: async () => authToken,\n });\n\n // Create context matching CartoCommandContext\n // Type assertion needed because we use minimal stream stubs for Worker compatibility\n // Clipanion only uses the write() method at runtime\n const context = {\n stdin: process.stdin,\n stdout,\n stderr,\n env: {},\n colorDepth: 1,\n client,\n runtime,\n } as unknown as Parameters<typeof cli.run>[1];\n\n try {\n const exitCode = await cli.run(augmentedTokens, context);\n const output = stdoutData.trim();\n const errorOutput = stderrData.trim();\n\n if (exitCode === 0) {\n // Parse JSON output from command\n try {\n const result = output ? JSON.parse(output) : null;\n return successEnvelope(commandPath, result, requestId);\n } catch {\n // Command succeeded but output wasn't JSON (shouldn't happen in tool mode)\n return successEnvelope(commandPath, { text: output }, requestId);\n }\n } else {\n // Command failed\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message: errorOutput || output || `Command exited with code ${exitCode}`,\n }, requestId);\n }\n } catch (error) {\n // Unexpected error during execution\n const message = error instanceof Error ? error.message : String(error);\n console.error(`[carto-cli] Execution error for '${commandPath}':`, error);\n\n return errorEnvelope(commandPath, {\n code: ErrorCodes.EXECUTION_ERROR,\n message,\n }, requestId);\n }\n}\n\n// Re-export for convenience\nexport { DEFAULT_ALLOWLIST, WRITE_ALLOWLIST } from './allowlist';\nexport type { AllowlistConfig } from './allowlist';\nexport type { CommandOutput } from './envelope';\n","// ABOUTME: Tokenizes command line strings for in-process CLI execution\n// ABOUTME: Handles quoted strings and shell-like argument parsing\n\n/**\n * Tokenizes a command line string, handling quoted strings.\n *\n * Examples:\n * - \"folder tree\" => ['folder', 'tree']\n * - \"--name 'My Folder'\" => ['--name', 'My Folder']\n * - '--name \"My Folder\"' => ['--name', 'My Folder']\n * - \"folder create --name 'Test's Folder'\" => handles escaped quotes\n */\nexport function tokenize(commandLine: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let inQuote: string | null = null;\n let escaped = false;\n\n for (let i = 0; i < commandLine.length; i++) {\n const char = commandLine[i];\n\n if (escaped) {\n current += char;\n escaped = false;\n continue;\n }\n\n if (char === '\\\\') {\n escaped = true;\n continue;\n }\n\n if (inQuote) {\n if (char === inQuote) {\n // Empty quoted string should still produce a token\n tokens.push(current);\n current = '';\n inQuote = null;\n } else {\n current += char;\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char;\n } else if (char === ' ' || char === '\\t') {\n if (current) {\n tokens.push(current);\n current = '';\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n tokens.push(current);\n }\n\n return tokens;\n}\n\n/**\n * Extracts the command path from tokens (before any options).\n *\n * Examples:\n * - ['folder', 'tree', '--library', 'x'] => 'folder tree'\n * - ['item', 'search', '-q', 'hello'] => 'item search'\n */\nexport function extractCommandPath(tokens: string[]): string {\n const path: string[] = [];\n for (const token of tokens) {\n if (token.startsWith('-')) break;\n path.push(token);\n }\n return path.join(' ');\n}\n","// ABOUTME: Validates commands against an allowlist for tool-mode execution\n// ABOUTME: Prevents unauthorized command execution in Worker context\n\nexport interface AllowlistConfig {\n commands: string[]; // e.g., ['folder tree', 'item search']\n}\n\nexport interface AllowlistResult {\n allowed: boolean;\n error?: {\n code: 'COMMAND_NOT_ALLOWED';\n message: string;\n };\n}\n\n/**\n * Checks if a command matches the allowlist.\n *\n * Defensive validation:\n * - Normalizes command path (lowercase, trim)\n * - Supports prefix matching for subcommands\n */\nexport function checkAllowlist(\n commandPath: string,\n config: AllowlistConfig\n): AllowlistResult {\n const normalizedPath = commandPath.toLowerCase().trim();\n\n // Check exact match\n if (config.commands.some(cmd => cmd.toLowerCase() === normalizedPath)) {\n return { allowed: true };\n }\n\n // Check prefix match (e.g., 'folder' allows 'folder tree', 'folder create')\n if (config.commands.some(cmd => normalizedPath.startsWith(cmd.toLowerCase() + ' '))) {\n return { allowed: true };\n }\n\n return {\n allowed: false,\n error: {\n code: 'COMMAND_NOT_ALLOWED',\n message: `Command '${commandPath}' is not in the allowlist. ` +\n `Allowed commands: ${config.commands.join(', ')}`,\n },\n };\n}\n\n/**\n * Default allowlist for Worker tool mode.\n * Read-only operations by default.\n */\nexport const DEFAULT_ALLOWLIST: AllowlistConfig = {\n commands: [\n // Folder reads\n 'folder tree',\n 'folder list',\n 'folder get',\n // Item reads\n 'item search',\n 'item get',\n 'item list',\n 'item get-by-uri',\n 'item segments',\n // Edge reads\n 'edge list',\n 'edge get',\n // Share link reads\n 'share-link list',\n 'share-link analytics',\n // Librarian\n 'librarian chat',\n ],\n};\n\n/**\n * Extended allowlist including write operations.\n * Use when agent needs to modify data.\n */\nexport const WRITE_ALLOWLIST: AllowlistConfig = {\n commands: [\n ...DEFAULT_ALLOWLIST.commands,\n // Folder writes\n 'folder create',\n 'folder update',\n 'folder delete',\n 'folder move',\n 'folder restructure',\n 'folder create-tree',\n // Item writes\n 'item create',\n 'item update',\n 'item delete',\n 'item update content',\n 'item upload',\n 'item assign',\n 'item move',\n // Edge writes\n 'edge create',\n 'edge update',\n 'edge delete',\n // Share link writes\n 'share-link create',\n 'share-link delete',\n ],\n};\n","// ABOUTME: Wraps CLI command outputs in structured JSON envelopes\n// ABOUTME: Provides consistent response format for Mastra tool integration\n\nexport interface CommandError {\n code: string;\n message: string;\n}\n\nexport interface CommandOutput<T = unknown> {\n ok: boolean;\n command: string;\n result?: T;\n error?: CommandError;\n requestId?: string;\n schemaVersion: 1;\n}\n\n/**\n * Creates a successful output envelope.\n */\nexport function successEnvelope<T>(\n command: string,\n result: T,\n requestId?: string\n): CommandOutput<T> {\n return {\n ok: true,\n command,\n result,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Creates an error output envelope.\n */\nexport function errorEnvelope(\n command: string,\n error: CommandError,\n requestId?: string\n): CommandOutput<never> {\n return {\n ok: false,\n command,\n error,\n requestId,\n schemaVersion: 1,\n };\n}\n\n/**\n * Common error codes for CLI operations.\n */\nexport const ErrorCodes = {\n COMMAND_NOT_ALLOWED: 'COMMAND_NOT_ALLOWED',\n COMMAND_NOT_FOUND: 'COMMAND_NOT_FOUND',\n INVALID_ARGUMENTS: 'INVALID_ARGUMENTS',\n AUTH_ERROR: 'AUTH_ERROR',\n EXECUTION_ERROR: 'EXECUTION_ERROR',\n PARSE_ERROR: 'PARSE_ERROR',\n} as const;\n","// ABOUTME: Abstracts runtime differences between CLI and Worker execution\n// ABOUTME: Provides consistent interface for auth, logging, and config\n\nexport interface CartoRuntime {\n // Authentication\n getAuthToken(): Promise<string>;\n\n // API access\n apiBaseUrl: string;\n\n // Environment flags\n isInteractive: boolean;\n isToolMode: boolean;\n\n // Logging (respects --quiet, routes to correct streams)\n log(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n}\n\n/**\n * Worker runtime - receives auth from request context.\n * Non-interactive, always tool mode.\n */\nexport class WorkerRuntime implements CartoRuntime {\n isInteractive = false;\n isToolMode = true;\n\n constructor(\n private authToken: string,\n public apiBaseUrl: string,\n ) {}\n\n async getAuthToken(): Promise<string> {\n return this.authToken;\n }\n\n log(message: string): void {\n console.log(`[carto-cli] ${message}`);\n }\n\n warn(message: string): void {\n console.warn(`[carto-cli] ${message}`);\n }\n\n error(message: string): void {\n console.error(`[carto-cli] ${message}`);\n }\n}\n\n/**\n * CLI runtime - reads from config file or env vars.\n * Interactive when terminal attached.\n *\n * Compatible with both Bun and Node.js runtimes.\n */\nexport class CliRuntime implements CartoRuntime {\n isInteractive: boolean;\n isToolMode = false;\n\n constructor(\n private config: { apiBaseUrl: string; authToken?: string },\n ) {\n // Works in both Bun and Node.js\n this.isInteractive = process.stdout.isTTY ?? false;\n }\n\n get apiBaseUrl(): string {\n return this.config.apiBaseUrl;\n }\n\n async getAuthToken(): Promise<string> {\n if (!this.config.authToken) {\n throw new Error('Not authenticated. Run `carto auth login` first.');\n }\n return this.config.authToken;\n }\n\n log(message: string): void {\n console.log(message);\n }\n\n warn(message: string): void {\n console.warn(message);\n }\n\n error(message: string): void {\n console.error(message);\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carto-knowledge/runner",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -20,8 +20,8 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "clipanion": "^4.0.0-rc.4",
23
- "@carto-knowledge/core": "0.2.1",
24
- "@carto-knowledge/commands": "0.2.4"
23
+ "@carto-knowledge/commands": "0.2.5",
24
+ "@carto-knowledge/core": "0.2.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/bun": "latest",