dsclaw 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/init.ts","../../src/gateway/config.ts","../../src/shared/logger.ts","../../src/shared/tracer.ts","../../src/gateway/user-session.ts","../../src/dsers/auth.ts","../../src/shared/errors.ts","../../src/shared/utils.ts","../../src/resilience/rate-limiter.ts","../../src/dsers/client.ts","../../src/dsers/config.ts","../../src/agents/core-agent.ts","../../src/shared/audit.ts","../../src/dsers/product.ts","../../src/dsers/account.ts","../../src/dsers/settings.ts","../../src/web/server.ts","../../src/channels/telegram.ts","../../src/memory/file-provider.ts","../../src/resilience/degradation.ts","../../src/gateway/gateway.ts","../../src/cli/start.ts","../../src/cli/doctor.ts"],"sourcesContent":["/**\n * DropClaw CLI entry point.\n * No subcommand → defaults to `start` (auto-opens browser).\n */\n\nimport { Command } from \"commander\";\nimport { initCommand } from \"./init.js\";\nimport { startCommand } from \"./start.js\";\nimport { doctorCommand } from \"./doctor.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"dsclaw\")\n .description(\"AI-powered dropshipping agent — chat with your DSers store.\")\n .version(\"0.1.0\");\n\nprogram.action(() => startCommand({}));\n\nprogram\n .command(\"init\")\n .description(\"Setup wizard — configure Telegram (optional)\")\n .action(initCommand);\n\nprogram\n .command(\"start\")\n .description(\"Start the DropClaw bot\")\n .option(\"-c, --config <path>\", \"Path to config file\")\n .option(\"--no-open\", \"Don't auto-open browser\")\n .action(startCommand);\n\nprogram\n .command(\"stop\")\n .description(\"Stop the DropClaw bot (PM2)\")\n .action(async () => {\n const { execSync } = await import(\"node:child_process\");\n try {\n execSync(\"pm2 stop dsclaw\", { stdio: \"inherit\" });\n } catch {\n console.log(\" Bot is not running or PM2 is not installed.\");\n }\n });\n\nprogram\n .command(\"status\")\n .description(\"Show bot status\")\n .action(async () => {\n const { execSync } = await import(\"node:child_process\");\n try {\n execSync(\"pm2 describe dsclaw\", { stdio: \"inherit\" });\n } catch {\n console.log(\" Bot is not running. Start with: dsclaw start\");\n }\n });\n\nprogram\n .command(\"doctor\")\n .description(\"Verify configuration\")\n .action(doctorCommand);\n\nprogram.parse();\n","/**\n * Optional setup wizard — for advanced configuration.\n * Web chat works with zero config; this is for adding Telegram or changing the port.\n */\n\nimport inquirer from \"inquirer\";\nimport {\n saveConfig,\n configExists,\n CONFIG_PATH,\n type DropClawConfig,\n} from \"../gateway/config.js\";\n\nexport async function initCommand(): Promise<void> {\n console.log(\"\\n DropClaw Setup (optional)\\n\");\n console.log(\" Web chat works out of the box — this is for extra settings.\\n\");\n\n if (configExists()) {\n const { overwrite } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"overwrite\",\n message: `Config already exists at ${CONFIG_PATH}. Overwrite?`,\n default: false,\n },\n ]);\n if (!overwrite) {\n console.log(\" Cancelled.\");\n return;\n }\n }\n\n const { port } = await inquirer.prompt({\n type: \"number\",\n name: \"port\",\n message: \"Web chat port (default 3000):\",\n default: 3000,\n });\n\n const { addTelegram } = await inquirer.prompt({\n type: \"confirm\",\n name: \"addTelegram\",\n message: \"Add Telegram bot?\",\n default: false,\n });\n\n const config: DropClawConfig = { port: port as number };\n\n if (addTelegram) {\n const { botToken } = await inquirer.prompt({\n type: \"password\",\n name: \"botToken\",\n message: \"Telegram Bot Token (from @BotFather):\",\n mask: \"*\",\n validate: (v: string) =>\n v.includes(\":\") ? true : \"Token format: 123456:ABC-DEF...\",\n });\n config.telegramBotToken = botToken as string;\n }\n\n saveConfig(config);\n console.log(`\\n Config saved to ${CONFIG_PATH}`);\n console.log(\" Run 'dropclaw start' to launch.\\n\");\n}\n","/**\n * Minimal configuration — defaults work out of the box.\n * Web chat starts automatically; Telegram is optional.\n */\n\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { z } from \"zod\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"config\");\n\nexport const CONFIG_DIR = join(homedir(), \".dropclaw\");\nexport const CONFIG_PATH = join(CONFIG_DIR, \"config.json\");\n\nexport const ConfigSchema = z.object({\n port: z.number().default(3000),\n telegramBotToken: z.string().optional(),\n});\n\nexport type DropClawConfig = z.infer<typeof ConfigSchema>;\n\nconst DEFAULT_CONFIG: DropClawConfig = { port: 3000 };\n\nexport function ensureConfigDir(): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n }\n}\n\nexport function loadConfig(path?: string): DropClawConfig {\n const configPath = path ?? CONFIG_PATH;\n\n if (!existsSync(configPath)) {\n log.info(\"No config file found — using defaults (web chat on port 3000)\");\n return DEFAULT_CONFIG;\n }\n\n const raw = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n\n const result = ConfigSchema.safeParse(parsed);\n if (!result.success) {\n log.warn(\"Config validation failed — using defaults\");\n return DEFAULT_CONFIG;\n }\n\n log.info(\"Configuration loaded\");\n return result.data;\n}\n\nexport function saveConfig(config: DropClawConfig): void {\n ensureConfigDir();\n writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });\n log.info({ path: CONFIG_PATH }, \"Configuration saved\");\n}\n\nexport function configExists(): boolean {\n return existsSync(CONFIG_PATH);\n}\n","/**\n * Structured logger powered by pino.\n * Automatically injects traceId from AsyncLocalStorage.\n */\n\nimport pino from \"pino\";\nimport { getTraceContext } from \"./tracer.js\";\n\nconst rootLogger = pino({\n level: process.env[\"LOG_LEVEL\"] ?? \"info\",\n transport:\n process.env[\"NODE_ENV\"] !== \"production\"\n ? { target: \"pino-pretty\", options: { colorize: true } }\n : undefined,\n mixin() {\n const ctx = getTraceContext();\n return {\n traceId: ctx.traceId,\n ...(ctx.userId ? { userId: ctx.userId } : {}),\n ...(ctx.channelId ? { channelId: ctx.channelId } : {}),\n ...(ctx.agentId ? { agentId: ctx.agentId } : {}),\n };\n },\n});\n\nexport function createLogger(module: string): pino.Logger {\n return rootLogger.child({ module });\n}\n\nexport { rootLogger as logger };\n","/**\n * Request-scoped tracing via AsyncLocalStorage.\n * Every inbound message gets a traceId that propagates\n * through agents, tools, API calls, and logs.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { nanoid } from \"nanoid\";\n\nexport interface TraceContext {\n traceId: string;\n userId?: string;\n channelId?: string;\n sessionId?: string;\n agentId?: string;\n}\n\nconst storage = new AsyncLocalStorage<TraceContext>();\n\nexport function runWithTrace<T>(\n ctx: Partial<TraceContext>,\n fn: () => T,\n): T {\n const traceId = ctx.traceId ?? nanoid(12);\n return storage.run({ traceId, ...ctx }, fn);\n}\n\nexport function getTraceContext(): TraceContext {\n return storage.getStore() ?? { traceId: nanoid(12) };\n}\n\nexport function getTraceId(): string {\n return getTraceContext().traceId;\n}\n","/**\n * User session state machine + encrypted credential storage.\n * Each Telegram user has their own session with DSers + LLM credentials.\n * Credentials are AES-256-GCM encrypted, bound to machine identity.\n */\n\nimport {\n randomBytes,\n createCipheriv,\n createDecipheriv,\n createHash,\n} from \"node:crypto\";\nimport {\n readFileSync,\n writeFileSync,\n mkdirSync,\n existsSync,\n unlinkSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { hostname, userInfo } from \"node:os\";\nimport { CONFIG_DIR } from \"./config.js\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"user-session\");\n\nconst ALG = \"aes-256-gcm\";\nconst IV_LEN = 12;\nconst TAG_LEN = 16;\nconst KEY_SEED = \"dropclaw-v1\";\nconst SESSIONS_DIR = join(CONFIG_DIR, \"sessions\");\n\nexport type SessionState =\n | \"new\"\n | \"onboard_demo\"\n | \"onboard_dsers_email\"\n | \"onboard_dsers_password\"\n | \"onboard_llm\"\n | \"ready\";\n\nexport interface UserSessionData {\n state: SessionState;\n dspiEmail?: string;\n dspiPassword?: string;\n llmProvider?: string;\n llmApiKey?: string;\n llmModel?: string;\n language?: string;\n}\n\nfunction deriveKey(): Buffer {\n let user = \"\";\n try {\n user = userInfo().username;\n } catch {\n user = process.env[\"USER\"] ?? process.env[\"USERNAME\"] ?? \"default\";\n }\n return createHash(\"sha256\")\n .update(`${KEY_SEED}:${hostname()}:${user}`)\n .digest();\n}\n\nfunction encrypt(data: string): string {\n const key = deriveKey();\n const iv = randomBytes(IV_LEN);\n const cipher = createCipheriv(ALG, key, iv, { authTagLength: TAG_LEN });\n const ct = Buffer.concat([cipher.update(data, \"utf8\"), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, ct]).toString(\"base64\");\n}\n\nfunction decrypt(encoded: string): string | null {\n try {\n const key = deriveKey();\n const buf = Buffer.from(encoded, \"base64\");\n if (buf.length < IV_LEN + TAG_LEN + 1) return null;\n const iv = buf.subarray(0, IV_LEN);\n const tag = buf.subarray(IV_LEN, IV_LEN + TAG_LEN);\n const ct = buf.subarray(IV_LEN + TAG_LEN);\n const decipher = createDecipheriv(ALG, key, iv, { authTagLength: TAG_LEN });\n decipher.setAuthTag(tag);\n return Buffer.concat([decipher.update(ct), decipher.final()]).toString(\n \"utf8\",\n );\n } catch {\n return null;\n }\n}\n\nfunction ensureSessionsDir(): void {\n if (!existsSync(SESSIONS_DIR)) {\n mkdirSync(SESSIONS_DIR, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction sessionPath(userId: string): string {\n const safe = userId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n return join(SESSIONS_DIR, `${safe}.enc`);\n}\n\nexport function loadSession(userId: string): UserSessionData {\n const p = sessionPath(userId);\n if (!existsSync(p)) {\n return { state: \"new\" };\n }\n try {\n const encrypted = readFileSync(p, \"utf-8\").trim();\n const json = decrypt(encrypted);\n if (!json) {\n log.warn({ userId }, \"Failed to decrypt session — starting fresh\");\n return { state: \"new\" };\n }\n return JSON.parse(json) as UserSessionData;\n } catch {\n return { state: \"new\" };\n }\n}\n\nexport function saveSession(userId: string, session: UserSessionData): void {\n ensureSessionsDir();\n const json = JSON.stringify(session);\n const encrypted = encrypt(json);\n writeFileSync(sessionPath(userId), encrypted, { mode: 0o600 });\n log.debug({ userId, state: session.state }, \"Session saved\");\n}\n\nexport function deleteSession(userId: string): void {\n const p = sessionPath(userId);\n if (existsSync(p)) {\n try {\n unlinkSync(p);\n } catch {\n /* ignore */\n }\n }\n}\n\nexport function isOnboarding(state: SessionState): boolean {\n return state !== \"ready\";\n}\n","/**\n * DSers authentication with session caching.\n * Uses email + password login matching the actual DSers API.\n * Ported from dsers-mcp-product with enhanced error classification.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { DSersClientConfig } from \"./config.js\";\nimport { createLogger } from \"../shared/logger.js\";\nimport { DropClawError, ErrorCategory } from \"../shared/errors.js\";\n\nconst log = createLogger(\"dsers:auth\");\nconst SESSION_TTL = 3600 * 6 * 1000;\n\ninterface SessionCache {\n session_id: string;\n state: string;\n ts: number;\n}\n\nexport class DSersAuth {\n private config: DSersClientConfig;\n private sessionId: string | null = null;\n private state: string | null = null;\n private fetchedAt = 0;\n\n constructor(config: DSersClientConfig) {\n this.config = config;\n if (config.sessionId) {\n this.sessionId = config.sessionId;\n this.state = config.sessionState ?? \"\";\n this.fetchedAt = Date.now();\n }\n }\n\n async getSession(): Promise<[string, string]> {\n if (this.sessionId && Date.now() - this.fetchedAt < SESSION_TTL) {\n return [this.sessionId, this.state ?? \"\"];\n }\n\n const cached = this.readCache();\n if (cached) {\n [this.sessionId, this.state, this.fetchedAt] = cached;\n return [this.sessionId, this.state];\n }\n\n return this.login();\n }\n\n async login(): Promise<[string, string]> {\n if (!this.config.email || !this.config.password) {\n throw new DropClawError({\n category: ErrorCategory.NEEDS_HUMAN,\n code: \"DSERS_NO_CREDENTIALS\",\n message: \"DSers email and password not configured.\",\n retryable: false,\n });\n }\n\n log.info(\"Authenticating with DSers...\");\n\n const resp = await fetch(\n `${this.config.baseUrl}/account-user-bff/v1/users/login`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n email: this.config.email,\n password: this.config.password,\n }),\n },\n );\n\n if (!resp.ok) {\n const body = await resp.text();\n throw new DropClawError({\n category:\n resp.status === 401 || resp.status === 403\n ? ErrorCategory.NEEDS_HUMAN\n : ErrorCategory.RETRYABLE,\n code: `DSERS_LOGIN_${resp.status}`,\n message: `DSers login failed (HTTP ${resp.status}): ${body.slice(0, 200)}`,\n retryable: resp.status >= 500,\n });\n }\n\n const data = (await resp.json()) as Record<string, unknown>;\n const inner = data[\"data\"] as Record<string, unknown> | undefined;\n if (!inner?.[\"sessionId\"]) {\n throw new DropClawError({\n category: ErrorCategory.NEEDS_HUMAN,\n code: \"DSERS_LOGIN_NO_SESSION\",\n message: \"DSers login succeeded but no session returned.\",\n retryable: false,\n details: { response: data },\n });\n }\n\n this.sessionId = inner[\"sessionId\"] as string;\n this.state = (inner[\"state\"] as string) ?? \"\";\n this.fetchedAt = Date.now();\n this.writeCache();\n\n log.info(\"DSers authentication successful\");\n return [this.sessionId, this.state];\n }\n\n invalidate(): void {\n this.sessionId = null;\n this.state = null;\n this.fetchedAt = 0;\n log.debug(\"Session invalidated\");\n }\n\n private readCache(): [string, string, number] | null {\n try {\n const p = this.config.sessionFile;\n if (!existsSync(p)) return null;\n const obj: SessionCache = JSON.parse(readFileSync(p, \"utf-8\"));\n if (Date.now() - obj.ts > SESSION_TTL) return null;\n return [obj.session_id, obj.state ?? \"\", obj.ts];\n } catch {\n return null;\n }\n }\n\n private writeCache(): void {\n if (this.config.sessionId) return;\n try {\n const p = this.config.sessionFile;\n mkdirSync(dirname(p), { recursive: true });\n const payload: SessionCache = {\n session_id: this.sessionId!,\n state: this.state ?? \"\",\n ts: this.fetchedAt,\n };\n writeFileSync(p, JSON.stringify(payload), { encoding: \"utf-8\", mode: 0o600 });\n try {\n chmodSync(p, 0o600);\n } catch {\n /* Windows */\n }\n } catch {\n log.warn(\"Failed to write session cache\");\n }\n }\n}\n","/**\n * Structured error classification for DropClaw.\n * Every error flowing through the system must have a category\n * so upstream layers (agents, channels) know how to react.\n */\n\nexport const ErrorCategory = {\n RETRYABLE: \"RETRYABLE\",\n NEEDS_HUMAN: \"NEEDS_HUMAN\",\n NEEDS_DATA: \"NEEDS_DATA\",\n FATAL: \"FATAL\",\n DEGRADED: \"DEGRADED\",\n} as const;\n\nexport type ErrorCategory =\n (typeof ErrorCategory)[keyof typeof ErrorCategory];\n\nexport interface StructuredError {\n category: ErrorCategory;\n code: string;\n message: string;\n retryable: boolean;\n details?: Record<string, unknown>;\n cause?: Error;\n}\n\nexport class DropClawError extends Error {\n readonly category: ErrorCategory;\n readonly code: string;\n readonly retryable: boolean;\n readonly details?: Record<string, unknown>;\n\n constructor(opts: StructuredError) {\n super(opts.message);\n this.name = \"DropClawError\";\n this.category = opts.category;\n this.code = opts.code;\n this.retryable = opts.retryable;\n this.details = opts.details;\n if (opts.cause) this.cause = opts.cause;\n }\n\n toJSON(): StructuredError {\n return {\n category: this.category,\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n details: this.details,\n };\n }\n}\n\nexport function classifyHttpError(\n status: number,\n body?: string,\n): ErrorCategory {\n if (status === 429) return ErrorCategory.RETRYABLE;\n if (status >= 500) return ErrorCategory.RETRYABLE;\n if (status === 401 || status === 403) return ErrorCategory.NEEDS_HUMAN;\n if (status === 404 || status === 422) return ErrorCategory.NEEDS_DATA;\n if (status === 400) return ErrorCategory.NEEDS_DATA;\n return ErrorCategory.FATAL;\n}\n","import { createHash } from \"node:crypto\";\n\n/**\n * Generate an idempotency key from operation parameters.\n * Uses a 5-minute time bucket so the same operation within\n * 5 minutes is considered duplicate.\n */\nexport function idempotencyKey(\n userId: string,\n action: string,\n params: Record<string, unknown>,\n): string {\n const timeBucket = Math.floor(Date.now() / (5 * 60 * 1000));\n const payload = JSON.stringify({ userId, action, params, timeBucket });\n return createHash(\"sha256\").update(payload).digest(\"hex\").slice(0, 16);\n}\n\n/**\n * Sleep for a given number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Parse Retry-After header value to milliseconds.\n * Supports both seconds (integer) and HTTP-date formats.\n */\nexport function parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const seconds = Number(value);\n if (!Number.isNaN(seconds)) return seconds * 1000;\n const date = Date.parse(value);\n if (!Number.isNaN(date)) return Math.max(0, date - Date.now());\n return null;\n}\n","/**\n * Three-layer rate limiting:\n * L1 Inbound: per-IP / per-channel flood protection\n * L2 Tenant: per-userId session serialization + debounce\n * L3 Outbound: per-service concurrency cap (DSers, LLM, mem0)\n */\n\nimport pLimit from \"p-limit\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"rate-limiter\");\n\n// --- L3: Outbound per-service concurrency limits ---\n\nexport interface OutboundLimits {\n dsers: number;\n llm: number;\n mem0: number;\n}\n\nconst DEFAULT_OUTBOUND_LIMITS: OutboundLimits = {\n dsers: 20,\n llm: 5,\n mem0: 10,\n};\n\nconst outboundLimiters = new Map<string, ReturnType<typeof pLimit>>();\n\nexport function getOutboundLimiter(\n service: keyof OutboundLimits,\n customLimits?: Partial<OutboundLimits>,\n): ReturnType<typeof pLimit> {\n if (!outboundLimiters.has(service)) {\n const limits = { ...DEFAULT_OUTBOUND_LIMITS, ...customLimits };\n const limiter = pLimit(limits[service]);\n outboundLimiters.set(service, limiter);\n log.info({ service, concurrency: limits[service] }, \"Outbound limiter created\");\n }\n return outboundLimiters.get(service)!;\n}\n\n// --- L2: Per-user message queue (serialization + debounce) ---\n\ninterface PendingMessage {\n resolve: (value: void) => void;\n timer?: ReturnType<typeof setTimeout>;\n}\n\nconst userQueues = new Map<string, Promise<void>>();\nconst debounceTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\n/**\n * Ensure messages from the same user are processed serially.\n * Returns a release function to call when processing is done.\n */\nexport async function acquireUserLock(userId: string): Promise<() => void> {\n while (userQueues.has(userId)) {\n await userQueues.get(userId);\n }\n\n let release!: () => void;\n const lock = new Promise<void>((resolve) => {\n release = () => {\n userQueues.delete(userId);\n resolve();\n };\n });\n\n userQueues.set(userId, lock);\n return release;\n}\n\n/**\n * Debounce rapid-fire messages from the same user.\n * Resolves after `delayMs` of silence.\n */\nexport function debounceUser(\n userId: string,\n delayMs = 500,\n): Promise<void> {\n return new Promise((resolve) => {\n const existing = debounceTimers.get(userId);\n if (existing) clearTimeout(existing);\n\n debounceTimers.set(\n userId,\n setTimeout(() => {\n debounceTimers.delete(userId);\n resolve();\n }, delayMs),\n );\n });\n}\n\n// --- L1: Inbound sliding window ---\n\ninterface WindowEntry {\n timestamps: number[];\n}\n\nconst inboundWindows = new Map<string, WindowEntry>();\n\n/**\n * Check if an inbound source has exceeded the rate limit.\n * @returns true if the request should be allowed, false if throttled.\n */\nexport function checkInboundLimit(\n sourceId: string,\n maxRequests = 30,\n windowMs = 60_000,\n): boolean {\n const now = Date.now();\n const entry = inboundWindows.get(sourceId) ?? { timestamps: [] };\n\n entry.timestamps = entry.timestamps.filter((t) => now - t < windowMs);\n\n if (entry.timestamps.length >= maxRequests) {\n log.warn({ sourceId, count: entry.timestamps.length }, \"Inbound rate limit hit\");\n return false;\n }\n\n entry.timestamps.push(now);\n inboundWindows.set(sourceId, entry);\n return true;\n}\n","/**\n * Enhanced DSers HTTP client with:\n * - 429 Retry-After handling\n * - 5xx exponential backoff (max 2 retries)\n * - Structured error classification\n * - traceId injection\n * - Session auto-refresh on 400 auth errors\n */\n\nimport { DSersAuth } from \"./auth.js\";\nimport type { DSersClientConfig } from \"./config.js\";\nimport { createLogger } from \"../shared/logger.js\";\nimport { getTraceId } from \"../shared/tracer.js\";\nimport {\n DropClawError,\n ErrorCategory,\n classifyHttpError,\n} from \"../shared/errors.js\";\nimport { parseRetryAfter, sleep } from \"../shared/utils.js\";\nimport { getOutboundLimiter } from \"../resilience/rate-limiter.js\";\n\nconst log = createLogger(\"dsers:client\");\n\nconst RETRYABLE_REASONS = new Set([\n \"TOKEN_NOT_FOUND\",\n \"TOKEN_EXPIRED\",\n \"UNAUTHORIZED\",\n \"INVALID_TOKEN\",\n]);\n\nconst MAX_RETRIES = 2;\n\nexport class DSersClient {\n private config: DSersClientConfig;\n private auth: DSersAuth;\n private limiter: ReturnType<typeof getOutboundLimiter>;\n\n constructor(config: DSersClientConfig) {\n this.config = config;\n this.auth = new DSersAuth(config);\n this.limiter = getOutboundLimiter(\"dsers\");\n }\n\n async request(\n method: string,\n path: string,\n opts?: {\n params?: Record<string, unknown>;\n json?: Record<string, unknown>;\n },\n attempt = 0,\n ): Promise<Record<string, unknown>> {\n return this.limiter(async () => {\n const [sessionId, state] = await this.auth.getSession();\n const traceId = getTraceId();\n\n const url = new URL(`${this.config.baseUrl}${path}`);\n if (opts?.params) {\n for (const [k, v] of Object.entries(opts.params)) {\n if (v != null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${sessionId}`,\n Cookie: `session_id=${sessionId}; state=${state}`,\n \"X-Trace-Id\": traceId,\n };\n\n log.debug({ method, path, traceId, attempt }, \"DSers API request\");\n\n const resp = await fetch(url.toString(), {\n method,\n headers,\n body: opts?.json ? JSON.stringify(opts.json) : undefined,\n });\n\n const bodyText = await resp.text();\n\n if (resp.status === 400 && attempt === 0) {\n try {\n const body = JSON.parse(bodyText) as Record<string, unknown>;\n if (RETRYABLE_REASONS.has(body[\"reason\"] as string)) {\n log.info({ reason: body[\"reason\"] }, \"Session expired, re-authenticating\");\n this.auth.invalidate();\n return this.request(method, path, opts, 1);\n }\n } catch {\n // not JSON\n }\n }\n\n if (resp.status === 429) {\n const retryAfterMs =\n parseRetryAfter(resp.headers.get(\"Retry-After\")) ?? 5000;\n if (attempt < MAX_RETRIES) {\n log.warn({ retryAfterMs, attempt }, \"Rate limited by DSers\");\n await sleep(retryAfterMs);\n return this.request(method, path, opts, attempt + 1);\n }\n }\n\n if (resp.status >= 500 && attempt < MAX_RETRIES) {\n const delay = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 500, 15000);\n log.warn({ status: resp.status, attempt }, \"DSers server error, retrying\");\n await sleep(delay);\n return this.request(method, path, opts, attempt + 1);\n }\n\n if (resp.status >= 400) {\n const category = classifyHttpError(resp.status, bodyText);\n throw new DropClawError({\n category,\n code: `DSERS_API_${resp.status}`,\n message: `DSers API ${method} ${path} returned ${resp.status}: ${bodyText.slice(0, 300)}`,\n retryable: category === ErrorCategory.RETRYABLE,\n details: { status: resp.status, path, method },\n });\n }\n\n return JSON.parse(bodyText) as Record<string, unknown>;\n });\n }\n\n async get(\n path: string,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n return this.request(\"GET\", path, { params });\n }\n\n async post(\n path: string,\n json?: Record<string, unknown>,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n return this.request(\"POST\", path, { json, params });\n }\n\n async put(\n path: string,\n json?: Record<string, unknown>,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n return this.request(\"PUT\", path, { json, params });\n }\n\n async del(\n path: string,\n params?: Record<string, unknown>,\n ): Promise<Record<string, unknown>> {\n return this.request(\"DELETE\", path, { params });\n }\n}\n","/**\n * DSers API configuration.\n * Uses email + password auth (matching actual DSers login flow).\n */\n\nimport { join } from \"node:path\";\nimport { CONFIG_DIR } from \"../gateway/config.js\";\n\nconst PROD_URL = \"https://bff-api-gw.dsers.com\";\n\nexport interface DSersClientConfig {\n baseUrl: string;\n email: string;\n password: string;\n sessionFile: string;\n sessionId?: string;\n sessionState?: string;\n}\n\nexport function createDSersConfig(\n email: string,\n password: string,\n baseUrl?: string,\n): DSersClientConfig {\n const safeEmail = email.replace(/[^a-zA-Z0-9_@.-]/g, \"_\");\n return {\n baseUrl: baseUrl ?? PROD_URL,\n email,\n password,\n sessionFile: join(CONFIG_DIR, `session-${safeEmail}.json`),\n };\n}\n","/**\n * DropClaw Core Agent — unified prototype agent using Vercel AI SDK.\n * Created per-user with their own DSers client and LLM config.\n * System prompt targets zero-technical-ability dropshipping users.\n */\n\nimport { generateText, streamText, type ModelMessage, tool as aiTool, stepCountIs } from \"ai\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { z } from \"zod\";\nimport type { AgentBase, AgentContext, AgentResponse, AgentTool } from \"./base.js\";\nimport type { DSersClient } from \"../dsers/client.js\";\nimport type { MemoryProvider } from \"../memory/provider.js\";\nimport { createLogger } from \"../shared/logger.js\";\nimport { writeAuditLog } from \"../shared/audit.js\";\nimport * as productApi from \"../dsers/product.js\";\nimport * as accountApi from \"../dsers/account.js\";\nimport * as settingsApi from \"../dsers/settings.js\";\n\nconst log = createLogger(\"agent:core\");\n\nexport interface LLMConfig {\n provider: string;\n apiKey: string;\n model: string;\n}\n\nfunction buildModel(llm: LLMConfig) {\n switch (llm.provider) {\n case \"openai\":\n return createOpenAI({ apiKey: llm.apiKey })(llm.model);\n case \"anthropic\":\n return createAnthropic({ apiKey: llm.apiKey })(llm.model);\n case \"google\":\n return createGoogleGenerativeAI({ apiKey: llm.apiKey })(llm.model);\n default:\n return createOpenAI({ apiKey: llm.apiKey })(llm.model);\n }\n}\n\nexport function getDefaultModel(provider: string): string {\n switch (provider) {\n case \"openai\": return \"gpt-4o\";\n case \"anthropic\": return \"claude-sonnet-4-20250514\";\n case \"google\": return \"gemini-2.0-flash\";\n default: return \"gpt-4o\";\n }\n}\n\nconst SYSTEM_PROMPT = `You are DropClaw, a friendly AI assistant that manages dropshipping stores through DSers.\nYour user has ZERO technical background — they are a small business owner or solo entrepreneur.\n\nCOMMUNICATION RULES:\n- Always respond in the SAME LANGUAGE the user writes in\n- Use simple, warm, conversational language — no jargon\n- When showing data (products, stores, orders), format it clearly with bullet points or numbered lists\n- Always confirm before executing write operations (push, delete, update pricing)\n- If something fails, explain what happened in plain language and suggest what to do next\n- Proactively offer helpful next steps after completing a task\n\nYOUR CAPABILITIES:\n- View connected stores and store details\n- Search and browse the import list (products from suppliers)\n- Import new products from AliExpress, Temu, or 1688\n- Push products to connected stores (Shopify, WooCommerce, etc.)\n- View products already in stores (\"My Products\")\n- Check and update pricing rules\n- View account plan and billing info\n- Check global settings and shipping configuration\n\nGUIDELINES:\n- When users describe products vaguely, search first and present options\n- For bulk operations, show a preview and ask for confirmation\n- Use simple summaries: \"You have 15 products waiting to be pushed\" instead of raw JSON\n- If the user seems confused, offer guided suggestions like \"Would you like me to show your stores first?\"`;\n\nexport class DropClawCoreAgent implements AgentBase {\n readonly id = \"dropclaw-core\";\n readonly name = \"DropClaw Core Agent\";\n\n private dsers: DSersClient;\n private memory: MemoryProvider;\n private llm: LLMConfig;\n private customTools: Map<string, AgentTool> = new Map();\n\n constructor(\n dsers: DSersClient,\n memory: MemoryProvider,\n llm: LLMConfig,\n ) {\n this.dsers = dsers;\n this.memory = memory;\n this.llm = llm;\n }\n\n registerTool(t: AgentTool): void {\n this.customTools.set(t.name, t);\n }\n\n removeTool(name: string): void {\n this.customTools.delete(name);\n }\n\n getTools(): AgentTool[] {\n return Array.from(this.customTools.values());\n }\n\n async process(\n message: string,\n context: AgentContext,\n ): Promise<AgentResponse> {\n const model = buildModel(this.llm);\n\n const memories = await this.memory\n .search(message, { userId: context.userId, limit: 5 })\n .catch(() => []);\n\n const memoryContext =\n memories.length > 0\n ? `\\n\\nRelevant memories:\\n${memories.map((m) => `- ${m.content}`).join(\"\\n\")}`\n : \"\";\n\n const messages: ModelMessage[] = [\n { role: \"system\", content: SYSTEM_PROMPT + memoryContext },\n ...context.history.map(\n (h) =>\n ({\n role: h.role as \"user\" | \"assistant\",\n content: h.content,\n }) as ModelMessage,\n ),\n { role: \"user\", content: message },\n ];\n\n const tools = this.buildAITools(context);\n\n log.info(\n { userId: context.userId, messageLen: message.length, toolCount: Object.keys(tools).length },\n \"Processing message\",\n );\n\n try {\n const result = await generateText({\n model,\n messages,\n tools,\n stopWhen: stepCountIs(5),\n });\n\n const toolCalls =\n result.steps\n ?.flatMap((step) =>\n step.toolCalls?.map((tc) => ({\n tool: tc.toolName,\n params: (\"input\" in tc ? tc.input : {}) as Record<string, unknown>,\n result: {\n success: true,\n data: step.toolResults?.find(\n (tr) => tr.toolCallId === tc.toolCallId,\n )?.output,\n },\n })),\n )\n .filter(Boolean) ?? [];\n\n if (result.text.length > 20) {\n this.memory\n .add(`User: \"${message.slice(0, 100)}\" -> ${toolCalls.length} tools used`, {\n userId: context.userId,\n category: \"pattern\",\n agentId: this.id,\n })\n .catch(() => {});\n }\n\n return {\n text: result.text,\n toolCalls: toolCalls as AgentResponse[\"toolCalls\"],\n };\n } catch (error) {\n log.error({ error, userId: context.userId }, \"Agent processing failed\");\n writeAuditLog({\n userId: context.userId,\n agentId: this.id,\n action: \"process_message\",\n target: \"llm\",\n result: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Streaming version of process() — yields text chunks for real-time display.\n * Returns textStream (async iterable) + response promise (resolves after completion).\n */\n processStream(\n message: string,\n context: AgentContext,\n ): { textStream: AsyncIterable<string>; response: Promise<AgentResponse> } {\n const model = buildModel(this.llm);\n\n const memories = this.memory\n .search(message, { userId: context.userId, limit: 5 })\n .catch(() => []);\n\n const tools = this.buildAITools(context);\n\n const self = this;\n\n const streamPromise = memories.then((mems) => {\n const memoryContext =\n mems.length > 0\n ? `\\n\\nRelevant memories:\\n${mems.map((m) => `- ${m.content}`).join(\"\\n\")}`\n : \"\";\n\n const messages: ModelMessage[] = [\n { role: \"system\", content: SYSTEM_PROMPT + memoryContext },\n ...context.history.map(\n (h) =>\n ({\n role: h.role as \"user\" | \"assistant\",\n content: h.content,\n }) as ModelMessage,\n ),\n { role: \"user\", content: message },\n ];\n\n log.info(\n { userId: context.userId, messageLen: message.length, streaming: true },\n \"Processing message (stream)\",\n );\n\n return streamText({\n model,\n messages,\n tools,\n stopWhen: stepCountIs(5),\n });\n });\n\n const textStream: AsyncIterable<string> = {\n [Symbol.asyncIterator]() {\n let innerIterator: AsyncIterator<string> | null = null;\n return {\n async next() {\n if (!innerIterator) {\n const result = await streamPromise;\n innerIterator = result.textStream[Symbol.asyncIterator]();\n }\n return innerIterator.next();\n },\n };\n },\n };\n\n const response: Promise<AgentResponse> = streamPromise.then(async (result) => {\n const text = await result.text;\n const steps = await result.steps;\n\n const toolCalls =\n steps\n ?.flatMap((step) =>\n step.toolCalls?.map((tc) => ({\n tool: tc.toolName,\n params: (\"input\" in tc ? tc.input : {}) as Record<string, unknown>,\n result: {\n success: true,\n data: step.toolResults?.find(\n (tr) => tr.toolCallId === tc.toolCallId,\n )?.output,\n },\n })),\n )\n .filter(Boolean) ?? [];\n\n if (text.length > 20) {\n self.memory\n .add(`User: \"${message.slice(0, 100)}\" -> ${toolCalls.length} tools used`, {\n userId: context.userId,\n category: \"pattern\",\n agentId: self.id,\n })\n .catch(() => {});\n }\n\n return {\n text,\n toolCalls: toolCalls as AgentResponse[\"toolCalls\"],\n };\n });\n\n return { textStream, response };\n }\n\n private buildAITools(context: AgentContext) {\n const dsers = this.dsers;\n const audit = (action: string, target: string, params?: Record<string, unknown>, result: \"pending\" | \"success\" = \"pending\") =>\n writeAuditLog({ userId: context.userId, agentId: this.id, action, target, params, result });\n\n return {\n listStores: aiTool<Record<string, never>, Record<string, unknown>>({\n description: \"List all connected stores (Shopify, WooCommerce, etc.) with their IDs and status.\",\n inputSchema: z.object({}),\n execute: async () => {\n audit(\"listStores\", \"dsers:account\");\n const result = await accountApi.listStores(dsers);\n audit(\"listStores\", \"dsers:account\", undefined, \"success\");\n return result;\n },\n }),\n\n getUserInfo: aiTool<Record<string, never>, Record<string, unknown>>({\n description: \"Get the user's DSers account info (email, name, plan).\",\n inputSchema: z.object({}),\n execute: async () => {\n audit(\"getUserInfo\", \"dsers:account\");\n const result = await accountApi.getUserInfo(dsers);\n audit(\"getUserInfo\", \"dsers:account\", undefined, \"success\");\n return result;\n },\n }),\n\n searchImportList: aiTool({\n description: \"Search the import list — products imported from suppliers but not yet pushed to stores.\",\n inputSchema: z.object({\n page: z.number().optional().describe(\"Page number (default 1)\"),\n pageSize: z.number().optional().describe(\"Items per page (default 20)\"),\n keyword: z.string().optional().describe(\"Search keyword\"),\n }),\n execute: async (input) => {\n audit(\"searchImportList\", \"dsers:product\", input as Record<string, unknown>);\n const result = await productApi.getImportList(dsers, input as Record<string, unknown>);\n audit(\"searchImportList\", \"dsers:product\", undefined, \"success\");\n return result;\n },\n }),\n\n importProduct: aiTool({\n description:\n \"Import a product from a supplier (AliExpress/Temu/1688) into the import list. \" +\n \"Needs the supplier product ID and platform (1=AliExpress, 2=Temu, 3=1688).\",\n inputSchema: z.object({\n supplyProductId: z.string().describe(\"Supplier product ID\"),\n supplyAppId: z.number().describe(\"1=AliExpress, 2=Temu, 3=1688\"),\n country: z.string().default(\"US\").describe(\"Target country\"),\n }),\n execute: async (input) => {\n audit(\"importProduct\", \"dsers:product\", input as Record<string, unknown>);\n const result = await productApi.importByProductId(dsers, input);\n audit(\"importProduct\", \"dsers:product\", undefined, \"success\");\n return result;\n },\n }),\n\n pushToStore: aiTool({\n description:\n \"Push products from import list to a connected store. ALWAYS confirm with user first.\",\n inputSchema: z.object({\n importListIds: z.array(z.string()).describe(\"Import list item IDs\"),\n storeIds: z.array(z.string()).describe(\"Target store IDs\"),\n pushStatus: z.enum([\"ACTIVE\", \"DRAFT\"]).default(\"DRAFT\"),\n }),\n execute: async (input) => {\n audit(\"pushToStore\", \"dsers:product\", input as Record<string, unknown>);\n const result = await productApi.pushToStore(dsers, input as Record<string, unknown>);\n audit(\"pushToStore\", \"dsers:product\", undefined, \"success\");\n return result;\n },\n }),\n\n getMyProducts: aiTool({\n description: \"Get products already pushed to stores. Check status, inventory, or find products to update.\",\n inputSchema: z.object({\n page: z.number().optional(),\n pageSize: z.number().optional(),\n keyword: z.string().optional(),\n storeId: z.string().optional(),\n }),\n execute: async (input) => {\n audit(\"getMyProducts\", \"dsers:product\", input as Record<string, unknown>);\n const result = await productApi.getMyProducts(dsers, input as Record<string, unknown>);\n audit(\"getMyProducts\", \"dsers:product\", undefined, \"success\");\n return result;\n },\n }),\n\n getPricingRules: aiTool({\n description: \"Get pricing rules for a store (markup, rounding, etc.).\",\n inputSchema: z.object({\n storeId: z.string().describe(\"Store ID to get pricing rules for\"),\n }),\n execute: async (input) => {\n audit(\"getPricingRules\", \"dsers:settings\", input as Record<string, unknown>);\n const result = await settingsApi.getPricingRules(dsers, input.storeId);\n audit(\"getPricingRules\", \"dsers:settings\", undefined, \"success\");\n return result;\n },\n }),\n\n getGlobalSettings: aiTool<Record<string, never>, Record<string, unknown>>({\n description: \"Get global DSers settings (notifications, sync preferences, etc.).\",\n inputSchema: z.object({}),\n execute: async () => {\n audit(\"getGlobalSettings\", \"dsers:settings\");\n const result = await settingsApi.getGlobalSettings(dsers);\n audit(\"getGlobalSettings\", \"dsers:settings\", undefined, \"success\");\n return result;\n },\n }),\n\n getCurrentPlan: aiTool<Record<string, never>, Record<string, unknown>>({\n description: \"Check the user's current DSers subscription plan and limits.\",\n inputSchema: z.object({}),\n execute: async () => {\n audit(\"getCurrentPlan\", \"dsers:settings\");\n const result = await settingsApi.getCurrentPlan(dsers);\n audit(\"getCurrentPlan\", \"dsers:settings\", undefined, \"success\");\n return result;\n },\n }),\n };\n }\n}\n","/**\n * Audit log for tracking all write operations.\n * Every action an agent takes is recorded so the user\n * can always answer \"what did the bot do?\"\n */\n\nimport { appendFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { CONFIG_DIR } from \"../gateway/config.js\";\nimport { getTraceId } from \"./tracer.js\";\n\nconst AUDIT_DIR = join(CONFIG_DIR, \"audit\");\n\nexport interface AuditEntry {\n timestamp: string;\n traceId: string;\n userId: string;\n agentId: string;\n action: string;\n target: string;\n params?: Record<string, unknown>;\n result: \"success\" | \"failed\" | \"pending\";\n error?: string;\n}\n\nfunction ensureAuditDir(): void {\n if (!existsSync(AUDIT_DIR)) {\n mkdirSync(AUDIT_DIR, { recursive: true });\n }\n}\n\nexport function writeAuditLog(entry: Omit<AuditEntry, \"timestamp\" | \"traceId\">): void {\n ensureAuditDir();\n const full: AuditEntry = {\n ...entry,\n timestamp: new Date().toISOString(),\n traceId: getTraceId(),\n };\n\n const date = full.timestamp.slice(0, 10);\n const file = join(AUDIT_DIR, `${date}.jsonl`);\n\n try {\n appendFileSync(file, JSON.stringify(full) + \"\\n\");\n } catch {\n // Audit write failure should never crash the system\n }\n}\n\nexport function auditFilePath(date: string): string {\n return join(AUDIT_DIR, `${date}.jsonl`);\n}\n","/**\n * DSers Product API — import, preview, push.\n * Core operations for the DropClaw product workflow.\n */\n\nimport type { DSersClient } from \"./client.js\";\n\nexport async function getImportList(\n client: DSersClient,\n params?: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const filtered = params\n ? Object.fromEntries(Object.entries(params).filter(([, v]) => v != null))\n : {};\n return client.get(\"/dsers-product-bff/import-list\", filtered);\n}\n\nexport async function getImportListItem(\n client: DSersClient,\n id: string,\n): Promise<Record<string, unknown>> {\n return client.get(`/dsers-product-bff/import-list/${id}`);\n}\n\nexport async function importByProductId(\n client: DSersClient,\n body: {\n supplyProductId: string;\n supplyAppId: string | number;\n country: string;\n language?: string[];\n },\n): Promise<Record<string, unknown>> {\n return client.post(\"/dsers-product-bff/import-list/product-id\", body);\n}\n\nexport async function importByProductIdBatch(\n client: DSersClient,\n body: {\n supplyProductIds: string[];\n supplyAppId: string | number;\n country: string;\n isBackError?: number;\n },\n): Promise<Record<string, unknown>> {\n return client.post(\"/dsers-product-bff/import-list/product-id-batch\", body);\n}\n\nexport async function updateImportListItem(\n client: DSersClient,\n id: string,\n updates: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n const existing = await client.get(`/dsers-product-bff/import-list/${id}`);\n const product = existing?.[\"data\"] ?? existing;\n const data =\n product !== null && typeof product === \"object\" && !Array.isArray(product)\n ? { ...(product as Record<string, unknown>), ...updates }\n : updates;\n return client.put(`/dsers-product-bff/import-list/${id}`, data);\n}\n\nexport async function pushToStore(\n client: DSersClient,\n payload: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n return client.post(\"/dsers-product-bff/import-list/push\", {\n data: payload,\n });\n}\n\nexport async function getPushStatus(\n client: DSersClient,\n eventId: string,\n): Promise<Record<string, unknown>> {\n return client.get(`/dsers-product-bff/import-list/push/${eventId}`);\n}\n\nexport async function getMyProducts(\n client: DSersClient,\n params: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-product-bff/my-product\", params);\n}\n\nexport async function getStoreShippingProfile(\n client: DSersClient,\n storeId?: string,\n): Promise<Record<string, unknown>> {\n const params = storeId != null ? { storeId } : undefined;\n return client.get(\n \"/dsers-product-bff/import-list/push/store-shipping-profile\",\n params,\n );\n}\n","/**\n * DSers Account API — stores, users, staff.\n * Adapted from dsers-mcp-product.\n */\n\nimport type { DSersClient } from \"./client.js\";\n\nexport async function listStores(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.post(\"/account-user-bff/v1/stores/user/list\");\n}\n\nexport async function getStoreDetail(\n client: DSersClient,\n storeId: string,\n): Promise<Record<string, unknown>> {\n return client.get(\"/account-user-bff/v1/stores/detail\", { storeId });\n}\n\nexport async function getUserInfo(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/account-user-bff/v1/users/info\");\n}\n\nexport async function getDefaultStore(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/account-user-bff/v1/users/default/store\");\n}\n","/**\n * DSers Settings API — pricing, shipping, billing, and plan settings.\n * Ported from dsers-mcp-product.\n */\n\nimport type { DSersClient } from \"./client.js\";\n\nexport async function getGlobalSettings(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/infra-setting-bff/setting/list\");\n}\n\nexport async function getPricingRules(\n client: DSersClient,\n storeId: string,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-settings-bff/product/pricing-rule\", { storeId });\n}\n\nexport async function updatePricingRule(\n client: DSersClient,\n rule: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n return client.put(\"/dsers-settings-bff/product/pricing-rule\", rule);\n}\n\nexport async function getAutoSyncPrice(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-settings-bff/product/auto-sync-price\");\n}\n\nexport async function getCurrentPlan(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-plan-bff/plan\");\n}\n\nexport async function getPlanLimits(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-plan-bff/limit\");\n}\n\nexport async function getShippingAddresses(\n client: DSersClient,\n page?: number,\n pageSize?: number,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-settings-bff/order/shipping-address\", {\n page,\n pageSize,\n });\n}\n\nexport async function getBillList(\n client: DSersClient,\n page?: number,\n pageSize?: number,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-pay-bff/v1/bill/list\", { page, pageSize });\n}\n\nexport async function getPaymentMethods(\n client: DSersClient,\n): Promise<Record<string, unknown>> {\n return client.get(\"/dsers-pay-bff/v1/pay/methods\");\n}\n","/**\n * Web Chat Server — HTTP + WebSocket.\n * Serves chat.html and handles real-time messaging via WebSocket.\n * Implements ChannelAdapter for gateway integration.\n * Supports streaming for Claude-like token-by-token output.\n */\n\nimport { createServer, type Server } from \"node:http\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { v4 as uuid } from \"uuid\";\nimport type {\n ChannelAdapter,\n MessageHandler,\n NormalizedMessage,\n OutboundMessage,\n ActionCard,\n} from \"../channels/adapter.js\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"channel:web\");\n\nfunction findChatHtml(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(thisDir, \"chat.html\"),\n join(thisDir, \"web\", \"chat.html\"),\n join(thisDir, \"..\", \"web\", \"chat.html\"),\n join(thisDir, \"..\", \"src\", \"web\", \"chat.html\"),\n join(thisDir, \"..\", \"..\", \"src\", \"web\", \"chat.html\"),\n ];\n\n for (const p of candidates) {\n if (existsSync(p)) {\n return readFileSync(p, \"utf-8\");\n }\n }\n\n throw new Error(\n \"chat.html not found. Looked in:\\n\" + candidates.join(\"\\n\"),\n );\n}\n\nexport class WebChatServer implements ChannelAdapter {\n readonly name = \"web\";\n private server: Server | null = null;\n private wss: WebSocketServer | null = null;\n private handler: MessageHandler | null = null;\n private connections = new Map<string, WebSocket>();\n private _connected = false;\n private port = 3000;\n\n get connected(): boolean {\n return this._connected;\n }\n\n async connect(config: Record<string, unknown>): Promise<void> {\n this.port = (config[\"port\"] as number) ?? 3000;\n\n const chatHtml = findChatHtml();\n\n this.server = createServer((req, res) => {\n if (req.url === \"/\" || req.url === \"/index.html\") {\n res.writeHead(200, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(chatHtml);\n return;\n }\n\n if (req.url === \"/health\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, clients: this.connections.size }));\n return;\n }\n\n res.writeHead(404);\n res.end(\"Not Found\");\n });\n\n this.wss = new WebSocketServer({ server: this.server, path: \"/ws\" });\n\n this.wss.on(\"connection\", (ws, req) => {\n const url = new URL(req.url ?? \"/\", `http://localhost:${this.port}`);\n let clientId = url.searchParams.get(\"userId\") || uuid();\n\n this.wsSend(ws, { type: \"session\", userId: clientId });\n this.connections.set(clientId, ws);\n log.info({ userId: clientId }, \"Web client connected\");\n\n ws.on(\"message\", async (raw) => {\n try {\n const msg = JSON.parse(raw.toString()) as Record<string, unknown>;\n if (msg[\"userId\"]) clientId = msg[\"userId\"] as string;\n this.connections.set(clientId, ws);\n\n if (!this.handler) return;\n\n const msgType = msg[\"type\"] as string;\n if (msgType === \"message\" || msgType === \"callback\") {\n const normalized: NormalizedMessage = {\n traceId: uuid(),\n channelId: \"web\",\n channelName: \"Web Chat\",\n userId: clientId,\n text: msgType === \"callback\"\n ? (msg[\"data\"] as string)\n : (msg[\"text\"] as string),\n timestamp: new Date(),\n metadata: {\n isCallback: msgType === \"callback\",\n },\n };\n await this.handler(normalized);\n }\n } catch (error) {\n log.error({ error }, \"WS message handler failed\");\n }\n });\n\n ws.on(\"close\", () => {\n this.connections.delete(clientId);\n log.debug({ userId: clientId }, \"Web client disconnected\");\n });\n\n ws.on(\"error\", (err) => {\n log.warn({ error: err.message, userId: clientId }, \"WS error\");\n });\n });\n\n return new Promise<void>((resolve, reject) => {\n this.server!.listen(this.port, () => {\n this._connected = true;\n log.info({ port: this.port }, \"Web chat server started\");\n resolve();\n });\n this.server!.on(\"error\", reject);\n });\n }\n\n async disconnect(): Promise<void> {\n for (const ws of this.connections.values()) {\n ws.close();\n }\n this.connections.clear();\n this.wss?.close();\n await new Promise<void>((resolve) => {\n if (this.server) this.server.close(() => resolve());\n else resolve();\n });\n this._connected = false;\n log.info(\"Web chat server stopped\");\n }\n\n async reconnect(): Promise<void> {\n await this.disconnect();\n await this.connect({ port: this.port });\n }\n\n onMessage(handler: MessageHandler): void {\n this.handler = handler;\n }\n\n async send(targetUserId: string, message: OutboundMessage): Promise<void> {\n if (message.card) {\n await this.sendCard(targetUserId, message.card);\n return;\n }\n if (message.text) {\n this.wsSendTo(targetUserId, { type: \"message\", text: message.text });\n }\n }\n\n async sendCard(targetUserId: string, card: ActionCard): Promise<void> {\n this.wsSendTo(targetUserId, {\n type: \"card\",\n title: card.title,\n summary: card.summary,\n actions: card.actions,\n });\n }\n\n async deleteMessage(): Promise<void> {\n // Web doesn't delete messages; use sendClearInput instead\n }\n\n // ─── Streaming Methods ─────────────────────────────────────\n\n sendStreamStart(userId: string): void {\n this.wsSendTo(userId, { type: \"stream_start\" });\n }\n\n sendStreamDelta(userId: string, delta: string): void {\n this.wsSendTo(userId, { type: \"stream_delta\", delta });\n }\n\n sendStreamEnd(userId: string): void {\n this.wsSendTo(userId, { type: \"stream_end\" });\n }\n\n // ─── Web-Specific Methods ──────────────────────────────────\n\n sendTyping(userId: string, active: boolean): void {\n this.wsSendTo(userId, { type: \"typing\", active });\n }\n\n sendClearInput(userId: string): void {\n this.wsSendTo(userId, { type: \"clear_input\" });\n }\n\n sendSetInputType(userId: string, inputType: \"text\" | \"password\"): void {\n this.wsSendTo(userId, { type: \"set_input_type\", inputType });\n }\n\n // ─── Internal ──────────────────────────────────────────────\n\n private wsSendTo(userId: string, data: Record<string, unknown>): void {\n const ws = this.connections.get(userId);\n if (ws && ws.readyState === WebSocket.OPEN) {\n this.wsSend(ws, data);\n }\n }\n\n private wsSend(ws: WebSocket, data: Record<string, unknown>): void {\n ws.send(JSON.stringify(data));\n }\n}\n","/**\n * Telegram channel adapter using grammY.\n * Normalizes messages, supports inline keyboards, auto-reconnects,\n * and can delete sensitive messages (passwords, API keys).\n */\n\nimport { Bot, type Context, InlineKeyboard } from \"grammy\";\nimport { v4 as uuid } from \"uuid\";\nimport type {\n ChannelAdapter,\n MessageHandler,\n NormalizedMessage,\n OutboundMessage,\n ActionCard,\n} from \"./adapter.js\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"channel:telegram\");\n\nexport class TelegramAdapter implements ChannelAdapter {\n readonly name = \"telegram\";\n private bot: Bot | null = null;\n private handler: MessageHandler | null = null;\n private _connected = false;\n private botToken = \"\";\n\n get connected(): boolean {\n return this._connected;\n }\n\n async connect(config: Record<string, unknown>): Promise<void> {\n this.botToken = config[\"botToken\"] as string;\n if (!this.botToken) throw new Error(\"Telegram botToken is required\");\n\n this.bot = new Bot(this.botToken);\n\n this.bot.on(\"message:text\", async (ctx) => {\n if (!this.handler) return;\n\n const normalized: NormalizedMessage = {\n traceId: uuid(),\n channelId: \"telegram\",\n channelName: \"Telegram\",\n userId: String(ctx.from.id),\n userName:\n ctx.from.username ??\n [ctx.from.first_name, ctx.from.last_name].filter(Boolean).join(\" \"),\n text: ctx.message.text,\n timestamp: new Date(ctx.message.date * 1000),\n metadata: {\n chatId: ctx.chat.id,\n messageId: ctx.message.message_id,\n },\n };\n\n try {\n await this.handler(normalized);\n } catch (error) {\n log.error({ error, userId: normalized.userId }, \"Message handler error\");\n await ctx.reply(\"Sorry, something went wrong. Please try again.\");\n }\n });\n\n this.bot.on(\"callback_query:data\", async (ctx) => {\n if (!this.handler) return;\n await ctx.answerCallbackQuery();\n\n const normalized: NormalizedMessage = {\n traceId: uuid(),\n channelId: \"telegram\",\n channelName: \"Telegram\",\n userId: String(ctx.from.id),\n userName: ctx.from.username ?? ctx.from.first_name,\n text: ctx.callbackQuery.data,\n timestamp: new Date(),\n metadata: {\n chatId: ctx.chat?.id,\n isCallback: true,\n },\n };\n\n try {\n await this.handler(normalized);\n } catch (error) {\n log.error({ error }, \"Callback handler error\");\n }\n });\n\n this.bot.catch((err) => {\n log.error({ error: err.message }, \"Bot error — reconnecting...\");\n this._connected = false;\n setTimeout(() => this.reconnect(), 5000);\n });\n\n await this.bot.init();\n log.info({ botName: this.bot.botInfo.username }, \"Telegram bot initialized\");\n\n this.bot.start({\n onStart: () => {\n this._connected = true;\n log.info(\"Telegram bot polling started\");\n },\n });\n }\n\n async disconnect(): Promise<void> {\n this.bot?.stop();\n this._connected = false;\n log.info(\"Telegram bot disconnected\");\n }\n\n async reconnect(): Promise<void> {\n log.info(\"Reconnecting Telegram bot...\");\n await this.disconnect();\n await this.connect({ botToken: this.botToken });\n }\n\n onMessage(handler: MessageHandler): void {\n this.handler = handler;\n }\n\n async send(targetUserId: string, message: OutboundMessage): Promise<void> {\n if (!this.bot) throw new Error(\"Bot not connected\");\n\n if (message.card) {\n await this.sendCard(targetUserId, message.card);\n return;\n }\n\n if (message.text) {\n await this.bot.api.sendMessage(targetUserId, message.text, {\n parse_mode: \"Markdown\",\n });\n }\n }\n\n async sendCard(targetUserId: string, card: ActionCard): Promise<void> {\n if (!this.bot) throw new Error(\"Bot not connected\");\n\n const keyboard = new InlineKeyboard();\n for (const action of card.actions) {\n keyboard.text(action.label, action.callbackData).row();\n }\n\n const text = `*${card.title}*\\n\\n${card.summary}`;\n\n await this.bot.api.sendMessage(targetUserId, text, {\n parse_mode: \"Markdown\",\n reply_markup: keyboard,\n });\n }\n\n async deleteMessage(chatId: string | number, messageId: number): Promise<void> {\n if (!this.bot) return;\n try {\n await this.bot.api.deleteMessage(chatId, messageId);\n } catch (error) {\n log.warn({ chatId, messageId, error }, \"Failed to delete message\");\n }\n }\n}\n","/**\n * Local JSON-based memory provider.\n * Stores memories as JSONL files, one per user.\n * Simple keyword-based search (no vector embeddings).\n * Replaced by mem0 in Plan C for production use.\n */\n\nimport {\n readFileSync,\n writeFileSync,\n appendFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport type { MemoryProvider, Memory, MemoryMeta, MemoryFilter } from \"./provider.js\";\nimport { CONFIG_DIR } from \"../gateway/config.js\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"memory:file\");\nconst MEMORY_DIR = join(CONFIG_DIR, \"memories\");\n\ninterface StoredMemory {\n id: string;\n content: string;\n metadata: MemoryMeta;\n createdAt: string;\n updatedAt: string;\n}\n\nexport class FileMemoryProvider implements MemoryProvider {\n readonly name = \"file\";\n readonly degraded = false;\n\n constructor() {\n if (!existsSync(MEMORY_DIR)) {\n mkdirSync(MEMORY_DIR, { recursive: true });\n }\n }\n\n async add(content: string, metadata: MemoryMeta): Promise<string> {\n const id = randomUUID();\n const now = new Date().toISOString();\n const entry: StoredMemory = {\n id,\n content,\n metadata,\n createdAt: now,\n updatedAt: now,\n };\n\n const file = this.userFile(metadata.userId);\n appendFileSync(file, JSON.stringify(entry) + \"\\n\");\n log.debug({ id, userId: metadata.userId }, \"Memory added\");\n return id;\n }\n\n async search(query: string, filters: MemoryFilter): Promise<Memory[]> {\n const all = await this.getAll(filters);\n const keywords = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((w) => w.length > 2);\n\n if (keywords.length === 0) {\n return all.slice(0, filters.limit ?? 10);\n }\n\n const scored = all\n .map((m) => {\n const text = m.content.toLowerCase();\n const matchCount = keywords.filter((k) => text.includes(k)).length;\n return { memory: m, score: matchCount / keywords.length };\n })\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, filters.limit ?? 10);\n\n return scored.map((s) => ({ ...s.memory, score: s.score }));\n }\n\n async getAll(filters: MemoryFilter): Promise<Memory[]> {\n const files = filters.userId\n ? [this.userFile(filters.userId)]\n : readdirSync(MEMORY_DIR)\n .filter((f) => f.endsWith(\".jsonl\"))\n .map((f) => join(MEMORY_DIR, f));\n\n const results: Memory[] = [];\n\n for (const file of files) {\n if (!existsSync(file)) continue;\n\n const lines = readFileSync(file, \"utf-8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const stored: StoredMemory = JSON.parse(line);\n\n if (filters.category && stored.metadata.category !== filters.category) continue;\n if (\n filters.sessionId &&\n stored.metadata.sessionId !== filters.sessionId\n ) continue;\n if (\n filters.tags &&\n filters.tags.length > 0 &&\n !filters.tags.some((t) => stored.metadata.tags?.includes(t))\n ) continue;\n\n results.push({\n id: stored.id,\n content: stored.content,\n metadata: stored.metadata,\n createdAt: new Date(stored.createdAt),\n updatedAt: new Date(stored.updatedAt),\n });\n } catch {\n // Skip malformed lines\n }\n }\n }\n\n return results.slice(0, filters.limit ?? 100);\n }\n\n async update(id: string, content: string): Promise<void> {\n const files = readdirSync(MEMORY_DIR)\n .filter((f) => f.endsWith(\".jsonl\"))\n .map((f) => join(MEMORY_DIR, f));\n\n for (const file of files) {\n if (!existsSync(file)) continue;\n const lines = readFileSync(file, \"utf-8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n const updated = lines.map((line) => {\n try {\n const stored: StoredMemory = JSON.parse(line);\n if (stored.id === id) {\n stored.content = content;\n stored.updatedAt = new Date().toISOString();\n }\n return JSON.stringify(stored);\n } catch {\n return line;\n }\n });\n\n writeFileSync(file, updated.join(\"\\n\") + \"\\n\");\n }\n }\n\n async delete(id: string): Promise<void> {\n const files = readdirSync(MEMORY_DIR)\n .filter((f) => f.endsWith(\".jsonl\"))\n .map((f) => join(MEMORY_DIR, f));\n\n for (const file of files) {\n if (!existsSync(file)) continue;\n const lines = readFileSync(file, \"utf-8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n const filtered = lines.filter((line) => {\n try {\n const stored: StoredMemory = JSON.parse(line);\n return stored.id !== id;\n } catch {\n return true;\n }\n });\n\n writeFileSync(file, filtered.join(\"\\n\") + (filtered.length > 0 ? \"\\n\" : \"\"));\n }\n }\n\n private userFile(userId: string): string {\n const safe = userId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n return join(MEMORY_DIR, `${safe}.jsonl`);\n }\n}\n","/**\n * Degradation strategies for when external services are unavailable.\n * Each service has a defined fallback path.\n */\n\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"degradation\");\n\nexport type ServiceName = \"dsers\" | \"llm\" | \"mem0\";\n\nexport interface DegradationState {\n service: ServiceName;\n degraded: boolean;\n reason?: string;\n since?: Date;\n fallbackActive: boolean;\n}\n\nconst states = new Map<ServiceName, DegradationState>();\n\nexport function markDegraded(\n service: ServiceName,\n reason: string,\n): void {\n states.set(service, {\n service,\n degraded: true,\n reason,\n since: new Date(),\n fallbackActive: true,\n });\n log.warn({ service, reason }, \"Service marked as degraded\");\n}\n\nexport function markRecovered(service: ServiceName): void {\n const prev = states.get(service);\n if (prev?.degraded) {\n log.info(\n { service, degradedSince: prev.since },\n \"Service recovered\",\n );\n }\n states.set(service, {\n service,\n degraded: false,\n fallbackActive: false,\n });\n}\n\nexport function isDegraded(service: ServiceName): boolean {\n return states.get(service)?.degraded ?? false;\n}\n\nexport function getDegradationStatus(): DegradationState[] {\n return [...states.values()];\n}\n\n/**\n * Produce a user-friendly degradation message for channel output.\n */\nexport function degradationMessage(service: ServiceName): string {\n switch (service) {\n case \"dsers\":\n return \"DSers service is temporarily unavailable. Your request has been queued and will be processed when the service recovers.\";\n case \"llm\":\n return \"AI service is experiencing issues. Using simplified responses until it recovers.\";\n case \"mem0\":\n return \"Memory service is temporarily offline. I can still help but won't remember preferences from this conversation.\";\n }\n}\n","/**\n * DropClaw Gateway — central orchestrator.\n *\n * Flow:\n * 1. User opens web chat (or sends Telegram message)\n * 2. Gateway loads user session (encrypted on disk)\n * 3. If not \"ready\": handle onboarding conversation (no LLM needed)\n * 4. If \"ready\": route to AI agent with streaming (web) or batch (Telegram)\n *\n * Web chat is the default channel (zero config).\n * Telegram is optional (requires bot token in config).\n */\n\nimport type { DropClawConfig } from \"./config.js\";\nimport {\n loadSession,\n saveSession,\n isOnboarding,\n type UserSessionData,\n} from \"./user-session.js\";\nimport { DSersClient } from \"../dsers/client.js\";\nimport { createDSersConfig } from \"../dsers/config.js\";\nimport { DropClawCoreAgent, getDefaultModel, type LLMConfig } from \"../agents/core-agent.js\";\nimport { WebChatServer } from \"../web/server.js\";\nimport { TelegramAdapter } from \"../channels/telegram.js\";\nimport { FileMemoryProvider } from \"../memory/file-provider.js\";\nimport type { ChannelAdapter, NormalizedMessage } from \"../channels/adapter.js\";\nimport type { MemoryProvider } from \"../memory/provider.js\";\nimport type { AgentMessage } from \"../agents/base.js\";\nimport { createLogger } from \"../shared/logger.js\";\nimport { runWithTrace } from \"../shared/tracer.js\";\nimport { writeAuditLog } from \"../shared/audit.js\";\nimport { checkInboundLimit, acquireUserLock, debounceUser } from \"../resilience/rate-limiter.js\";\nimport { isDegraded, degradationMessage } from \"../resilience/degradation.js\";\n\nconst log = createLogger(\"gateway\");\n\nconst sessionHistories = new Map<string, AgentMessage[]>();\nconst MAX_HISTORY = 20;\n\nexport class DropClawGateway {\n private config: DropClawConfig;\n private channels: ChannelAdapter[] = [];\n private webChannel: WebChatServer | null = null;\n private memory: MemoryProvider;\n private agents = new Map<string, DropClawCoreAgent>();\n private dsersClients = new Map<string, DSersClient>();\n private running = false;\n\n constructor(config: DropClawConfig) {\n this.config = config;\n this.memory = new FileMemoryProvider();\n }\n\n async start(): Promise<void> {\n log.info(\"Starting DropClaw Gateway...\");\n\n const web = new WebChatServer();\n web.onMessage((msg) => this.handleMessage(web, msg));\n await web.connect({ port: this.config.port });\n this.webChannel = web;\n this.channels.push(web);\n log.info({ port: this.config.port }, \"Web chat channel connected\");\n\n if (this.config.telegramBotToken) {\n try {\n const tg = new TelegramAdapter();\n tg.onMessage((msg) => this.handleMessage(tg, msg));\n await tg.connect({ botToken: this.config.telegramBotToken });\n this.channels.push(tg);\n log.info(\"Telegram channel connected\");\n } catch (error) {\n log.warn({ error }, \"Telegram failed to connect — web chat still available\");\n }\n }\n\n this.running = true;\n log.info(\"DropClaw Gateway started\");\n }\n\n private async handleMessage(\n channel: ChannelAdapter,\n message: NormalizedMessage,\n ): Promise<void> {\n await runWithTrace(\n {\n traceId: message.traceId,\n userId: message.userId,\n channelId: message.channelId,\n },\n async () => {\n const userId = message.userId;\n\n if (!checkInboundLimit(userId)) {\n log.warn({ userId }, \"Rate limit exceeded\");\n await channel.send(userId, { text: \"Too many messages. Please wait a moment.\" });\n return;\n }\n\n await debounceUser(userId);\n const release = await acquireUserLock(userId);\n try {\n const session = loadSession(userId);\n\n if (isOnboarding(session.state)) {\n await this.handleOnboarding(channel, message, session);\n } else {\n if (isDegraded(\"llm\")) {\n await channel.send(userId, { text: degradationMessage(\"llm\") });\n return;\n }\n await this.handleReady(channel, message, session);\n }\n } catch (error) {\n log.error({ error, userId }, \"Failed to handle message\");\n await channel.send(userId, {\n text: \"Something went wrong. Please try again.\",\n });\n } finally {\n release();\n }\n },\n );\n }\n\n // ─── Onboarding State Machine ─────────────────────────────────────\n\n private async handleOnboarding(\n channel: ChannelAdapter,\n message: NormalizedMessage,\n session: UserSessionData,\n ): Promise<void> {\n const userId = message.userId;\n const text = message.text.trim();\n const isCallback = message.metadata[\"isCallback\"] === true;\n const isWeb = channel instanceof WebChatServer;\n\n switch (session.state) {\n case \"new\":\n case \"onboard_demo\":\n await this.onboardWelcome(channel, userId, session);\n break;\n\n case \"onboard_dsers_email\":\n await this.onboardEmail(channel, userId, text, session);\n break;\n\n case \"onboard_dsers_password\":\n await this.onboardPassword(channel, message, session, isWeb);\n break;\n\n case \"onboard_llm\":\n await this.onboardLLM(channel, message, session, isCallback, isWeb);\n break;\n }\n }\n\n private async onboardWelcome(\n channel: ChannelAdapter,\n userId: string,\n session: UserSessionData,\n ): Promise<void> {\n const welcome =\n \"Welcome to *DropClaw*! I'm your AI assistant for dropshipping.\\n\\n\" +\n \"I can help you:\\n\" +\n \"- Import products from AliExpress, Temu, 1688\\n\" +\n \"- Push products to your Shopify/WooCommerce store\\n\" +\n \"- Check inventory, pricing rules, and orders\\n\" +\n \"- ...all through this chat!\\n\\n\" +\n \"Let's get you set up. It takes about 1 minute.\\n\\n\" +\n \"*Step 1/3:* What is your DSers account email?\";\n\n await channel.send(userId, { text: welcome });\n\n session.state = \"onboard_dsers_email\";\n saveSession(userId, session);\n }\n\n private async onboardEmail(\n channel: ChannelAdapter,\n userId: string,\n text: string,\n session: UserSessionData,\n ): Promise<void> {\n if (!text.includes(\"@\") || !text.includes(\".\")) {\n await channel.send(userId, {\n text: \"That doesn't look like an email address. Please enter your DSers login email:\",\n });\n return;\n }\n\n session.dspiEmail = text;\n session.state = \"onboard_dsers_password\";\n saveSession(userId, session);\n\n if (channel instanceof WebChatServer) {\n channel.sendSetInputType(userId, \"password\");\n }\n\n await channel.send(userId, {\n text:\n \"Got it!\\n\\n\" +\n \"*Step 2/3:* Now enter your DSers password.\" +\n (channel instanceof WebChatServer\n ? \"\"\n : \"\\n_I will delete your message immediately for security._\"),\n });\n }\n\n private async onboardPassword(\n channel: ChannelAdapter,\n message: NormalizedMessage,\n session: UserSessionData,\n isWeb: boolean,\n ): Promise<void> {\n const userId = message.userId;\n const password = message.text.trim();\n\n if (isWeb) {\n (channel as WebChatServer).sendClearInput(userId);\n (channel as WebChatServer).sendSetInputType(userId, \"text\");\n } else {\n await channel.deleteMessage(\n message.metadata[\"chatId\"] as string | number,\n message.metadata[\"messageId\"] as number,\n );\n }\n\n if (password.length < 1) {\n await channel.send(userId, { text: \"Password cannot be empty. Please try again:\" });\n if (isWeb) (channel as WebChatServer).sendSetInputType(userId, \"password\");\n return;\n }\n\n session.dspiPassword = password;\n saveSession(userId, session);\n\n await channel.send(userId, { text: \"Verifying with DSers...\" });\n\n try {\n const dsersConfig = createDSersConfig(session.dspiEmail!, password);\n const client = new DSersClient(dsersConfig);\n await client.get(\"/account-user-bff/v1/users/info\");\n\n this.dsersClients.set(userId, client);\n\n session.state = \"onboard_llm\";\n saveSession(userId, session);\n\n await channel.send(userId, {\n card: {\n title: \"DSers Connected!\",\n summary:\n \"Your DSers account is verified.\\n\\n\" +\n \"*Step 3/3:* Choose your AI provider.\\n\" +\n \"This powers my intelligence. You can get a free API key from any provider.\",\n actions: [\n { label: \"OpenAI (GPT-4o)\", callbackData: \"llm:openai\" },\n { label: \"Anthropic (Claude)\", callbackData: \"llm:anthropic\" },\n { label: \"Google (Gemini)\", callbackData: \"llm:google\" },\n ],\n },\n });\n } catch (error) {\n session.dspiPassword = undefined;\n session.state = \"onboard_dsers_password\";\n saveSession(userId, session);\n\n if (isWeb) (channel as WebChatServer).sendSetInputType(userId, \"password\");\n\n const msg =\n error instanceof Error && error.message.includes(\"401\")\n ? \"Wrong email or password. Please re-enter your password:\"\n : `Login failed: ${error instanceof Error ? error.message : \"unknown error\"}. Please try again:`;\n\n await channel.send(userId, { text: msg });\n }\n }\n\n private async onboardLLM(\n channel: ChannelAdapter,\n message: NormalizedMessage,\n session: UserSessionData,\n isCallback: boolean,\n isWeb: boolean,\n ): Promise<void> {\n const userId = message.userId;\n const text = message.text.trim();\n\n if (isCallback && text.startsWith(\"llm:\")) {\n const provider = text.replace(\"llm:\", \"\");\n session.llmProvider = provider;\n saveSession(userId, session);\n\n const providerName =\n provider === \"openai\" ? \"OpenAI\" :\n provider === \"anthropic\" ? \"Anthropic\" : \"Google\";\n\n if (isWeb) (channel as WebChatServer).sendSetInputType(userId, \"password\");\n\n await channel.send(userId, {\n text: `You chose *${providerName}*. Now paste your API key below.` +\n (isWeb ? \"\" : \"\\n_I will delete your message immediately._\"),\n });\n return;\n }\n\n if (!session.llmProvider) {\n await channel.send(userId, {\n card: {\n title: \"Choose AI Provider\",\n summary: \"Please select your AI provider first:\",\n actions: [\n { label: \"OpenAI (GPT-4o)\", callbackData: \"llm:openai\" },\n { label: \"Anthropic (Claude)\", callbackData: \"llm:anthropic\" },\n { label: \"Google (Gemini)\", callbackData: \"llm:google\" },\n ],\n },\n });\n return;\n }\n\n if (isWeb) {\n (channel as WebChatServer).sendClearInput(userId);\n (channel as WebChatServer).sendSetInputType(userId, \"text\");\n } else {\n await channel.deleteMessage(\n message.metadata[\"chatId\"] as string | number,\n message.metadata[\"messageId\"] as number,\n );\n }\n\n if (text.length < 10) {\n await channel.send(userId, { text: \"That doesn't look like a valid API key. Please paste your key:\" });\n if (isWeb) (channel as WebChatServer).sendSetInputType(userId, \"password\");\n return;\n }\n\n session.llmApiKey = text;\n session.llmModel = getDefaultModel(session.llmProvider);\n session.state = \"ready\";\n saveSession(userId, session);\n\n await channel.send(userId, {\n text:\n \"All set! DropClaw is ready.\\n\\n\" +\n \"Try these:\\n\" +\n '- \"Show me my stores\"\\n' +\n '- \"What\\'s in my import list?\"\\n' +\n '- \"Search for phone cases on AliExpress\"\\n' +\n '- \"Check my pricing rules\"\\n\\n' +\n \"Just type naturally — I understand everyday language!\",\n });\n\n writeAuditLog({\n userId,\n agentId: \"gateway\",\n action: \"onboarding_complete\",\n target: \"user-session\",\n result: \"success\",\n });\n }\n\n // ─── Ready State: Route to AI Agent ───────────────────────────────\n\n private async handleReady(\n channel: ChannelAdapter,\n message: NormalizedMessage,\n session: UserSessionData,\n ): Promise<void> {\n const userId = message.userId;\n\n if (message.text.trim().toLowerCase() === \"/reset\") {\n this.agents.delete(userId);\n this.dsersClients.delete(userId);\n sessionHistories.delete(userId);\n saveSession(userId, { state: \"new\" });\n await channel.send(userId, { text: \"Account reset. Send any message to start over.\" });\n return;\n }\n\n const agent = this.getOrCreateAgent(userId, session);\n const sessionKey = `${channel.name}:${userId}`;\n const history = sessionHistories.get(sessionKey) ?? [];\n\n const context = {\n userId,\n sessionId: sessionKey,\n channelId: channel.name,\n history: history.slice(-MAX_HISTORY),\n };\n\n writeAuditLog({\n userId,\n agentId: agent.id,\n action: \"receive_message\",\n target: channel.name,\n params: { text: message.text.slice(0, 100) },\n result: \"success\",\n });\n\n try {\n if (channel instanceof WebChatServer) {\n await this.handleReadyStreaming(channel, userId, message.text, agent, context, history, sessionKey);\n } else {\n await this.handleReadyBatch(channel, userId, message.text, agent, context, history, sessionKey);\n }\n } catch (error) {\n log.error({ error, userId }, \"Agent processing failed\");\n\n writeAuditLog({\n userId,\n agentId: agent.id,\n action: \"process_failed\",\n target: channel.name,\n result: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n });\n\n const errMsg = error instanceof Error ? error.message : \"\";\n if (errMsg.includes(\"401\") || errMsg.includes(\"API key\")) {\n await channel.send(userId, {\n text: \"Your API key may be invalid or expired. Send /reset to reconfigure.\",\n });\n } else {\n await channel.send(userId, {\n text: \"I'm having trouble right now. Please try again in a moment.\",\n });\n }\n }\n }\n\n private async handleReadyStreaming(\n channel: WebChatServer,\n userId: string,\n text: string,\n agent: DropClawCoreAgent,\n context: Parameters<DropClawCoreAgent[\"process\"]>[1],\n history: AgentMessage[],\n sessionKey: string,\n ): Promise<void> {\n channel.sendTyping(userId, true);\n\n const { textStream, response } = agent.processStream(text, context);\n\n channel.sendTyping(userId, false);\n channel.sendStreamStart(userId);\n\n for await (const delta of textStream) {\n channel.sendStreamDelta(userId, delta);\n }\n\n channel.sendStreamEnd(userId);\n\n const result = await response;\n\n history.push({ role: \"user\", content: text });\n history.push({ role: \"assistant\", content: result.text });\n sessionHistories.set(sessionKey, history.slice(-MAX_HISTORY * 2));\n\n writeAuditLog({\n userId,\n agentId: agent.id,\n action: \"send_response\",\n target: \"web\",\n params: {\n responseLen: result.text.length,\n toolCalls: result.toolCalls?.length ?? 0,\n streaming: true,\n },\n result: \"success\",\n });\n }\n\n private async handleReadyBatch(\n channel: ChannelAdapter,\n userId: string,\n text: string,\n agent: DropClawCoreAgent,\n context: Parameters<DropClawCoreAgent[\"process\"]>[1],\n history: AgentMessage[],\n sessionKey: string,\n ): Promise<void> {\n const result = await agent.process(text, context);\n\n history.push({ role: \"user\", content: text });\n history.push({ role: \"assistant\", content: result.text });\n sessionHistories.set(sessionKey, history.slice(-MAX_HISTORY * 2));\n\n if (result.text) {\n await channel.send(userId, { text: result.text });\n }\n\n writeAuditLog({\n userId,\n agentId: agent.id,\n action: \"send_response\",\n target: channel.name,\n params: {\n responseLen: result.text.length,\n toolCalls: result.toolCalls?.length ?? 0,\n },\n result: \"success\",\n });\n }\n\n private getOrCreateAgent(userId: string, session: UserSessionData): DropClawCoreAgent {\n let agent = this.agents.get(userId);\n if (agent) return agent;\n\n const dsersConfig = createDSersConfig(\n session.dspiEmail!,\n session.dspiPassword!,\n );\n const dsersClient = new DSersClient(dsersConfig);\n this.dsersClients.set(userId, dsersClient);\n\n const llm: LLMConfig = {\n provider: session.llmProvider!,\n apiKey: session.llmApiKey!,\n model: session.llmModel ?? getDefaultModel(session.llmProvider!),\n };\n\n agent = new DropClawCoreAgent(dsersClient, this.memory, llm);\n this.agents.set(userId, agent);\n return agent;\n }\n\n async stop(): Promise<void> {\n log.info(\"Stopping DropClaw Gateway...\");\n for (const ch of this.channels) {\n await ch.disconnect();\n }\n this.running = false;\n log.info(\"DropClaw Gateway stopped\");\n }\n\n isRunning(): boolean {\n return this.running;\n }\n}\n","/**\n * Start the DropClaw bot.\n * Zero config required — web chat starts by default on port 3000.\n */\n\nimport { loadConfig } from \"../gateway/config.js\";\nimport { DropClawGateway } from \"../gateway/gateway.js\";\nimport { createLogger } from \"../shared/logger.js\";\n\nconst log = createLogger(\"cli:start\");\n\nasync function openBrowser(url: string): Promise<void> {\n const { exec } = await import(\"node:child_process\");\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${url}`, () => {});\n}\n\nexport async function startCommand(opts: {\n config?: string;\n open?: boolean;\n}): Promise<void> {\n try {\n const config = loadConfig(opts.config);\n const url = `http://localhost:${config.port}`;\n\n console.log(\"\\n DropClaw\");\n console.log(` Web Chat: ${url}`);\n if (config.telegramBotToken) {\n console.log(\" Telegram: enabled\");\n }\n console.log();\n\n const gateway = new DropClawGateway(config);\n await gateway.start();\n\n if (opts.open !== false) {\n await openBrowser(url);\n }\n\n console.log(` DropClaw is running. Chat at ${url}\\n`);\n\n const shutdown = async () => {\n log.info(\"Shutting down gracefully...\");\n await gateway.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n } catch (error) {\n log.fatal({ error }, \"Failed to start\");\n console.error(\n `\\n Failed to start: ${error instanceof Error ? error.message : error}`,\n );\n process.exit(1);\n }\n}\n","/**\n * Doctor command — verifies configuration and connectivity.\n */\n\nimport { loadConfig, configExists, CONFIG_PATH } from \"../gateway/config.js\";\n\ninterface CheckResult {\n name: string;\n status: \"ok\" | \"warn\" | \"fail\";\n message: string;\n}\n\nexport async function doctorCommand(): Promise<void> {\n console.log(\"\\n DropClaw Doctor\\n\");\n const results: CheckResult[] = [];\n\n if (configExists()) {\n try {\n const config = loadConfig();\n results.push({ name: \"Config file\", status: \"ok\", message: CONFIG_PATH });\n\n results.push({\n name: \"Web chat\",\n status: \"ok\",\n message: `Port ${config.port}`,\n });\n\n if (config.telegramBotToken) {\n const tokenValid = config.telegramBotToken.includes(\":\");\n results.push({\n name: \"Telegram token\",\n status: tokenValid ? \"ok\" : \"warn\",\n message: tokenValid ? \"Format valid\" : \"Format suspicious\",\n });\n }\n } catch (e) {\n results.push({\n name: \"Config file\",\n status: \"fail\",\n message: e instanceof Error ? e.message : String(e),\n });\n }\n } else {\n results.push({\n name: \"Config file\",\n status: \"fail\",\n message: \"Not found. Run 'dropclaw init' first.\",\n });\n }\n\n try {\n const resp = await fetch(\"https://bff-api-gw.dsers.com/\", {\n method: \"HEAD\",\n signal: AbortSignal.timeout(5000),\n });\n results.push({\n name: \"DSers API\",\n status: resp.status < 500 ? \"ok\" : \"warn\",\n message: `Reachable (HTTP ${resp.status})`,\n });\n } catch (e) {\n results.push({\n name: \"DSers API\",\n status: \"warn\",\n message: e instanceof Error ? e.message : \"Unreachable\",\n });\n }\n\n for (const r of results) {\n const icon = r.status === \"ok\" ? \" [OK]\" : r.status === \"warn\" ? \" [!!]\" : \"[FAIL]\";\n console.log(` ${icon} ${r.name}: ${r.message}`);\n }\n\n const failed = results.filter((r) => r.status === \"fail\").length;\n console.log(\n failed === 0\n ? \"\\n All checks passed.\\n\"\n : `\\n ${failed} check(s) failed. Fix issues above.\\n`,\n );\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","mkdirSync","existsSync","join","log","join","existsSync","mkdirSync","readFileSync","writeFileSync","readFileSync","writeFileSync","mkdirSync","existsSync","log","existsSync","readFileSync","mkdirSync","writeFileSync","createHash","log","log","join","join","z","mkdirSync","existsSync","join","join","existsSync","mkdirSync","log","z","readFileSync","existsSync","join","dirname","log","dirname","join","existsSync","readFileSync","uuid","log","uuid","readFileSync","writeFileSync","appendFileSync","existsSync","mkdirSync","join","log","join","existsSync","mkdirSync","appendFileSync","readFileSync","writeFileSync","log","log","log"]}