deepline 0.0.1
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/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +745 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +750 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/index.d.mts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +332 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +299 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/auth.ts","../../src/config.ts","../../src/errors.ts","../../src/http.ts","../../src/client.ts","../../src/cli/commands/tools.ts","../../src/cli/commands/play.ts","../../src/cli/commands/enrich.ts","../../src/cli/index.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { hostname } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport { resolveConfig, baseUrlSlug, loadCliEnv, autoDetectBaseUrl, parseEnvFile } from '../../config.js';\n\nconst EXIT_OK = 0;\nconst EXIT_AUTH = 1;\nconst EXIT_SERVER = 2;\n\nfunction envFilePath(baseUrl: string): string {\n const slug = baseUrlSlug(baseUrl);\n return join(homedir(), '.local', 'deepline', slug, '.env');\n}\n\nfunction saveEnvValues(values: Record<string, string>, baseUrl: string): void {\n const filePath = envFilePath(baseUrl);\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Merge with existing values\n const existing = existsSync(filePath) ? parseEnvFile(filePath) : {};\n const merged = { ...existing, ...values };\n\n const lines = Object.entries(merged)\n .filter(([, v]) => v !== '')\n .map(([k, v]) => `${k}=${v}`);\n writeFileSync(filePath, lines.join('\\n') + '\\n', 'utf-8');\n}\n\nasync function httpJson(\n method: string,\n url: string,\n apiKey: string | null,\n body?: unknown,\n): Promise<{ status: number; data: Record<string, unknown> }> {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;\n\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n let data: Record<string, unknown>;\n try {\n data = (await response.json()) as Record<string, unknown>;\n } catch {\n data = {};\n }\n return { status: response.status, data };\n}\n\nfunction openInBrowser(url: string): void {\n const { execSync } = require('node:child_process') as typeof import('node:child_process');\n const platform = process.platform;\n try {\n if (platform === 'darwin') execSync(`open \"${url}\"`);\n else if (platform === 'win32') execSync(`start \"\" \"${url}\"`);\n else execSync(`xdg-open \"${url}\"`);\n } catch {\n // Browser open is best-effort\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function handleRegister(args: string[]): Promise<number> {\n const baseUrl = autoDetectBaseUrl().replace(/\\/$/, '');\n\n let orgName = '';\n let agentName = '';\n let noWait = false;\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--org-name' && args[i + 1]) orgName = args[++i]!;\n else if (args[i] === '--agent-name' && args[i + 1]) agentName = args[++i]!;\n else if (args[i] === '--no-wait') noWait = true;\n }\n\n if (!agentName) {\n try {\n agentName = hostname() || 'Deepline CLI (TS)';\n } catch {\n agentName = 'Deepline CLI (TS)';\n }\n }\n\n const payload: Record<string, string> = {};\n if (orgName) payload.org_name = orgName;\n if (agentName) payload.agent_name = agentName;\n\n const { status, data } = await httpJson('POST', `${baseUrl}/api/v2/auth/cli/register`, null, payload);\n\n if (status >= 400) {\n console.error(`Auth register failed (status ${status}).`);\n if (data.error) console.error(String(data.error));\n return EXIT_SERVER;\n }\n\n const claimUrl = String(data.claim_url || '');\n const claimToken = String(data.claim_token || '');\n\n if (claimToken) {\n saveEnvValues({ DEEPLINE_CLAIM_TOKEN: claimToken }, baseUrl);\n }\n\n if (claimUrl) {\n console.log(' Opening approval page in your browser.');\n console.log(` If it didn't open, cmd+click: ${claimUrl}`);\n openInBrowser(claimUrl);\n }\n\n if (data.cli_message) {\n console.log(String(data.cli_message));\n }\n\n if (noWait) return EXIT_OK;\n\n if (!claimToken) {\n console.error('Missing claim token from register response.');\n return EXIT_SERVER;\n }\n\n // Poll for claim approval\n while (true) {\n const { status: s, data: statusData } = await httpJson(\n 'POST',\n `${baseUrl}/api/v2/auth/cli/status`,\n null,\n { claim_token: claimToken, reveal: true },\n );\n\n if (s === 401 || s === 403) {\n console.log('Status: unauthorized');\n return EXIT_AUTH;\n }\n if (s >= 500 || s === 0 || s === 400) {\n await sleep(2000);\n continue;\n }\n if (s >= 400) {\n console.error(`Auth status error (status ${s}).`);\n return EXIT_SERVER;\n }\n\n const state = String(statusData.status || '').toLowerCase();\n if (state === 'claimed') {\n const apiKey = String(statusData.api_key || '');\n if (apiKey) {\n saveEnvValues({ DEEPLINE_API_KEY: apiKey, DEEPLINE_CLAIM_TOKEN: '' }, baseUrl);\n console.log('');\n console.log('DEEPLINE');\n console.log('All set! Your CLI is connected.');\n if (statusData.org_name) {\n console.log(` Signed in with organization: ${statusData.org_name}`);\n }\n return EXIT_OK;\n }\n }\n if (state === 'expired') {\n console.log('That approval link expired. Please run: deepline auth register');\n return EXIT_AUTH;\n }\n await sleep(2000);\n }\n}\n\nexport async function handleStatus(args: string[]): Promise<number> {\n const baseUrl = autoDetectBaseUrl().replace(/\\/$/, '');\n const reveal = args.includes('--reveal');\n\n // Health check\n try {\n const { status: hStatus, data: hData } = await httpJson('GET', `${baseUrl}/api/v2/health`, null);\n if (hStatus === 200) {\n console.log(`Host: ${baseUrl}`);\n console.log(`Host status: ${hData.status || 'ok'}`);\n console.log(`Host version: ${hData.version || '(unknown)'}`);\n }\n } catch {\n console.log(`Host: ${baseUrl} (unreachable)`);\n }\n\n const env = loadCliEnv(baseUrl);\n const apiKey = process.env.DEEPLINE_API_KEY?.trim() || env.DEEPLINE_API_KEY || '';\n\n if (!apiKey) {\n console.log('Status: not connected');\n console.log('Run: deepline auth register');\n return EXIT_OK;\n }\n\n const { status, data } = await httpJson('POST', `${baseUrl}/api/v2/auth/cli/status`, apiKey, {\n api_key: apiKey,\n reveal,\n });\n\n if (status === 401 || status === 403) {\n console.log('Status: unauthorized');\n console.log('Run: deepline auth register');\n return EXIT_AUTH;\n }\n if (status >= 400) {\n console.error(`Auth status error (status ${status}).`);\n return EXIT_SERVER;\n }\n\n console.log(`Status: ${data.status || '(unknown)'}`);\n console.log(`Rate limit tier: ${data.rate_limit_tier || '(unknown)'}`);\n if (data.org_name) console.log(`Workspace: ${data.org_name}`);\n if (data.org_slug) console.log(`Workspace slug: ${data.org_slug}`);\n if (data.org_id != null) console.log(`Org ID: ${data.org_id}`);\n if (data.user_id != null) console.log(`User ID: ${data.user_id}`);\n\n if (reveal) {\n const apiKeyResp = String(data.api_key || apiKey);\n if (apiKeyResp) {\n saveEnvValues({ DEEPLINE_API_KEY: apiKeyResp, DEEPLINE_CLAIM_TOKEN: '' }, baseUrl);\n console.log(`Saved API key to ${envFilePath(baseUrl)}`);\n }\n }\n\n return EXIT_OK;\n}\n\nexport async function handleAuth(args: string[]): Promise<number> {\n const subcommand = args[0];\n const subArgs = args.slice(1);\n\n switch (subcommand) {\n case 'register':\n return handleRegister(subArgs);\n case 'status':\n return handleStatus(subArgs);\n default:\n // Default to status\n return handleStatus(args);\n }\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DeeplineClientOptions, ResolvedConfig } from './types.js';\nimport { ConfigError } from './errors.js';\n\nconst PROD_URL = 'https://code.deepline.com';\nconst DEFAULT_TIMEOUT = 60_000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nfunction baseUrlSlug(baseUrl: string): string {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n return 'unknown';\n }\n const host = url.hostname || 'unknown';\n const port = url.port ? parseInt(url.port, 10) : null;\n let slug = host.replace(/[^a-zA-Z0-9]/g, '-');\n if (port && port !== 80 && port !== 443) {\n slug = `${slug}-${port}`;\n }\n return slug.toLowerCase().replace(/^-+|-+$/g, '');\n}\n\nfunction parseEnvFile(filePath: string): Record<string, string> {\n if (!existsSync(filePath)) return {};\n const env: Record<string, string> = {};\n const content = readFileSync(filePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex < 0) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Strip surrounding quotes\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n if (key && value) {\n env[key] = value;\n }\n }\n return env;\n}\n\nfunction loadCliEnv(baseUrl: string): Record<string, string> {\n const slug = baseUrlSlug(baseUrl);\n const envPath = join(homedir(), '.local', 'deepline', slug, '.env');\n return parseEnvFile(envPath);\n}\n\nfunction isLocalhost(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';\n } catch {\n return false;\n }\n}\n\nfunction autoDetectBaseUrl(): string {\n // Check env var first\n const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();\n if (envBase) return envBase;\n\n // Check if localhost:3000 is likely (dev mode)\n const localEnvPath = join(homedir(), '.local', 'deepline', 'localhost-3000', '.env');\n if (existsSync(localEnvPath)) {\n return 'http://localhost:3000';\n }\n\n return PROD_URL;\n}\n\nexport function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig {\n // Resolve base URL\n const baseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();\n\n // Load CLI env file for this host\n const cliEnv = loadCliEnv(baseUrl);\n\n // Resolve API key: option > env var > CLI env file\n const apiKey =\n options?.apiKey?.trim() ||\n process.env.DEEPLINE_API_KEY?.trim() ||\n cliEnv.DEEPLINE_API_KEY ||\n '';\n\n if (!apiKey) {\n throw new ConfigError(\n `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`,\n );\n }\n\n return {\n apiKey,\n baseUrl: baseUrl.replace(/\\/$/, ''),\n timeout: options?.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n };\n}\n\nexport { baseUrlSlug, loadCliEnv, parseEnvFile, autoDetectBaseUrl, PROD_URL };\n","export class DeeplineError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public code?: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'DeeplineError';\n }\n}\n\nexport class AuthError extends DeeplineError {\n constructor(message = 'Authentication failed. Check your DEEPLINE_API_KEY.') {\n super(message, 401, 'AUTH_ERROR');\n this.name = 'AuthError';\n }\n}\n\nexport class RateLimitError extends DeeplineError {\n public retryAfterMs: number;\n\n constructor(retryAfterMs = 5000, message?: string) {\n super(message ?? `Rate limited. Retry after ${retryAfterMs}ms.`, 429, 'RATE_LIMIT');\n this.name = 'RateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\nexport class ConfigError extends DeeplineError {\n constructor(message: string) {\n super(message, undefined, 'CONFIG_ERROR');\n this.name = 'ConfigError';\n }\n}\n","import type { ResolvedConfig } from './types.js';\nimport { AuthError, DeeplineError, RateLimitError } from './errors.js';\n\nconst SDK_VERSION = '0.1.0';\n\ninterface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async request<T = unknown>(path: string, options?: RequestOptions): Promise<T> {\n const url = `${this.config.baseUrl}${path}`;\n const method = options?.method ?? 'GET';\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,\n ...options?.headers,\n };\n\n if (options?.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 30_000);\n await sleep(backoffMs);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options?.timeout ?? this.config.timeout,\n );\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status === 401 || response.status === 403) {\n throw new AuthError();\n }\n\n if (response.status === 429) {\n const retryAfter = parseRetryAfter(response);\n lastError = new RateLimitError(retryAfter);\n if (attempt < this.config.maxRetries) continue;\n throw lastError;\n }\n\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = body;\n }\n\n if (!response.ok) {\n const msg =\n typeof parsed === 'object' && parsed && 'error' in parsed\n ? String((parsed as Record<string, unknown>).error)\n : `HTTP ${response.status}`;\n throw new DeeplineError(msg, response.status, 'API_ERROR', {\n response: parsed,\n });\n }\n\n return parsed as T;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof AuthError || error instanceof DeeplineError) {\n throw error;\n }\n if (error instanceof RateLimitError) {\n lastError = error;\n if (attempt < this.config.maxRetries) continue;\n throw error;\n }\n // Network / timeout errors\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt < this.config.maxRetries) continue;\n }\n }\n\n throw lastError ?? new DeeplineError('Request failed after retries');\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(path, { method: 'POST', body });\n }\n}\n\nfunction parseRetryAfter(response: Response): number {\n const header = response.headers.get('retry-after');\n if (header) {\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds > 0) {\n return seconds * 1000;\n }\n }\n return 5000;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { resolveConfig } from './config.js';\nimport { HttpClient } from './http.js';\nimport type { DeeplineClientOptions, ResolvedConfig, PlayRunResult, ToolDefinition } from './types.js';\n\nexport class DeeplineClient {\n private readonly http: HttpClient;\n private readonly config: ResolvedConfig;\n\n constructor(options?: DeeplineClientOptions) {\n this.config = resolveConfig(options);\n this.http = new HttpClient(this.config);\n }\n\n get baseUrl(): string {\n return this.config.baseUrl;\n }\n\n /** List available tools. */\n async listTools(): Promise<ToolDefinition[]> {\n const res = await this.http.get<{ tools: ToolDefinition[] }>('/api/v2/tools');\n return res.tools;\n }\n\n /** Execute a single tool. */\n async executeTool(toolId: string, input: Record<string, unknown>): Promise<unknown> {\n const res = await this.http.post<{ result: unknown }>(\n `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,\n { payload: input },\n );\n return res.result ?? res;\n }\n\n /**\n * Submit a play for cloud execution.\n * Returns a workflowId. Use pollPlay() to get status.\n */\n async submitPlay(code: string, csvPath: string, name?: string): Promise<{ workflowId: string }> {\n return this.http.post<{ workflowId: string }>('/api/v2/plays/run', {\n code,\n csvPath,\n name,\n });\n }\n\n /** Poll workflow status. */\n async getPlayStatus(workflowId: string): Promise<PlayStatus> {\n return this.http.get<PlayStatus>(`/api/v2/plays/run/${workflowId}`);\n }\n\n /** Cancel a running play. */\n async cancelPlay(workflowId: string): Promise<void> {\n await this.http.request(`/api/v2/plays/run/${workflowId}`, { method: 'DELETE' });\n }\n\n /**\n * Run a play end-to-end: submit, poll until done, return result.\n * onProgress is called on each poll with current status.\n */\n async runPlay(\n code: string,\n csvPath: string,\n name?: string,\n options?: {\n onProgress?: (status: PlayStatus) => void;\n pollIntervalMs?: number;\n signal?: AbortSignal;\n },\n ): Promise<PlayRunResult> {\n const { workflowId } = await this.submitPlay(code, csvPath, name);\n const pollInterval = options?.pollIntervalMs ?? 2000;\n const start = Date.now();\n\n while (true) {\n if (options?.signal?.aborted) {\n await this.cancelPlay(workflowId);\n return {\n success: false,\n workflowId,\n logs: [],\n durationMs: Date.now() - start,\n error: 'Cancelled by user',\n };\n }\n\n const status = await this.getPlayStatus(workflowId);\n options?.onProgress?.(status);\n\n const terminal = ['COMPLETED', 'FAILED', 'CANCELLED', 'TERMINATED', 'TIMED_OUT'];\n if (terminal.includes(status.temporalStatus)) {\n return {\n success: status.temporalStatus === 'COMPLETED',\n workflowId,\n result: status.result,\n logs: status.progress?.logs ?? [],\n durationMs: Date.now() - start,\n error: status.progress?.error ?? (status.temporalStatus !== 'COMPLETED' ? status.temporalStatus : undefined),\n };\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n }\n\n /** Health check. */\n async health(): Promise<{ status: string; version?: string }> {\n return this.http.get<{ status: string; version?: string }>('/api/v2/health');\n }\n}\n\nexport interface PlayStatus {\n workflowId: string;\n temporalStatus: string;\n progress?: {\n status: string;\n totalRows?: number;\n logs: string[];\n error?: string;\n };\n result?: unknown;\n}\n","import { DeeplineClient } from '../../client.js';\n\nexport async function handleTools(args: string[]): Promise<number> {\n const subcommand = args[0];\n const subArgs = args.slice(1);\n\n switch (subcommand) {\n case 'list':\n return listTools();\n case 'execute':\n case 'run':\n return executeTool(subArgs);\n default:\n return listTools();\n }\n}\n\nasync function listTools(): Promise<number> {\n const dl = new DeeplineClient();\n const tools = await dl.listTools();\n\n console.log(`${tools.length} tools available:\\n`);\n for (const tool of tools) {\n const cats = tool.categories.length ? ` [${tool.categories.join(', ')}]` : '';\n console.log(` ${tool.toolId}${cats}`);\n console.log(` ${tool.description}`);\n }\n return 0;\n}\n\nasync function executeTool(args: string[]): Promise<number> {\n const toolId = args[0];\n if (!toolId) {\n console.error('Usage: deepline tools execute <toolId> [--param key=value ...] [--json \\'{\"k\":\"v\"}\\']');\n return 1;\n }\n\n const params: Record<string, unknown> = {};\n for (let i = 1; i < args.length; i++) {\n const arg = args[i]!;\n if ((arg === '--param' || arg === '-p') && args[i + 1]) {\n const kv = args[++i]!;\n const eqIdx = kv.indexOf('=');\n if (eqIdx > 0) params[kv.slice(0, eqIdx)] = kv.slice(eqIdx + 1);\n } else if (arg === '--json' && args[i + 1]) {\n Object.assign(params, JSON.parse(args[++i]!));\n }\n }\n\n const dl = new DeeplineClient();\n const result = await dl.executeTool(toolId, params);\n console.log(JSON.stringify(result, null, 2));\n return 0;\n}\n","import { readFileSync } from 'node:fs';\nimport { basename, resolve } from 'node:path';\nimport { DeeplineClient, type PlayStatus } from '../../client.js';\n\nfunction camelToKebab(str: string): string {\n return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction extractPlayName(code: string, filePath: string): string {\n // Try to extract from function name: export default async function enrichLeads(\n const nameMatch = code.match(/export\\s+default\\s+async\\s+function\\s+(\\w+)/);\n if (nameMatch?.[1]) {\n return camelToKebab(nameMatch[1]);\n }\n // Fallback: derive from filename (enrich-leads.play.ts -> enrich-leads)\n const base = basename(filePath).replace(/\\.(play\\.)?(ts|js|mjs)$/, '');\n return base.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');\n}\n\nexport async function handlePlay(args: string[]): Promise<number> {\n const playPath = args[0];\n if (!playPath) {\n console.error('Usage: deepline play <play-file.ts> --csv <file.csv>');\n return 1;\n }\n\n let csvPath = '';\n for (let i = 1; i < args.length; i++) {\n const arg = args[i]!;\n if ((arg === '--csv' || arg === '--input' || arg === '-i') && args[i + 1]) {\n csvPath = resolve(args[++i]!);\n }\n }\n\n // Read play source code\n const absPlayPath = resolve(playPath);\n let code: string;\n try {\n code = readFileSync(absPlayPath, 'utf-8');\n } catch {\n console.error(`Cannot read play file: ${absPlayPath}`);\n return 1;\n }\n\n // Extract play name from function name or filename\n const playName = extractPlayName(code, absPlayPath);\n\n // Extract the default export function as a string\n // Play files export: `export default async function name(ctx, input) { ... }`\n // We need just the function body for eval on the server\n const fnMatch = code.match(\n /export\\s+default\\s+(async\\s+function\\s*\\w*\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*\\})/,\n );\n const playCode = fnMatch ? fnMatch[1]! : code;\n\n if (!csvPath) {\n // Try to find CSV path in play code or args\n const csvArg = args.find((a) => a.endsWith('.csv'));\n if (csvArg) csvPath = resolve(csvArg);\n }\n\n if (!csvPath) {\n console.error('CSV path required: --csv <file.csv>');\n return 1;\n }\n\n const dl = new DeeplineClient();\n\n // Set up Ctrl+C handler\n const controller = new AbortController();\n const onSigint = () => {\n console.log('\\nCancelling play...');\n controller.abort();\n };\n process.on('SIGINT', onSigint);\n\n let lastLogIndex = 0;\n\n try {\n console.log(`Submitting play: ${playPath} (${playName})`);\n console.log(`CSV: ${csvPath}`);\n console.log(`Server: ${dl.baseUrl}`);\n console.log('');\n\n const result = await dl.runPlay(playCode, csvPath, playName, {\n signal: controller.signal,\n pollIntervalMs: 1500,\n onProgress: (status: PlayStatus) => {\n // Stream new log lines\n const logs = status.progress?.logs ?? [];\n for (let i = lastLogIndex; i < logs.length; i++) {\n console.log(logs[i]);\n }\n lastLogIndex = logs.length;\n\n // Show status changes\n if (status.progress?.status) {\n process.stdout.write(\n `\\r [${status.progress.status}]${status.progress.totalRows ? ` ${status.progress.totalRows} rows` : ''}`,\n );\n }\n },\n });\n\n console.log('');\n\n if (result.success) {\n console.log(`\\nPlay completed in ${(result.durationMs / 1000).toFixed(1)}s`);\n if (result.result) {\n // Print summary, not full result dump\n const r = result.result as Record<string, unknown>;\n if (r.rows && Array.isArray(r.rows)) {\n console.log(` ${(r.rows as unknown[]).length} rows output`);\n }\n if (r.stats) {\n console.log(` Stats: ${JSON.stringify(r.stats)}`);\n }\n }\n return 0;\n } else {\n console.error(`\\nPlay failed: ${result.error}`);\n return 1;\n }\n } finally {\n process.removeListener('SIGINT', onSigint);\n }\n}\n","import { handlePlay } from './play.js';\n\n/**\n * `deepline enrich` is just an alias for `deepline play`.\n * All enrichment runs through the play execution engine.\n */\nexport async function handleEnrich(args: string[]): Promise<number> {\n console.log('Note: `enrich` runs via the play engine. Use `deepline play` directly.');\n console.log('');\n return handlePlay(args);\n}\n","#!/usr/bin/env node\n\nimport { handleAuth } from './commands/auth.js';\nimport { handleTools } from './commands/tools.js';\nimport { handleEnrich } from './commands/enrich.js';\nimport { handlePlay } from './commands/play.js';\n\nconst VERSION = '0.0.1';\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n const subArgs = args.slice(1);\n\n let exitCode = 0;\n\n try {\n switch (command) {\n case 'auth':\n exitCode = await handleAuth(subArgs);\n break;\n case 'tools':\n exitCode = await handleTools(subArgs);\n break;\n case 'enrich':\n exitCode = await handleEnrich(subArgs);\n break;\n case 'play':\n exitCode = await handlePlay(subArgs);\n break;\n case 'health': {\n const baseUrl = detectBaseUrl();\n try {\n const res = await fetch(`${baseUrl}/api/v2/health`);\n const data = await res.json();\n console.log(JSON.stringify(data, null, 2));\n } catch (error) {\n console.error(`Cannot reach ${baseUrl}: ${error instanceof Error ? error.message : error}`);\n exitCode = 1;\n }\n break;\n }\n case 'version':\n case '--version':\n case '-v':\n console.log(`deepline ${VERSION}`);\n break;\n case 'help':\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n break;\n default:\n console.error(`Unknown command: ${command}`);\n printHelp();\n exitCode = 1;\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n } else {\n console.error(`Error: ${error}`);\n }\n exitCode = 1;\n }\n\n process.exit(exitCode);\n}\n\nfunction detectBaseUrl(): string {\n if (process.env.DEEPLINE_API_BASE_URL) {\n return process.env.DEEPLINE_API_BASE_URL.replace(/\\/$/, '');\n }\n return 'https://code.deepline.com';\n}\n\nfunction printHelp(): void {\n console.log(`\ndeepline — Deepline CLI (TypeScript SDK)\n\nUsage:\n deepline <command> [options]\n\nCommands:\n auth register Register this device (opens browser for approval)\n auth status Show connection status\n tools list List available tools\n tools execute Execute a tool\n tools find Find a tool by name\n enrich Run CSV enrichment pipeline\n play Run a play file\n health Check server health\n version Show version\n\nOptions:\n --help, -h Show this help\n --version, -v Show version\n\nExamples:\n deepline auth register\n deepline tools list\n deepline tools execute apollo_searchPeople --param domain=anthropic.com\n deepline play enrich-leads.play.ts --input file=leads.csv\n`.trim());\n}\n\nmain();\n"],"mappings":"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","names":["existsSync","homedir","join","join","homedir","existsSync","resolve","sleep","resolve","resolve","readFileSync","readFileSync"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
interface DeeplineClientOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
}
|
|
7
|
+
interface ResolvedConfig {
|
|
8
|
+
apiKey: string;
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
timeout: number;
|
|
11
|
+
maxRetries: number;
|
|
12
|
+
}
|
|
13
|
+
interface ToolExecuteResult {
|
|
14
|
+
job_id: string;
|
|
15
|
+
status: string;
|
|
16
|
+
result: Record<string, unknown>;
|
|
17
|
+
error?: string;
|
|
18
|
+
credits?: number | null;
|
|
19
|
+
}
|
|
20
|
+
interface ToolDefinition {
|
|
21
|
+
toolId: string;
|
|
22
|
+
provider: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
description: string;
|
|
25
|
+
categories: string[];
|
|
26
|
+
inputSchema?: Record<string, unknown>;
|
|
27
|
+
outputSchema?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface PlayRunResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
workflowId: string;
|
|
32
|
+
result?: unknown;
|
|
33
|
+
logs: string[];
|
|
34
|
+
durationMs: number;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class DeeplineClient {
|
|
39
|
+
private readonly http;
|
|
40
|
+
private readonly config;
|
|
41
|
+
constructor(options?: DeeplineClientOptions);
|
|
42
|
+
get baseUrl(): string;
|
|
43
|
+
/** List available tools. */
|
|
44
|
+
listTools(): Promise<ToolDefinition[]>;
|
|
45
|
+
/** Execute a single tool. */
|
|
46
|
+
executeTool(toolId: string, input: Record<string, unknown>): Promise<unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* Submit a play for cloud execution.
|
|
49
|
+
* Returns a workflowId. Use pollPlay() to get status.
|
|
50
|
+
*/
|
|
51
|
+
submitPlay(code: string, csvPath: string, name?: string): Promise<{
|
|
52
|
+
workflowId: string;
|
|
53
|
+
}>;
|
|
54
|
+
/** Poll workflow status. */
|
|
55
|
+
getPlayStatus(workflowId: string): Promise<PlayStatus>;
|
|
56
|
+
/** Cancel a running play. */
|
|
57
|
+
cancelPlay(workflowId: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Run a play end-to-end: submit, poll until done, return result.
|
|
60
|
+
* onProgress is called on each poll with current status.
|
|
61
|
+
*/
|
|
62
|
+
runPlay(code: string, csvPath: string, name?: string, options?: {
|
|
63
|
+
onProgress?: (status: PlayStatus) => void;
|
|
64
|
+
pollIntervalMs?: number;
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}): Promise<PlayRunResult>;
|
|
67
|
+
/** Health check. */
|
|
68
|
+
health(): Promise<{
|
|
69
|
+
status: string;
|
|
70
|
+
version?: string;
|
|
71
|
+
}>;
|
|
72
|
+
}
|
|
73
|
+
interface PlayStatus {
|
|
74
|
+
workflowId: string;
|
|
75
|
+
temporalStatus: string;
|
|
76
|
+
progress?: {
|
|
77
|
+
status: string;
|
|
78
|
+
totalRows?: number;
|
|
79
|
+
logs: string[];
|
|
80
|
+
error?: string;
|
|
81
|
+
};
|
|
82
|
+
result?: unknown;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare class DeeplineError extends Error {
|
|
86
|
+
statusCode?: number | undefined;
|
|
87
|
+
code?: string | undefined;
|
|
88
|
+
details?: Record<string, unknown> | undefined;
|
|
89
|
+
constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: Record<string, unknown> | undefined);
|
|
90
|
+
}
|
|
91
|
+
declare class AuthError extends DeeplineError {
|
|
92
|
+
constructor(message?: string);
|
|
93
|
+
}
|
|
94
|
+
declare class RateLimitError extends DeeplineError {
|
|
95
|
+
retryAfterMs: number;
|
|
96
|
+
constructor(retryAfterMs?: number, message?: string);
|
|
97
|
+
}
|
|
98
|
+
declare class ConfigError extends DeeplineError {
|
|
99
|
+
constructor(message: string);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
declare const PROD_URL = "https://code.deepline.com";
|
|
103
|
+
declare function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig;
|
|
104
|
+
|
|
105
|
+
export { AuthError, ConfigError, DeeplineClient, type DeeplineClientOptions, DeeplineError, PROD_URL, type PlayRunResult, type PlayStatus, RateLimitError, type ResolvedConfig, type ToolDefinition, type ToolExecuteResult, resolveConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
interface DeeplineClientOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
}
|
|
7
|
+
interface ResolvedConfig {
|
|
8
|
+
apiKey: string;
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
timeout: number;
|
|
11
|
+
maxRetries: number;
|
|
12
|
+
}
|
|
13
|
+
interface ToolExecuteResult {
|
|
14
|
+
job_id: string;
|
|
15
|
+
status: string;
|
|
16
|
+
result: Record<string, unknown>;
|
|
17
|
+
error?: string;
|
|
18
|
+
credits?: number | null;
|
|
19
|
+
}
|
|
20
|
+
interface ToolDefinition {
|
|
21
|
+
toolId: string;
|
|
22
|
+
provider: string;
|
|
23
|
+
displayName: string;
|
|
24
|
+
description: string;
|
|
25
|
+
categories: string[];
|
|
26
|
+
inputSchema?: Record<string, unknown>;
|
|
27
|
+
outputSchema?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface PlayRunResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
workflowId: string;
|
|
32
|
+
result?: unknown;
|
|
33
|
+
logs: string[];
|
|
34
|
+
durationMs: number;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class DeeplineClient {
|
|
39
|
+
private readonly http;
|
|
40
|
+
private readonly config;
|
|
41
|
+
constructor(options?: DeeplineClientOptions);
|
|
42
|
+
get baseUrl(): string;
|
|
43
|
+
/** List available tools. */
|
|
44
|
+
listTools(): Promise<ToolDefinition[]>;
|
|
45
|
+
/** Execute a single tool. */
|
|
46
|
+
executeTool(toolId: string, input: Record<string, unknown>): Promise<unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* Submit a play for cloud execution.
|
|
49
|
+
* Returns a workflowId. Use pollPlay() to get status.
|
|
50
|
+
*/
|
|
51
|
+
submitPlay(code: string, csvPath: string, name?: string): Promise<{
|
|
52
|
+
workflowId: string;
|
|
53
|
+
}>;
|
|
54
|
+
/** Poll workflow status. */
|
|
55
|
+
getPlayStatus(workflowId: string): Promise<PlayStatus>;
|
|
56
|
+
/** Cancel a running play. */
|
|
57
|
+
cancelPlay(workflowId: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Run a play end-to-end: submit, poll until done, return result.
|
|
60
|
+
* onProgress is called on each poll with current status.
|
|
61
|
+
*/
|
|
62
|
+
runPlay(code: string, csvPath: string, name?: string, options?: {
|
|
63
|
+
onProgress?: (status: PlayStatus) => void;
|
|
64
|
+
pollIntervalMs?: number;
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}): Promise<PlayRunResult>;
|
|
67
|
+
/** Health check. */
|
|
68
|
+
health(): Promise<{
|
|
69
|
+
status: string;
|
|
70
|
+
version?: string;
|
|
71
|
+
}>;
|
|
72
|
+
}
|
|
73
|
+
interface PlayStatus {
|
|
74
|
+
workflowId: string;
|
|
75
|
+
temporalStatus: string;
|
|
76
|
+
progress?: {
|
|
77
|
+
status: string;
|
|
78
|
+
totalRows?: number;
|
|
79
|
+
logs: string[];
|
|
80
|
+
error?: string;
|
|
81
|
+
};
|
|
82
|
+
result?: unknown;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare class DeeplineError extends Error {
|
|
86
|
+
statusCode?: number | undefined;
|
|
87
|
+
code?: string | undefined;
|
|
88
|
+
details?: Record<string, unknown> | undefined;
|
|
89
|
+
constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: Record<string, unknown> | undefined);
|
|
90
|
+
}
|
|
91
|
+
declare class AuthError extends DeeplineError {
|
|
92
|
+
constructor(message?: string);
|
|
93
|
+
}
|
|
94
|
+
declare class RateLimitError extends DeeplineError {
|
|
95
|
+
retryAfterMs: number;
|
|
96
|
+
constructor(retryAfterMs?: number, message?: string);
|
|
97
|
+
}
|
|
98
|
+
declare class ConfigError extends DeeplineError {
|
|
99
|
+
constructor(message: string);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
declare const PROD_URL = "https://code.deepline.com";
|
|
103
|
+
declare function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig;
|
|
104
|
+
|
|
105
|
+
export { AuthError, ConfigError, DeeplineClient, type DeeplineClientOptions, DeeplineError, PROD_URL, type PlayRunResult, type PlayStatus, RateLimitError, type ResolvedConfig, type ToolDefinition, type ToolExecuteResult, resolveConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
AuthError: () => AuthError,
|
|
24
|
+
ConfigError: () => ConfigError,
|
|
25
|
+
DeeplineClient: () => DeeplineClient,
|
|
26
|
+
DeeplineError: () => DeeplineError,
|
|
27
|
+
PROD_URL: () => PROD_URL,
|
|
28
|
+
RateLimitError: () => RateLimitError,
|
|
29
|
+
resolveConfig: () => resolveConfig
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(src_exports);
|
|
32
|
+
|
|
33
|
+
// src/config.ts
|
|
34
|
+
var import_node_fs = require("fs");
|
|
35
|
+
var import_node_os = require("os");
|
|
36
|
+
var import_node_path = require("path");
|
|
37
|
+
|
|
38
|
+
// src/errors.ts
|
|
39
|
+
var DeeplineError = class extends Error {
|
|
40
|
+
constructor(message, statusCode, code, details) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.statusCode = statusCode;
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.details = details;
|
|
45
|
+
this.name = "DeeplineError";
|
|
46
|
+
}
|
|
47
|
+
statusCode;
|
|
48
|
+
code;
|
|
49
|
+
details;
|
|
50
|
+
};
|
|
51
|
+
var AuthError = class extends DeeplineError {
|
|
52
|
+
constructor(message = "Authentication failed. Check your DEEPLINE_API_KEY.") {
|
|
53
|
+
super(message, 401, "AUTH_ERROR");
|
|
54
|
+
this.name = "AuthError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var RateLimitError = class extends DeeplineError {
|
|
58
|
+
retryAfterMs;
|
|
59
|
+
constructor(retryAfterMs = 5e3, message) {
|
|
60
|
+
super(message ?? `Rate limited. Retry after ${retryAfterMs}ms.`, 429, "RATE_LIMIT");
|
|
61
|
+
this.name = "RateLimitError";
|
|
62
|
+
this.retryAfterMs = retryAfterMs;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var ConfigError = class extends DeeplineError {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message, void 0, "CONFIG_ERROR");
|
|
68
|
+
this.name = "ConfigError";
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/config.ts
|
|
73
|
+
var PROD_URL = "https://code.deepline.com";
|
|
74
|
+
var DEFAULT_TIMEOUT = 6e4;
|
|
75
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
76
|
+
function baseUrlSlug(baseUrl) {
|
|
77
|
+
let url;
|
|
78
|
+
try {
|
|
79
|
+
url = new URL(baseUrl);
|
|
80
|
+
} catch {
|
|
81
|
+
return "unknown";
|
|
82
|
+
}
|
|
83
|
+
const host = url.hostname || "unknown";
|
|
84
|
+
const port = url.port ? parseInt(url.port, 10) : null;
|
|
85
|
+
let slug = host.replace(/[^a-zA-Z0-9]/g, "-");
|
|
86
|
+
if (port && port !== 80 && port !== 443) {
|
|
87
|
+
slug = `${slug}-${port}`;
|
|
88
|
+
}
|
|
89
|
+
return slug.toLowerCase().replace(/^-+|-+$/g, "");
|
|
90
|
+
}
|
|
91
|
+
function parseEnvFile(filePath) {
|
|
92
|
+
if (!(0, import_node_fs.existsSync)(filePath)) return {};
|
|
93
|
+
const env = {};
|
|
94
|
+
const content = (0, import_node_fs.readFileSync)(filePath, "utf-8");
|
|
95
|
+
for (const line of content.split(/\r?\n/)) {
|
|
96
|
+
const trimmed = line.trim();
|
|
97
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
98
|
+
const eqIndex = trimmed.indexOf("=");
|
|
99
|
+
if (eqIndex < 0) continue;
|
|
100
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
101
|
+
let value = trimmed.slice(eqIndex + 1).trim();
|
|
102
|
+
if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
|
|
103
|
+
value = value.slice(1, -1);
|
|
104
|
+
}
|
|
105
|
+
if (key && value) {
|
|
106
|
+
env[key] = value;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return env;
|
|
110
|
+
}
|
|
111
|
+
function loadCliEnv(baseUrl) {
|
|
112
|
+
const slug = baseUrlSlug(baseUrl);
|
|
113
|
+
const envPath = (0, import_node_path.join)((0, import_node_os.homedir)(), ".local", "deepline", slug, ".env");
|
|
114
|
+
return parseEnvFile(envPath);
|
|
115
|
+
}
|
|
116
|
+
function autoDetectBaseUrl() {
|
|
117
|
+
const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();
|
|
118
|
+
if (envBase) return envBase;
|
|
119
|
+
const localEnvPath = (0, import_node_path.join)((0, import_node_os.homedir)(), ".local", "deepline", "localhost-3000", ".env");
|
|
120
|
+
if ((0, import_node_fs.existsSync)(localEnvPath)) {
|
|
121
|
+
return "http://localhost:3000";
|
|
122
|
+
}
|
|
123
|
+
return PROD_URL;
|
|
124
|
+
}
|
|
125
|
+
function resolveConfig(options) {
|
|
126
|
+
const baseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();
|
|
127
|
+
const cliEnv = loadCliEnv(baseUrl);
|
|
128
|
+
const apiKey = options?.apiKey?.trim() || process.env.DEEPLINE_API_KEY?.trim() || cliEnv.DEEPLINE_API_KEY || "";
|
|
129
|
+
if (!apiKey) {
|
|
130
|
+
throw new ConfigError(
|
|
131
|
+
`No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
apiKey,
|
|
136
|
+
baseUrl: baseUrl.replace(/\/$/, ""),
|
|
137
|
+
timeout: options?.timeout ?? DEFAULT_TIMEOUT,
|
|
138
|
+
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/http.ts
|
|
143
|
+
var SDK_VERSION = "0.1.0";
|
|
144
|
+
var HttpClient = class {
|
|
145
|
+
constructor(config) {
|
|
146
|
+
this.config = config;
|
|
147
|
+
}
|
|
148
|
+
config;
|
|
149
|
+
async request(path, options) {
|
|
150
|
+
const url = `${this.config.baseUrl}${path}`;
|
|
151
|
+
const method = options?.method ?? "GET";
|
|
152
|
+
const headers = {
|
|
153
|
+
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
154
|
+
"User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
|
|
155
|
+
...options?.headers
|
|
156
|
+
};
|
|
157
|
+
if (options?.body !== void 0) {
|
|
158
|
+
headers["Content-Type"] = "application/json";
|
|
159
|
+
}
|
|
160
|
+
let lastError = null;
|
|
161
|
+
for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
|
|
162
|
+
if (attempt > 0) {
|
|
163
|
+
const backoffMs = Math.min(1e3 * Math.pow(2, attempt - 1), 3e4);
|
|
164
|
+
await sleep(backoffMs);
|
|
165
|
+
}
|
|
166
|
+
const controller = new AbortController();
|
|
167
|
+
const timeoutId = setTimeout(
|
|
168
|
+
() => controller.abort(),
|
|
169
|
+
options?.timeout ?? this.config.timeout
|
|
170
|
+
);
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(url, {
|
|
173
|
+
method,
|
|
174
|
+
headers,
|
|
175
|
+
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
176
|
+
signal: controller.signal
|
|
177
|
+
});
|
|
178
|
+
clearTimeout(timeoutId);
|
|
179
|
+
if (response.status === 401 || response.status === 403) {
|
|
180
|
+
throw new AuthError();
|
|
181
|
+
}
|
|
182
|
+
if (response.status === 429) {
|
|
183
|
+
const retryAfter = parseRetryAfter(response);
|
|
184
|
+
lastError = new RateLimitError(retryAfter);
|
|
185
|
+
if (attempt < this.config.maxRetries) continue;
|
|
186
|
+
throw lastError;
|
|
187
|
+
}
|
|
188
|
+
const body = await response.text();
|
|
189
|
+
let parsed;
|
|
190
|
+
try {
|
|
191
|
+
parsed = JSON.parse(body);
|
|
192
|
+
} catch {
|
|
193
|
+
parsed = body;
|
|
194
|
+
}
|
|
195
|
+
if (!response.ok) {
|
|
196
|
+
const msg = typeof parsed === "object" && parsed && "error" in parsed ? String(parsed.error) : `HTTP ${response.status}`;
|
|
197
|
+
throw new DeeplineError(msg, response.status, "API_ERROR", {
|
|
198
|
+
response: parsed
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return parsed;
|
|
202
|
+
} catch (error) {
|
|
203
|
+
clearTimeout(timeoutId);
|
|
204
|
+
if (error instanceof AuthError || error instanceof DeeplineError) {
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
if (error instanceof RateLimitError) {
|
|
208
|
+
lastError = error;
|
|
209
|
+
if (attempt < this.config.maxRetries) continue;
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
212
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
213
|
+
if (attempt < this.config.maxRetries) continue;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
throw lastError ?? new DeeplineError("Request failed after retries");
|
|
217
|
+
}
|
|
218
|
+
async get(path) {
|
|
219
|
+
return this.request(path, { method: "GET" });
|
|
220
|
+
}
|
|
221
|
+
async post(path, body) {
|
|
222
|
+
return this.request(path, { method: "POST", body });
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
function parseRetryAfter(response) {
|
|
226
|
+
const header = response.headers.get("retry-after");
|
|
227
|
+
if (header) {
|
|
228
|
+
const seconds = Number(header);
|
|
229
|
+
if (Number.isFinite(seconds) && seconds > 0) {
|
|
230
|
+
return seconds * 1e3;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return 5e3;
|
|
234
|
+
}
|
|
235
|
+
function sleep(ms) {
|
|
236
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/client.ts
|
|
240
|
+
var DeeplineClient = class {
|
|
241
|
+
http;
|
|
242
|
+
config;
|
|
243
|
+
constructor(options) {
|
|
244
|
+
this.config = resolveConfig(options);
|
|
245
|
+
this.http = new HttpClient(this.config);
|
|
246
|
+
}
|
|
247
|
+
get baseUrl() {
|
|
248
|
+
return this.config.baseUrl;
|
|
249
|
+
}
|
|
250
|
+
/** List available tools. */
|
|
251
|
+
async listTools() {
|
|
252
|
+
const res = await this.http.get("/api/v2/tools");
|
|
253
|
+
return res.tools;
|
|
254
|
+
}
|
|
255
|
+
/** Execute a single tool. */
|
|
256
|
+
async executeTool(toolId, input) {
|
|
257
|
+
const res = await this.http.post(
|
|
258
|
+
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
259
|
+
{ payload: input }
|
|
260
|
+
);
|
|
261
|
+
return res.result ?? res;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Submit a play for cloud execution.
|
|
265
|
+
* Returns a workflowId. Use pollPlay() to get status.
|
|
266
|
+
*/
|
|
267
|
+
async submitPlay(code, csvPath, name) {
|
|
268
|
+
return this.http.post("/api/v2/plays/run", {
|
|
269
|
+
code,
|
|
270
|
+
csvPath,
|
|
271
|
+
name
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/** Poll workflow status. */
|
|
275
|
+
async getPlayStatus(workflowId) {
|
|
276
|
+
return this.http.get(`/api/v2/plays/run/${workflowId}`);
|
|
277
|
+
}
|
|
278
|
+
/** Cancel a running play. */
|
|
279
|
+
async cancelPlay(workflowId) {
|
|
280
|
+
await this.http.request(`/api/v2/plays/run/${workflowId}`, { method: "DELETE" });
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Run a play end-to-end: submit, poll until done, return result.
|
|
284
|
+
* onProgress is called on each poll with current status.
|
|
285
|
+
*/
|
|
286
|
+
async runPlay(code, csvPath, name, options) {
|
|
287
|
+
const { workflowId } = await this.submitPlay(code, csvPath, name);
|
|
288
|
+
const pollInterval = options?.pollIntervalMs ?? 2e3;
|
|
289
|
+
const start = Date.now();
|
|
290
|
+
while (true) {
|
|
291
|
+
if (options?.signal?.aborted) {
|
|
292
|
+
await this.cancelPlay(workflowId);
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
workflowId,
|
|
296
|
+
logs: [],
|
|
297
|
+
durationMs: Date.now() - start,
|
|
298
|
+
error: "Cancelled by user"
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
const status = await this.getPlayStatus(workflowId);
|
|
302
|
+
options?.onProgress?.(status);
|
|
303
|
+
const terminal = ["COMPLETED", "FAILED", "CANCELLED", "TERMINATED", "TIMED_OUT"];
|
|
304
|
+
if (terminal.includes(status.temporalStatus)) {
|
|
305
|
+
return {
|
|
306
|
+
success: status.temporalStatus === "COMPLETED",
|
|
307
|
+
workflowId,
|
|
308
|
+
result: status.result,
|
|
309
|
+
logs: status.progress?.logs ?? [],
|
|
310
|
+
durationMs: Date.now() - start,
|
|
311
|
+
error: status.progress?.error ?? (status.temporalStatus !== "COMPLETED" ? status.temporalStatus : void 0)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/** Health check. */
|
|
318
|
+
async health() {
|
|
319
|
+
return this.http.get("/api/v2/health");
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
323
|
+
0 && (module.exports = {
|
|
324
|
+
AuthError,
|
|
325
|
+
ConfigError,
|
|
326
|
+
DeeplineClient,
|
|
327
|
+
DeeplineError,
|
|
328
|
+
PROD_URL,
|
|
329
|
+
RateLimitError,
|
|
330
|
+
resolveConfig
|
|
331
|
+
});
|
|
332
|
+
//# sourceMappingURL=index.js.map
|