dataclaw-agent-kit 0.1.1 → 0.1.2
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/bin.js
CHANGED
|
@@ -888,7 +888,17 @@ function detectIdeEnvironments(targetDir = process.cwd()) {
|
|
|
888
888
|
configPath: windsurfGlobalConfig,
|
|
889
889
|
skillsDir: path2.join(targetDir, ".windsurf", "rules")
|
|
890
890
|
};
|
|
891
|
-
|
|
891
|
+
const codexLocal = path2.join(targetDir, ".codex");
|
|
892
|
+
const codexGlobal = path2.join(home, ".codex");
|
|
893
|
+
const codexDetected = fs2.existsSync(codexLocal) || fs2.existsSync(codexGlobal);
|
|
894
|
+
const codexInfo = {
|
|
895
|
+
id: "codex",
|
|
896
|
+
name: "Codex (.codex/mcp.json + skills)",
|
|
897
|
+
detected: codexDetected,
|
|
898
|
+
configPath: path2.join(targetDir, ".codex", "mcp.json"),
|
|
899
|
+
skillsDir: path2.join(targetDir, ".codex", "skills")
|
|
900
|
+
};
|
|
901
|
+
return [cursorInfo, claudeDesktopInfo, claudeCodeInfo, windsurfInfo, codexInfo];
|
|
892
902
|
}
|
|
893
903
|
|
|
894
904
|
// src/cli/generator.ts
|
|
@@ -1180,7 +1190,7 @@ async function runInitWizard() {
|
|
|
1180
1190
|
}
|
|
1181
1191
|
console.log(
|
|
1182
1192
|
pc.cyan(`
|
|
1183
|
-
\u{1F389} \u5B89\u88C5\u5B8C\u6210\uFF01\u5728 Cursor Composer \u6216
|
|
1193
|
+
\u{1F389} \u5B89\u88C5\u5B8C\u6210\uFF01\u5728 Cursor Composer\u3001Claude \u6216 Codex \u4E2D\u76F4\u63A5\u63D0\u95EE\u4F53\u9A8C:
|
|
1184
1194
|
"\u5E2E\u6211\u628A\u8FD9\u4E2A\u6296\u97F3\u94FE\u63A5\u7684\u5185\u5BB9\u8F6C\u6210\u6587\u7AE0: https://v.douyin.com/..."
|
|
1185
1195
|
"\u5206\u6790\u6296\u97F3\u4E0A\u505A\u5C0F\u5403\u52A0\u76DF\u7684\u70B9\u8D5E\u6700\u9AD8\u89C6\u9891\u4E0E\u8BC4\u8BBA\u75DB\u70B9"
|
|
1186
1196
|
`)
|
|
@@ -1209,4 +1219,4 @@ export {
|
|
|
1209
1219
|
writeSkillsToDir,
|
|
1210
1220
|
runInitWizard
|
|
1211
1221
|
};
|
|
1212
|
-
//# sourceMappingURL=chunk-
|
|
1222
|
+
//# sourceMappingURL=chunk-XH4I6W6J.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/client.ts","../src/types.ts","../src/mcp/server.ts","../src/mcp/tools/media.ts","../src/mcp/tools/douyin.ts","../src/mcp/tools/channels.ts","../src/cli/detect.ts","../src/cli/generator.ts","../src/cli/index.ts"],"sourcesContent":["import { setTimeout as sleep } from \"node:timers/promises\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type {\n DataClawConfig,\n UserProfileResponse,\n VideoResolveInput,\n AudioTranscribeInput,\n DySearchVideosInput,\n DyGetVideoDetailInput,\n DyGetPlayStatsInput,\n DyGetCommentsInput,\n DyGetUserProfileInput,\n ChannelsSearchAuthorsInput,\n ChannelsGetAuthorFeedsInput,\n ChannelsResolveShareUrlInput,\n} from \"../types.js\";\nimport { Readable } from \"node:stream\";\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return \"未知错误\";\n}\nfunction formatBytes(bytes?: number | null): string {\n if (!bytes || bytes <= 0) return \"\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;\n}\n\ninterface TranscriptSegment {\n start?: number | null;\n end?: number | null;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface SubtitleData {\n text?: string;\n segments?: TranscriptSegment[];\n r2_key?: string;\n [key: string]: unknown;\n}\n\nfunction formatSegmentsToSrt(segments: TranscriptSegment[]): string {\n const pad = (n: number, width = 2) => String(n).padStart(width, \"0\");\n return segments\n .filter((s) => Boolean(s.text && s.text.trim()))\n .map((s, index) => {\n const startMs = Math.round(Number(s.start || 0) * 1000);\n const endMs = Math.round(Number(s.end ?? (Number(s.start || 0) + 2)) * 1000);\n\n const sH = Math.floor(startMs / 3600000);\n const sM = Math.floor((startMs % 3600000) / 60000);\n const sS = Math.floor((startMs % 60000) / 1000);\n const sMs = startMs % 1000;\n\n const eH = Math.floor(endMs / 3600000);\n const eM = Math.floor((endMs % 3600000) / 60000);\n const eS = Math.floor((endMs % 60000) / 1000);\n const eMs = endMs % 1000;\n\n const startTime = `${pad(sH)}:${pad(sM)}:${pad(sS)},${pad(sMs, 3)}`;\n const endTime = `${pad(eH)}:${pad(eM)}:${pad(eS)},${pad(eMs, 3)}`;\n return `${index + 1}\\n${startTime} --> ${endTime}\\n${s.text?.trim() || \"\"}\\n`;\n })\n .join(\"\\n\");\n}\n\n\nconst DY_SEARCH_SORT: Record<string, string> = {\n general: \"0\",\n most_liked: \"1\",\n most_recent: \"2\",\n};\n\n\nconst DY_AWEME_RE =\n /(?:modal_id|vid|item_id|aweme_id)=([0-9]{6,})|(?:video|slides|note|photo|article|shipin)\\/([0-9]{6,})/;\n\nfunction douyinAwemeId(raw?: string): string | undefined {\n const text = raw?.trim();\n if (!text) return undefined;\n if (/^\\d+$/.test(text)) return text;\n const match = text.match(DY_AWEME_RE);\n return match?.[1] || match?.[2];\n}\n\nfunction douyinVideoUrl(input: { url?: string; share_url?: string; aweme_id?: string }): string {\n const direct = input.url?.trim() || input.share_url?.trim();\n if (direct) return direct;\n const id = douyinAwemeId(input.aweme_id);\n if (id) return `https://www.douyin.com/video/${id}`;\n throw new Error(\"请提供 url 或 aweme_id\");\n}\n\nfunction douyinCommentTarget(input: { url?: string; share_url?: string; aweme_id?: string }): {\n url: string;\n video_id?: string;\n} {\n const direct = input.url?.trim() || input.share_url?.trim();\n const awemeId = douyinAwemeId(input.aweme_id) || douyinAwemeId(direct);\n if (awemeId) {\n const url = direct && /^https?:\\/\\//i.test(direct) ? direct : `https://www.douyin.com/video/${awemeId}`;\n return { url, video_id: awemeId };\n }\n if (direct) return { url: direct };\n throw new Error(\"请提供 url 或 aweme_id\");\n}\n\n\nexport class DataClawClient {\n private apiKey: string;\n private baseUrl: string;\n private ossPublicBase: string;\n\n constructor(config: DataClawConfig = {}) {\n this.apiKey = config.apiKey || process.env.DATACLAW_API_KEY || \"\";\n this.baseUrl = (config.baseUrl || process.env.DATACLAW_BASE_URL || \"https://www.geodataclaw.com\").replace(/\\/+$/, \"\");\n this.ossPublicBase = (process.env.DATACLAW_OSS_BASE_URL || \"https://oss.geodataclaw.com\").replace(/\\/+$/, \"\");\n }\n\n get isConfigured(): boolean {\n return Boolean(this.apiKey);\n }\n\n private async request<T = Record<string, unknown>>(endpoint: string, options: RequestInit = {}): Promise<T> {\n if (!this.apiKey) {\n throw new Error(\n \"【未配置 API-Key】请设置环境变量 DATACLAW_API_KEY,或运行 `npx dataclaw-agent-kit init` 重新配置。\"\n );\n }\n\n const url = `${this.baseUrl}${endpoint.startsWith(\"/\") ? endpoint : `/${endpoint}`}`;\n const headers = new Headers(options.headers || {});\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-API-Key\", this.apiKey);\n headers.set(\"X-Client-Website\", \"dataclaw\");\n if (!headers.has(\"Content-Type\") && !(options.body instanceof FormData)) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n ...options,\n headers,\n });\n } catch (err: unknown) {\n throw new Error(`请求 DataClaw 服务失败 (${url}): ${getErrorMessage(err)}`);\n }\n\n if (response.status === 401) {\n throw new Error(\"【鉴权失败】您的 DataClaw API-Key 无效或已过期,请前往官网个人中心重新生成。\");\n }\n\n if (response.status === 402) {\n throw new Error(\"【积分不足】您的 DataClaw 账户积分不足以支付本次操作,请前往个人中心充值。\");\n }\n\n const resJson: unknown = await response.json().catch(() => null);\n\n if (!response.ok) {\n let errMsg = `HTTP 错误: ${response.status} ${response.statusText}`;\n if (resJson && typeof resJson === \"object\") {\n if (\"message\" in resJson && typeof resJson.message === \"string\") {\n errMsg = resJson.message;\n } else if (\"error\" in resJson && typeof resJson.error === \"string\") {\n errMsg = resJson.error;\n } else if (\"detail\" in resJson && typeof resJson.detail === \"string\") {\n errMsg = resJson.detail;\n }\n }\n if (/credit|积分|balance/i.test(errMsg)) {\n throw new Error(`【积分不足】${errMsg}。请前往 DataClaw 个人中心充值。`);\n }\n throw new Error(`DataClaw API 错误: ${errMsg}`);\n }\n\n if (resJson && typeof resJson === \"object\" && \"success\" in resJson && resJson.success === false) {\n const msg = \"message\" in resJson && typeof resJson.message === \"string\" ? resJson.message : \"未知业务错误\";\n if (/credit|积分|balance/i.test(msg)) {\n throw new Error(`【积分不足】${msg}。请前往 DataClaw 个人中心充值。`);\n }\n throw new Error(`业务错误: ${msg}`);\n }\n\n if (resJson && typeof resJson === \"object\" && \"data\" in resJson) {\n return resJson.data as T;\n }\n\n return resJson as T;\n }\n\n // ==========================================\n // 用户鉴权与信息校验\n // ==========================================\n\n async getMe(): Promise<UserProfileResponse> {\n const res = await this.request<Record<string, unknown>>(\"/api/auth/me\", { method: \"GET\" });\n const user = (res && typeof res === \"object\" && \"user\" in res ? res.user : res) as Record<string, unknown>;\n return {\n id: typeof user?.id === \"number\" ? user.id : 0,\n username: typeof user?.username === \"string\" ? user.username : \"\",\n credit: typeof user?.credit === \"number\" ? user.credit : undefined,\n role: typeof user?.role === \"string\" ? user.role : undefined,\n };\n }\n\n // ==========================================\n // 本地文件预签名直传 R2 / OSS (temp/mcp/ 规范)\n // ==========================================\n\n async uploadLocalFileToR2(localFilePath: string): Promise<string> {\n if (!fs.existsSync(localFilePath)) {\n throw new Error(`本地文件不存在: ${localFilePath}`);\n }\n\n const stat = fs.statSync(localFilePath);\n if (!stat.isFile()) {\n throw new Error(`指定的路径不是普通文件: ${localFilePath}`);\n }\n\n const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n const ext = path.extname(localFilePath) || \".mp4\";\n const uniqueId = crypto.randomUUID();\n const objectKey = `temp/mcp/${dateStr}/${uniqueId}${ext}`;\n\n // 1. 请求预签名 PUT URL\n const uploadInfo = await this.request<{ url: string; method?: string }>(\"/api/upload/url\", {\n method: \"POST\",\n body: JSON.stringify({\n key: objectKey,\n contentType: \"application/octet-stream\",\n expireSeconds: 3600,\n }),\n });\n\n if (!uploadInfo?.url) {\n throw new Error(\"获取对象存储预签名上传 URL 失败\");\n }\n\n // 直传 R2 使用文件流,避免将长视频整体读入内存。\n const fileStream = Readable.toWeb(fs.createReadStream(localFilePath)) as ReadableStream<Uint8Array>;\n const putRes = await fetch(uploadInfo.url, {\n method: uploadInfo.method || \"PUT\",\n headers: {\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Length\": stat.size.toString(),\n },\n body: fileStream,\n duplex: \"half\",\n } as RequestInit & { duplex: \"half\" });\n\n if (!putRes.ok) {\n throw new Error(`本地文件直传存储失败: ${putRes.status} ${putRes.statusText}`);\n }\n\n return `${this.ossPublicBase}/${objectKey}`;\n }\n\n // ==========================================\n // 多媒体域 Tools\n // ==========================================\n\n async resolveVideo(params: VideoResolveInput): Promise<Record<string, unknown>> {\n const rawUrl = params.url.trim();\n if (!rawUrl) {\n throw new Error(\"请提供需要解析的视频分享链接或包含链接的文案\");\n }\n\n // 1. 调用系统去水印任务创建接口(对应 /tools/material/remove-watermark 页面)\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string; status?: string }>;\n }>(\"/api/task/remove-watermark\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP视频去水印解析\",\n links: [rawUrl],\n enqueue: true,\n }),\n });\n\n const task = batchRes?.tasks?.[0];\n if (!task?.task_id) {\n throw new Error(\"创建去水印解析任务失败,未返回 task_id\");\n }\n\n // 2. 轮询等待任务执行完成(短视频去水印通常在 1~3 秒内完成)\n const maxAttempts = 40;\n const intervalMs = 1000;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n await sleep(intervalMs);\n\n const taskInfo = await this.request<{\n task_id: string;\n status: string;\n title?: string;\n error_message?: string;\n error?: string;\n task_params?: {\n platform?: string;\n };\n task_result?: {\n title?: string;\n author?: string;\n cover_url?: string;\n content?: string;\n statistics?: Record<string, unknown>;\n images?: string[];\n proxy_images?: string[];\n metadata?: Record<string, unknown>;\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n };\n };\n }>(`/api/v2/task/info?task_id=${encodeURIComponent(task.task_id)}`, {\n method: \"GET\",\n });\n\n console.error(\n `[DataClaw] 任务 ${task.task_id} 轮询状态: ${taskInfo.status} (${attempt + 1}/${maxAttempts})`\n );\n\n const isCompleted =\n taskInfo.status === \"completed\" ||\n taskInfo.status === \"success\" ||\n taskInfo.status === \"partial_completed\";\n\n if (isCompleted) {\n const tr = taskInfo.task_result || {};\n const meta = (tr.metadata as Record<string, unknown> | undefined) || tr;\n const video =\n (tr.video as Record<string, unknown> | undefined) ||\n (meta.video as Record<string, unknown> | undefined) ||\n {};\n\n const rawStreams = (video.streams as Array<Record<string, unknown>> | undefined) || [];\n const streams = rawStreams.map((s) => {\n const sizeNum = typeof s.size === \"number\" ? s.size : undefined;\n return {\n quality: (s.quality as string) || \"default\",\n type: (s.type as string) || \"video\",\n size: sizeNum,\n size_formatted: sizeNum ? formatBytes(sizeNum) : undefined,\n url: (s.url as string) || \"\",\n proxy_url: (s.proxy_url as string) || \"\",\n };\n });\n\n const availableResolutions = streams\n .filter((s) => s.type === \"video\" || !s.type)\n .map((s) => `${s.quality}${s.size_formatted ? ` (${s.size_formatted})` : \"\"}`);\n\n const playUrl =\n (video.play_url as string) ||\n (streams.find((s) => s.type === \"video\" && s.url)?.url as string | undefined) ||\n (video.play_proxy_url as string) ||\n \"\";\n\n const proxyUrl =\n (video.play_proxy_url as string) ||\n (streams.find((s) => s.type === \"video\" && s.proxy_url)?.proxy_url as string | undefined) ||\n \"\";\n\n const durationSeconds =\n (video.duration as number) ||\n (\"duration\" in meta && typeof meta.duration === \"number\" ? meta.duration : 0);\n\n const durationFormatted =\n durationSeconds > 0\n ? `${Math.floor(durationSeconds / 60)}分${durationSeconds % 60}秒`\n : undefined;\n\n const coverUrl =\n (tr.cover_url as string) || (meta.cover_url as string) || \"\";\n\n const images =\n (tr.images as string[]) || (tr.proxy_images as string[]) || (meta.images as string[]) || [];\n\n return {\n platform: taskInfo.task_params?.platform || \"auto\",\n title: (tr.title as string) || (meta.title as string) || (taskInfo.title as string) || \"\",\n author: tr.author || meta.author || \"\",\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n images,\n content: (tr.content as string) || \"\",\n statistics: tr.statistics || meta.statistics || {},\n task_id: task.task_id,\n };\n }\n\n if (taskInfo.status === \"failed\") {\n const reason = taskInfo.error_message || taskInfo.error || \"未知解析错误\";\n throw new Error(`视频解析任务失败: ${reason}`);\n }\n }\n\n throw new Error(\"视频去水印解析超时,请稍后重试\");\n }\n\n private async fetchSubtitleFromOss(r2Key: string): Promise<SubtitleData | null> {\n const key = r2Key.replace(/^\\//, \"\");\n const url = /^https?:\\/\\//i.test(key) ? key : `${this.ossPublicBase}/${key}`;\n try {\n const res = await fetch(url, { cache: \"no-store\" });\n if (!res.ok) return null;\n const data = (await res.json()) as SubtitleData;\n return data;\n } catch {\n return null;\n }\n }\n\n async transcribeAudio(params: AudioTranscribeInput): Promise<Record<string, unknown>> {\n // 本地文件先直传对象存储,再进入异步链接转文本任务链路。\n const rawUrl = params.local_file_path\n ? await this.uploadLocalFileToR2(params.local_file_path)\n : (params.media_url || \"\").trim();\n if (!rawUrl) {\n throw new Error(\"必须提供 media_url 或 local_file_path 之一\");\n }\n\n // 2. 判断是否为微信视频号链接(对应 /tools/copy/extract-finder)\n const isFinder = /channels\\.weixin\\.qq\\.com|weixin\\.qq\\.com\\/sph\\/|finder\\.video\\.qq\\.com/i.test(rawUrl);\n\n let taskId = \"\";\n if (params.local_file_path) {\n // 本地文件走 POST /api/task/create/batch (task_type: local_media_transcribe)\n const fileName = path.basename(params.local_file_path);\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/create/batch\", {\n method: \"POST\",\n body: JSON.stringify({\n title: `本地文件转文本-${fileName}`,\n task_type: \"local_media_transcribe\",\n links: [rawUrl],\n task_params: {\n platform: \"local\",\n options: {\n original_name: fileName,\n },\n },\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n } else if (isFinder) {\n // 视频号走 POST /api/task/create/batch (task_type: finder_link_to_text)\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/create/batch\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP视频号转文本\",\n task_type: \"finder_link_to_text\",\n links: [rawUrl],\n task_params: { platform: \"finder\" },\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n } else {\n // 普通短视频(抖音、快手、小红书等)走 POST /api/task/link-to-text\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/link-to-text\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP链接转文本\",\n links: [rawUrl],\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n }\n\n if (!taskId) {\n throw new Error(\"创建转文案任务失败,未返回 task_id\");\n }\n\n // 本地长文件使用后台任务,允许更长处理时间;链接转写保持原轮询窗口。\n const maxAttempts = params.local_file_path ? 1800 : 60;\n const intervalMs = params.local_file_path ? 2000 : 1000;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n await sleep(intervalMs);\n\n const taskInfo = await this.request<{\n task_id: string;\n status: string;\n title?: string;\n error_message?: string;\n error?: string;\n task_result?: {\n title?: string;\n author?: unknown;\n cover_url?: string;\n content?: string;\n desc?: string;\n statistics?: Record<string, unknown>;\n metadata?: {\n title?: string;\n author?: unknown;\n cover_url?: string;\n duration?: number;\n statistics?: Record<string, unknown>;\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n streams?: Array<Record<string, unknown>>;\n subtitle?: SubtitleData;\n };\n };\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n streams?: Array<Record<string, unknown>>;\n subtitle?: SubtitleData;\n };\n };\n }>(`/api/v2/task/info?task_id=${encodeURIComponent(taskId)}`, {\n method: \"GET\",\n });\n console.error(\n `[DataClaw] 转文案任务 ${taskId} 轮询状态: ${taskInfo.status} (${attempt + 1}/${maxAttempts})`\n );\n\n const isCompleted =\n taskInfo.status === \"completed\" ||\n taskInfo.status === \"success\" ||\n taskInfo.status === \"partial_completed\";\n\n if (isCompleted) {\n const tr = taskInfo.task_result || {};\n const meta = tr.metadata || {};\n const video = tr.video || meta.video || {};\n const subtitle = video.subtitle || {};\n let text = subtitle.text || \"\";\n let segments = subtitle.segments || [];\n\n // 若大字幕在 OSS/R2,就地补齐\n if ((!text || segments.length === 0) && subtitle.r2_key) {\n const ossData = await this.fetchSubtitleFromOss(subtitle.r2_key);\n if (ossData) {\n text = text || ossData.text || \"\";\n segments = segments.length > 0 ? segments : ossData.segments || [];\n }\n }\n\n // 若仍无字幕,兜底使用正文描述\n if (!text) {\n text = tr.content || tr.desc || \"\";\n }\n\n const rawStreams = video.streams || [];\n const streams = rawStreams.map((s) => {\n const sizeNum = typeof s.size === \"number\" ? s.size : undefined;\n return {\n quality: (s.quality as string) || \"default\",\n type: (s.type as string) || \"video\",\n size: sizeNum,\n size_formatted: sizeNum ? formatBytes(sizeNum) : undefined,\n url: (s.url as string) || \"\",\n proxy_url: (s.proxy_url as string) || \"\",\n };\n });\n\n const availableResolutions = streams\n .filter((s) => s.type === \"video\" || !s.type)\n .map((s) => `${s.quality}${s.size_formatted ? ` (${s.size_formatted})` : \"\"}`);\n\n const playUrl =\n video.play_url ||\n streams.find((s) => s.type === \"video\" && s.url)?.url ||\n video.play_proxy_url ||\n \"\";\n\n const proxyUrl =\n video.play_proxy_url ||\n streams.find((s) => s.type === \"video\" && s.proxy_url)?.proxy_url ||\n \"\";\n\n const durationSeconds =\n video.duration ||\n meta.duration ||\n 0;\n\n const durationFormatted =\n durationSeconds > 0\n ? `${Math.floor(durationSeconds / 60)}分${durationSeconds % 60}秒`\n : undefined;\n\n const coverUrl = tr.cover_url || meta.cover_url || \"\";\n const title = tr.title || meta.title || taskInfo.title || \"\";\n const author = tr.author || meta.author || \"\";\n const srt = formatSegmentsToSrt(segments);\n\n if (params.output_format === \"srt\") {\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n srt: srt || text,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n task_id: taskId,\n };\n }\n if (params.output_format === \"verbose_json\") {\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n text,\n srt,\n segments,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n statistics: tr.statistics || meta.statistics || {},\n task_id: taskId,\n };\n }\n\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n text: text || \"(未检测到口播语音)\",\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n statistics: tr.statistics || meta.statistics || {},\n task_id: taskId,\n };\n }\n\n if (taskInfo.status === \"failed\") {\n const reason = taskInfo.error_message || taskInfo.error || \"未知转写错误\";\n throw new Error(`视频转文案任务失败: ${reason}`);\n }\n }\n\n throw new Error(\"转文案任务处理超时,请稍后前往 DataClaw 网页端查看详情\");\n }\n\n // ==========================================\n // 抖音域 Tools\n // ==========================================\n\n async searchDyVideos(params: DySearchVideosInput): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {\n keyword: params.keyword,\n sort_type: DY_SEARCH_SORT[params.sort_type] ?? \"0\",\n publish_time: params.publish_time ?? \"0\",\n cursor: params.cursor ?? 0,\n };\n if (params.search_id) body.search_id = params.search_id;\n if (params.backtrace) body.backtrace = params.backtrace;\n return this.request<Record<string, unknown>>(\"/api/v2/dy/search/video\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n }\n\n async getDyVideoDetail(params: DyGetVideoDetailInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/dy/detail\", {\n method: \"POST\",\n body: JSON.stringify({ url: douyinVideoUrl(params) }),\n });\n }\n async getDyPlayStats(params: DyGetPlayStatsInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/dy/video/play-stats\", {\n method: \"POST\",\n body: JSON.stringify({ url: douyinVideoUrl(params) }),\n });\n }\n\n\n async getDyComments(params: DyGetCommentsInput): Promise<Record<string, unknown>> {\n const target = douyinCommentTarget(params);\n return this.request<Record<string, unknown>>(\"/api/v2/dy/video/comments\", {\n method: \"POST\",\n body: JSON.stringify({\n url: target.url,\n ...(target.video_id ? { video_id: target.video_id } : {}),\n cursor: params.cursor ?? 0,\n count: params.count ?? 50,\n }),\n });\n }\n\n async getDyUserProfile(params: DyGetUserProfileInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/dy/user/detail\", {\n method: \"POST\",\n body: JSON.stringify({\n sec_user_id: params.sec_user_id,\n url: params.url || params.profile_url,\n }),\n });\n }\n\n // ==========================================\n // 视频号域 Tools\n // ==========================================\n\n async searchChannelsAuthors(params: ChannelsSearchAuthorsInput): Promise<Record<string, unknown>> {\n const query = params.keyword.trim();\n if (!query) throw new Error(\"请提供搜索关键词\");\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/search-authors\", {\n method: \"POST\",\n body: JSON.stringify({\n query,\n count: params.count ?? 20,\n buffer: params.buffer ?? \"\",\n scene: params.scene ?? 1,\n }),\n });\n }\n\n async getChannelsAuthorFeeds(params: ChannelsGetAuthorFeedsInput): Promise<Record<string, unknown>> {\n const username = params.finder_username.trim();\n if (!username) throw new Error(\"请提供 finder_username\");\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/feeds\", {\n method: \"POST\",\n body: JSON.stringify({\n username,\n buffer: params.last_buffer?.trim() ?? \"\",\n count: 15,\n scene: 0,\n }),\n });\n }\n\n async resolveChannelsShareUrl(params: ChannelsResolveShareUrlInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/video-by-share-url\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n}\n","import { z } from \"zod\";\n\n// ==========================================\n// 1. Media Tools Schemas\n// ==========================================\n\nexport const VideoResolveSchema = z.object({\n url: z.string().describe(\"抖音、视频号、小红书、快手、B站等各大平台的分享文案或链接(支持完整链接、短链或包含分享文本的整段文字)\"),\n});\nexport type VideoResolveInput = z.infer<typeof VideoResolveSchema>;\n\nexport const AudioTranscribeSchema = z.object({\n media_url: z.string().optional().describe(\"网络音视频直链 URL 或短视频分享文案/链接(支持普通短视频与微信视频号,与 local_file_path 二选一)\"),\n local_file_path: z.string().optional().describe(\"本地音视频文件绝对路径(与 media_url 二选一;会先上传到对象存储,再创建异步转写任务)\"),\n output_format: z.enum([\"text\", \"srt\", \"verbose_json\"]).default(\"text\").describe(\"返回格式:纯文本、SRT字幕、或带时间戳的段落详情\"),\n});\nexport type AudioTranscribeInput = z.infer<typeof AudioTranscribeSchema>;\n\n// ==========================================\n// 2. Douyin Tools Schemas\n// ==========================================\n\nexport const DySearchVideosSchema = z.object({\n keyword: z.string().describe(\"搜索关键词\"),\n sort_type: z.enum([\"general\", \"most_recent\", \"most_liked\"]).default(\"general\").describe(\"排序:综合(general→0)、最多点赞(most_liked→1)、最新(most_recent→2)\"),\n publish_time: z.enum([\"0\", \"1\", \"7\", \"180\"]).default(\"0\").describe(\"发布时间:0 不限,1 最近一天,7 最近一周,180 最近半年\"),\n count: z.number().min(1).max(20).default(10).describe(\"兼容字段。上游页大小固定,调用时忽略\"),\n cursor: z.number().optional().describe(\"分页游标,首页不传或传 0,下一页使用上次返回的 cursor\"),\n search_id: z.string().optional().describe(\"翻页时带回上次返回的 search_id\"),\n backtrace: z.string().optional().describe(\"翻页时带回上次返回的 backtrace\"),\n});\nexport type DySearchVideosInput = z.infer<typeof DySearchVideosSchema>;\n\nexport const DyGetVideoDetailSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。请求体字段就是 url,例如 https://www.douyin.com/video/ID 或 https://www.douyin.com/jingxuan?modal_id=ID\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时转成 https://www.douyin.com/video/{aweme_id}\"),\n});\nexport type DyGetVideoDetailInput = z.infer<typeof DyGetVideoDetailSchema>;\nexport const DyGetPlayStatsSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。请求体字段就是 url\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时转成视频长链\"),\n});\nexport type DyGetPlayStatsInput = z.infer<typeof DyGetPlayStatsSchema>;\n\n\nexport const DyGetCommentsSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。例如 https://www.douyin.com/video/ID 或 https://www.douyin.com/jingxuan?modal_id=ID\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时使用,不要把整段链接填在这里\"),\n cursor: z.number().default(0).describe(\"分页游标,第一页传 0\"),\n count: z.number().min(1).max(50).default(50).describe(\"每页评论数,默认 50,最大 50\"),\n});\nexport type DyGetCommentsInput = z.infer<typeof DyGetCommentsSchema>;\n\nexport const DyGetUserProfileSchema = z.object({\n sec_user_id: z.string().optional().describe(\"博主 sec_user_id(与 url 二选一)\"),\n url: z.string().optional().describe(\"博主主页链接、分享短链或分享文案(与 sec_user_id 二选一)\"),\n profile_url: z.string().optional().describe(\"(别名兼容)博主主页链接\"),\n});\nexport type DyGetUserProfileInput = z.infer<typeof DyGetUserProfileSchema>;\n\n// ==========================================\n// 3. WeChat Channels Tools Schemas\n// ==========================================\n\nexport const ChannelsSearchAuthorsSchema = z.object({\n keyword: z.string().describe(\"创作者关键词或博主昵称\"),\n count: z.number().int().min(1).max(50).default(20).describe(\"每页作者数量,默认 20\"),\n buffer: z.string().default(\"\").describe(\"分页游标,首页为空,下一页使用上次返回的 buffer\"),\n scene: z.number().int().default(1).describe(\"搜索场景,默认 1\"),\n});\nexport type ChannelsSearchAuthorsInput = z.infer<typeof ChannelsSearchAuthorsSchema>;\n\nexport const ChannelsGetAuthorFeedsSchema = z.object({\n finder_username: z.string().describe(\"视频号作者唯一标识 finder_username\"),\n last_buffer: z.string().optional().describe(\"翻页 buffer(首页无需传)\"),\n});\nexport type ChannelsGetAuthorFeedsInput = z.infer<typeof ChannelsGetAuthorFeedsSchema>;\n\nexport const ChannelsResolveShareUrlSchema = z.object({\n share_url: z.string().describe(\"微信视频号分享链接,例如包含 finder.video.qq.com 或短链接\"),\n});\nexport type ChannelsResolveShareUrlInput = z.infer<typeof ChannelsResolveShareUrlSchema>;\n\n\n// ==========================================\n// 4. Client & Auth Types\n// ==========================================\n\nexport interface DataClawConfig {\n apiKey?: string;\n baseUrl?: string;\n}\n\nexport interface UserProfileResponse {\n id: number;\n username: string;\n credit?: number;\n role?: string;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { DataClawClient } from \"./client.js\";\nimport { registerMediaTools } from \"./tools/media.js\";\nimport { registerDouyinTools } from \"./tools/douyin.js\";\nimport { registerChannelsTools } from \"./tools/channels.js\";\n\nexport function createMcpServer(client = new DataClawClient()): McpServer {\n const server = new McpServer({\n name: \"dataclaw-agent-kit\",\n version: \"0.1.1\",\n });\n\n registerMediaTools(server, client);\n registerDouyinTools(server, client);\n registerChannelsTools(server, client);\n\n return server;\n}\n\nexport async function startMcpServer(client = new DataClawClient()): Promise<void> {\n const server = createMcpServer(client);\n const transport = new StdioServerTransport();\n\n console.error(\"🦞 [DataClaw MCP Server] 正在启动 (stdio 传输协议)...\");\n if (!client.isConfigured) {\n console.error(\n \"⚠️ [DataClaw] 未检测到 DATACLAW_API_KEY 环境变量。请确保在 MCP Client 配置中正确传递了 env.DATACLAW_API_KEY。\"\n );\n }\n\n await server.connect(transport);\n console.error(\"🚀 [DataClaw MCP Server] 运行就绪,已注册 10 个标准化 Tools。\");\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport { VideoResolveSchema, AudioTranscribeSchema } from \"../../types.js\";\n\nexport function registerMediaTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_video_resolve\",\n {\n description: \"传入抖音、视频号、小红书、快手、B站等各大平台的分享文案或链接,自动识别平台去水印解析,提取无水印高清视频播放直链、封面图、标题、作者及时长数据(对应 /tools/material/remove-watermark 页面)\",\n inputSchema: VideoResolveSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.resolveVideo(args);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `视频解析失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_audio_transcribe\",\n {\n description: \"传入短视频分享文案/链接(自动识别抖音、小红书、快手等普通视频与微信视频号并自动解密转写,对应 /tools/copy/extract 和 /tools/copy/extract-finder),或本地音视频文件(先直传对象存储,再创建异步转写任务),转写为纯文本、SRT字幕或带时间戳段落详情\",\n inputSchema: AudioTranscribeSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.transcribeAudio(args);\n return {\n content: [\n {\n type: \"text\" as const,\n text: typeof result === \"string\" ? result : JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `音频转写失败: ${message}` }],\n };\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport {\n DySearchVideosSchema,\n DyGetVideoDetailSchema,\n DyGetPlayStatsSchema,\n DyGetCommentsSchema,\n DyGetUserProfileSchema,\n} from \"../../types.js\";\n\nexport function registerDouyinTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_dy_search_videos\",\n {\n description: \"关键词搜索抖音热门视频,支持按综合、最新、最多点赞排序及发布时间筛选,返回包含点赞、播放、标题和作者的作品列表\",\n inputSchema: DySearchVideosSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.searchDyVideos(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `抖音视频搜索失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_dy_get_video_detail\",\n {\n description: \"获取指定抖音视频详情:标题、作者、封面、播放地址,以及点赞、评论、分享、收藏数。不含播放量,也不含秒级互动趋势。只传 url\",\n inputSchema: DyGetVideoDetailSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyVideoDetail(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音视频详情失败: ${message}` }],\n };\n }\n }\n );\n server.registerTool(\n \"dataclaw_dy_get_play_stats\",\n {\n description: \"查询抖音视频播放量、完播率等星图统计。详情接口不含播放量,必须单独调用本工具。只传 url,或 aweme_id(会转成 url)\",\n inputSchema: DyGetPlayStatsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyPlayStats(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音播放量失败: ${message}` }],\n };\n }\n }\n );\n\n\n server.registerTool(\n \"dataclaw_dy_get_comments\",\n {\n description: \"获取指定抖音视频的一级评论(含置顶、点赞数、回复数)。传 url 或 aweme_id,不要把整段链接填进 aweme_id\",\n inputSchema: DyGetCommentsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyComments(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音评论失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_dy_get_user_profile\",\n {\n description: \"获取抖音博主主页资料:昵称、粉丝数、作品数、简介。不含粉丝画像和历史作品列表\",\n inputSchema: DyGetUserProfileSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyUserProfile(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音博主信息失败: ${message}` }],\n };\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport {\n ChannelsSearchAuthorsSchema,\n ChannelsGetAuthorFeedsSchema,\n ChannelsResolveShareUrlSchema,\n} from \"../../types.js\";\n\nexport function registerChannelsTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_channels_search_authors\",\n {\n description: \"关键词搜索微信视频号创作者/博主,获取博主 finder_username、头像及认证简介\",\n inputSchema: ChannelsSearchAuthorsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.searchChannelsAuthors(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `搜索视频号创作者失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_channels_get_author_feeds\",\n {\n description: \"根据作者 finder_username 获取视频号作品 Feed,每页 15 条。首页不传 last_buffer,下一页传上次返回的 buffer\",\n inputSchema: ChannelsGetAuthorFeedsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getChannelsAuthorFeeds(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取视频号作品列表失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_channels_resolve_share_url\",\n {\n description: \"根据微信视频号分享文本或短链解析作品全量数据、互动指标及无水印高清视频源\",\n inputSchema: ChannelsResolveShareUrlSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.resolveChannelsShareUrl(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `解析视频号分享链接失败: ${message}` }],\n };\n }\n }\n );\n\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport type IdeTarget = \"cursor\" | \"claude-desktop\" | \"claude-code\" | \"windsurf\";\n\nexport interface IdeInfo {\n id: IdeTarget;\n name: string;\n detected: boolean;\n configPath?: string;\n skillsDir?: string;\n}\n\nexport function detectIdeEnvironments(targetDir: string = process.cwd()): IdeInfo[] {\n const home = os.homedir();\n const platform = process.platform;\n\n // 1. Cursor\n const cursorLocal = path.join(targetDir, \".cursor\");\n const cursorGlobal = path.join(home, \".cursor\");\n const cursorDetected = fs.existsSync(cursorLocal) || fs.existsSync(cursorGlobal);\n const cursorInfo: IdeInfo = {\n id: \"cursor\",\n name: \"Cursor (.cursor/rules + mcp.json)\",\n detected: cursorDetected,\n configPath: path.join(targetDir, \".cursor\", \"mcp.json\"),\n skillsDir: path.join(targetDir, \".cursor\", \"rules\"),\n };\n\n // 2. Claude Desktop\n let claudeDesktopConfigPath = \"\";\n if (platform === \"darwin\") {\n claudeDesktopConfigPath = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude_desktop_config.json\");\n } else if (platform === \"win32\") {\n const appData = process.env.APPDATA || path.join(home, \"AppData\", \"Roaming\");\n claudeDesktopConfigPath = path.join(appData, \"Claude\", \"claude_desktop_config.json\");\n } else {\n claudeDesktopConfigPath = path.join(home, \".config\", \"Claude\", \"claude_desktop_config.json\");\n }\n const claudeDesktopDetected = fs.existsSync(path.dirname(claudeDesktopConfigPath));\n const claudeDesktopInfo: IdeInfo = {\n id: \"claude-desktop\",\n name: \"Claude Desktop (claude_desktop_config.json)\",\n detected: claudeDesktopDetected,\n configPath: claudeDesktopConfigPath,\n };\n\n // 3. Claude Code\n const claudeCodeLocal = path.join(targetDir, \".claude\");\n const claudeCodeGlobal = path.join(home, \".claude\");\n const claudeCodeDetected = fs.existsSync(claudeCodeLocal) || fs.existsSync(claudeCodeGlobal);\n const claudeCodeInfo: IdeInfo = {\n id: \"claude-code\",\n name: \"Claude Code (.claude/skills)\",\n detected: claudeCodeDetected,\n configPath: path.join(targetDir, \".claude\", \"mcp.json\"),\n skillsDir: path.join(targetDir, \".claude\", \"skills\"),\n };\n\n // 4. Windsurf\n const windsurfGlobalConfig = path.join(home, \".codeium\", \"windsurf\", \"mcp_config.json\");\n const windsurfLocal = path.join(targetDir, \".windsurf\");\n const windsurfDetected = fs.existsSync(windsurfLocal) || fs.existsSync(path.dirname(windsurfGlobalConfig));\n const windsurfInfo: IdeInfo = {\n id: \"windsurf\",\n name: \"Windsurf (mcp_config.json)\",\n detected: windsurfDetected,\n configPath: windsurfGlobalConfig,\n skillsDir: path.join(targetDir, \".windsurf\", \"rules\"),\n };\n\n return [cursorInfo, claudeDesktopInfo, claudeCodeInfo, windsurfInfo];\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { IdeTarget } from \"./detect.js\";\n\nexport const MEDIA_SKILL_TEMPLATE = `---\ndescription: 视频去水印下载、全平台图集提取与音视频智能转文案 SOP\nglobs: \n---\n\n# 视频去水印下载与文案提取 SOP (Video Download & Transcribe)\n\n当用户意图涉及“下载视频/无水印提取”、“提取抖音/视频号/小红书等平台文案”、“把视频转成文字/提取字幕/总结大意”时,请严格按以下分支策略调用 DataClaw MCP 工具:\n\n## 分支策略与执行流程\n\n### 分支 A:用户需要提取文案 / 字幕 / 总结视频大意(一步直达)\n**核心原则**:转文案**无需**先调用解析工具获取直链,直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\` 一步直达,耗时更短且支持官方字幕缓存秒回。\n\n1. **直接调用转文案工具** \\\\\\`dataclaw_audio_transcribe\\\\\\`:\n - **网络短视频**:传参 \\\\\\`media_url = <用户提供的分享链接或文案>\\\\\\`。\n - 支持抖音、小红书、快手、B站等普通短视频(系统自动走 \\\\\\`/tools/copy/extract\\\\\\` 链路)。\n - 支持微信视频号短链(系统自动走 \\\\\\`/tools/copy/extract-finder\\\\\\` 链路,自动完成 WASM 解密)。\n - **本地音视频文件**:传参 local_file_path = <本地绝对路径>;MCP 会先直传对象存储,再创建异步转写任务,长文件等待任务完成。\n - **输出格式选择**:\n - 用户需要纯文本/总结大意:传 \\\\\\`output_format = \"text\"\\\\\\`。\n - 用户需要字幕/时间轴:传 \\\\\\`output_format = \"srt\"\\\\\\`。\n - 用户需要详细时间切片数据:传 \\\\\\`output_format = \"verbose_json\"\\\\\\`。\n\n2. **文案排版与提炼输出**:\n - 提取文案后,为用户按以下结构整理呈现:\n - **【主题概要】**:一句话概括视频核心内容。\n - **【关键金句 / 核心知识点】**:3~5 条高价值要点。\n - **【逐段逐句文案】**:清洗去除口癖分段文稿(若选了 srt 则提供标准带时间轴字幕格式)。\n\n---\n\n### 分支 B:用户需要下载无水印视频 / 获取高清图集\n当用户意图是“下载视频”、“保存原画素材”、“去除水印”或“下载小红书/抖音图集”时:\n\n1. **调用通用去水印工具** \\\\\\`dataclaw_video_resolve\\\\\\`:\n - 传参 \\\\\\`url = <用户提供的链接或包含链接的文案>\\\\\\`。\n - 系统自动识别平台(对应 \\\\\\`/tools/material/remove-watermark\\\\\\`),支持抖音、视频号、小红书、快手、TikTok 等全平台。\n2. **下载引导呈现**:\n - **若是视频**:返回无水印高清直链 \\\\\\`video_play_url\\\\\\`、视频封面 \\\\\\`cover_url\\\\\\`、标题 \\\\\\`title\\\\\\`、作者 \\\\\\`author\\\\\\` 及时长 \\\\\\`duration\\\\\\`。\n - **若是图集**:返回全量无水印高清图片直链列表 \\\\\\`images\\\\\\`。\n - 引导用户在浏览器中点击下载,或提供终端 \\\\\\`curl / wget\\\\\\` 下载命令。\n`;\n\nexport const DOUYIN_SKILL_TEMPLATE = `---\ndescription: 抖音热门视频复盘、爆款文案拆解与评论区痛点挖掘 SOP\nglobs: \n---\n\n# 抖音爆款视频复盘与痛点分析 SOP (Douyin Hot Video Audit)\n\n当用户意图涉及“分析抖音上做 [品类/行业] 的爆款视频”、“调研竞品评论区痛点/用户反馈”、“拆解对标账号的高赞脚本”时,请严格遵循以下步骤:\n\n## 执行流程\n\n1. **关键词检索热门视频**:\n - 调用工具 \\\\\\`dataclaw_dy_search_videos\\\\\\`:\n - \\\\\\`keyword\\\\\\`: 用户的目标行业、产品或主题关键词。\n - \\\\\\`sort_type\\\\\\`: 优先传 \\\\\\`\"most_liked\"\\\\\\`(最多点赞)或 \\\\\\`\"most_recent\"\\\\\\`(最新)。\n - \\\\\\`publish_time\\\\\\`: \\\\\\`\"0\"\\\\\\` 不限,\\\\\\`\"1\"\\\\\\` 最近一天,\\\\\\`\"7\"\\\\\\` 最近一周,\\\\\\`\"180\"\\\\\\` 最近半年。\n - 页大小固定,不要依赖 \\\\\\`count\\\\\\`。翻页带回上次返回的 \\\\\\`cursor\\\\\\`、\\\\\\`search_id\\\\\\`、\\\\\\`backtrace\\\\\\`。\n - 筛选出点赞量与互动最高的 TOP 3~5 个视频作品。\n\n2. **获取作品详情与互动指标**:\n - 针对筛选出的目标视频,调用 \\\\\\`dataclaw_dy_get_video_detail\\\\\\`。\n - 只拿标题、作者、封面、播放地址和点赞、评论、分享、收藏数。没有播放量,也没有秒级互动趋势。\n - 需要播放量或完播率时,另调 \\\\\\`dataclaw_dy_get_play_stats\\\\\\`,传同一个 \\\\\\`url\\\\\\`。详情和播放量的请求体字段都是 \\\\\\`url\\\\\\`,不要传 \\\\\\`share_url\\\\\\`。\n\n3. **抓取评论**:\n - 针对目标视频,调用 \\\\\\`dataclaw_dy_get_comments\\\\\\`,传 \\\\\\`url\\\\\\` 或纯数字 \\\\\\`aweme_id\\\\\\`。每页默认 50 条,最大 50。要更多就用上次返回的 \\\\\\`cursor\\\\\\` 再翻页。\n - 重点提取高赞热评与槽点。\n\n4. **爆款脚本逐字文案提炼(按需)**:\n - 若用户需要深入拆解爆款的台词脚本或钩子设计,直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\`(传入该视频的 share_url),获取逐字口播稿。\n\n5. **综合复盘分析输出**:\n - 综合以上数据,为用户输出深度复盘报告:\n - **【黄金开头拆解】**:前 3 秒钩子视觉与文案设计,分析其高完播原因。\n - **【脚本结构拆解】**:痛点引发 -> 价值阐述 -> 行动召唤 (CTA) 的节奏分布。\n - **【高频共鸣词云】**:观众讨论最热烈的关键词与情绪倾向。\n - **【痛点与未满足需求】**:评论区高赞吐槽、疑问及潜在买点。\n - **【爆款可复制建议】**:总结 3 条可直接落地的脚本创作建议。\n`;\n\nexport const CHANNELS_SKILL_TEMPLATE = `---\ndescription: 微信视频号创作者深度拆解、爆款 Feed 与互动监控 SOP\nglobs: \n---\n\n# 微信视频号达人与作品监控 SOP (Channels Creator Monitor)\n\n当用户意图涉及“拆解这个视频号博主”、“看看这个视频号最近发了什么”、“分析视频号竞品账号的表现”时,请严格遵循以下步骤:\n\n## 执行流程\n\n1. **创作者检索与定位**:\n - 若用户提供了博主昵称或关键词,调用 \\\\\\`dataclaw_channels_search_authors\\\\\\` 进行搜索。\n - 确认目标作者,获取其唯一标识 \\\\\\`finder_username\\\\\\`、头像及认证简介。\n\n2. **拉取近期作品 Feed**:\n - 调用 \\\\\\`dataclaw_channels_get_author_feeds\\\\\\`,传入作者 \\\\\\`finder_username\\\\\\`。\n - 每页 15 条。要 10~30 条就再传上次返回的 \\\\\\`last_buffer\\\\\\` / \\\\\\`buffer\\\\\\` 翻一页。\n\n3. **作品全量数据与文案/视频提取(按需)**:\n - **若需提取视频口播文案**:直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\`(传入作品分享短链,系统底层自动通过 WASM 解密视频号加密视频流并转写为文案或 SRT 字幕)。\n - **若需无水印下载视频**:调用 \\\\\\`dataclaw_video_resolve\\\\\\`(传入视频号分享短链),提取高清下载直链。\n\n4. **达人矩阵与运营策略提炼**:\n - 为用户输出深度分析报告:\n - **【发文节奏与偏好】**:近期更新频率、发布时间段偏好。\n - **【爆款内容特征】**:点赞/转发破万的题材特征与封面文案套路。\n - **【口播台词套路】**:针对代表作提取的台词脚本节奏与话术拆解。\n - **【互动转化分析】**:评论区互动热点与用户私域转化引导方式。\n - **【模仿与超越建议】**:对标同行的差异化定位策略。\n`;\n\nexport interface GenerationResult {\n configWritten?: string;\n skillsWritten: string[];\n}\n\nexport function writeMcpConfig(\n configFilePath: string,\n apiKey: string,\n customBaseUrl?: string\n): void {\n const dir = path.dirname(configFilePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n let existingJson: Record<string, unknown> = {};\n if (fs.existsSync(configFilePath)) {\n try {\n const content = fs.readFileSync(configFilePath, \"utf-8\");\n const parsed: unknown = JSON.parse(content);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n existingJson = parsed as Record<string, unknown>;\n }\n } catch {\n // 容错已损坏的 JSON\n }\n }\n\n const existingMcpServers = (\n existingJson.mcpServers && typeof existingJson.mcpServers === \"object\" && !Array.isArray(existingJson.mcpServers)\n ? existingJson.mcpServers\n : {}\n ) as Record<string, unknown>;\n\n const envVars: Record<string, string> = {\n DATACLAW_API_KEY: apiKey,\n };\n if (customBaseUrl) {\n envVars.DATACLAW_BASE_URL = customBaseUrl;\n }\n\n existingMcpServers.dataclaw = {\n command: \"npx\",\n args: [\"-y\", \"dataclaw-agent-kit\", \"mcp\"],\n env: envVars,\n };\n\n existingJson.mcpServers = existingMcpServers;\n fs.writeFileSync(configFilePath, JSON.stringify(existingJson, null, 2), \"utf-8\");\n}\n\nexport function writeSkillsToDir(\n skillsDir: string,\n skillKeys: Array<\"media\" | \"douyin\" | \"channels\">,\n extension: \".mdc\" | \".md\" = \".mdc\"\n): string[] {\n if (!fs.existsSync(skillsDir)) {\n fs.mkdirSync(skillsDir, { recursive: true });\n }\n\n const written: string[] = [];\n\n if (skillKeys.includes(\"media\")) {\n const file = path.join(skillsDir, `dataclaw-media${extension}`);\n fs.writeFileSync(file, MEDIA_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n if (skillKeys.includes(\"douyin\")) {\n const file = path.join(skillsDir, `dataclaw-douyin${extension}`);\n fs.writeFileSync(file, DOUYIN_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n if (skillKeys.includes(\"channels\")) {\n const file = path.join(skillsDir, `dataclaw-channels${extension}`);\n fs.writeFileSync(file, CHANNELS_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n return written;\n}\n","import path from \"node:path\";\nimport pc from \"picocolors\";\nimport prompts from \"prompts\";\nimport { DataClawClient } from \"../mcp/client.js\";\nimport { detectIdeEnvironments, type IdeTarget } from \"./detect.js\";\nimport { writeMcpConfig, writeSkillsToDir } from \"./generator.js\";\n\nexport async function runInitWizard(): Promise<void> {\n console.log(\n pc.cyan(`\n┌──────────────────────────────────────────────────────────┐\n│ 🦞 DataClaw AI Agent Kit (MCP & Skills) 安装向导 │\n└──────────────────────────────────────────────────────────┘\n`)\n );\n\n const defaultApiKey = process.env.DATACLAW_API_KEY || \"\";\n const detectedIdes = detectIdeEnvironments();\n\n // 1. 输入 API Key\n const keyResponse = await prompts({\n type: \"password\",\n name: \"apiKey\",\n message: \"请输入您的 DataClaw API-Key (从个人中心获取):\",\n initial: defaultApiKey,\n validate: (val: string) => (val.trim().length > 0 ? true : \"API-Key 不能为空\"),\n });\n\n const apiKey = (keyResponse.apiKey as string | undefined)?.trim();\n if (!apiKey) {\n console.log(pc.yellow(\"已取消安装向导。\"));\n return;\n }\n\n // 2. 验证 API Key\n const client = new DataClawClient({ apiKey });\n console.log(pc.dim(\"正在验证 API-Key 有效性...\"));\n try {\n const me = await client.getMe();\n console.log(\n pc.green(`✔ 鉴权验证成功!当前用户: ${me.username} (积分余额: ${me.credit ?? \"无限制\"} 点)`)\n );\n } catch (err: unknown) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n console.log(pc.yellow(`⚠️ 鉴权验证未通过: ${errorMsg}`));\n const confirm = await prompts({\n type: \"confirm\",\n name: \"continueAnyway\",\n message: \"是否仍要继续使用此 API-Key 完成安装?\",\n initial: true,\n });\n if (!confirm.continueAnyway) {\n console.log(pc.yellow(\"已取消安装。\"));\n return;\n }\n }\n\n // 3. 选择 IDE 宿主环境\n const ideChoices = detectedIdes.map((ide) => ({\n title: ide.name,\n value: ide.id,\n selected: ide.detected,\n }));\n\n const ideResponse = await prompts({\n type: \"multiselect\",\n name: \"targets\",\n message: \"请选择需要注入配置的 AI 宿主环境:\",\n choices: ideChoices,\n min: 1,\n hint: \"- 空格切换选中,回车确认\",\n });\n\n const selectedTargets = (ideResponse.targets as IdeTarget[] | undefined) || [];\n if (selectedTargets.length === 0) {\n console.log(pc.yellow(\"未选择任何宿主环境,已退出。\"));\n return;\n }\n\n // 4. 选择启用的技能\n const skillResponse = await prompts({\n type: \"multiselect\",\n name: \"skills\",\n message: \"请勾选需要启用的第一期场景技能:\",\n choices: [\n {\n title: \"[视频处理] 视频无水印直链提取与音频智能语音转写 SOP\",\n value: \"media\",\n selected: true,\n },\n {\n title: \"[抖音分析] 热门视频检索、爆款文案与评论痛点挖掘 SOP\",\n value: \"douyin\",\n selected: true,\n },\n {\n title: \"[微信视频号] 达人主页深度拆解与作品动态监控 SOP\",\n value: \"channels\",\n selected: true,\n },\n ],\n min: 1,\n });\n\n const selectedSkills = (skillResponse.skills as Array<\"media\" | \"douyin\" | \"channels\"> | undefined) || [];\n if (selectedSkills.length === 0) {\n console.log(pc.yellow(\"未选择任何技能,已退出。\"));\n return;\n }\n\n console.log(\"\");\n\n // 5. 写入配置与技能\n for (const target of selectedTargets) {\n const ideMeta = detectedIdes.find((item) => item.id === target);\n if (!ideMeta) continue;\n\n // 写入 MCP Server 配置\n if (ideMeta.configPath) {\n try {\n writeMcpConfig(ideMeta.configPath, apiKey);\n console.log(pc.green(`✔ 配置文件已写入: ${path.relative(process.cwd(), ideMeta.configPath) || ideMeta.configPath}`));\n } catch (err: unknown) {\n console.error(pc.red(`✖ 写入配置文件失败 (${ideMeta.configPath}): ${err instanceof Error ? err.message : String(err)}`));\n }\n }\n\n // 写入技能 Markdown SOP\n if (ideMeta.skillsDir) {\n try {\n const ext = target === \"cursor\" ? \".mdc\" : \".md\";\n const writtenFiles = writeSkillsToDir(ideMeta.skillsDir, selectedSkills, ext);\n for (const f of writtenFiles) {\n console.log(pc.green(`✔ 场景技能已生成: ${path.relative(process.cwd(), f) || f}`));\n }\n } catch (err: unknown) {\n console.error(pc.red(`✖ 写入技能文件失败: ${err instanceof Error ? err.message : String(err)}`));\n }\n }\n }\n\n console.log(\n pc.cyan(`\n🎉 安装完成!在 Cursor Composer 或 Claude 中直接提问体验:\n \"帮我把这个抖音链接的内容转成文章: https://v.douyin.com/...\"\n \"分析抖音上做小吃加盟的点赞最高视频与评论痛点\"\n`)\n );\n}\n"],"mappings":"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","names":["fs","path","fs","path","path","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp/client.ts","../src/types.ts","../src/mcp/server.ts","../src/mcp/tools/media.ts","../src/mcp/tools/douyin.ts","../src/mcp/tools/channels.ts","../src/cli/detect.ts","../src/cli/generator.ts","../src/cli/index.ts"],"sourcesContent":["import { setTimeout as sleep } from \"node:timers/promises\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type {\n DataClawConfig,\n UserProfileResponse,\n VideoResolveInput,\n AudioTranscribeInput,\n DySearchVideosInput,\n DyGetVideoDetailInput,\n DyGetPlayStatsInput,\n DyGetCommentsInput,\n DyGetUserProfileInput,\n ChannelsSearchAuthorsInput,\n ChannelsGetAuthorFeedsInput,\n ChannelsResolveShareUrlInput,\n} from \"../types.js\";\nimport { Readable } from \"node:stream\";\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return \"未知错误\";\n}\nfunction formatBytes(bytes?: number | null): string {\n if (!bytes || bytes <= 0) return \"\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;\n}\n\ninterface TranscriptSegment {\n start?: number | null;\n end?: number | null;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface SubtitleData {\n text?: string;\n segments?: TranscriptSegment[];\n r2_key?: string;\n [key: string]: unknown;\n}\n\nfunction formatSegmentsToSrt(segments: TranscriptSegment[]): string {\n const pad = (n: number, width = 2) => String(n).padStart(width, \"0\");\n return segments\n .filter((s) => Boolean(s.text && s.text.trim()))\n .map((s, index) => {\n const startMs = Math.round(Number(s.start || 0) * 1000);\n const endMs = Math.round(Number(s.end ?? (Number(s.start || 0) + 2)) * 1000);\n\n const sH = Math.floor(startMs / 3600000);\n const sM = Math.floor((startMs % 3600000) / 60000);\n const sS = Math.floor((startMs % 60000) / 1000);\n const sMs = startMs % 1000;\n\n const eH = Math.floor(endMs / 3600000);\n const eM = Math.floor((endMs % 3600000) / 60000);\n const eS = Math.floor((endMs % 60000) / 1000);\n const eMs = endMs % 1000;\n\n const startTime = `${pad(sH)}:${pad(sM)}:${pad(sS)},${pad(sMs, 3)}`;\n const endTime = `${pad(eH)}:${pad(eM)}:${pad(eS)},${pad(eMs, 3)}`;\n return `${index + 1}\\n${startTime} --> ${endTime}\\n${s.text?.trim() || \"\"}\\n`;\n })\n .join(\"\\n\");\n}\n\n\nconst DY_SEARCH_SORT: Record<string, string> = {\n general: \"0\",\n most_liked: \"1\",\n most_recent: \"2\",\n};\n\n\nconst DY_AWEME_RE =\n /(?:modal_id|vid|item_id|aweme_id)=([0-9]{6,})|(?:video|slides|note|photo|article|shipin)\\/([0-9]{6,})/;\n\nfunction douyinAwemeId(raw?: string): string | undefined {\n const text = raw?.trim();\n if (!text) return undefined;\n if (/^\\d+$/.test(text)) return text;\n const match = text.match(DY_AWEME_RE);\n return match?.[1] || match?.[2];\n}\n\nfunction douyinVideoUrl(input: { url?: string; share_url?: string; aweme_id?: string }): string {\n const direct = input.url?.trim() || input.share_url?.trim();\n if (direct) return direct;\n const id = douyinAwemeId(input.aweme_id);\n if (id) return `https://www.douyin.com/video/${id}`;\n throw new Error(\"请提供 url 或 aweme_id\");\n}\n\nfunction douyinCommentTarget(input: { url?: string; share_url?: string; aweme_id?: string }): {\n url: string;\n video_id?: string;\n} {\n const direct = input.url?.trim() || input.share_url?.trim();\n const awemeId = douyinAwemeId(input.aweme_id) || douyinAwemeId(direct);\n if (awemeId) {\n const url = direct && /^https?:\\/\\//i.test(direct) ? direct : `https://www.douyin.com/video/${awemeId}`;\n return { url, video_id: awemeId };\n }\n if (direct) return { url: direct };\n throw new Error(\"请提供 url 或 aweme_id\");\n}\n\n\nexport class DataClawClient {\n private apiKey: string;\n private baseUrl: string;\n private ossPublicBase: string;\n\n constructor(config: DataClawConfig = {}) {\n this.apiKey = config.apiKey || process.env.DATACLAW_API_KEY || \"\";\n this.baseUrl = (config.baseUrl || process.env.DATACLAW_BASE_URL || \"https://www.geodataclaw.com\").replace(/\\/+$/, \"\");\n this.ossPublicBase = (process.env.DATACLAW_OSS_BASE_URL || \"https://oss.geodataclaw.com\").replace(/\\/+$/, \"\");\n }\n\n get isConfigured(): boolean {\n return Boolean(this.apiKey);\n }\n\n private async request<T = Record<string, unknown>>(endpoint: string, options: RequestInit = {}): Promise<T> {\n if (!this.apiKey) {\n throw new Error(\n \"【未配置 API-Key】请设置环境变量 DATACLAW_API_KEY,或运行 `npx dataclaw-agent-kit init` 重新配置。\"\n );\n }\n\n const url = `${this.baseUrl}${endpoint.startsWith(\"/\") ? endpoint : `/${endpoint}`}`;\n const headers = new Headers(options.headers || {});\n headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n headers.set(\"X-API-Key\", this.apiKey);\n headers.set(\"X-Client-Website\", \"dataclaw\");\n if (!headers.has(\"Content-Type\") && !(options.body instanceof FormData)) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n ...options,\n headers,\n });\n } catch (err: unknown) {\n throw new Error(`请求 DataClaw 服务失败 (${url}): ${getErrorMessage(err)}`);\n }\n\n if (response.status === 401) {\n throw new Error(\"【鉴权失败】您的 DataClaw API-Key 无效或已过期,请前往官网个人中心重新生成。\");\n }\n\n if (response.status === 402) {\n throw new Error(\"【积分不足】您的 DataClaw 账户积分不足以支付本次操作,请前往个人中心充值。\");\n }\n\n const resJson: unknown = await response.json().catch(() => null);\n\n if (!response.ok) {\n let errMsg = `HTTP 错误: ${response.status} ${response.statusText}`;\n if (resJson && typeof resJson === \"object\") {\n if (\"message\" in resJson && typeof resJson.message === \"string\") {\n errMsg = resJson.message;\n } else if (\"error\" in resJson && typeof resJson.error === \"string\") {\n errMsg = resJson.error;\n } else if (\"detail\" in resJson && typeof resJson.detail === \"string\") {\n errMsg = resJson.detail;\n }\n }\n if (/credit|积分|balance/i.test(errMsg)) {\n throw new Error(`【积分不足】${errMsg}。请前往 DataClaw 个人中心充值。`);\n }\n throw new Error(`DataClaw API 错误: ${errMsg}`);\n }\n\n if (resJson && typeof resJson === \"object\" && \"success\" in resJson && resJson.success === false) {\n const msg = \"message\" in resJson && typeof resJson.message === \"string\" ? resJson.message : \"未知业务错误\";\n if (/credit|积分|balance/i.test(msg)) {\n throw new Error(`【积分不足】${msg}。请前往 DataClaw 个人中心充值。`);\n }\n throw new Error(`业务错误: ${msg}`);\n }\n\n if (resJson && typeof resJson === \"object\" && \"data\" in resJson) {\n return resJson.data as T;\n }\n\n return resJson as T;\n }\n\n // ==========================================\n // 用户鉴权与信息校验\n // ==========================================\n\n async getMe(): Promise<UserProfileResponse> {\n const res = await this.request<Record<string, unknown>>(\"/api/auth/me\", { method: \"GET\" });\n const user = (res && typeof res === \"object\" && \"user\" in res ? res.user : res) as Record<string, unknown>;\n return {\n id: typeof user?.id === \"number\" ? user.id : 0,\n username: typeof user?.username === \"string\" ? user.username : \"\",\n credit: typeof user?.credit === \"number\" ? user.credit : undefined,\n role: typeof user?.role === \"string\" ? user.role : undefined,\n };\n }\n\n // ==========================================\n // 本地文件预签名直传 R2 / OSS (temp/mcp/ 规范)\n // ==========================================\n\n async uploadLocalFileToR2(localFilePath: string): Promise<string> {\n if (!fs.existsSync(localFilePath)) {\n throw new Error(`本地文件不存在: ${localFilePath}`);\n }\n\n const stat = fs.statSync(localFilePath);\n if (!stat.isFile()) {\n throw new Error(`指定的路径不是普通文件: ${localFilePath}`);\n }\n\n const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n const ext = path.extname(localFilePath) || \".mp4\";\n const uniqueId = crypto.randomUUID();\n const objectKey = `temp/mcp/${dateStr}/${uniqueId}${ext}`;\n\n // 1. 请求预签名 PUT URL\n const uploadInfo = await this.request<{ url: string; method?: string }>(\"/api/upload/url\", {\n method: \"POST\",\n body: JSON.stringify({\n key: objectKey,\n contentType: \"application/octet-stream\",\n expireSeconds: 3600,\n }),\n });\n\n if (!uploadInfo?.url) {\n throw new Error(\"获取对象存储预签名上传 URL 失败\");\n }\n\n // 直传 R2 使用文件流,避免将长视频整体读入内存。\n const fileStream = Readable.toWeb(fs.createReadStream(localFilePath)) as ReadableStream<Uint8Array>;\n const putRes = await fetch(uploadInfo.url, {\n method: uploadInfo.method || \"PUT\",\n headers: {\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Length\": stat.size.toString(),\n },\n body: fileStream,\n duplex: \"half\",\n } as RequestInit & { duplex: \"half\" });\n\n if (!putRes.ok) {\n throw new Error(`本地文件直传存储失败: ${putRes.status} ${putRes.statusText}`);\n }\n\n return `${this.ossPublicBase}/${objectKey}`;\n }\n\n // ==========================================\n // 多媒体域 Tools\n // ==========================================\n\n async resolveVideo(params: VideoResolveInput): Promise<Record<string, unknown>> {\n const rawUrl = params.url.trim();\n if (!rawUrl) {\n throw new Error(\"请提供需要解析的视频分享链接或包含链接的文案\");\n }\n\n // 1. 调用系统去水印任务创建接口(对应 /tools/material/remove-watermark 页面)\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string; status?: string }>;\n }>(\"/api/task/remove-watermark\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP视频去水印解析\",\n links: [rawUrl],\n enqueue: true,\n }),\n });\n\n const task = batchRes?.tasks?.[0];\n if (!task?.task_id) {\n throw new Error(\"创建去水印解析任务失败,未返回 task_id\");\n }\n\n // 2. 轮询等待任务执行完成(短视频去水印通常在 1~3 秒内完成)\n const maxAttempts = 40;\n const intervalMs = 1000;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n await sleep(intervalMs);\n\n const taskInfo = await this.request<{\n task_id: string;\n status: string;\n title?: string;\n error_message?: string;\n error?: string;\n task_params?: {\n platform?: string;\n };\n task_result?: {\n title?: string;\n author?: string;\n cover_url?: string;\n content?: string;\n statistics?: Record<string, unknown>;\n images?: string[];\n proxy_images?: string[];\n metadata?: Record<string, unknown>;\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n };\n };\n }>(`/api/v2/task/info?task_id=${encodeURIComponent(task.task_id)}`, {\n method: \"GET\",\n });\n\n console.error(\n `[DataClaw] 任务 ${task.task_id} 轮询状态: ${taskInfo.status} (${attempt + 1}/${maxAttempts})`\n );\n\n const isCompleted =\n taskInfo.status === \"completed\" ||\n taskInfo.status === \"success\" ||\n taskInfo.status === \"partial_completed\";\n\n if (isCompleted) {\n const tr = taskInfo.task_result || {};\n const meta = (tr.metadata as Record<string, unknown> | undefined) || tr;\n const video =\n (tr.video as Record<string, unknown> | undefined) ||\n (meta.video as Record<string, unknown> | undefined) ||\n {};\n\n const rawStreams = (video.streams as Array<Record<string, unknown>> | undefined) || [];\n const streams = rawStreams.map((s) => {\n const sizeNum = typeof s.size === \"number\" ? s.size : undefined;\n return {\n quality: (s.quality as string) || \"default\",\n type: (s.type as string) || \"video\",\n size: sizeNum,\n size_formatted: sizeNum ? formatBytes(sizeNum) : undefined,\n url: (s.url as string) || \"\",\n proxy_url: (s.proxy_url as string) || \"\",\n };\n });\n\n const availableResolutions = streams\n .filter((s) => s.type === \"video\" || !s.type)\n .map((s) => `${s.quality}${s.size_formatted ? ` (${s.size_formatted})` : \"\"}`);\n\n const playUrl =\n (video.play_url as string) ||\n (streams.find((s) => s.type === \"video\" && s.url)?.url as string | undefined) ||\n (video.play_proxy_url as string) ||\n \"\";\n\n const proxyUrl =\n (video.play_proxy_url as string) ||\n (streams.find((s) => s.type === \"video\" && s.proxy_url)?.proxy_url as string | undefined) ||\n \"\";\n\n const durationSeconds =\n (video.duration as number) ||\n (\"duration\" in meta && typeof meta.duration === \"number\" ? meta.duration : 0);\n\n const durationFormatted =\n durationSeconds > 0\n ? `${Math.floor(durationSeconds / 60)}分${durationSeconds % 60}秒`\n : undefined;\n\n const coverUrl =\n (tr.cover_url as string) || (meta.cover_url as string) || \"\";\n\n const images =\n (tr.images as string[]) || (tr.proxy_images as string[]) || (meta.images as string[]) || [];\n\n return {\n platform: taskInfo.task_params?.platform || \"auto\",\n title: (tr.title as string) || (meta.title as string) || (taskInfo.title as string) || \"\",\n author: tr.author || meta.author || \"\",\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n images,\n content: (tr.content as string) || \"\",\n statistics: tr.statistics || meta.statistics || {},\n task_id: task.task_id,\n };\n }\n\n if (taskInfo.status === \"failed\") {\n const reason = taskInfo.error_message || taskInfo.error || \"未知解析错误\";\n throw new Error(`视频解析任务失败: ${reason}`);\n }\n }\n\n throw new Error(\"视频去水印解析超时,请稍后重试\");\n }\n\n private async fetchSubtitleFromOss(r2Key: string): Promise<SubtitleData | null> {\n const key = r2Key.replace(/^\\//, \"\");\n const url = /^https?:\\/\\//i.test(key) ? key : `${this.ossPublicBase}/${key}`;\n try {\n const res = await fetch(url, { cache: \"no-store\" });\n if (!res.ok) return null;\n const data = (await res.json()) as SubtitleData;\n return data;\n } catch {\n return null;\n }\n }\n\n async transcribeAudio(params: AudioTranscribeInput): Promise<Record<string, unknown>> {\n // 本地文件先直传对象存储,再进入异步链接转文本任务链路。\n const rawUrl = params.local_file_path\n ? await this.uploadLocalFileToR2(params.local_file_path)\n : (params.media_url || \"\").trim();\n if (!rawUrl) {\n throw new Error(\"必须提供 media_url 或 local_file_path 之一\");\n }\n\n // 2. 判断是否为微信视频号链接(对应 /tools/copy/extract-finder)\n const isFinder = /channels\\.weixin\\.qq\\.com|weixin\\.qq\\.com\\/sph\\/|finder\\.video\\.qq\\.com/i.test(rawUrl);\n\n let taskId = \"\";\n if (params.local_file_path) {\n // 本地文件走 POST /api/task/create/batch (task_type: local_media_transcribe)\n const fileName = path.basename(params.local_file_path);\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/create/batch\", {\n method: \"POST\",\n body: JSON.stringify({\n title: `本地文件转文本-${fileName}`,\n task_type: \"local_media_transcribe\",\n links: [rawUrl],\n task_params: {\n platform: \"local\",\n options: {\n original_name: fileName,\n },\n },\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n } else if (isFinder) {\n // 视频号走 POST /api/task/create/batch (task_type: finder_link_to_text)\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/create/batch\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP视频号转文本\",\n task_type: \"finder_link_to_text\",\n links: [rawUrl],\n task_params: { platform: \"finder\" },\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n } else {\n // 普通短视频(抖音、快手、小红书等)走 POST /api/task/link-to-text\n const batchRes = await this.request<{\n batch_id: string;\n count: number;\n tasks: Array<{ task_id: string }>;\n }>(\"/api/task/link-to-text\", {\n method: \"POST\",\n body: JSON.stringify({\n title: \"MCP链接转文本\",\n links: [rawUrl],\n enqueue: true,\n }),\n });\n taskId = batchRes?.tasks?.[0]?.task_id || \"\";\n }\n\n if (!taskId) {\n throw new Error(\"创建转文案任务失败,未返回 task_id\");\n }\n\n // 本地长文件使用后台任务,允许更长处理时间;链接转写保持原轮询窗口。\n const maxAttempts = params.local_file_path ? 1800 : 60;\n const intervalMs = params.local_file_path ? 2000 : 1000;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n await sleep(intervalMs);\n\n const taskInfo = await this.request<{\n task_id: string;\n status: string;\n title?: string;\n error_message?: string;\n error?: string;\n task_result?: {\n title?: string;\n author?: unknown;\n cover_url?: string;\n content?: string;\n desc?: string;\n statistics?: Record<string, unknown>;\n metadata?: {\n title?: string;\n author?: unknown;\n cover_url?: string;\n duration?: number;\n statistics?: Record<string, unknown>;\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n streams?: Array<Record<string, unknown>>;\n subtitle?: SubtitleData;\n };\n };\n video?: {\n duration?: number;\n play_url?: string;\n play_proxy_url?: string;\n streams?: Array<Record<string, unknown>>;\n subtitle?: SubtitleData;\n };\n };\n }>(`/api/v2/task/info?task_id=${encodeURIComponent(taskId)}`, {\n method: \"GET\",\n });\n console.error(\n `[DataClaw] 转文案任务 ${taskId} 轮询状态: ${taskInfo.status} (${attempt + 1}/${maxAttempts})`\n );\n\n const isCompleted =\n taskInfo.status === \"completed\" ||\n taskInfo.status === \"success\" ||\n taskInfo.status === \"partial_completed\";\n\n if (isCompleted) {\n const tr = taskInfo.task_result || {};\n const meta = tr.metadata || {};\n const video = tr.video || meta.video || {};\n const subtitle = video.subtitle || {};\n let text = subtitle.text || \"\";\n let segments = subtitle.segments || [];\n\n // 若大字幕在 OSS/R2,就地补齐\n if ((!text || segments.length === 0) && subtitle.r2_key) {\n const ossData = await this.fetchSubtitleFromOss(subtitle.r2_key);\n if (ossData) {\n text = text || ossData.text || \"\";\n segments = segments.length > 0 ? segments : ossData.segments || [];\n }\n }\n\n // 若仍无字幕,兜底使用正文描述\n if (!text) {\n text = tr.content || tr.desc || \"\";\n }\n\n const rawStreams = video.streams || [];\n const streams = rawStreams.map((s) => {\n const sizeNum = typeof s.size === \"number\" ? s.size : undefined;\n return {\n quality: (s.quality as string) || \"default\",\n type: (s.type as string) || \"video\",\n size: sizeNum,\n size_formatted: sizeNum ? formatBytes(sizeNum) : undefined,\n url: (s.url as string) || \"\",\n proxy_url: (s.proxy_url as string) || \"\",\n };\n });\n\n const availableResolutions = streams\n .filter((s) => s.type === \"video\" || !s.type)\n .map((s) => `${s.quality}${s.size_formatted ? ` (${s.size_formatted})` : \"\"}`);\n\n const playUrl =\n video.play_url ||\n streams.find((s) => s.type === \"video\" && s.url)?.url ||\n video.play_proxy_url ||\n \"\";\n\n const proxyUrl =\n video.play_proxy_url ||\n streams.find((s) => s.type === \"video\" && s.proxy_url)?.proxy_url ||\n \"\";\n\n const durationSeconds =\n video.duration ||\n meta.duration ||\n 0;\n\n const durationFormatted =\n durationSeconds > 0\n ? `${Math.floor(durationSeconds / 60)}分${durationSeconds % 60}秒`\n : undefined;\n\n const coverUrl = tr.cover_url || meta.cover_url || \"\";\n const title = tr.title || meta.title || taskInfo.title || \"\";\n const author = tr.author || meta.author || \"\";\n const srt = formatSegmentsToSrt(segments);\n\n if (params.output_format === \"srt\") {\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n srt: srt || text,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n task_id: taskId,\n };\n }\n if (params.output_format === \"verbose_json\") {\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n text,\n srt,\n segments,\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n statistics: tr.statistics || meta.statistics || {},\n task_id: taskId,\n };\n }\n\n return {\n title,\n author,\n cover_url: coverUrl,\n duration: durationSeconds,\n duration_formatted: durationFormatted,\n text: text || \"(未检测到口播语音)\",\n video_play_url: playUrl,\n video_download_proxy_url: proxyUrl,\n available_resolutions: availableResolutions,\n streams,\n statistics: tr.statistics || meta.statistics || {},\n task_id: taskId,\n };\n }\n\n if (taskInfo.status === \"failed\") {\n const reason = taskInfo.error_message || taskInfo.error || \"未知转写错误\";\n throw new Error(`视频转文案任务失败: ${reason}`);\n }\n }\n\n throw new Error(\"转文案任务处理超时,请稍后前往 DataClaw 网页端查看详情\");\n }\n\n // ==========================================\n // 抖音域 Tools\n // ==========================================\n\n async searchDyVideos(params: DySearchVideosInput): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {\n keyword: params.keyword,\n sort_type: DY_SEARCH_SORT[params.sort_type] ?? \"0\",\n publish_time: params.publish_time ?? \"0\",\n cursor: params.cursor ?? 0,\n };\n if (params.search_id) body.search_id = params.search_id;\n if (params.backtrace) body.backtrace = params.backtrace;\n return this.request<Record<string, unknown>>(\"/api/v2/dy/search/video\", {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n }\n\n async getDyVideoDetail(params: DyGetVideoDetailInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/dy/detail\", {\n method: \"POST\",\n body: JSON.stringify({ url: douyinVideoUrl(params) }),\n });\n }\n async getDyPlayStats(params: DyGetPlayStatsInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/dy/video/play-stats\", {\n method: \"POST\",\n body: JSON.stringify({ url: douyinVideoUrl(params) }),\n });\n }\n\n\n async getDyComments(params: DyGetCommentsInput): Promise<Record<string, unknown>> {\n const target = douyinCommentTarget(params);\n return this.request<Record<string, unknown>>(\"/api/v2/dy/video/comments\", {\n method: \"POST\",\n body: JSON.stringify({\n url: target.url,\n ...(target.video_id ? { video_id: target.video_id } : {}),\n cursor: params.cursor ?? 0,\n count: params.count ?? 50,\n }),\n });\n }\n\n async getDyUserProfile(params: DyGetUserProfileInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/dy/user/detail\", {\n method: \"POST\",\n body: JSON.stringify({\n sec_user_id: params.sec_user_id,\n url: params.url || params.profile_url,\n }),\n });\n }\n\n // ==========================================\n // 视频号域 Tools\n // ==========================================\n\n async searchChannelsAuthors(params: ChannelsSearchAuthorsInput): Promise<Record<string, unknown>> {\n const query = params.keyword.trim();\n if (!query) throw new Error(\"请提供搜索关键词\");\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/search-authors\", {\n method: \"POST\",\n body: JSON.stringify({\n query,\n count: params.count ?? 20,\n buffer: params.buffer ?? \"\",\n scene: params.scene ?? 1,\n }),\n });\n }\n\n async getChannelsAuthorFeeds(params: ChannelsGetAuthorFeedsInput): Promise<Record<string, unknown>> {\n const username = params.finder_username.trim();\n if (!username) throw new Error(\"请提供 finder_username\");\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/feeds\", {\n method: \"POST\",\n body: JSON.stringify({\n username,\n buffer: params.last_buffer?.trim() ?? \"\",\n count: 15,\n scene: 0,\n }),\n });\n }\n\n async resolveChannelsShareUrl(params: ChannelsResolveShareUrlInput): Promise<Record<string, unknown>> {\n return this.request<Record<string, unknown>>(\"/api/v2/mp/finder/video-by-share-url\", {\n method: \"POST\",\n body: JSON.stringify(params),\n });\n }\n\n}\n","import { z } from \"zod\";\n\n// ==========================================\n// 1. Media Tools Schemas\n// ==========================================\n\nexport const VideoResolveSchema = z.object({\n url: z.string().describe(\"抖音、视频号、小红书、快手、B站等各大平台的分享文案或链接(支持完整链接、短链或包含分享文本的整段文字)\"),\n});\nexport type VideoResolveInput = z.infer<typeof VideoResolveSchema>;\n\nexport const AudioTranscribeSchema = z.object({\n media_url: z.string().optional().describe(\"网络音视频直链 URL 或短视频分享文案/链接(支持普通短视频与微信视频号,与 local_file_path 二选一)\"),\n local_file_path: z.string().optional().describe(\"本地音视频文件绝对路径(与 media_url 二选一;会先上传到对象存储,再创建异步转写任务)\"),\n output_format: z.enum([\"text\", \"srt\", \"verbose_json\"]).default(\"text\").describe(\"返回格式:纯文本、SRT字幕、或带时间戳的段落详情\"),\n});\nexport type AudioTranscribeInput = z.infer<typeof AudioTranscribeSchema>;\n\n// ==========================================\n// 2. Douyin Tools Schemas\n// ==========================================\n\nexport const DySearchVideosSchema = z.object({\n keyword: z.string().describe(\"搜索关键词\"),\n sort_type: z.enum([\"general\", \"most_recent\", \"most_liked\"]).default(\"general\").describe(\"排序:综合(general→0)、最多点赞(most_liked→1)、最新(most_recent→2)\"),\n publish_time: z.enum([\"0\", \"1\", \"7\", \"180\"]).default(\"0\").describe(\"发布时间:0 不限,1 最近一天,7 最近一周,180 最近半年\"),\n count: z.number().min(1).max(20).default(10).describe(\"兼容字段。上游页大小固定,调用时忽略\"),\n cursor: z.number().optional().describe(\"分页游标,首页不传或传 0,下一页使用上次返回的 cursor\"),\n search_id: z.string().optional().describe(\"翻页时带回上次返回的 search_id\"),\n backtrace: z.string().optional().describe(\"翻页时带回上次返回的 backtrace\"),\n});\nexport type DySearchVideosInput = z.infer<typeof DySearchVideosSchema>;\n\nexport const DyGetVideoDetailSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。请求体字段就是 url,例如 https://www.douyin.com/video/ID 或 https://www.douyin.com/jingxuan?modal_id=ID\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时转成 https://www.douyin.com/video/{aweme_id}\"),\n});\nexport type DyGetVideoDetailInput = z.infer<typeof DyGetVideoDetailSchema>;\nexport const DyGetPlayStatsSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。请求体字段就是 url\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时转成视频长链\"),\n});\nexport type DyGetPlayStatsInput = z.infer<typeof DyGetPlayStatsSchema>;\n\n\nexport const DyGetCommentsSchema = z.object({\n url: z.string().optional().describe(\"抖音视频链接或分享文案。例如 https://www.douyin.com/video/ID 或 https://www.douyin.com/jingxuan?modal_id=ID\"),\n aweme_id: z.string().optional().describe(\"抖音视频 ID。未传 url 时使用,不要把整段链接填在这里\"),\n cursor: z.number().default(0).describe(\"分页游标,第一页传 0\"),\n count: z.number().min(1).max(50).default(50).describe(\"每页评论数,默认 50,最大 50\"),\n});\nexport type DyGetCommentsInput = z.infer<typeof DyGetCommentsSchema>;\n\nexport const DyGetUserProfileSchema = z.object({\n sec_user_id: z.string().optional().describe(\"博主 sec_user_id(与 url 二选一)\"),\n url: z.string().optional().describe(\"博主主页链接、分享短链或分享文案(与 sec_user_id 二选一)\"),\n profile_url: z.string().optional().describe(\"(别名兼容)博主主页链接\"),\n});\nexport type DyGetUserProfileInput = z.infer<typeof DyGetUserProfileSchema>;\n\n// ==========================================\n// 3. WeChat Channels Tools Schemas\n// ==========================================\n\nexport const ChannelsSearchAuthorsSchema = z.object({\n keyword: z.string().describe(\"创作者关键词或博主昵称\"),\n count: z.number().int().min(1).max(50).default(20).describe(\"每页作者数量,默认 20\"),\n buffer: z.string().default(\"\").describe(\"分页游标,首页为空,下一页使用上次返回的 buffer\"),\n scene: z.number().int().default(1).describe(\"搜索场景,默认 1\"),\n});\nexport type ChannelsSearchAuthorsInput = z.infer<typeof ChannelsSearchAuthorsSchema>;\n\nexport const ChannelsGetAuthorFeedsSchema = z.object({\n finder_username: z.string().describe(\"视频号作者唯一标识 finder_username\"),\n last_buffer: z.string().optional().describe(\"翻页 buffer(首页无需传)\"),\n});\nexport type ChannelsGetAuthorFeedsInput = z.infer<typeof ChannelsGetAuthorFeedsSchema>;\n\nexport const ChannelsResolveShareUrlSchema = z.object({\n share_url: z.string().describe(\"微信视频号分享链接,例如包含 finder.video.qq.com 或短链接\"),\n});\nexport type ChannelsResolveShareUrlInput = z.infer<typeof ChannelsResolveShareUrlSchema>;\n\n\n// ==========================================\n// 4. Client & Auth Types\n// ==========================================\n\nexport interface DataClawConfig {\n apiKey?: string;\n baseUrl?: string;\n}\n\nexport interface UserProfileResponse {\n id: number;\n username: string;\n credit?: number;\n role?: string;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { DataClawClient } from \"./client.js\";\nimport { registerMediaTools } from \"./tools/media.js\";\nimport { registerDouyinTools } from \"./tools/douyin.js\";\nimport { registerChannelsTools } from \"./tools/channels.js\";\n\nexport function createMcpServer(client = new DataClawClient()): McpServer {\n const server = new McpServer({\n name: \"dataclaw-agent-kit\",\n version: \"0.1.1\",\n });\n\n registerMediaTools(server, client);\n registerDouyinTools(server, client);\n registerChannelsTools(server, client);\n\n return server;\n}\n\nexport async function startMcpServer(client = new DataClawClient()): Promise<void> {\n const server = createMcpServer(client);\n const transport = new StdioServerTransport();\n\n console.error(\"🦞 [DataClaw MCP Server] 正在启动 (stdio 传输协议)...\");\n if (!client.isConfigured) {\n console.error(\n \"⚠️ [DataClaw] 未检测到 DATACLAW_API_KEY 环境变量。请确保在 MCP Client 配置中正确传递了 env.DATACLAW_API_KEY。\"\n );\n }\n\n await server.connect(transport);\n console.error(\"🚀 [DataClaw MCP Server] 运行就绪,已注册 10 个标准化 Tools。\");\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport { VideoResolveSchema, AudioTranscribeSchema } from \"../../types.js\";\n\nexport function registerMediaTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_video_resolve\",\n {\n description: \"传入抖音、视频号、小红书、快手、B站等各大平台的分享文案或链接,自动识别平台去水印解析,提取无水印高清视频播放直链、封面图、标题、作者及时长数据(对应 /tools/material/remove-watermark 页面)\",\n inputSchema: VideoResolveSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.resolveVideo(args);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `视频解析失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_audio_transcribe\",\n {\n description: \"传入短视频分享文案/链接(自动识别抖音、小红书、快手等普通视频与微信视频号并自动解密转写,对应 /tools/copy/extract 和 /tools/copy/extract-finder),或本地音视频文件(先直传对象存储,再创建异步转写任务),转写为纯文本、SRT字幕或带时间戳段落详情\",\n inputSchema: AudioTranscribeSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.transcribeAudio(args);\n return {\n content: [\n {\n type: \"text\" as const,\n text: typeof result === \"string\" ? result : JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `音频转写失败: ${message}` }],\n };\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport {\n DySearchVideosSchema,\n DyGetVideoDetailSchema,\n DyGetPlayStatsSchema,\n DyGetCommentsSchema,\n DyGetUserProfileSchema,\n} from \"../../types.js\";\n\nexport function registerDouyinTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_dy_search_videos\",\n {\n description: \"关键词搜索抖音热门视频,支持按综合、最新、最多点赞排序及发布时间筛选,返回包含点赞、播放、标题和作者的作品列表\",\n inputSchema: DySearchVideosSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.searchDyVideos(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `抖音视频搜索失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_dy_get_video_detail\",\n {\n description: \"获取指定抖音视频详情:标题、作者、封面、播放地址,以及点赞、评论、分享、收藏数。不含播放量,也不含秒级互动趋势。只传 url\",\n inputSchema: DyGetVideoDetailSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyVideoDetail(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音视频详情失败: ${message}` }],\n };\n }\n }\n );\n server.registerTool(\n \"dataclaw_dy_get_play_stats\",\n {\n description: \"查询抖音视频播放量、完播率等星图统计。详情接口不含播放量,必须单独调用本工具。只传 url,或 aweme_id(会转成 url)\",\n inputSchema: DyGetPlayStatsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyPlayStats(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音播放量失败: ${message}` }],\n };\n }\n }\n );\n\n\n server.registerTool(\n \"dataclaw_dy_get_comments\",\n {\n description: \"获取指定抖音视频的一级评论(含置顶、点赞数、回复数)。传 url 或 aweme_id,不要把整段链接填进 aweme_id\",\n inputSchema: DyGetCommentsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyComments(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音评论失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_dy_get_user_profile\",\n {\n description: \"获取抖音博主主页资料:昵称、粉丝数、作品数、简介。不含粉丝画像和历史作品列表\",\n inputSchema: DyGetUserProfileSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getDyUserProfile(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取抖音博主信息失败: ${message}` }],\n };\n }\n }\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataClawClient } from \"../client.js\";\nimport {\n ChannelsSearchAuthorsSchema,\n ChannelsGetAuthorFeedsSchema,\n ChannelsResolveShareUrlSchema,\n} from \"../../types.js\";\n\nexport function registerChannelsTools(server: McpServer, client: DataClawClient): void {\n server.registerTool(\n \"dataclaw_channels_search_authors\",\n {\n description: \"关键词搜索微信视频号创作者/博主,获取博主 finder_username、头像及认证简介\",\n inputSchema: ChannelsSearchAuthorsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.searchChannelsAuthors(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `搜索视频号创作者失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_channels_get_author_feeds\",\n {\n description: \"根据作者 finder_username 获取视频号作品 Feed,每页 15 条。首页不传 last_buffer,下一页传上次返回的 buffer\",\n inputSchema: ChannelsGetAuthorFeedsSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.getChannelsAuthorFeeds(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `获取视频号作品列表失败: ${message}` }],\n };\n }\n }\n );\n\n server.registerTool(\n \"dataclaw_channels_resolve_share_url\",\n {\n description: \"根据微信视频号分享文本或短链解析作品全量数据、互动指标及无水印高清视频源\",\n inputSchema: ChannelsResolveShareUrlSchema.shape,\n },\n async (args) => {\n try {\n const result = await client.resolveChannelsShareUrl(args);\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `解析视频号分享链接失败: ${message}` }],\n };\n }\n }\n );\n\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nexport type IdeTarget = \"cursor\" | \"claude-desktop\" | \"claude-code\" | \"windsurf\" | \"codex\";\n\nexport interface IdeInfo {\n id: IdeTarget;\n name: string;\n detected: boolean;\n configPath?: string;\n skillsDir?: string;\n}\n\nexport function detectIdeEnvironments(targetDir: string = process.cwd()): IdeInfo[] {\n const home = os.homedir();\n const platform = process.platform;\n\n // 1. Cursor\n const cursorLocal = path.join(targetDir, \".cursor\");\n const cursorGlobal = path.join(home, \".cursor\");\n const cursorDetected = fs.existsSync(cursorLocal) || fs.existsSync(cursorGlobal);\n const cursorInfo: IdeInfo = {\n id: \"cursor\",\n name: \"Cursor (.cursor/rules + mcp.json)\",\n detected: cursorDetected,\n configPath: path.join(targetDir, \".cursor\", \"mcp.json\"),\n skillsDir: path.join(targetDir, \".cursor\", \"rules\"),\n };\n\n // 2. Claude Desktop\n let claudeDesktopConfigPath = \"\";\n if (platform === \"darwin\") {\n claudeDesktopConfigPath = path.join(home, \"Library\", \"Application Support\", \"Claude\", \"claude_desktop_config.json\");\n } else if (platform === \"win32\") {\n const appData = process.env.APPDATA || path.join(home, \"AppData\", \"Roaming\");\n claudeDesktopConfigPath = path.join(appData, \"Claude\", \"claude_desktop_config.json\");\n } else {\n claudeDesktopConfigPath = path.join(home, \".config\", \"Claude\", \"claude_desktop_config.json\");\n }\n const claudeDesktopDetected = fs.existsSync(path.dirname(claudeDesktopConfigPath));\n const claudeDesktopInfo: IdeInfo = {\n id: \"claude-desktop\",\n name: \"Claude Desktop (claude_desktop_config.json)\",\n detected: claudeDesktopDetected,\n configPath: claudeDesktopConfigPath,\n };\n\n // 3. Claude Code\n const claudeCodeLocal = path.join(targetDir, \".claude\");\n const claudeCodeGlobal = path.join(home, \".claude\");\n const claudeCodeDetected = fs.existsSync(claudeCodeLocal) || fs.existsSync(claudeCodeGlobal);\n const claudeCodeInfo: IdeInfo = {\n id: \"claude-code\",\n name: \"Claude Code (.claude/skills)\",\n detected: claudeCodeDetected,\n configPath: path.join(targetDir, \".claude\", \"mcp.json\"),\n skillsDir: path.join(targetDir, \".claude\", \"skills\"),\n };\n\n // 4. Windsurf\n const windsurfGlobalConfig = path.join(home, \".codeium\", \"windsurf\", \"mcp_config.json\");\n const windsurfLocal = path.join(targetDir, \".windsurf\");\n const windsurfDetected = fs.existsSync(windsurfLocal) || fs.existsSync(path.dirname(windsurfGlobalConfig));\n const windsurfInfo: IdeInfo = {\n id: \"windsurf\",\n name: \"Windsurf (mcp_config.json)\",\n detected: windsurfDetected,\n configPath: windsurfGlobalConfig,\n skillsDir: path.join(targetDir, \".windsurf\", \"rules\"),\n };\n // 5. Codex\n const codexLocal = path.join(targetDir, \".codex\");\n const codexGlobal = path.join(home, \".codex\");\n const codexDetected = fs.existsSync(codexLocal) || fs.existsSync(codexGlobal);\n const codexInfo: IdeInfo = {\n id: \"codex\",\n name: \"Codex (.codex/mcp.json + skills)\",\n detected: codexDetected,\n configPath: path.join(targetDir, \".codex\", \"mcp.json\"),\n skillsDir: path.join(targetDir, \".codex\", \"skills\"),\n };\n\n return [cursorInfo, claudeDesktopInfo, claudeCodeInfo, windsurfInfo, codexInfo];\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { IdeTarget } from \"./detect.js\";\n\nexport const MEDIA_SKILL_TEMPLATE = `---\ndescription: 视频去水印下载、全平台图集提取与音视频智能转文案 SOP\nglobs: \n---\n\n# 视频去水印下载与文案提取 SOP (Video Download & Transcribe)\n\n当用户意图涉及“下载视频/无水印提取”、“提取抖音/视频号/小红书等平台文案”、“把视频转成文字/提取字幕/总结大意”时,请严格按以下分支策略调用 DataClaw MCP 工具:\n\n## 分支策略与执行流程\n\n### 分支 A:用户需要提取文案 / 字幕 / 总结视频大意(一步直达)\n**核心原则**:转文案**无需**先调用解析工具获取直链,直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\` 一步直达,耗时更短且支持官方字幕缓存秒回。\n\n1. **直接调用转文案工具** \\\\\\`dataclaw_audio_transcribe\\\\\\`:\n - **网络短视频**:传参 \\\\\\`media_url = <用户提供的分享链接或文案>\\\\\\`。\n - 支持抖音、小红书、快手、B站等普通短视频(系统自动走 \\\\\\`/tools/copy/extract\\\\\\` 链路)。\n - 支持微信视频号短链(系统自动走 \\\\\\`/tools/copy/extract-finder\\\\\\` 链路,自动完成 WASM 解密)。\n - **本地音视频文件**:传参 local_file_path = <本地绝对路径>;MCP 会先直传对象存储,再创建异步转写任务,长文件等待任务完成。\n - **输出格式选择**:\n - 用户需要纯文本/总结大意:传 \\\\\\`output_format = \"text\"\\\\\\`。\n - 用户需要字幕/时间轴:传 \\\\\\`output_format = \"srt\"\\\\\\`。\n - 用户需要详细时间切片数据:传 \\\\\\`output_format = \"verbose_json\"\\\\\\`。\n\n2. **文案排版与提炼输出**:\n - 提取文案后,为用户按以下结构整理呈现:\n - **【主题概要】**:一句话概括视频核心内容。\n - **【关键金句 / 核心知识点】**:3~5 条高价值要点。\n - **【逐段逐句文案】**:清洗去除口癖分段文稿(若选了 srt 则提供标准带时间轴字幕格式)。\n\n---\n\n### 分支 B:用户需要下载无水印视频 / 获取高清图集\n当用户意图是“下载视频”、“保存原画素材”、“去除水印”或“下载小红书/抖音图集”时:\n\n1. **调用通用去水印工具** \\\\\\`dataclaw_video_resolve\\\\\\`:\n - 传参 \\\\\\`url = <用户提供的链接或包含链接的文案>\\\\\\`。\n - 系统自动识别平台(对应 \\\\\\`/tools/material/remove-watermark\\\\\\`),支持抖音、视频号、小红书、快手、TikTok 等全平台。\n2. **下载引导呈现**:\n - **若是视频**:返回无水印高清直链 \\\\\\`video_play_url\\\\\\`、视频封面 \\\\\\`cover_url\\\\\\`、标题 \\\\\\`title\\\\\\`、作者 \\\\\\`author\\\\\\` 及时长 \\\\\\`duration\\\\\\`。\n - **若是图集**:返回全量无水印高清图片直链列表 \\\\\\`images\\\\\\`。\n - 引导用户在浏览器中点击下载,或提供终端 \\\\\\`curl / wget\\\\\\` 下载命令。\n`;\n\nexport const DOUYIN_SKILL_TEMPLATE = `---\ndescription: 抖音热门视频复盘、爆款文案拆解与评论区痛点挖掘 SOP\nglobs: \n---\n\n# 抖音爆款视频复盘与痛点分析 SOP (Douyin Hot Video Audit)\n\n当用户意图涉及“分析抖音上做 [品类/行业] 的爆款视频”、“调研竞品评论区痛点/用户反馈”、“拆解对标账号的高赞脚本”时,请严格遵循以下步骤:\n\n## 执行流程\n\n1. **关键词检索热门视频**:\n - 调用工具 \\\\\\`dataclaw_dy_search_videos\\\\\\`:\n - \\\\\\`keyword\\\\\\`: 用户的目标行业、产品或主题关键词。\n - \\\\\\`sort_type\\\\\\`: 优先传 \\\\\\`\"most_liked\"\\\\\\`(最多点赞)或 \\\\\\`\"most_recent\"\\\\\\`(最新)。\n - \\\\\\`publish_time\\\\\\`: \\\\\\`\"0\"\\\\\\` 不限,\\\\\\`\"1\"\\\\\\` 最近一天,\\\\\\`\"7\"\\\\\\` 最近一周,\\\\\\`\"180\"\\\\\\` 最近半年。\n - 页大小固定,不要依赖 \\\\\\`count\\\\\\`。翻页带回上次返回的 \\\\\\`cursor\\\\\\`、\\\\\\`search_id\\\\\\`、\\\\\\`backtrace\\\\\\`。\n - 筛选出点赞量与互动最高的 TOP 3~5 个视频作品。\n\n2. **获取作品详情与互动指标**:\n - 针对筛选出的目标视频,调用 \\\\\\`dataclaw_dy_get_video_detail\\\\\\`。\n - 只拿标题、作者、封面、播放地址和点赞、评论、分享、收藏数。没有播放量,也没有秒级互动趋势。\n - 需要播放量或完播率时,另调 \\\\\\`dataclaw_dy_get_play_stats\\\\\\`,传同一个 \\\\\\`url\\\\\\`。详情和播放量的请求体字段都是 \\\\\\`url\\\\\\`,不要传 \\\\\\`share_url\\\\\\`。\n\n3. **抓取评论**:\n - 针对目标视频,调用 \\\\\\`dataclaw_dy_get_comments\\\\\\`,传 \\\\\\`url\\\\\\` 或纯数字 \\\\\\`aweme_id\\\\\\`。每页默认 50 条,最大 50。要更多就用上次返回的 \\\\\\`cursor\\\\\\` 再翻页。\n - 重点提取高赞热评与槽点。\n\n4. **爆款脚本逐字文案提炼(按需)**:\n - 若用户需要深入拆解爆款的台词脚本或钩子设计,直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\`(传入该视频的 share_url),获取逐字口播稿。\n\n5. **综合复盘分析输出**:\n - 综合以上数据,为用户输出深度复盘报告:\n - **【黄金开头拆解】**:前 3 秒钩子视觉与文案设计,分析其高完播原因。\n - **【脚本结构拆解】**:痛点引发 -> 价值阐述 -> 行动召唤 (CTA) 的节奏分布。\n - **【高频共鸣词云】**:观众讨论最热烈的关键词与情绪倾向。\n - **【痛点与未满足需求】**:评论区高赞吐槽、疑问及潜在买点。\n - **【爆款可复制建议】**:总结 3 条可直接落地的脚本创作建议。\n`;\n\nexport const CHANNELS_SKILL_TEMPLATE = `---\ndescription: 微信视频号创作者深度拆解、爆款 Feed 与互动监控 SOP\nglobs: \n---\n\n# 微信视频号达人与作品监控 SOP (Channels Creator Monitor)\n\n当用户意图涉及“拆解这个视频号博主”、“看看这个视频号最近发了什么”、“分析视频号竞品账号的表现”时,请严格遵循以下步骤:\n\n## 执行流程\n\n1. **创作者检索与定位**:\n - 若用户提供了博主昵称或关键词,调用 \\\\\\`dataclaw_channels_search_authors\\\\\\` 进行搜索。\n - 确认目标作者,获取其唯一标识 \\\\\\`finder_username\\\\\\`、头像及认证简介。\n\n2. **拉取近期作品 Feed**:\n - 调用 \\\\\\`dataclaw_channels_get_author_feeds\\\\\\`,传入作者 \\\\\\`finder_username\\\\\\`。\n - 每页 15 条。要 10~30 条就再传上次返回的 \\\\\\`last_buffer\\\\\\` / \\\\\\`buffer\\\\\\` 翻一页。\n\n3. **作品全量数据与文案/视频提取(按需)**:\n - **若需提取视频口播文案**:直接调用 \\\\\\`dataclaw_audio_transcribe\\\\\\`(传入作品分享短链,系统底层自动通过 WASM 解密视频号加密视频流并转写为文案或 SRT 字幕)。\n - **若需无水印下载视频**:调用 \\\\\\`dataclaw_video_resolve\\\\\\`(传入视频号分享短链),提取高清下载直链。\n\n4. **达人矩阵与运营策略提炼**:\n - 为用户输出深度分析报告:\n - **【发文节奏与偏好】**:近期更新频率、发布时间段偏好。\n - **【爆款内容特征】**:点赞/转发破万的题材特征与封面文案套路。\n - **【口播台词套路】**:针对代表作提取的台词脚本节奏与话术拆解。\n - **【互动转化分析】**:评论区互动热点与用户私域转化引导方式。\n - **【模仿与超越建议】**:对标同行的差异化定位策略。\n`;\n\nexport interface GenerationResult {\n configWritten?: string;\n skillsWritten: string[];\n}\n\nexport function writeMcpConfig(\n configFilePath: string,\n apiKey: string,\n customBaseUrl?: string\n): void {\n const dir = path.dirname(configFilePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n let existingJson: Record<string, unknown> = {};\n if (fs.existsSync(configFilePath)) {\n try {\n const content = fs.readFileSync(configFilePath, \"utf-8\");\n const parsed: unknown = JSON.parse(content);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n existingJson = parsed as Record<string, unknown>;\n }\n } catch {\n // 容错已损坏的 JSON\n }\n }\n\n const existingMcpServers = (\n existingJson.mcpServers && typeof existingJson.mcpServers === \"object\" && !Array.isArray(existingJson.mcpServers)\n ? existingJson.mcpServers\n : {}\n ) as Record<string, unknown>;\n\n const envVars: Record<string, string> = {\n DATACLAW_API_KEY: apiKey,\n };\n if (customBaseUrl) {\n envVars.DATACLAW_BASE_URL = customBaseUrl;\n }\n\n existingMcpServers.dataclaw = {\n command: \"npx\",\n args: [\"-y\", \"dataclaw-agent-kit\", \"mcp\"],\n env: envVars,\n };\n\n existingJson.mcpServers = existingMcpServers;\n fs.writeFileSync(configFilePath, JSON.stringify(existingJson, null, 2), \"utf-8\");\n}\n\nexport function writeSkillsToDir(\n skillsDir: string,\n skillKeys: Array<\"media\" | \"douyin\" | \"channels\">,\n extension: \".mdc\" | \".md\" = \".mdc\"\n): string[] {\n if (!fs.existsSync(skillsDir)) {\n fs.mkdirSync(skillsDir, { recursive: true });\n }\n\n const written: string[] = [];\n\n if (skillKeys.includes(\"media\")) {\n const file = path.join(skillsDir, `dataclaw-media${extension}`);\n fs.writeFileSync(file, MEDIA_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n if (skillKeys.includes(\"douyin\")) {\n const file = path.join(skillsDir, `dataclaw-douyin${extension}`);\n fs.writeFileSync(file, DOUYIN_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n if (skillKeys.includes(\"channels\")) {\n const file = path.join(skillsDir, `dataclaw-channels${extension}`);\n fs.writeFileSync(file, CHANNELS_SKILL_TEMPLATE, \"utf-8\");\n written.push(file);\n }\n\n return written;\n}\n","import path from \"node:path\";\nimport pc from \"picocolors\";\nimport prompts from \"prompts\";\nimport { DataClawClient } from \"../mcp/client.js\";\nimport { detectIdeEnvironments, type IdeTarget } from \"./detect.js\";\nimport { writeMcpConfig, writeSkillsToDir } from \"./generator.js\";\n\nexport async function runInitWizard(): Promise<void> {\n console.log(\n pc.cyan(`\n┌──────────────────────────────────────────────────────────┐\n│ 🦞 DataClaw AI Agent Kit (MCP & Skills) 安装向导 │\n└──────────────────────────────────────────────────────────┘\n`)\n );\n\n const defaultApiKey = process.env.DATACLAW_API_KEY || \"\";\n const detectedIdes = detectIdeEnvironments();\n\n // 1. 输入 API Key\n const keyResponse = await prompts({\n type: \"password\",\n name: \"apiKey\",\n message: \"请输入您的 DataClaw API-Key (从个人中心获取):\",\n initial: defaultApiKey,\n validate: (val: string) => (val.trim().length > 0 ? true : \"API-Key 不能为空\"),\n });\n\n const apiKey = (keyResponse.apiKey as string | undefined)?.trim();\n if (!apiKey) {\n console.log(pc.yellow(\"已取消安装向导。\"));\n return;\n }\n\n // 2. 验证 API Key\n const client = new DataClawClient({ apiKey });\n console.log(pc.dim(\"正在验证 API-Key 有效性...\"));\n try {\n const me = await client.getMe();\n console.log(\n pc.green(`✔ 鉴权验证成功!当前用户: ${me.username} (积分余额: ${me.credit ?? \"无限制\"} 点)`)\n );\n } catch (err: unknown) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n console.log(pc.yellow(`⚠️ 鉴权验证未通过: ${errorMsg}`));\n const confirm = await prompts({\n type: \"confirm\",\n name: \"continueAnyway\",\n message: \"是否仍要继续使用此 API-Key 完成安装?\",\n initial: true,\n });\n if (!confirm.continueAnyway) {\n console.log(pc.yellow(\"已取消安装。\"));\n return;\n }\n }\n\n // 3. 选择 IDE 宿主环境\n const ideChoices = detectedIdes.map((ide) => ({\n title: ide.name,\n value: ide.id,\n selected: ide.detected,\n }));\n\n const ideResponse = await prompts({\n type: \"multiselect\",\n name: \"targets\",\n message: \"请选择需要注入配置的 AI 宿主环境:\",\n choices: ideChoices,\n min: 1,\n hint: \"- 空格切换选中,回车确认\",\n });\n\n const selectedTargets = (ideResponse.targets as IdeTarget[] | undefined) || [];\n if (selectedTargets.length === 0) {\n console.log(pc.yellow(\"未选择任何宿主环境,已退出。\"));\n return;\n }\n\n // 4. 选择启用的技能\n const skillResponse = await prompts({\n type: \"multiselect\",\n name: \"skills\",\n message: \"请勾选需要启用的第一期场景技能:\",\n choices: [\n {\n title: \"[视频处理] 视频无水印直链提取与音频智能语音转写 SOP\",\n value: \"media\",\n selected: true,\n },\n {\n title: \"[抖音分析] 热门视频检索、爆款文案与评论痛点挖掘 SOP\",\n value: \"douyin\",\n selected: true,\n },\n {\n title: \"[微信视频号] 达人主页深度拆解与作品动态监控 SOP\",\n value: \"channels\",\n selected: true,\n },\n ],\n min: 1,\n });\n\n const selectedSkills = (skillResponse.skills as Array<\"media\" | \"douyin\" | \"channels\"> | undefined) || [];\n if (selectedSkills.length === 0) {\n console.log(pc.yellow(\"未选择任何技能,已退出。\"));\n return;\n }\n\n console.log(\"\");\n\n // 5. 写入配置与技能\n for (const target of selectedTargets) {\n const ideMeta = detectedIdes.find((item) => item.id === target);\n if (!ideMeta) continue;\n\n // 写入 MCP Server 配置\n if (ideMeta.configPath) {\n try {\n writeMcpConfig(ideMeta.configPath, apiKey);\n console.log(pc.green(`✔ 配置文件已写入: ${path.relative(process.cwd(), ideMeta.configPath) || ideMeta.configPath}`));\n } catch (err: unknown) {\n console.error(pc.red(`✖ 写入配置文件失败 (${ideMeta.configPath}): ${err instanceof Error ? err.message : String(err)}`));\n }\n }\n\n // 写入技能 Markdown SOP\n if (ideMeta.skillsDir) {\n try {\n const ext = target === \"cursor\" ? \".mdc\" : \".md\";\n const writtenFiles = writeSkillsToDir(ideMeta.skillsDir, selectedSkills, ext);\n for (const f of writtenFiles) {\n console.log(pc.green(`✔ 场景技能已生成: ${path.relative(process.cwd(), f) || f}`));\n }\n } catch (err: unknown) {\n console.error(pc.red(`✖ 写入技能文件失败: ${err instanceof Error ? err.message : String(err)}`));\n }\n }\n }\n\n console.log(\n pc.cyan(`\n🎉 安装完成!在 Cursor Composer、Claude 或 Codex 中直接提问体验:\n \"帮我把这个抖音链接的内容转成文章: https://v.douyin.com/...\"\n \"分析抖音上做小吃加盟的点赞最高视频与评论痛点\"\n`)\n );\n}\n"],"mappings":"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","names":["fs","path","fs","path","path","path"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -174,7 +174,7 @@ declare class DataClawClient {
|
|
|
174
174
|
declare function createMcpServer(client?: DataClawClient): McpServer;
|
|
175
175
|
declare function startMcpServer(client?: DataClawClient): Promise<void>;
|
|
176
176
|
|
|
177
|
-
type IdeTarget = "cursor" | "claude-desktop" | "claude-code" | "windsurf";
|
|
177
|
+
type IdeTarget = "cursor" | "claude-desktop" | "claude-code" | "windsurf" | "codex";
|
|
178
178
|
interface IdeInfo {
|
|
179
179
|
id: IdeTarget;
|
|
180
180
|
name: string;
|
package/dist/index.js
CHANGED