dataclaw-agent-kit 0.1.2 → 0.1.4

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.
@@ -40,7 +40,10 @@ ${s.text?.trim() || ""}
40
40
  var DY_SEARCH_SORT = {
41
41
  general: "0",
42
42
  most_liked: "1",
43
- most_recent: "2"
43
+ most_recent: "2",
44
+ "0": "0",
45
+ "1": "1",
46
+ "2": "2"
44
47
  };
45
48
  var DY_AWEME_RE = /(?:modal_id|vid|item_id|aweme_id)=([0-9]{6,})|(?:video|slides|note|photo|article|shipin)\/([0-9]{6,})/;
46
49
  function douyinAwemeId(raw) {
@@ -67,6 +70,241 @@ function douyinCommentTarget(input) {
67
70
  if (direct) return { url: direct };
68
71
  throw new Error("\u8BF7\u63D0\u4F9B url \u6216 aweme_id");
69
72
  }
73
+ function pruneDySearchResponse(raw) {
74
+ if (!raw || typeof raw !== "object") return raw;
75
+ const rawData = raw.data && typeof raw.data === "object" ? raw.data : raw;
76
+ const list = Array.isArray(rawData.data) ? rawData.data : Array.isArray(rawData.items) ? rawData.items : Array.isArray(raw.data) ? raw.data : Array.isArray(raw.items) ? raw.items : null;
77
+ if (!list) return raw;
78
+ const items = list.map((item) => {
79
+ if (!item || typeof item !== "object") return item;
80
+ const aweme = item.aweme_info ? item.aweme_info : item;
81
+ const author = aweme.author && typeof aweme.author === "object" ? aweme.author : {};
82
+ const stats = aweme.statistics && typeof aweme.statistics === "object" ? aweme.statistics : {};
83
+ const rawVideo = aweme.video && typeof aweme.video === "object" ? aweme.video : {};
84
+ const video = rawVideo.video && typeof rawVideo.video === "object" ? rawVideo.video : rawVideo;
85
+ const cover = video.cover && typeof video.cover === "object" ? video.cover : video.origin_cover;
86
+ const coverUrls = Array.isArray(cover?.url_list) ? cover.url_list : [];
87
+ const durationRaw = typeof video.duration === "number" ? video.duration : typeof aweme.duration === "number" ? aweme.duration : 0;
88
+ const durationSeconds = durationRaw > 1e3 ? Math.round(durationRaw / 1e3) : durationRaw;
89
+ return {
90
+ aweme_id: aweme.aweme_id || aweme.item_id || "",
91
+ title: aweme.desc || aweme.title || "",
92
+ create_time: aweme.create_time,
93
+ duration: durationSeconds,
94
+ duration_formatted: durationSeconds > 0 ? `${Math.floor(durationSeconds / 60)}\u5206${durationSeconds % 60}\u79D2` : void 0,
95
+ author: {
96
+ nickname: author.nickname || "",
97
+ sec_uid: author.sec_uid || "",
98
+ signature: author.signature || void 0,
99
+ avatar: Array.isArray(author.avatar_thumb?.url_list) ? author.avatar_thumb.url_list[0] : void 0
100
+ },
101
+ statistics: {
102
+ digg_count: typeof stats.digg_count === "number" ? stats.digg_count : 0,
103
+ comment_count: typeof stats.comment_count === "number" ? stats.comment_count : 0,
104
+ share_count: typeof stats.share_count === "number" ? stats.share_count : 0,
105
+ collect_count: typeof stats.collect_count === "number" ? stats.collect_count : 0
106
+ },
107
+ cover_url: coverUrls[0] || "",
108
+ share_url: aweme.share_url || (aweme.aweme_id ? `https://www.douyin.com/video/${aweme.aweme_id}` : void 0)
109
+ };
110
+ });
111
+ return {
112
+ count: items.length,
113
+ cursor: rawData.cursor ?? raw.cursor ?? 0,
114
+ has_more: Boolean(rawData.has_more ?? raw.has_more),
115
+ search_id: rawData.search_id ?? raw.search_id,
116
+ backtrace: rawData.backtrace ?? raw.backtrace,
117
+ items
118
+ };
119
+ }
120
+ function pruneDyDetailResponse(raw) {
121
+ if (!raw || typeof raw !== "object") return raw;
122
+ const detail = raw.aweme_detail && typeof raw.aweme_detail === "object" ? raw.aweme_detail : raw;
123
+ if (!detail || !detail.aweme_id && !detail.desc && !detail.statistics) return raw;
124
+ const author = detail.author && typeof detail.author === "object" ? detail.author : {};
125
+ const stats = detail.statistics && typeof detail.statistics === "object" ? detail.statistics : {};
126
+ const video = detail.video && typeof detail.video === "object" ? detail.video : {};
127
+ const playAddr = video.play_addr && typeof video.play_addr === "object" ? video.play_addr : video.play_addr_h264;
128
+ const playUrls = Array.isArray(playAddr?.url_list) ? playAddr.url_list : [];
129
+ const coverObj = video.origin_cover || video.cover;
130
+ const coverUrls = Array.isArray(coverObj?.url_list) ? coverObj.url_list : [];
131
+ const durationRaw = typeof video.duration === "number" ? video.duration : typeof detail.duration === "number" ? detail.duration : 0;
132
+ const durationSeconds = durationRaw > 1e3 ? Math.round(durationRaw / 1e3) : durationRaw;
133
+ const textExtra = Array.isArray(detail.text_extra) ? detail.text_extra : [];
134
+ const hashtags = textExtra.map((t) => t.hashtag_name).filter(Boolean);
135
+ return {
136
+ aweme_id: detail.aweme_id || "",
137
+ title: detail.desc || detail.title || "",
138
+ create_time: detail.create_time,
139
+ share_url: detail.share_url || (detail.aweme_id ? `https://www.douyin.com/video/${detail.aweme_id}` : ""),
140
+ author: {
141
+ nickname: author.nickname || "",
142
+ sec_uid: author.sec_uid || "",
143
+ unique_id: author.unique_id || author.short_id || "",
144
+ signature: author.signature || "",
145
+ avatar: Array.isArray(author.avatar_thumb?.url_list) ? author.avatar_thumb.url_list[0] : void 0
146
+ },
147
+ statistics: {
148
+ digg_count: typeof stats.digg_count === "number" ? stats.digg_count : 0,
149
+ comment_count: typeof stats.comment_count === "number" ? stats.comment_count : 0,
150
+ collect_count: typeof stats.collect_count === "number" ? stats.collect_count : 0,
151
+ share_count: typeof stats.share_count === "number" ? stats.share_count : 0
152
+ },
153
+ video: {
154
+ duration: durationSeconds,
155
+ duration_formatted: durationSeconds > 0 ? `${Math.floor(durationSeconds / 60)}\u5206${durationSeconds % 60}\u79D2` : void 0,
156
+ play_url: playUrls[0] || video.play_url || "",
157
+ cover_url: coverUrls[0] || video.cover_url || ""
158
+ },
159
+ hashtags
160
+ };
161
+ }
162
+ function pruneDyPlayStatsResponse(raw) {
163
+ if (!raw || typeof raw !== "object") return raw;
164
+ const vi = raw.video_info && typeof raw.video_info === "object" ? raw.video_info : raw;
165
+ if (!vi || vi.play_count === void 0 && vi.finish_rate === void 0) return raw;
166
+ return {
167
+ item_id: vi.item_id || vi.video_id || raw.item_id || "",
168
+ play_count: vi.play_count ?? 0,
169
+ finish_rate: vi.finish_rate ?? null,
170
+ play_over_rate: vi.play_over_rate ?? vi.finish_rate ?? null,
171
+ like_cnt: vi.like_cnt ?? vi.digg_count ?? void 0,
172
+ comment_cnt: vi.comment_cnt ?? vi.comment_count ?? void 0,
173
+ share_cnt: vi.share_cnt ?? vi.share_count ?? void 0,
174
+ play_count_formatted: typeof vi.play_count === "number" ? vi.play_count.toLocaleString() : void 0
175
+ };
176
+ }
177
+ function pruneDyCommentsResponse(raw) {
178
+ if (!raw || typeof raw !== "object") return raw;
179
+ const commentsRaw = Array.isArray(raw.comments) ? raw.comments : null;
180
+ if (!commentsRaw) return raw;
181
+ const comments = commentsRaw.map((item) => {
182
+ if (!item || typeof item !== "object") return item;
183
+ const c = item;
184
+ const user = c.user && typeof c.user === "object" ? c.user : {};
185
+ return {
186
+ cid: c.cid || "",
187
+ text: c.text || "",
188
+ digg_count: typeof c.digg_count === "number" ? c.digg_count : 0,
189
+ reply_count: typeof c.reply_comment_total === "number" ? c.reply_comment_total : 0,
190
+ create_time: c.create_time,
191
+ ip_label: c.ip_label || "",
192
+ user: {
193
+ nickname: user.nickname || "\u6296\u97F3\u7528\u6237",
194
+ sec_uid: user.sec_uid || ""
195
+ }
196
+ };
197
+ });
198
+ return {
199
+ aweme_id: raw.aweme_id,
200
+ count: comments.length,
201
+ total: raw.total,
202
+ cursor: raw.cursor ?? 0,
203
+ has_more: Boolean(raw.has_more),
204
+ comments
205
+ };
206
+ }
207
+ function pruneDyUserProfileResponse(raw) {
208
+ if (!raw || typeof raw !== "object") return raw;
209
+ const user = raw.user && typeof raw.user === "object" ? raw.user : raw.data && typeof raw.data === "object" ? raw.data : raw;
210
+ if (!user || !user.nickname && !user.sec_uid && !user.unique_id) return raw;
211
+ const avatar = Array.isArray(user.avatar_larger?.url_list) ? user.avatar_larger.url_list[0] : Array.isArray(user.avatar_thumb?.url_list) ? user.avatar_thumb.url_list[0] : void 0;
212
+ return {
213
+ nickname: user.nickname || "",
214
+ sec_uid: user.sec_uid || "",
215
+ unique_id: user.unique_id || user.short_id || "",
216
+ signature: user.signature || "",
217
+ avatar,
218
+ follower_count: typeof user.follower_count === "number" ? user.follower_count : 0,
219
+ following_count: typeof user.following_count === "number" ? user.following_count : 0,
220
+ total_favorited: typeof user.total_favorited === "number" ? user.total_favorited : 0,
221
+ aweme_count: typeof user.aweme_count === "number" ? user.aweme_count : 0,
222
+ ip_location: user.ip_location || void 0,
223
+ verification: user.custom_verify || user.enterprise_verify_reason || void 0
224
+ };
225
+ }
226
+ function pruneChannelsSearchAuthorsResponse(raw) {
227
+ if (!raw || typeof raw !== "object") return raw;
228
+ const rawData = raw.data && typeof raw.data === "object" ? raw.data : raw;
229
+ const list = Array.isArray(rawData.list) ? rawData.list : Array.isArray(raw.list) ? raw.list : Array.isArray(raw.authors) ? raw.authors : null;
230
+ if (!list) return raw;
231
+ const authors = list.map((item) => {
232
+ if (!item || typeof item !== "object") return item;
233
+ const a = item;
234
+ return {
235
+ finder_username: a.username || a.finder_username || "",
236
+ nickname: a.nickname || "",
237
+ head_url: a.headUrl || a.head_url || "",
238
+ signature: a.signature || a.desc || "",
239
+ auth_profession: a.authProfession || a.auth_profession || void 0,
240
+ fans_count: a.fansCount ?? a.fans_count ?? void 0
241
+ };
242
+ });
243
+ return {
244
+ count: authors.length,
245
+ buffer: rawData.buffer || raw.buffer || "",
246
+ continue_flag: Boolean(rawData.continueFlag ?? rawData.continue_flag ?? raw.continueFlag),
247
+ authors
248
+ };
249
+ }
250
+ function pruneChannelsFeedsResponse(raw) {
251
+ if (!raw || typeof raw !== "object") return raw;
252
+ const rawData = raw.data && typeof raw.data === "object" ? raw.data : raw;
253
+ const list = Array.isArray(rawData.list) ? rawData.list : Array.isArray(raw.list) ? raw.list : Array.isArray(raw.feeds) ? raw.feeds : null;
254
+ if (!list) return raw;
255
+ const feeds = list.map((item) => {
256
+ if (!item || typeof item !== "object") return item;
257
+ const f = item;
258
+ const mediaList = Array.isArray(f.media) ? f.media : [];
259
+ const media = mediaList[0] || {};
260
+ return {
261
+ object_id: f.objectId || f.object_id || "",
262
+ description: f.description || "",
263
+ createtime: f.createtime || f.create_time,
264
+ statistics: {
265
+ like_count: f.likeCount ?? f.like_count ?? 0,
266
+ forward_count: f.forwardCount ?? f.forward_count ?? 0,
267
+ fav_count: f.favCount ?? f.fav_count ?? 0,
268
+ comment_count: f.commentCount ?? f.comment_count ?? 0
269
+ },
270
+ cover_url: media.thumbUrl || media.coverUrl || "",
271
+ media_type: f.mediaType || media.mediaType
272
+ };
273
+ });
274
+ return {
275
+ count: feeds.length,
276
+ last_buffer: rawData.lastBuffer || rawData.last_buffer || raw.lastBuffer || raw.last_buffer || "",
277
+ continue_flag: Boolean(rawData.continueFlag ?? rawData.continue_flag ?? raw.continueFlag),
278
+ feeds
279
+ };
280
+ }
281
+ function pruneChannelsShareUrlResponse(raw) {
282
+ if (!raw || typeof raw !== "object") return raw;
283
+ const data = raw.data && typeof raw.data === "object" ? raw.data : raw;
284
+ const feed = data.feedInfo || data.feed || data;
285
+ if (!feed || !feed.objectId && !feed.description && !feed.media) return raw;
286
+ const contact = feed.contact && typeof feed.contact === "object" ? feed.contact : {};
287
+ const mediaList = Array.isArray(feed.media) ? feed.media : [];
288
+ const media = mediaList[0] || {};
289
+ return {
290
+ object_id: feed.objectId || data.objectId || "",
291
+ description: feed.description || data.description || "",
292
+ createtime: feed.createtime || data.createtime,
293
+ author: {
294
+ nickname: contact.nickname || data.nickname || "",
295
+ head_url: contact.headUrl || data.headUrl || "",
296
+ finder_username: contact.username || ""
297
+ },
298
+ statistics: {
299
+ like_count: feed.likeCount ?? data.likeCount ?? 0,
300
+ forward_count: feed.forwardCount ?? data.forwardCount ?? 0,
301
+ fav_count: feed.favCount ?? data.favCount ?? 0,
302
+ comment_count: feed.commentCount ?? data.commentCount ?? 0
303
+ },
304
+ video_url: media.url || feed.videoUrl || data.videoUrl || "",
305
+ cover_url: media.thumbUrl || feed.coverUrl || data.coverUrl || ""
306
+ };
307
+ }
70
308
  var DataClawClient = class {
71
309
  apiKey;
72
310
  baseUrl;
@@ -282,14 +520,23 @@ var DataClawClient = class {
282
520
  }
283
521
  }
284
522
  async transcribeAudio(params) {
285
- const rawUrl = params.local_file_path ? await this.uploadLocalFileToR2(params.local_file_path) : (params.media_url || "").trim();
523
+ let localFilePath = params.local_file_path?.trim();
524
+ let mediaUrl = (params.media_url || "").trim();
525
+ if (!localFilePath && mediaUrl) {
526
+ const cleanPath = mediaUrl.startsWith("file://") ? mediaUrl.slice(7) : mediaUrl;
527
+ if (fs.existsSync(cleanPath) && (path.isAbsolute(cleanPath) || /^[a-zA-Z]:[/\\]/.test(cleanPath) || cleanPath.startsWith("./") || cleanPath.startsWith("../"))) {
528
+ localFilePath = cleanPath;
529
+ mediaUrl = "";
530
+ }
531
+ }
532
+ const rawUrl = localFilePath ? await this.uploadLocalFileToR2(localFilePath) : mediaUrl;
286
533
  if (!rawUrl) {
287
534
  throw new Error("\u5FC5\u987B\u63D0\u4F9B media_url \u6216 local_file_path \u4E4B\u4E00");
288
535
  }
289
536
  const isFinder = /channels\.weixin\.qq\.com|weixin\.qq\.com\/sph\/|finder\.video\.qq\.com/i.test(rawUrl);
290
537
  let taskId = "";
291
- if (params.local_file_path) {
292
- const fileName = path.basename(params.local_file_path);
538
+ if (localFilePath) {
539
+ const fileName = path.basename(localFilePath);
293
540
  const batchRes = await this.request("/api/task/create/batch", {
294
541
  method: "POST",
295
542
  body: JSON.stringify({
@@ -448,26 +695,29 @@ var DataClawClient = class {
448
695
  };
449
696
  if (params.search_id) body.search_id = params.search_id;
450
697
  if (params.backtrace) body.backtrace = params.backtrace;
451
- return this.request("/api/v2/dy/search/video", {
698
+ const res = await this.request("/api/v2/dy/search/video", {
452
699
  method: "POST",
453
700
  body: JSON.stringify(body)
454
701
  });
702
+ return params.raw ? res : pruneDySearchResponse(res);
455
703
  }
456
704
  async getDyVideoDetail(params) {
457
- return this.request("/api/v2/dy/detail", {
705
+ const res = await this.request("/api/v2/dy/detail", {
458
706
  method: "POST",
459
707
  body: JSON.stringify({ url: douyinVideoUrl(params) })
460
708
  });
709
+ return params.raw ? res : pruneDyDetailResponse(res);
461
710
  }
462
711
  async getDyPlayStats(params) {
463
- return this.request("/api/dy/video/play-stats", {
712
+ const res = await this.request("/api/dy/video/play-stats", {
464
713
  method: "POST",
465
714
  body: JSON.stringify({ url: douyinVideoUrl(params) })
466
715
  });
716
+ return params.raw ? res : pruneDyPlayStatsResponse(res);
467
717
  }
468
718
  async getDyComments(params) {
469
719
  const target = douyinCommentTarget(params);
470
- return this.request("/api/v2/dy/video/comments", {
720
+ const res = await this.request("/api/v2/dy/video/comments", {
471
721
  method: "POST",
472
722
  body: JSON.stringify({
473
723
  url: target.url,
@@ -476,15 +726,17 @@ var DataClawClient = class {
476
726
  count: params.count ?? 50
477
727
  })
478
728
  });
729
+ return params.raw ? res : pruneDyCommentsResponse(res);
479
730
  }
480
731
  async getDyUserProfile(params) {
481
- return this.request("/api/v2/dy/user/detail", {
732
+ const res = await this.request("/api/v2/dy/user/detail", {
482
733
  method: "POST",
483
734
  body: JSON.stringify({
484
735
  sec_user_id: params.sec_user_id,
485
736
  url: params.url || params.profile_url
486
737
  })
487
738
  });
739
+ return params.raw ? res : pruneDyUserProfileResponse(res);
488
740
  }
489
741
  // ==========================================
490
742
  // 视频号域 Tools
@@ -492,7 +744,7 @@ var DataClawClient = class {
492
744
  async searchChannelsAuthors(params) {
493
745
  const query = params.keyword.trim();
494
746
  if (!query) throw new Error("\u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD");
495
- return this.request("/api/v2/mp/finder/search-authors", {
747
+ const res = await this.request("/api/v2/mp/finder/search-authors", {
496
748
  method: "POST",
497
749
  body: JSON.stringify({
498
750
  query,
@@ -501,11 +753,12 @@ var DataClawClient = class {
501
753
  scene: params.scene ?? 1
502
754
  })
503
755
  });
756
+ return params.raw ? res : pruneChannelsSearchAuthorsResponse(res);
504
757
  }
505
758
  async getChannelsAuthorFeeds(params) {
506
759
  const username = params.finder_username.trim();
507
760
  if (!username) throw new Error("\u8BF7\u63D0\u4F9B finder_username");
508
- return this.request("/api/v2/mp/finder/feeds", {
761
+ const res = await this.request("/api/v2/mp/finder/feeds", {
509
762
  method: "POST",
510
763
  body: JSON.stringify({
511
764
  username,
@@ -514,12 +767,14 @@ var DataClawClient = class {
514
767
  scene: 0
515
768
  })
516
769
  });
770
+ return params.raw ? res : pruneChannelsFeedsResponse(res);
517
771
  }
518
772
  async resolveChannelsShareUrl(params) {
519
- return this.request("/api/v2/mp/finder/video-by-share-url", {
773
+ const res = await this.request("/api/v2/mp/finder/video-by-share-url", {
520
774
  method: "POST",
521
775
  body: JSON.stringify(params)
522
776
  });
777
+ return params.raw ? res : pruneChannelsShareUrlResponse(res);
523
778
  }
524
779
  };
525
780
 
@@ -535,44 +790,52 @@ var AudioTranscribeSchema = z.object({
535
790
  });
536
791
  var DySearchVideosSchema = z.object({
537
792
  keyword: z.string().describe("\u641C\u7D22\u5173\u952E\u8BCD"),
538
- sort_type: z.enum(["general", "most_recent", "most_liked"]).default("general").describe("\u6392\u5E8F\uFF1A\u7EFC\u5408(general\u21920)\u3001\u6700\u591A\u70B9\u8D5E(most_liked\u21921)\u3001\u6700\u65B0(most_recent\u21922)"),
539
- publish_time: z.enum(["0", "1", "7", "180"]).default("0").describe("\u53D1\u5E03\u65F6\u95F4\uFF1A0 \u4E0D\u9650\uFF0C1 \u6700\u8FD1\u4E00\u5929\uFF0C7 \u6700\u8FD1\u4E00\u5468\uFF0C180 \u6700\u8FD1\u534A\u5E74"),
793
+ sort_type: z.enum(["general", "most_recent", "most_liked", "0", "1", "2"]).default("general").describe("\u6392\u5E8F\uFF1A\u7EFC\u5408(general\u21920)\u3001\u6700\u591A\u70B9\u8D5E(most_liked\u21921)\u3001\u6700\u65B0(most_recent\u21922)"),
794
+ publish_time: z.union([z.string().refine(() => true), z.number()]).transform((v) => String(v)).default("0").describe("\u53D1\u5E03\u65F6\u95F4\uFF1A0 \u4E0D\u9650\uFF0C1 \u6700\u8FD1\u4E00\u5929\uFF0C7 \u6700\u8FD1\u4E00\u5468\uFF0C180 \u6700\u8FD1\u534A\u5E74"),
540
795
  count: z.number().min(1).max(20).default(10).describe("\u517C\u5BB9\u5B57\u6BB5\u3002\u4E0A\u6E38\u9875\u5927\u5C0F\u56FA\u5B9A\uFF0C\u8C03\u7528\u65F6\u5FFD\u7565"),
541
796
  cursor: z.number().optional().describe("\u5206\u9875\u6E38\u6807\uFF0C\u9996\u9875\u4E0D\u4F20\u6216\u4F20 0\uFF0C\u4E0B\u4E00\u9875\u4F7F\u7528\u4E0A\u6B21\u8FD4\u56DE\u7684 cursor"),
542
797
  search_id: z.string().optional().describe("\u7FFB\u9875\u65F6\u5E26\u56DE\u4E0A\u6B21\u8FD4\u56DE\u7684 search_id"),
543
- backtrace: z.string().optional().describe("\u7FFB\u9875\u65F6\u5E26\u56DE\u4E0A\u6B21\u8FD4\u56DE\u7684 backtrace")
798
+ backtrace: z.string().optional().describe("\u7FFB\u9875\u65F6\u5E26\u56DE\u4E0A\u6B21\u8FD4\u56DE\u7684 backtrace"),
799
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u5E73\u53F0\u5168\u91CF\u539F\u59CB JSON \u6570\u636E\u3002\u9ED8\u8BA4 false\uFF08\u63A8\u8350\uFF0C\u7CBE\u7B80\u6A21\u5F0F\u53EF\u8282\u7EA6 90%+ \u4E0A\u4E0B\u6587 Token\uFF09")
544
800
  });
545
801
  var DyGetVideoDetailSchema = z.object({
546
802
  url: z.string().optional().describe("\u6296\u97F3\u89C6\u9891\u94FE\u63A5\u6216\u5206\u4EAB\u6587\u6848\u3002\u8BF7\u6C42\u4F53\u5B57\u6BB5\u5C31\u662F url\uFF0C\u4F8B\u5982 https://www.douyin.com/video/ID \u6216 https://www.douyin.com/jingxuan?modal_id=ID"),
547
- aweme_id: z.string().optional().describe("\u6296\u97F3\u89C6\u9891 ID\u3002\u672A\u4F20 url \u65F6\u8F6C\u6210 https://www.douyin.com/video/{aweme_id}")
803
+ aweme_id: z.string().optional().describe("\u6296\u97F3\u89C6\u9891 ID\u3002\u672A\u4F20 url \u65F6\u8F6C\u6210 https://www.douyin.com/video/{aweme_id}"),
804
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u5E73\u53F0\u5168\u91CF\u539F\u59CB JSON \u6570\u636E\u3002\u9ED8\u8BA4 false\uFF08\u7CBE\u7B80\u6A21\u5F0F\u4EC5\u63D0\u53D6\u6838\u5FC3\u6587\u6848\u3001\u4F5C\u8005\u53CA\u4E92\u52A8\u6570\u636E\uFF09")
548
805
  });
549
806
  var DyGetPlayStatsSchema = z.object({
550
807
  url: z.string().optional().describe("\u6296\u97F3\u89C6\u9891\u94FE\u63A5\u6216\u5206\u4EAB\u6587\u6848\u3002\u8BF7\u6C42\u4F53\u5B57\u6BB5\u5C31\u662F url"),
551
- aweme_id: z.string().optional().describe("\u6296\u97F3\u89C6\u9891 ID\u3002\u672A\u4F20 url \u65F6\u8F6C\u6210\u89C6\u9891\u957F\u94FE")
808
+ aweme_id: z.string().optional().describe("\u6296\u97F3\u89C6\u9891 ID\u3002\u672A\u4F20 url \u65F6\u8F6C\u6210\u89C6\u9891\u957F\u94FE"),
809
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u539F\u59CB\u7EDF\u8BA1\u6570\u636E\u3002\u9ED8\u8BA4 false")
552
810
  });
553
811
  var DyGetCommentsSchema = z.object({
554
812
  url: z.string().optional().describe("\u6296\u97F3\u89C6\u9891\u94FE\u63A5\u6216\u5206\u4EAB\u6587\u6848\u3002\u4F8B\u5982 https://www.douyin.com/video/ID \u6216 https://www.douyin.com/jingxuan?modal_id=ID"),
555
813
  aweme_id: z.string().optional().describe("\u6296\u97F3\u89C6\u9891 ID\u3002\u672A\u4F20 url \u65F6\u4F7F\u7528\uFF0C\u4E0D\u8981\u628A\u6574\u6BB5\u94FE\u63A5\u586B\u5728\u8FD9\u91CC"),
556
814
  cursor: z.number().default(0).describe("\u5206\u9875\u6E38\u6807\uFF0C\u7B2C\u4E00\u9875\u4F20 0"),
557
- count: z.number().min(1).max(50).default(50).describe("\u6BCF\u9875\u8BC4\u8BBA\u6570\uFF0C\u9ED8\u8BA4 50\uFF0C\u6700\u5927 50")
815
+ count: z.number().min(1).max(50).default(50).describe("\u6BCF\u9875\u8BC4\u8BBA\u6570\uFF0C\u9ED8\u8BA4 50\uFF0C\u6700\u5927 50"),
816
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u8BC4\u8BBA\u539F\u59CB\u6570\u636E\u3002\u9ED8\u8BA4 false\uFF08\u7CBE\u7B80\u6A21\u5F0F\u4EC5\u4FDD\u7559\u8BC4\u8BBA\u6587\u672C\u3001\u70B9\u8D5E\u6570\u3001\u56DE\u590D\u6570\u7B49\u6838\u5FC3\u6307\u6807\uFF09")
558
817
  });
559
818
  var DyGetUserProfileSchema = z.object({
560
819
  sec_user_id: z.string().optional().describe("\u535A\u4E3B sec_user_id\uFF08\u4E0E url \u4E8C\u9009\u4E00\uFF09"),
561
820
  url: z.string().optional().describe("\u535A\u4E3B\u4E3B\u9875\u94FE\u63A5\u3001\u5206\u4EAB\u77ED\u94FE\u6216\u5206\u4EAB\u6587\u6848\uFF08\u4E0E sec_user_id \u4E8C\u9009\u4E00\uFF09"),
562
- profile_url: z.string().optional().describe("\uFF08\u522B\u540D\u517C\u5BB9\uFF09\u535A\u4E3B\u4E3B\u9875\u94FE\u63A5")
821
+ profile_url: z.string().optional().describe("\uFF08\u522B\u540D\u517C\u5BB9\uFF09\u535A\u4E3B\u4E3B\u9875\u94FE\u63A5"),
822
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u7528\u6237\u5168\u91CF\u6570\u636E\u3002\u9ED8\u8BA4 false")
563
823
  });
564
824
  var ChannelsSearchAuthorsSchema = z.object({
565
825
  keyword: z.string().describe("\u521B\u4F5C\u8005\u5173\u952E\u8BCD\u6216\u535A\u4E3B\u6635\u79F0"),
566
826
  count: z.number().int().min(1).max(50).default(20).describe("\u6BCF\u9875\u4F5C\u8005\u6570\u91CF\uFF0C\u9ED8\u8BA4 20"),
567
827
  buffer: z.string().default("").describe("\u5206\u9875\u6E38\u6807\uFF0C\u9996\u9875\u4E3A\u7A7A\uFF0C\u4E0B\u4E00\u9875\u4F7F\u7528\u4E0A\u6B21\u8FD4\u56DE\u7684 buffer"),
568
- scene: z.number().int().default(1).describe("\u641C\u7D22\u573A\u666F\uFF0C\u9ED8\u8BA4 1")
828
+ scene: z.number().int().default(1).describe("\u641C\u7D22\u573A\u666F\uFF0C\u9ED8\u8BA4 1"),
829
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u539F\u59CB\u641C\u7D22\u7ED3\u679C\u3002\u9ED8\u8BA4 false")
569
830
  });
570
831
  var ChannelsGetAuthorFeedsSchema = z.object({
571
832
  finder_username: z.string().describe("\u89C6\u9891\u53F7\u4F5C\u8005\u552F\u4E00\u6807\u8BC6 finder_username"),
572
- last_buffer: z.string().optional().describe("\u7FFB\u9875 buffer\uFF08\u9996\u9875\u65E0\u9700\u4F20\uFF09")
833
+ last_buffer: z.string().optional().describe("\u7FFB\u9875 buffer\uFF08\u9996\u9875\u65E0\u9700\u4F20\uFF09"),
834
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u4F5C\u54C1\u5217\u8868\u3002\u9ED8\u8BA4 false\uFF08\u7CBE\u7B80\u6A21\u5F0F\u4EC5\u63D0\u53D6\u4F5C\u54C1\u63CF\u8FF0\u3001\u5C01\u9762\u53CA\u4E92\u52A8\u6570\uFF09")
573
835
  });
574
836
  var ChannelsResolveShareUrlSchema = z.object({
575
- share_url: z.string().describe("\u5FAE\u4FE1\u89C6\u9891\u53F7\u5206\u4EAB\u94FE\u63A5\uFF0C\u4F8B\u5982\u5305\u542B finder.video.qq.com \u6216\u77ED\u94FE\u63A5")
837
+ share_url: z.string().describe("\u5FAE\u4FE1\u89C6\u9891\u53F7\u5206\u4EAB\u94FE\u63A5\uFF0C\u4F8B\u5982\u5305\u542B finder.video.qq.com \u6216\u77ED\u94FE\u63A5"),
838
+ raw: z.boolean().default(false).describe("\u662F\u5426\u8FD4\u56DE\u672A\u7CBE\u7B80\u7684\u4F5C\u54C1\u8BE6\u60C5\u3002\u9ED8\u8BA4 false")
576
839
  });
577
840
 
578
841
  // src/mcp/server.ts
@@ -815,7 +1078,7 @@ function registerChannelsTools(server, client) {
815
1078
  function createMcpServer(client = new DataClawClient()) {
816
1079
  const server = new McpServer({
817
1080
  name: "dataclaw-agent-kit",
818
- version: "0.1.1"
1081
+ version: "0.1.2"
819
1082
  });
820
1083
  registerMediaTools(server, client);
821
1084
  registerDouyinTools(server, client);
@@ -839,7 +1102,9 @@ async function startMcpServer(client = new DataClawClient()) {
839
1102
  import fs2 from "fs";
840
1103
  import path2 from "path";
841
1104
  import os from "os";
842
- function detectIdeEnvironments(targetDir = process.cwd()) {
1105
+ function detectIdeEnvironments(options = process.cwd()) {
1106
+ const targetDir = typeof options === "string" ? options : options.targetDir || process.cwd();
1107
+ const isGlobal = typeof options === "object" ? Boolean(options.isGlobal) : false;
843
1108
  const home = os.homedir();
844
1109
  const platform = process.platform;
845
1110
  const cursorLocal = path2.join(targetDir, ".cursor");
@@ -847,10 +1112,10 @@ function detectIdeEnvironments(targetDir = process.cwd()) {
847
1112
  const cursorDetected = fs2.existsSync(cursorLocal) || fs2.existsSync(cursorGlobal);
848
1113
  const cursorInfo = {
849
1114
  id: "cursor",
850
- name: "Cursor (.cursor/rules + mcp.json)",
1115
+ name: isGlobal ? "Cursor \u5168\u5C40\u7528\u6237\u7EA7 (~/.cursor/mcp.json + rules\uFF0C\u6240\u6709\u5DE5\u7A0B\u901A\u7528)" : "Cursor \u5F53\u524D\u5DE5\u4F5C\u533A (.cursor/rules + mcp.json)",
851
1116
  detected: cursorDetected,
852
- configPath: path2.join(targetDir, ".cursor", "mcp.json"),
853
- skillsDir: path2.join(targetDir, ".cursor", "rules")
1117
+ configPath: isGlobal ? path2.join(home, ".cursor", "mcp.json") : path2.join(targetDir, ".cursor", "mcp.json"),
1118
+ skillsDir: isGlobal ? path2.join(home, ".cursor", "rules") : path2.join(targetDir, ".cursor", "rules")
854
1119
  };
855
1120
  let claudeDesktopConfigPath = "";
856
1121
  if (platform === "darwin") {
@@ -864,69 +1129,82 @@ function detectIdeEnvironments(targetDir = process.cwd()) {
864
1129
  const claudeDesktopDetected = fs2.existsSync(path2.dirname(claudeDesktopConfigPath));
865
1130
  const claudeDesktopInfo = {
866
1131
  id: "claude-desktop",
867
- name: "Claude Desktop (claude_desktop_config.json)",
1132
+ name: "Claude Desktop (\u5168\u5C40\u5E94\u7528 claude_desktop_config.json)",
868
1133
  detected: claudeDesktopDetected,
869
1134
  configPath: claudeDesktopConfigPath
870
1135
  };
871
1136
  const claudeCodeLocal = path2.join(targetDir, ".claude");
872
1137
  const claudeCodeGlobal = path2.join(home, ".claude");
873
- const claudeCodeDetected = fs2.existsSync(claudeCodeLocal) || fs2.existsSync(claudeCodeGlobal);
1138
+ const claudeMcpLocal = path2.join(targetDir, ".mcp.json");
1139
+ const claudeGlobalJson = path2.join(home, ".claude.json");
1140
+ const claudeCodeDetected = fs2.existsSync(claudeCodeLocal) || fs2.existsSync(claudeCodeGlobal) || fs2.existsSync(claudeMcpLocal) || fs2.existsSync(claudeGlobalJson);
874
1141
  const claudeCodeInfo = {
875
1142
  id: "claude-code",
876
- name: "Claude Code (.claude/skills)",
1143
+ name: isGlobal ? "Claude Code \u5168\u5C40\u7528\u6237\u7EA7 (~/.claude.json\uFF0C\u6240\u6709\u7EC8\u7AEF\u901A\u7528)" : "Claude Code \u5F53\u524D\u5DE5\u4F5C\u533A (.mcp.json + CLAUDE.md)",
877
1144
  detected: claudeCodeDetected,
878
- configPath: path2.join(targetDir, ".claude", "mcp.json"),
879
- skillsDir: path2.join(targetDir, ".claude", "skills")
1145
+ configPath: isGlobal ? claudeGlobalJson : claudeMcpLocal,
1146
+ skillsDir: isGlobal ? path2.join(home, ".claude", "skills") : path2.join(targetDir, ".claude", "skills")
880
1147
  };
881
1148
  const windsurfGlobalConfig = path2.join(home, ".codeium", "windsurf", "mcp_config.json");
882
1149
  const windsurfLocal = path2.join(targetDir, ".windsurf");
883
1150
  const windsurfDetected = fs2.existsSync(windsurfLocal) || fs2.existsSync(path2.dirname(windsurfGlobalConfig));
884
1151
  const windsurfInfo = {
885
1152
  id: "windsurf",
886
- name: "Windsurf (mcp_config.json)",
1153
+ name: "Windsurf (\u5168\u5C40 mcp_config.json)",
887
1154
  detected: windsurfDetected,
888
1155
  configPath: windsurfGlobalConfig,
889
- skillsDir: path2.join(targetDir, ".windsurf", "rules")
1156
+ skillsDir: isGlobal ? path2.join(home, ".codeium", "windsurf", "rules") : path2.join(targetDir, ".windsurf", "rules")
890
1157
  };
891
- const codexLocal = path2.join(targetDir, ".codex");
892
- const codexGlobal = path2.join(home, ".codex");
893
- const codexDetected = fs2.existsSync(codexLocal) || fs2.existsSync(codexGlobal);
1158
+ const codexGlobalToml = path2.join(home, ".codex", "config.toml");
1159
+ const codexGlobalDir = path2.join(home, ".codex");
1160
+ const codexLocalDir = path2.join(targetDir, ".codex");
1161
+ const codexDetected = fs2.existsSync(codexGlobalDir) || fs2.existsSync(codexLocalDir);
894
1162
  const codexInfo = {
895
1163
  id: "codex",
896
- name: "Codex (.codex/mcp.json + skills)",
1164
+ name: isGlobal ? "Codex \u5168\u5C40\u7528\u6237\u7EA7 (~/.codex/config.toml)" : "Codex (OpenAI ~/.codex/config.toml + AGENTS.md)",
897
1165
  detected: codexDetected,
898
- configPath: path2.join(targetDir, ".codex", "mcp.json"),
899
- skillsDir: path2.join(targetDir, ".codex", "skills")
1166
+ configPath: codexGlobalToml,
1167
+ skillsDir: isGlobal ? path2.join(home, ".codex", "skills") : path2.join(targetDir, ".codex", "skills")
1168
+ };
1169
+ const ompGlobalDir = path2.join(home, ".omp");
1170
+ const ompLocalDir = path2.join(targetDir, ".omp");
1171
+ const ompDetected = fs2.existsSync(ompGlobalDir) || fs2.existsSync(ompLocalDir);
1172
+ const ompInfo = {
1173
+ id: "omp",
1174
+ name: isGlobal ? "OMP \u5168\u5C40\u7528\u6237\u7EA7 (~/.omp/agent/mcp.json + ~/.omp/skills)" : "OMP \u5F53\u524D\u5DE5\u4F5C\u533A (.omp/mcp.json + .omp/skills + AGENTS.md)",
1175
+ detected: ompDetected,
1176
+ configPath: isGlobal ? path2.join(home, ".omp", "agent", "mcp.json") : path2.join(targetDir, ".omp", "mcp.json"),
1177
+ skillsDir: isGlobal ? path2.join(home, ".omp", "skills") : path2.join(targetDir, ".omp", "skills")
900
1178
  };
901
- return [cursorInfo, claudeDesktopInfo, claudeCodeInfo, windsurfInfo, codexInfo];
1179
+ return [cursorInfo, claudeDesktopInfo, claudeCodeInfo, windsurfInfo, codexInfo, ompInfo];
902
1180
  }
903
1181
 
904
1182
  // src/cli/generator.ts
905
1183
  import fs3 from "fs";
906
1184
  import path3 from "path";
907
- var MEDIA_SKILL_TEMPLATE = `---
908
- description: \u89C6\u9891\u53BB\u6C34\u5370\u4E0B\u8F7D\u3001\u5168\u5E73\u53F0\u56FE\u96C6\u63D0\u53D6\u4E0E\u97F3\u89C6\u9891\u667A\u80FD\u8F6C\u6587\u6848 SOP
909
- globs:
910
- ---
911
-
912
- # \u89C6\u9891\u53BB\u6C34\u5370\u4E0B\u8F7D\u4E0E\u6587\u6848\u63D0\u53D6 SOP (Video Download & Transcribe)
1185
+ var SKILL_DEFINITIONS = {
1186
+ media: {
1187
+ key: "media",
1188
+ name: "dataclaw-media",
1189
+ description: "\u89C6\u9891\u53BB\u6C34\u5370\u4E0B\u8F7D\u3001\u5168\u5E73\u53F0\u56FE\u96C6\u63D0\u53D6\u4E0E\u97F3\u89C6\u9891\u667A\u80FD\u8F6C\u6587\u6848 SOP",
1190
+ body: `# \u89C6\u9891\u53BB\u6C34\u5370\u4E0B\u8F7D\u4E0E\u6587\u6848\u63D0\u53D6 SOP (Video Download & Transcribe)
913
1191
 
914
1192
  \u5F53\u7528\u6237\u610F\u56FE\u6D89\u53CA\u201C\u4E0B\u8F7D\u89C6\u9891/\u65E0\u6C34\u5370\u63D0\u53D6\u201D\u3001\u201C\u63D0\u53D6\u6296\u97F3/\u89C6\u9891\u53F7/\u5C0F\u7EA2\u4E66\u7B49\u5E73\u53F0\u6587\u6848\u201D\u3001\u201C\u628A\u89C6\u9891\u8F6C\u6210\u6587\u5B57/\u63D0\u53D6\u5B57\u5E55/\u603B\u7ED3\u5927\u610F\u201D\u65F6\uFF0C\u8BF7\u4E25\u683C\u6309\u4EE5\u4E0B\u5206\u652F\u7B56\u7565\u8C03\u7528 DataClaw MCP \u5DE5\u5177\uFF1A
915
1193
 
916
1194
  ## \u5206\u652F\u7B56\u7565\u4E0E\u6267\u884C\u6D41\u7A0B
917
1195
 
918
1196
  ### \u5206\u652F A\uFF1A\u7528\u6237\u9700\u8981\u63D0\u53D6\u6587\u6848 / \u5B57\u5E55 / \u603B\u7ED3\u89C6\u9891\u5927\u610F\uFF08\u4E00\u6B65\u76F4\u8FBE\uFF09
919
- **\u6838\u5FC3\u539F\u5219**\uFF1A\u8F6C\u6587\u6848**\u65E0\u9700**\u5148\u8C03\u7528\u89E3\u6790\u5DE5\u5177\u83B7\u53D6\u76F4\u94FE\uFF0C\u76F4\u63A5\u8C03\u7528 \\\`dataclaw_audio_transcribe\\\` \u4E00\u6B65\u76F4\u8FBE\uFF0C\u8017\u65F6\u66F4\u77ED\u4E14\u652F\u6301\u5B98\u65B9\u5B57\u5E55\u7F13\u5B58\u79D2\u56DE\u3002
1197
+ **\u6838\u5FC3\u539F\u5219**\uFF1A\u8F6C\u6587\u6848**\u65E0\u9700**\u5148\u8C03\u7528\u89E3\u6790\u5DE5\u5177\u83B7\u53D6\u76F4\u94FE\uFF0C\u76F4\u63A5\u8C03\u7528 \`dataclaw_audio_transcribe\` \u4E00\u6B65\u76F4\u8FBE\uFF0C\u8017\u65F6\u66F4\u77ED\u4E14\u652F\u6301\u5B98\u65B9\u5B57\u5E55\u7F13\u5B58\u79D2\u56DE\u3002
920
1198
 
921
- 1. **\u76F4\u63A5\u8C03\u7528\u8F6C\u6587\u6848\u5DE5\u5177** \\\`dataclaw_audio_transcribe\\\`\uFF1A
922
- - **\u7F51\u7EDC\u77ED\u89C6\u9891**\uFF1A\u4F20\u53C2 \\\`media_url = <\u7528\u6237\u63D0\u4F9B\u7684\u5206\u4EAB\u94FE\u63A5\u6216\u6587\u6848>\\\`\u3002
923
- - \u652F\u6301\u6296\u97F3\u3001\u5C0F\u7EA2\u4E66\u3001\u5FEB\u624B\u3001B\u7AD9\u7B49\u666E\u901A\u77ED\u89C6\u9891\uFF08\u7CFB\u7EDF\u81EA\u52A8\u8D70 \\\`/tools/copy/extract\\\` \u94FE\u8DEF\uFF09\u3002
924
- - \u652F\u6301\u5FAE\u4FE1\u89C6\u9891\u53F7\u77ED\u94FE\uFF08\u7CFB\u7EDF\u81EA\u52A8\u8D70 \\\`/tools/copy/extract-finder\\\` \u94FE\u8DEF\uFF0C\u81EA\u52A8\u5B8C\u6210 WASM \u89E3\u5BC6\uFF09\u3002
925
- - **\u672C\u5730\u97F3\u89C6\u9891\u6587\u4EF6**\uFF1A\u4F20\u53C2 local_file_path = <\u672C\u5730\u7EDD\u5BF9\u8DEF\u5F84>\uFF1BMCP \u4F1A\u5148\u76F4\u4F20\u5BF9\u8C61\u5B58\u50A8\uFF0C\u518D\u521B\u5EFA\u5F02\u6B65\u8F6C\u5199\u4EFB\u52A1\uFF0C\u957F\u6587\u4EF6\u7B49\u5F85\u4EFB\u52A1\u5B8C\u6210\u3002
1199
+ 1. **\u76F4\u63A5\u8C03\u7528\u8F6C\u6587\u6848\u5DE5\u5177** \`dataclaw_audio_transcribe\`\uFF1A
1200
+ - **\u7F51\u7EDC\u77ED\u89C6\u9891**\uFF1A\u4F20\u53C2 \`media_url = <\u7528\u6237\u63D0\u4F9B\u7684\u5206\u4EAB\u94FE\u63A5\u6216\u6587\u6848>\`\u3002
1201
+ - \u652F\u6301\u6296\u97F3\u3001\u5C0F\u7EA2\u4E66\u3001\u5FEB\u624B\u3001B\u7AD9\u7B49\u666E\u901A\u77ED\u89C6\u9891\uFF08\u7CFB\u7EDF\u81EA\u52A8\u8D70 \`/tools/copy/extract\` \u94FE\u8DEF\uFF09\u3002
1202
+ - \u652F\u6301\u5FAE\u4FE1\u89C6\u9891\u53F7\u77ED\u94FE\uFF08\u7CFB\u7EDF\u81EA\u52A8\u8D70 \`/tools/copy/extract-finder\` \u94FE\u8DEF\uFF0C\u81EA\u52A8\u5B8C\u6210 WASM \u89E3\u5BC6\uFF09\u3002
1203
+ - **\u672C\u5730\u97F3\u89C6\u9891\u6587\u4EF6**\uFF1A\u4F20\u53C2 \`local_file_path = <\u672C\u5730\u7EDD\u5BF9\u8DEF\u5F84>\`\uFF1BMCP \u4F1A\u5148\u76F4\u4F20\u5BF9\u8C61\u5B58\u50A8\uFF0C\u518D\u521B\u5EFA\u5F02\u6B65\u8F6C\u5199\u4EFB\u52A1\uFF0C\u957F\u6587\u4EF6\u7B49\u5F85\u4EFB\u52A1\u5B8C\u6210\u3002
926
1204
  - **\u8F93\u51FA\u683C\u5F0F\u9009\u62E9**\uFF1A
927
- - \u7528\u6237\u9700\u8981\u7EAF\u6587\u672C/\u603B\u7ED3\u5927\u610F\uFF1A\u4F20 \\\`output_format = "text"\\\`\u3002
928
- - \u7528\u6237\u9700\u8981\u5B57\u5E55/\u65F6\u95F4\u8F74\uFF1A\u4F20 \\\`output_format = "srt"\\\`\u3002
929
- - \u7528\u6237\u9700\u8981\u8BE6\u7EC6\u65F6\u95F4\u5207\u7247\u6570\u636E\uFF1A\u4F20 \\\`output_format = "verbose_json"\\\`\u3002
1205
+ - \u7528\u6237\u9700\u8981\u7EAF\u6587\u672C/\u603B\u7ED3\u5927\u610F\uFF1A\u4F20 \`output_format = "text"\`\u3002
1206
+ - \u7528\u6237\u9700\u8981\u5B57\u5E55/\u65F6\u95F4\u8F74\uFF1A\u4F20 \`output_format = "srt"\`\u3002
1207
+ - \u7528\u6237\u9700\u8981\u8BE6\u7EC6\u65F6\u95F4\u5207\u7247\u6570\u636E\uFF1A\u4F20 \`output_format = "verbose_json"\`\u3002
930
1208
 
931
1209
  2. **\u6587\u6848\u6392\u7248\u4E0E\u63D0\u70BC\u8F93\u51FA**\uFF1A
932
1210
  - \u63D0\u53D6\u6587\u6848\u540E\uFF0C\u4E3A\u7528\u6237\u6309\u4EE5\u4E0B\u7ED3\u6784\u6574\u7406\u5448\u73B0\uFF1A
@@ -939,44 +1217,43 @@ globs:
939
1217
  ### \u5206\u652F B\uFF1A\u7528\u6237\u9700\u8981\u4E0B\u8F7D\u65E0\u6C34\u5370\u89C6\u9891 / \u83B7\u53D6\u9AD8\u6E05\u56FE\u96C6
940
1218
  \u5F53\u7528\u6237\u610F\u56FE\u662F\u201C\u4E0B\u8F7D\u89C6\u9891\u201D\u3001\u201C\u4FDD\u5B58\u539F\u753B\u7D20\u6750\u201D\u3001\u201C\u53BB\u9664\u6C34\u5370\u201D\u6216\u201C\u4E0B\u8F7D\u5C0F\u7EA2\u4E66/\u6296\u97F3\u56FE\u96C6\u201D\u65F6\uFF1A
941
1219
 
942
- 1. **\u8C03\u7528\u901A\u7528\u53BB\u6C34\u5370\u5DE5\u5177** \\\`dataclaw_video_resolve\\\`\uFF1A
943
- - \u4F20\u53C2 \\\`url = <\u7528\u6237\u63D0\u4F9B\u7684\u94FE\u63A5\u6216\u5305\u542B\u94FE\u63A5\u7684\u6587\u6848>\\\`\u3002
944
- - \u7CFB\u7EDF\u81EA\u52A8\u8BC6\u522B\u5E73\u53F0\uFF08\u5BF9\u5E94 \\\`/tools/material/remove-watermark\\\`\uFF09\uFF0C\u652F\u6301\u6296\u97F3\u3001\u89C6\u9891\u53F7\u3001\u5C0F\u7EA2\u4E66\u3001\u5FEB\u624B\u3001TikTok \u7B49\u5168\u5E73\u53F0\u3002
1220
+ 1. **\u8C03\u7528\u901A\u7528\u53BB\u6C34\u5370\u5DE5\u5177** \`dataclaw_video_resolve\`\uFF1A
1221
+ - \u4F20\u53C2 \`url = <\u7528\u6237\u63D0\u4F9B\u7684\u94FE\u63A5\u6216\u5305\u542B\u94FE\u63A5\u7684\u6587\u6848>\`\u3002
1222
+ - \u7CFB\u7EDF\u81EA\u52A8\u8BC6\u522B\u5E73\u53F0\uFF08\u5BF9\u5E94 \`/tools/material/remove-watermark\`\uFF09\uFF0C\u652F\u6301\u6296\u97F3\u3001\u89C6\u9891\u53F7\u3001\u5C0F\u7EA2\u4E66\u3001\u5FEB\u624B\u3001TikTok \u7B49\u5168\u5E73\u53F0\u3002
945
1223
  2. **\u4E0B\u8F7D\u5F15\u5BFC\u5448\u73B0**\uFF1A
946
- - **\u82E5\u662F\u89C6\u9891**\uFF1A\u8FD4\u56DE\u65E0\u6C34\u5370\u9AD8\u6E05\u76F4\u94FE \\\`video_play_url\\\`\u3001\u89C6\u9891\u5C01\u9762 \\\`cover_url\\\`\u3001\u6807\u9898 \\\`title\\\`\u3001\u4F5C\u8005 \\\`author\\\` \u53CA\u65F6\u957F \\\`duration\\\`\u3002
947
- - **\u82E5\u662F\u56FE\u96C6**\uFF1A\u8FD4\u56DE\u5168\u91CF\u65E0\u6C34\u5370\u9AD8\u6E05\u56FE\u7247\u76F4\u94FE\u5217\u8868 \\\`images\\\`\u3002
948
- - \u5F15\u5BFC\u7528\u6237\u5728\u6D4F\u89C8\u5668\u4E2D\u70B9\u51FB\u4E0B\u8F7D\uFF0C\u6216\u63D0\u4F9B\u7EC8\u7AEF \\\`curl / wget\\\` \u4E0B\u8F7D\u547D\u4EE4\u3002
949
- `;
950
- var DOUYIN_SKILL_TEMPLATE = `---
951
- description: \u6296\u97F3\u70ED\u95E8\u89C6\u9891\u590D\u76D8\u3001\u7206\u6B3E\u6587\u6848\u62C6\u89E3\u4E0E\u8BC4\u8BBA\u533A\u75DB\u70B9\u6316\u6398 SOP
952
- globs:
953
- ---
954
-
955
- # \u6296\u97F3\u7206\u6B3E\u89C6\u9891\u590D\u76D8\u4E0E\u75DB\u70B9\u5206\u6790 SOP (Douyin Hot Video Audit)
1224
+ - **\u82E5\u662F\u89C6\u9891**\uFF1A\u8FD4\u56DE\u65E0\u6C34\u5370\u9AD8\u6E05\u76F4\u94FE \`video_play_url\`\u3001\u89C6\u9891\u5C01\u9762 \`cover_url\`\u3001\u6807\u9898 \`title\`\u3001\u4F5C\u8005 \`author\` \u53CA\u65F6\u957F \`duration\`\u3002
1225
+ - **\u82E5\u662F\u56FE\u96C6**\uFF1A\u8FD4\u56DE\u5168\u91CF\u65E0\u6C34\u5370\u9AD8\u6E05\u56FE\u7247\u76F4\u94FE\u5217\u8868 \`images\`\u3002
1226
+ - \u5F15\u5BFC\u7528\u6237\u5728\u6D4F\u89C8\u5668\u4E2D\u70B9\u51FB\u4E0B\u8F7D\uFF0C\u6216\u63D0\u4F9B\u7EC8\u7AEF \`curl / wget\` \u4E0B\u8F7D\u547D\u4EE4\u3002`
1227
+ },
1228
+ douyin: {
1229
+ key: "douyin",
1230
+ name: "dataclaw-douyin",
1231
+ description: "\u6296\u97F3\u70ED\u95E8\u89C6\u9891\u590D\u76D8\u3001\u7206\u6B3E\u6587\u6848\u62C6\u89E3\u4E0E\u8BC4\u8BBA\u533A\u75DB\u70B9\u6316\u6398 SOP",
1232
+ body: `# \u6296\u97F3\u7206\u6B3E\u89C6\u9891\u590D\u76D8\u4E0E\u75DB\u70B9\u5206\u6790 SOP (Douyin Hot Video Audit)
956
1233
 
957
1234
  \u5F53\u7528\u6237\u610F\u56FE\u6D89\u53CA\u201C\u5206\u6790\u6296\u97F3\u4E0A\u505A [\u54C1\u7C7B/\u884C\u4E1A] \u7684\u7206\u6B3E\u89C6\u9891\u201D\u3001\u201C\u8C03\u7814\u7ADE\u54C1\u8BC4\u8BBA\u533A\u75DB\u70B9/\u7528\u6237\u53CD\u9988\u201D\u3001\u201C\u62C6\u89E3\u5BF9\u6807\u8D26\u53F7\u7684\u9AD8\u8D5E\u811A\u672C\u201D\u65F6\uFF0C\u8BF7\u4E25\u683C\u9075\u5FAA\u4EE5\u4E0B\u6B65\u9AA4\uFF1A
958
1235
 
959
1236
  ## \u6267\u884C\u6D41\u7A0B
960
1237
 
961
1238
  1. **\u5173\u952E\u8BCD\u68C0\u7D22\u70ED\u95E8\u89C6\u9891**\uFF1A
962
- - \u8C03\u7528\u5DE5\u5177 \\\`dataclaw_dy_search_videos\\\`\uFF1A
963
- - \\\`keyword\\\`: \u7528\u6237\u7684\u76EE\u6807\u884C\u4E1A\u3001\u4EA7\u54C1\u6216\u4E3B\u9898\u5173\u952E\u8BCD\u3002
964
- - \\\`sort_type\\\`: \u4F18\u5148\u4F20 \\\`"most_liked"\\\`\uFF08\u6700\u591A\u70B9\u8D5E\uFF09\u6216 \\\`"most_recent"\\\`\uFF08\u6700\u65B0\uFF09\u3002
965
- - \\\`publish_time\\\`: \\\`"0"\\\` \u4E0D\u9650\uFF0C\\\`"1"\\\` \u6700\u8FD1\u4E00\u5929\uFF0C\\\`"7"\\\` \u6700\u8FD1\u4E00\u5468\uFF0C\\\`"180"\\\` \u6700\u8FD1\u534A\u5E74\u3002
966
- - \u9875\u5927\u5C0F\u56FA\u5B9A\uFF0C\u4E0D\u8981\u4F9D\u8D56 \\\`count\\\`\u3002\u7FFB\u9875\u5E26\u56DE\u4E0A\u6B21\u8FD4\u56DE\u7684 \\\`cursor\\\`\u3001\\\`search_id\\\`\u3001\\\`backtrace\\\`\u3002
1239
+ - \u8C03\u7528\u5DE5\u5177 \`dataclaw_dy_search_videos\`\uFF1A
1240
+ - \`keyword\`: \u7528\u6237\u7684\u76EE\u6807\u884C\u4E1A\u3001\u4EA7\u54C1\u6216\u4E3B\u9898\u5173\u952E\u8BCD\u3002
1241
+ - \`sort_type\`: \u4F18\u5148\u4F20 \`"most_liked"\`\uFF08\u6700\u591A\u70B9\u8D5E\uFF09\u6216 \`"most_recent"\`\uFF08\u6700\u65B0\uFF09\u3002
1242
+ - \`publish_time\`: \`"0"\` \u4E0D\u9650\uFF0C\`"1"\` \u6700\u8FD1\u4E00\u5929\uFF0C\`"7"\` \u6700\u8FD1\u4E00\u5468\uFF0C\`"180"\` \u6700\u8FD1\u534A\u5E74\u3002
1243
+ - \u9875\u5927\u5C0F\u56FA\u5B9A\uFF0C\u4E0D\u8981\u4F9D\u8D56 \`count\`\u3002\u7FFB\u9875\u5E26\u56DE\u4E0A\u6B21\u8FD4\u56DE\u7684 \`cursor\`\u3001\`search_id\`\u3001\`backtrace\`\u3002
967
1244
  - \u7B5B\u9009\u51FA\u70B9\u8D5E\u91CF\u4E0E\u4E92\u52A8\u6700\u9AD8\u7684 TOP 3~5 \u4E2A\u89C6\u9891\u4F5C\u54C1\u3002
968
1245
 
969
1246
  2. **\u83B7\u53D6\u4F5C\u54C1\u8BE6\u60C5\u4E0E\u4E92\u52A8\u6307\u6807**\uFF1A
970
- - \u9488\u5BF9\u7B5B\u9009\u51FA\u7684\u76EE\u6807\u89C6\u9891\uFF0C\u8C03\u7528 \\\`dataclaw_dy_get_video_detail\\\`\u3002
1247
+ - \u9488\u5BF9\u7B5B\u9009\u51FA\u7684\u76EE\u6807\u89C6\u9891\uFF0C\u8C03\u7528 \`dataclaw_dy_get_video_detail\`\u3002
971
1248
  - \u53EA\u62FF\u6807\u9898\u3001\u4F5C\u8005\u3001\u5C01\u9762\u3001\u64AD\u653E\u5730\u5740\u548C\u70B9\u8D5E\u3001\u8BC4\u8BBA\u3001\u5206\u4EAB\u3001\u6536\u85CF\u6570\u3002\u6CA1\u6709\u64AD\u653E\u91CF\uFF0C\u4E5F\u6CA1\u6709\u79D2\u7EA7\u4E92\u52A8\u8D8B\u52BF\u3002
972
- - \u9700\u8981\u64AD\u653E\u91CF\u6216\u5B8C\u64AD\u7387\u65F6\uFF0C\u53E6\u8C03 \\\`dataclaw_dy_get_play_stats\\\`\uFF0C\u4F20\u540C\u4E00\u4E2A \\\`url\\\`\u3002\u8BE6\u60C5\u548C\u64AD\u653E\u91CF\u7684\u8BF7\u6C42\u4F53\u5B57\u6BB5\u90FD\u662F \\\`url\\\`\uFF0C\u4E0D\u8981\u4F20 \\\`share_url\\\`\u3002
1249
+ - \u9700\u8981\u64AD\u653E\u91CF\u6216\u5B8C\u64AD\u7387\u65F6\uFF0C\u53E6\u8C03 \`dataclaw_dy_get_play_stats\`\uFF0C\u4F20\u540C\u4E00\u4E2A \`url\`\u3002\u8BE6\u60C5\u548C\u64AD\u653E\u91CF\u7684\u8BF7\u6C42\u4F53\u5B57\u6BB5\u90FD\u662F \`url\`\uFF0C\u4E0D\u8981\u4F20 \`share_url\`\u3002
973
1250
 
974
1251
  3. **\u6293\u53D6\u8BC4\u8BBA**\uFF1A
975
- - \u9488\u5BF9\u76EE\u6807\u89C6\u9891\uFF0C\u8C03\u7528 \\\`dataclaw_dy_get_comments\\\`\uFF0C\u4F20 \\\`url\\\` \u6216\u7EAF\u6570\u5B57 \\\`aweme_id\\\`\u3002\u6BCF\u9875\u9ED8\u8BA4 50 \u6761\uFF0C\u6700\u5927 50\u3002\u8981\u66F4\u591A\u5C31\u7528\u4E0A\u6B21\u8FD4\u56DE\u7684 \\\`cursor\\\` \u518D\u7FFB\u9875\u3002
1252
+ - \u9488\u5BF9\u76EE\u6807\u89C6\u9891\uFF0C\u8C03\u7528 \`dataclaw_dy_get_comments\`\uFF0C\u4F20 \`url\` \u6216\u7EAF\u6570\u5B57 \`aweme_id\`\u3002\u6BCF\u9875\u9ED8\u8BA4 50 \u6761\uFF0C\u6700\u5927 50\u3002\u8981\u66F4\u591A\u5C31\u7528\u4E0A\u6B21\u8FD4\u56DE\u7684 \`cursor\` \u518D\u7FFB\u9875\u3002
976
1253
  - \u91CD\u70B9\u63D0\u53D6\u9AD8\u8D5E\u70ED\u8BC4\u4E0E\u69FD\u70B9\u3002
977
1254
 
978
1255
  4. **\u7206\u6B3E\u811A\u672C\u9010\u5B57\u6587\u6848\u63D0\u70BC\uFF08\u6309\u9700\uFF09**\uFF1A
979
- - \u82E5\u7528\u6237\u9700\u8981\u6DF1\u5165\u62C6\u89E3\u7206\u6B3E\u7684\u53F0\u8BCD\u811A\u672C\u6216\u94A9\u5B50\u8BBE\u8BA1\uFF0C\u76F4\u63A5\u8C03\u7528 \\\`dataclaw_audio_transcribe\\\`\uFF08\u4F20\u5165\u8BE5\u89C6\u9891\u7684 share_url\uFF09\uFF0C\u83B7\u53D6\u9010\u5B57\u53E3\u64AD\u7A3F\u3002
1256
+ - \u82E5\u7528\u6237\u9700\u8981\u6DF1\u5165\u62C6\u89E3\u7206\u6B3E\u7684\u53F0\u8BCD\u811A\u672C\u6216\u94A9\u5B50\u8BBE\u8BA1\uFF0C\u76F4\u63A5\u8C03\u7528 \`dataclaw_audio_transcribe\`\uFF08\u4F20\u5165\u8BE5\u89C6\u9891\u7684 share_url\uFF09\uFF0C\u83B7\u53D6\u9010\u5B57\u53E3\u64AD\u7A3F\u3002
980
1257
 
981
1258
  5. **\u7EFC\u5408\u590D\u76D8\u5206\u6790\u8F93\u51FA**\uFF1A
982
1259
  - \u7EFC\u5408\u4EE5\u4E0A\u6570\u636E\uFF0C\u4E3A\u7528\u6237\u8F93\u51FA\u6DF1\u5EA6\u590D\u76D8\u62A5\u544A\uFF1A
@@ -984,30 +1261,29 @@ globs:
984
1261
  - **\u3010\u811A\u672C\u7ED3\u6784\u62C6\u89E3\u3011**\uFF1A\u75DB\u70B9\u5F15\u53D1 -> \u4EF7\u503C\u9610\u8FF0 -> \u884C\u52A8\u53EC\u5524 (CTA) \u7684\u8282\u594F\u5206\u5E03\u3002
985
1262
  - **\u3010\u9AD8\u9891\u5171\u9E23\u8BCD\u4E91\u3011**\uFF1A\u89C2\u4F17\u8BA8\u8BBA\u6700\u70ED\u70C8\u7684\u5173\u952E\u8BCD\u4E0E\u60C5\u7EEA\u503E\u5411\u3002
986
1263
  - **\u3010\u75DB\u70B9\u4E0E\u672A\u6EE1\u8DB3\u9700\u6C42\u3011**\uFF1A\u8BC4\u8BBA\u533A\u9AD8\u8D5E\u5410\u69FD\u3001\u7591\u95EE\u53CA\u6F5C\u5728\u4E70\u70B9\u3002
987
- - **\u3010\u7206\u6B3E\u53EF\u590D\u5236\u5EFA\u8BAE\u3011**\uFF1A\u603B\u7ED3 3 \u6761\u53EF\u76F4\u63A5\u843D\u5730\u7684\u811A\u672C\u521B\u4F5C\u5EFA\u8BAE\u3002
988
- `;
989
- var CHANNELS_SKILL_TEMPLATE = `---
990
- description: \u5FAE\u4FE1\u89C6\u9891\u53F7\u521B\u4F5C\u8005\u6DF1\u5EA6\u62C6\u89E3\u3001\u7206\u6B3E Feed \u4E0E\u4E92\u52A8\u76D1\u63A7 SOP
991
- globs:
992
- ---
993
-
994
- # \u5FAE\u4FE1\u89C6\u9891\u53F7\u8FBE\u4EBA\u4E0E\u4F5C\u54C1\u76D1\u63A7 SOP (Channels Creator Monitor)
1264
+ - **\u3010\u7206\u6B3E\u53EF\u590D\u5236\u5EFA\u8BAE\u3011**\uFF1A\u603B\u7ED3 3 \u6761\u53EF\u76F4\u63A5\u843D\u5730\u7684\u811A\u672C\u521B\u4F5C\u5EFA\u8BAE\u3002`
1265
+ },
1266
+ channels: {
1267
+ key: "channels",
1268
+ name: "dataclaw-channels",
1269
+ description: "\u5FAE\u4FE1\u89C6\u9891\u53F7\u521B\u4F5C\u8005\u6DF1\u5EA6\u62C6\u89E3\u3001\u7206\u6B3E Feed \u4E0E\u4E92\u52A8\u76D1\u63A7 SOP",
1270
+ body: `# \u5FAE\u4FE1\u89C6\u9891\u53F7\u8FBE\u4EBA\u4E0E\u4F5C\u54C1\u76D1\u63A7 SOP (Channels Creator Monitor)
995
1271
 
996
1272
  \u5F53\u7528\u6237\u610F\u56FE\u6D89\u53CA\u201C\u62C6\u89E3\u8FD9\u4E2A\u89C6\u9891\u53F7\u535A\u4E3B\u201D\u3001\u201C\u770B\u770B\u8FD9\u4E2A\u89C6\u9891\u53F7\u6700\u8FD1\u53D1\u4E86\u4EC0\u4E48\u201D\u3001\u201C\u5206\u6790\u89C6\u9891\u53F7\u7ADE\u54C1\u8D26\u53F7\u7684\u8868\u73B0\u201D\u65F6\uFF0C\u8BF7\u4E25\u683C\u9075\u5FAA\u4EE5\u4E0B\u6B65\u9AA4\uFF1A
997
1273
 
998
1274
  ## \u6267\u884C\u6D41\u7A0B
999
1275
 
1000
1276
  1. **\u521B\u4F5C\u8005\u68C0\u7D22\u4E0E\u5B9A\u4F4D**\uFF1A
1001
- - \u82E5\u7528\u6237\u63D0\u4F9B\u4E86\u535A\u4E3B\u6635\u79F0\u6216\u5173\u952E\u8BCD\uFF0C\u8C03\u7528 \\\`dataclaw_channels_search_authors\\\` \u8FDB\u884C\u641C\u7D22\u3002
1002
- - \u786E\u8BA4\u76EE\u6807\u4F5C\u8005\uFF0C\u83B7\u53D6\u5176\u552F\u4E00\u6807\u8BC6 \\\`finder_username\\\`\u3001\u5934\u50CF\u53CA\u8BA4\u8BC1\u7B80\u4ECB\u3002
1277
+ - \u82E5\u7528\u6237\u63D0\u4F9B\u4E86\u535A\u4E3B\u6635\u79F0\u6216\u5173\u952E\u8BCD\uFF0C\u8C03\u7528 \`dataclaw_channels_search_authors\` \u8FDB\u884C\u641C\u7D22\u3002
1278
+ - \u786E\u8BA4\u76EE\u6807\u4F5C\u8005\uFF0C\u83B7\u53D6\u5176\u552F\u4E00\u6807\u8BC6 \`finder_username\`\u3001\u5934\u50CF\u53CA\u8BA4\u8BC1\u7B80\u4ECB\u3002
1003
1279
 
1004
1280
  2. **\u62C9\u53D6\u8FD1\u671F\u4F5C\u54C1 Feed**\uFF1A
1005
- - \u8C03\u7528 \\\`dataclaw_channels_get_author_feeds\\\`\uFF0C\u4F20\u5165\u4F5C\u8005 \\\`finder_username\\\`\u3002
1006
- - \u6BCF\u9875 15 \u6761\u3002\u8981 10~30 \u6761\u5C31\u518D\u4F20\u4E0A\u6B21\u8FD4\u56DE\u7684 \\\`last_buffer\\\` / \\\`buffer\\\` \u7FFB\u4E00\u9875\u3002
1281
+ - \u8C03\u7528 \`dataclaw_channels_get_author_feeds\`\uFF0C\u4F20\u5165\u4F5C\u8005 \`finder_username\`\u3002
1282
+ - \u6BCF\u9875 15 \u6761\u3002\u8981 10~30 \u6761\u5C31\u518D\u4F20\u4E0A\u6B21\u8FD4\u56DE\u7684 \`last_buffer\` / \`buffer\` \u7FFB\u4E00\u9875\u3002
1007
1283
 
1008
1284
  3. **\u4F5C\u54C1\u5168\u91CF\u6570\u636E\u4E0E\u6587\u6848/\u89C6\u9891\u63D0\u53D6\uFF08\u6309\u9700\uFF09**\uFF1A
1009
- - **\u82E5\u9700\u63D0\u53D6\u89C6\u9891\u53E3\u64AD\u6587\u6848**\uFF1A\u76F4\u63A5\u8C03\u7528 \\\`dataclaw_audio_transcribe\\\`\uFF08\u4F20\u5165\u4F5C\u54C1\u5206\u4EAB\u77ED\u94FE\uFF0C\u7CFB\u7EDF\u5E95\u5C42\u81EA\u52A8\u901A\u8FC7 WASM \u89E3\u5BC6\u89C6\u9891\u53F7\u52A0\u5BC6\u89C6\u9891\u6D41\u5E76\u8F6C\u5199\u4E3A\u6587\u6848\u6216 SRT \u5B57\u5E55\uFF09\u3002
1010
- - **\u82E5\u9700\u65E0\u6C34\u5370\u4E0B\u8F7D\u89C6\u9891**\uFF1A\u8C03\u7528 \\\`dataclaw_video_resolve\\\`\uFF08\u4F20\u5165\u89C6\u9891\u53F7\u5206\u4EAB\u77ED\u94FE\uFF09\uFF0C\u63D0\u53D6\u9AD8\u6E05\u4E0B\u8F7D\u76F4\u94FE\u3002
1285
+ - **\u82E5\u9700\u63D0\u53D6\u89C6\u9891\u53E3\u64AD\u6587\u6848**\uFF1A\u76F4\u63A5\u8C03\u7528 \`dataclaw_audio_transcribe\`\uFF08\u4F20\u5165\u4F5C\u54C1\u5206\u4EAB\u77ED\u94FE\uFF0C\u7CFB\u7EDF\u5E95\u5C42\u81EA\u52A8\u901A\u8FC7 WASM \u89E3\u5BC6\u89C6\u9891\u53F7\u52A0\u5BC6\u89C6\u9891\u6D41\u5E76\u8F6C\u5199\u4E3A\u6587\u6848\u6216 SRT \u5B57\u5E55\uFF09\u3002
1286
+ - **\u82E5\u9700\u65E0\u6C34\u5370\u4E0B\u8F7D\u89C6\u9891**\uFF1A\u8C03\u7528 \`dataclaw_video_resolve\`\uFF08\u4F20\u5165\u89C6\u9891\u53F7\u5206\u4EAB\u77ED\u94FE\uFF09\uFF0C\u63D0\u53D6\u9AD8\u6E05\u4E0B\u8F7D\u76F4\u94FE\u3002
1011
1287
 
1012
1288
  4. **\u8FBE\u4EBA\u77E9\u9635\u4E0E\u8FD0\u8425\u7B56\u7565\u63D0\u70BC**\uFF1A
1013
1289
  - \u4E3A\u7528\u6237\u8F93\u51FA\u6DF1\u5EA6\u5206\u6790\u62A5\u544A\uFF1A
@@ -1015,9 +1291,39 @@ globs:
1015
1291
  - **\u3010\u7206\u6B3E\u5185\u5BB9\u7279\u5F81\u3011**\uFF1A\u70B9\u8D5E/\u8F6C\u53D1\u7834\u4E07\u7684\u9898\u6750\u7279\u5F81\u4E0E\u5C01\u9762\u6587\u6848\u5957\u8DEF\u3002
1016
1292
  - **\u3010\u53E3\u64AD\u53F0\u8BCD\u5957\u8DEF\u3011**\uFF1A\u9488\u5BF9\u4EE3\u8868\u4F5C\u63D0\u53D6\u7684\u53F0\u8BCD\u811A\u672C\u8282\u594F\u4E0E\u8BDD\u672F\u62C6\u89E3\u3002
1017
1293
  - **\u3010\u4E92\u52A8\u8F6C\u5316\u5206\u6790\u3011**\uFF1A\u8BC4\u8BBA\u533A\u4E92\u52A8\u70ED\u70B9\u4E0E\u7528\u6237\u79C1\u57DF\u8F6C\u5316\u5F15\u5BFC\u65B9\u5F0F\u3002
1018
- - **\u3010\u6A21\u4EFF\u4E0E\u8D85\u8D8A\u5EFA\u8BAE\u3011**\uFF1A\u5BF9\u6807\u540C\u884C\u7684\u5DEE\u5F02\u5316\u5B9A\u4F4D\u7B56\u7565\u3002
1294
+ - **\u3010\u6A21\u4EFF\u4E0E\u8D85\u8D8A\u5EFA\u8BAE\u3011**\uFF1A\u5BF9\u6807\u540C\u884C\u7684\u5DEE\u5F02\u5316\u5B9A\u4F4D\u7B56\u7565\u3002`
1295
+ }
1296
+ };
1297
+ function renderSkillMarkdown(key, format = "agent-skills") {
1298
+ const def = SKILL_DEFINITIONS[key];
1299
+ if (format === "cursor") {
1300
+ return `---
1301
+ description: ${def.description}
1302
+ globs:
1303
+ ---
1304
+
1305
+ ${def.body.trim()}
1019
1306
  `;
1307
+ }
1308
+ return `---
1309
+ name: ${def.name}
1310
+ description: ${def.description}
1311
+ ---
1312
+
1313
+ ${def.body.trim()}
1314
+ `;
1315
+ }
1316
+ var MEDIA_SKILL_TEMPLATE = renderSkillMarkdown("media", "agent-skills");
1317
+ var DOUYIN_SKILL_TEMPLATE = renderSkillMarkdown("douyin", "agent-skills");
1318
+ var CHANNELS_SKILL_TEMPLATE = renderSkillMarkdown("channels", "agent-skills");
1319
+ var MEDIA_CURSOR_RULE_TEMPLATE = renderSkillMarkdown("media", "cursor");
1320
+ var DOUYIN_CURSOR_RULE_TEMPLATE = renderSkillMarkdown("douyin", "cursor");
1321
+ var CHANNELS_CURSOR_RULE_TEMPLATE = renderSkillMarkdown("channels", "cursor");
1020
1322
  function writeMcpConfig(configFilePath, apiKey, customBaseUrl) {
1323
+ if (configFilePath.endsWith(".toml")) {
1324
+ writeCodexTomlConfig(configFilePath, apiKey, customBaseUrl);
1325
+ return;
1326
+ }
1021
1327
  const dir = path3.dirname(configFilePath);
1022
1328
  if (!fs3.existsSync(dir)) {
1023
1329
  fs3.mkdirSync(dir, { recursive: true });
@@ -1040,42 +1346,135 @@ function writeMcpConfig(configFilePath, apiKey, customBaseUrl) {
1040
1346
  if (customBaseUrl) {
1041
1347
  envVars.DATACLAW_BASE_URL = customBaseUrl;
1042
1348
  }
1043
- existingMcpServers.dataclaw = {
1044
- command: "npx",
1349
+ const serverConfig = {
1350
+ command: process.platform === "win32" ? "npx.cmd" : "npx",
1045
1351
  args: ["-y", "dataclaw-agent-kit", "mcp"],
1046
1352
  env: envVars
1047
1353
  };
1354
+ if (configFilePath.includes(".omp")) {
1355
+ serverConfig.type = "stdio";
1356
+ if (!existingJson.$schema) {
1357
+ existingJson.$schema = "https://raw.githubusercontent.com/can1357/oh-my-pi/main/packages/coding-agent/src/config/mcp-schema.json";
1358
+ }
1359
+ }
1360
+ existingMcpServers.dataclaw = serverConfig;
1048
1361
  existingJson.mcpServers = existingMcpServers;
1049
1362
  fs3.writeFileSync(configFilePath, JSON.stringify(existingJson, null, 2), "utf-8");
1050
1363
  }
1051
- function writeSkillsToDir(skillsDir, skillKeys, extension = ".mdc") {
1364
+ function writeSkillsToDir(skillsDir, skillKeys, formatOrExt = "agent-skills") {
1052
1365
  if (!fs3.existsSync(skillsDir)) {
1053
1366
  fs3.mkdirSync(skillsDir, { recursive: true });
1054
1367
  }
1368
+ const isCursor = formatOrExt === "cursor" || formatOrExt === ".mdc";
1055
1369
  const written = [];
1370
+ for (const key of skillKeys) {
1371
+ const def = SKILL_DEFINITIONS[key];
1372
+ if (!def) continue;
1373
+ if (isCursor) {
1374
+ const file = path3.join(skillsDir, `${def.name}.mdc`);
1375
+ fs3.writeFileSync(file, renderSkillMarkdown(key, "cursor"), "utf-8");
1376
+ written.push(file);
1377
+ } else {
1378
+ const skillFolder = path3.join(skillsDir, def.name);
1379
+ if (!fs3.existsSync(skillFolder)) {
1380
+ fs3.mkdirSync(skillFolder, { recursive: true });
1381
+ }
1382
+ const file = path3.join(skillFolder, "SKILL.md");
1383
+ fs3.writeFileSync(file, renderSkillMarkdown(key, "agent-skills"), "utf-8");
1384
+ written.push(file);
1385
+ const legacyFlatFile = path3.join(skillsDir, `${def.name}.md`);
1386
+ if (fs3.existsSync(legacyFlatFile)) {
1387
+ try {
1388
+ fs3.unlinkSync(legacyFlatFile);
1389
+ } catch {
1390
+ }
1391
+ }
1392
+ }
1393
+ }
1394
+ return written;
1395
+ }
1396
+ function writeCodexTomlConfig(configFilePath, apiKey, customBaseUrl) {
1397
+ const dir = path3.dirname(configFilePath);
1398
+ if (!fs3.existsSync(dir)) {
1399
+ fs3.mkdirSync(dir, { recursive: true });
1400
+ }
1401
+ const isWindows = process.platform === "win32";
1402
+ const cmd = isWindows ? "npx.cmd" : "npx";
1403
+ let envLines = ` DATACLAW_API_KEY = "${apiKey}"`;
1404
+ if (customBaseUrl) {
1405
+ envLines += `
1406
+ DATACLAW_BASE_URL = "${customBaseUrl}"`;
1407
+ }
1408
+ const dataclawBlock = `[mcp_servers.dataclaw]
1409
+ command = "${cmd}"
1410
+ args = ["-y", "dataclaw-agent-kit", "mcp"]
1411
+ startup_timeout_sec = 60
1412
+
1413
+ [mcp_servers.dataclaw.env]
1414
+ ${envLines}`;
1415
+ let content = "";
1416
+ if (fs3.existsSync(configFilePath)) {
1417
+ content = fs3.readFileSync(configFilePath, "utf-8");
1418
+ }
1419
+ const sectionRegex = /\[mcp_servers\.dataclaw\][\s\S]*?(?=(\n\[(?!mcp_servers\.dataclaw))|$)/;
1420
+ if (sectionRegex.test(content)) {
1421
+ content = content.replace(sectionRegex, dataclawBlock.trimEnd());
1422
+ } else {
1423
+ content = content.trimEnd() ? `${content.trimEnd()}
1424
+
1425
+ ${dataclawBlock}
1426
+ ` : `${dataclawBlock}
1427
+ `;
1428
+ }
1429
+ fs3.writeFileSync(configFilePath, content, "utf-8");
1430
+ }
1431
+ function appendInstructionDoc(filePath, skillKeys) {
1432
+ const START_MARKER = "<!-- DataClaw Agent Kit Skills Start -->";
1433
+ const END_MARKER = "<!-- DataClaw Agent Kit Skills End -->";
1434
+ const lines = [
1435
+ START_MARKER,
1436
+ "## \u{1F99E} DataClaw MCP & Agent Skills SOP",
1437
+ "\u5DF2\u542F\u7528 DataClaw \u97F3\u89C6\u9891\u53BB\u6C34\u5370\u89E3\u6790\u3001Whisper \u8F6C\u5199\u4E0E\u793E\u5A92\u6570\u636E\u5206\u6790\u80FD\u529B\u3002\u5728\u9047\u5230\u5BF9\u5E94\u610F\u56FE\u65F6\u8BF7\u81EA\u52A8\u8C03\u7528\uFF1A"
1438
+ ];
1056
1439
  if (skillKeys.includes("media")) {
1057
- const file = path3.join(skillsDir, `dataclaw-media${extension}`);
1058
- fs3.writeFileSync(file, MEDIA_SKILL_TEMPLATE, "utf-8");
1059
- written.push(file);
1440
+ lines.push(
1441
+ "- **\u89C6\u9891\u53BB\u6C34\u5370\u4E0E\u6587\u6848\u63D0\u53D6**\uFF1A\u7528\u6237\u9700\u8981\u6587\u6848/\u5B57\u5E55\u65F6\u76F4\u63A5\u8C03\u7528 `dataclaw_audio_transcribe`\uFF08\u4E00\u6B65\u76F4\u8FBE\uFF09\uFF1B\u9700\u8981\u4E0B\u8F7D\u89C6\u9891\u6216\u56FE\u96C6\u65F6\u8C03\u7528 `dataclaw_video_resolve`\u3002"
1442
+ );
1060
1443
  }
1061
1444
  if (skillKeys.includes("douyin")) {
1062
- const file = path3.join(skillsDir, `dataclaw-douyin${extension}`);
1063
- fs3.writeFileSync(file, DOUYIN_SKILL_TEMPLATE, "utf-8");
1064
- written.push(file);
1445
+ lines.push(
1446
+ "- **\u6296\u97F3\u70ED\u95E8\u89C6\u9891\u4E0E\u8BC4\u8BBA\u590D\u76D8**\uFF1A\u641C\u7D22\u5173\u952E\u8BCD\u8C03\u7528 `dataclaw_dy_search_videos`\uFF1B\u8BE6\u60C5\u8C03\u7528 `dataclaw_dy_get_video_detail`\uFF1B\u64AD\u653E\u91CF\u8C03\u7528 `dataclaw_dy_get_play_stats`\uFF1B\u8BC4\u8BBA\u75DB\u70B9\u8C03\u7528 `dataclaw_dy_get_comments`\u3002"
1447
+ );
1065
1448
  }
1066
1449
  if (skillKeys.includes("channels")) {
1067
- const file = path3.join(skillsDir, `dataclaw-channels${extension}`);
1068
- fs3.writeFileSync(file, CHANNELS_SKILL_TEMPLATE, "utf-8");
1069
- written.push(file);
1450
+ lines.push(
1451
+ "- **\u5FAE\u4FE1\u89C6\u9891\u53F7\u8FBE\u4EBA\u4E0E\u4F5C\u54C1\u76D1\u63A7**\uFF1A\u68C0\u7D22\u4F5C\u8005\u8C03\u7528 `dataclaw_channels_search_authors`\uFF1BFeed \u52A8\u6001\u8C03\u7528 `dataclaw_channels_get_author_feeds`\uFF1B\u4F5C\u54C1\u89E3\u6790\u8C03\u7528 `dataclaw_channels_resolve_share_url`\u3002"
1452
+ );
1070
1453
  }
1071
- return written;
1454
+ lines.push(END_MARKER);
1455
+ const blockText = lines.join("\n");
1456
+ let existing = "";
1457
+ if (fs3.existsSync(filePath)) {
1458
+ existing = fs3.readFileSync(filePath, "utf-8");
1459
+ }
1460
+ const regex = new RegExp(`${START_MARKER}[\\s\\S]*?${END_MARKER}`);
1461
+ if (regex.test(existing)) {
1462
+ existing = existing.replace(regex, blockText);
1463
+ } else {
1464
+ existing = existing.trimEnd() ? `${existing.trimEnd()}
1465
+
1466
+ ${blockText}
1467
+ ` : `${blockText}
1468
+ `;
1469
+ }
1470
+ fs3.writeFileSync(filePath, existing, "utf-8");
1072
1471
  }
1073
1472
 
1074
1473
  // src/cli/index.ts
1075
1474
  import path4 from "path";
1076
1475
  import pc from "picocolors";
1077
1476
  import prompts from "prompts";
1078
- async function runInitWizard() {
1477
+ async function runInitWizard(options = {}) {
1079
1478
  console.log(
1080
1479
  pc.cyan(`
1081
1480
  \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
@@ -1084,7 +1483,6 @@ async function runInitWizard() {
1084
1483
  `)
1085
1484
  );
1086
1485
  const defaultApiKey = process.env.DATACLAW_API_KEY || "";
1087
- const detectedIdes = detectIdeEnvironments();
1088
1486
  const keyResponse = await prompts({
1089
1487
  type: "password",
1090
1488
  name: "apiKey",
@@ -1118,6 +1516,31 @@ async function runInitWizard() {
1118
1516
  return;
1119
1517
  }
1120
1518
  }
1519
+ let isGlobal = Boolean(options.global);
1520
+ if (options.global === void 0) {
1521
+ const scopeResponse = await prompts({
1522
+ type: "select",
1523
+ name: "scope",
1524
+ message: "\u8BF7\u9009\u62E9\u914D\u7F6E\u751F\u6548\u8303\u56F4 (Scope):",
1525
+ choices: [
1526
+ {
1527
+ title: "\u5168\u5C40\u7528\u6237\u7EA7 (Global - \u5199\u5165 ~/.cursor \u7B49\uFF0C\u6240\u6709\u5DE5\u7A0B\u6253\u5F00\u5747\u53EF\u76F4\u63A5\u4F7F\u7528\uFF0C\u63A8\u8350)",
1528
+ value: "global"
1529
+ },
1530
+ {
1531
+ title: "\u5F53\u524D\u5DE5\u4F5C\u533A (Local - \u4EC5\u5728\u5F53\u524D\u76EE\u5F55\u751F\u6548)",
1532
+ value: "local"
1533
+ }
1534
+ ],
1535
+ initial: 0
1536
+ });
1537
+ if (!scopeResponse.scope) {
1538
+ console.log(pc.yellow("\u5DF2\u53D6\u6D88\u5B89\u88C5\u5411\u5BFC\u3002"));
1539
+ return;
1540
+ }
1541
+ isGlobal = scopeResponse.scope === "global";
1542
+ }
1543
+ const detectedIdes = detectIdeEnvironments({ isGlobal });
1121
1544
  const ideChoices = detectedIdes.map((ide) => ({
1122
1545
  title: ide.name,
1123
1546
  value: ide.id,
@@ -1178,8 +1601,8 @@ async function runInitWizard() {
1178
1601
  }
1179
1602
  if (ideMeta.skillsDir) {
1180
1603
  try {
1181
- const ext = target === "cursor" ? ".mdc" : ".md";
1182
- const writtenFiles = writeSkillsToDir(ideMeta.skillsDir, selectedSkills, ext);
1604
+ const format = target === "cursor" ? "cursor" : "agent-skills";
1605
+ const writtenFiles = writeSkillsToDir(ideMeta.skillsDir, selectedSkills, format);
1183
1606
  for (const f of writtenFiles) {
1184
1607
  console.log(pc.green(`\u2714 \u573A\u666F\u6280\u80FD\u5DF2\u751F\u6210: ${path4.relative(process.cwd(), f) || f}`));
1185
1608
  }
@@ -1187,10 +1610,27 @@ async function runInitWizard() {
1187
1610
  console.error(pc.red(`\u2716 \u5199\u5165\u6280\u80FD\u6587\u4EF6\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`));
1188
1611
  }
1189
1612
  }
1613
+ if (target === "claude-code" && !isGlobal) {
1614
+ try {
1615
+ const claudeMd = path4.join(process.cwd(), "CLAUDE.md");
1616
+ appendInstructionDoc(claudeMd, selectedSkills);
1617
+ console.log(pc.green(`\u2714 \u573A\u666F\u6280\u80FD\u5DF2\u6CE8\u5165: ${path4.relative(process.cwd(), claudeMd) || claudeMd}`));
1618
+ } catch (err) {
1619
+ console.error(pc.red(`\u2716 \u5199\u5165 CLAUDE.md \u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`));
1620
+ }
1621
+ } else if ((target === "codex" || target === "omp") && !isGlobal) {
1622
+ try {
1623
+ const agentsMd = path4.join(process.cwd(), "AGENTS.md");
1624
+ appendInstructionDoc(agentsMd, selectedSkills);
1625
+ console.log(pc.green(`\u2714 \u573A\u666F\u6280\u80FD\u5DF2\u6CE8\u5165: ${path4.relative(process.cwd(), agentsMd) || agentsMd}`));
1626
+ } catch (err) {
1627
+ console.error(pc.red(`\u2716 \u5199\u5165 AGENTS.md \u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`));
1628
+ }
1629
+ }
1190
1630
  }
1191
1631
  console.log(
1192
1632
  pc.cyan(`
1193
- \u{1F389} \u5B89\u88C5\u5B8C\u6210\uFF01\u5728 Cursor Composer\u3001Claude \u6216 Codex \u4E2D\u76F4\u63A5\u63D0\u95EE\u4F53\u9A8C:
1633
+ \u{1F389} \u5B89\u88C5\u5B8C\u6210\uFF01\u5728 Cursor Composer\u3001Claude\u3001Codex \u6216 OMP \u4E2D\u76F4\u63A5\u63D0\u95EE\u4F53\u9A8C:
1194
1634
  "\u5E2E\u6211\u628A\u8FD9\u4E2A\u6296\u97F3\u94FE\u63A5\u7684\u5185\u5BB9\u8F6C\u6210\u6587\u7AE0: https://v.douyin.com/..."
1195
1635
  "\u5206\u6790\u6296\u97F3\u4E0A\u505A\u5C0F\u5403\u52A0\u76DF\u7684\u70B9\u8D5E\u6700\u9AD8\u89C6\u9891\u4E0E\u8BC4\u8BBA\u75DB\u70B9"
1196
1636
  `)
@@ -1212,11 +1652,18 @@ export {
1212
1652
  createMcpServer,
1213
1653
  startMcpServer,
1214
1654
  detectIdeEnvironments,
1655
+ SKILL_DEFINITIONS,
1656
+ renderSkillMarkdown,
1215
1657
  MEDIA_SKILL_TEMPLATE,
1216
1658
  DOUYIN_SKILL_TEMPLATE,
1217
1659
  CHANNELS_SKILL_TEMPLATE,
1660
+ MEDIA_CURSOR_RULE_TEMPLATE,
1661
+ DOUYIN_CURSOR_RULE_TEMPLATE,
1662
+ CHANNELS_CURSOR_RULE_TEMPLATE,
1218
1663
  writeMcpConfig,
1219
1664
  writeSkillsToDir,
1665
+ writeCodexTomlConfig,
1666
+ appendInstructionDoc,
1220
1667
  runInitWizard
1221
1668
  };
1222
- //# sourceMappingURL=chunk-XH4I6W6J.js.map
1669
+ //# sourceMappingURL=chunk-5CAQMDT2.js.map