@talesofai/neta-skills 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +234 -0
  4. package/README.md +237 -0
  5. package/bin/apis/activity.js +14 -0
  6. package/bin/apis/artifact.js +64 -0
  7. package/bin/apis/audio.js +10 -0
  8. package/bin/apis/collection.js +87 -0
  9. package/bin/apis/config.js +49 -0
  10. package/bin/apis/feeds.js +34 -0
  11. package/bin/apis/gpt.js +10 -0
  12. package/bin/apis/hashtag.js +23 -0
  13. package/bin/apis/index.js +62 -0
  14. package/bin/apis/prompt.js +120 -0
  15. package/bin/apis/recsys.js +29 -0
  16. package/bin/apis/space.js +48 -0
  17. package/bin/apis/task.js +21 -0
  18. package/bin/apis/tcp.js +16 -0
  19. package/bin/apis/types.js +76 -0
  20. package/bin/apis/user.js +45 -0
  21. package/bin/apis/verse.js +18 -0
  22. package/bin/cli.js +16 -0
  23. package/bin/commands/community/create_comment.cmd.en_us.yml +4 -0
  24. package/bin/commands/community/create_comment.cmd.js +40 -0
  25. package/bin/commands/community/create_comment.cmd.zh_cn.yml +3 -0
  26. package/bin/commands/community/favor_collection.cmd.en_us.yml +4 -0
  27. package/bin/commands/community/favor_collection.cmd.js +29 -0
  28. package/bin/commands/community/favor_collection.cmd.zh_cn.yml +3 -0
  29. package/bin/commands/community/get_fan_list.cmd.en_us.yml +4 -0
  30. package/bin/commands/community/get_fan_list.cmd.js +36 -0
  31. package/bin/commands/community/get_fan_list.cmd.zh_cn.yml +3 -0
  32. package/bin/commands/community/get_hashtag_characters.cmd.en_us.yml +4 -0
  33. package/bin/commands/community/get_hashtag_characters.cmd.js +46 -0
  34. package/bin/commands/community/get_hashtag_characters.cmd.zh_cn.yml +3 -0
  35. package/bin/commands/community/get_hashtag_collections.cmd.en_us.yml +6 -0
  36. package/bin/commands/community/get_hashtag_collections.cmd.js +54 -0
  37. package/bin/commands/community/get_hashtag_collections.cmd.zh_cn.yml +5 -0
  38. package/bin/commands/community/get_hashtag_info.cmd.en_us.yml +4 -0
  39. package/bin/commands/community/get_hashtag_info.cmd.js +42 -0
  40. package/bin/commands/community/get_hashtag_info.cmd.zh_cn.yml +3 -0
  41. package/bin/commands/community/get_subscribe_list.cmd.en_us.yml +4 -0
  42. package/bin/commands/community/get_subscribe_list.cmd.js +36 -0
  43. package/bin/commands/community/get_subscribe_list.cmd.zh_cn.yml +3 -0
  44. package/bin/commands/community/like_collection.cmd.en_us.yml +4 -0
  45. package/bin/commands/community/like_collection.cmd.js +29 -0
  46. package/bin/commands/community/like_collection.cmd.zh_cn.yml +4 -0
  47. package/bin/commands/community/list_space_topics.cmd.en_us.yml +7 -0
  48. package/bin/commands/community/list_space_topics.cmd.js +39 -0
  49. package/bin/commands/community/list_space_topics.cmd.zh_cn.yml +6 -0
  50. package/bin/commands/community/list_spaces.cmd.en_us.yml +4 -0
  51. package/bin/commands/community/list_spaces.cmd.js +19 -0
  52. package/bin/commands/community/list_spaces.cmd.zh_cn.yml +3 -0
  53. package/bin/commands/community/read_collection.cmd.en_us.yml +4 -0
  54. package/bin/commands/community/read_collection.cmd.js +83 -0
  55. package/bin/commands/community/read_collection.cmd.zh_cn.yml +3 -0
  56. package/bin/commands/community/request_interactive_feed.cmd.en_us.yml +4 -0
  57. package/bin/commands/community/request_interactive_feed.cmd.js +54 -0
  58. package/bin/commands/community/request_interactive_feed.cmd.zh_cn.yml +5 -0
  59. package/bin/commands/community/subscribe_user.cmd.en_us.yml +4 -0
  60. package/bin/commands/community/subscribe_user.cmd.js +33 -0
  61. package/bin/commands/community/subscribe_user.cmd.zh_cn.yml +3 -0
  62. package/bin/commands/community/suggest_categories.cmd.en_us.yml +4 -0
  63. package/bin/commands/community/suggest_categories.cmd.js +26 -0
  64. package/bin/commands/community/suggest_categories.cmd.zh_cn.yml +3 -0
  65. package/bin/commands/community/suggest_content.cmd.en_us.yml +5 -0
  66. package/bin/commands/community/suggest_content.cmd.js +59 -0
  67. package/bin/commands/community/suggest_content.cmd.zh_cn.yml +4 -0
  68. package/bin/commands/community/suggest_keywords.cmd.en_us.yml +4 -0
  69. package/bin/commands/community/suggest_keywords.cmd.js +26 -0
  70. package/bin/commands/community/suggest_keywords.cmd.zh_cn.yml +3 -0
  71. package/bin/commands/community/suggest_tags.cmd.en_us.yml +4 -0
  72. package/bin/commands/community/suggest_tags.cmd.js +26 -0
  73. package/bin/commands/community/suggest_tags.cmd.zh_cn.yml +3 -0
  74. package/bin/commands/community/validate_tax_path.cmd.en_us.yml +4 -0
  75. package/bin/commands/community/validate_tax_path.cmd.js +24 -0
  76. package/bin/commands/community/validate_tax_path.cmd.zh_cn.yml +3 -0
  77. package/bin/commands/creative/edit_colleciton.cmd.en_us.yml +11 -0
  78. package/bin/commands/creative/edit_colleciton.cmd.js +140 -0
  79. package/bin/commands/creative/edit_colleciton.cmd.zh_cn.yml +10 -0
  80. package/bin/commands/creative/make_image.cmd.en_us.yml +20 -0
  81. package/bin/commands/creative/make_image.cmd.js +58 -0
  82. package/bin/commands/creative/make_image.cmd.zh_cn.yml +19 -0
  83. package/bin/commands/creative/make_song.cmd.en_us.yml +8 -0
  84. package/bin/commands/creative/make_song.cmd.js +53 -0
  85. package/bin/commands/creative/make_song.cmd.zh_cn.yml +7 -0
  86. package/bin/commands/creative/make_video.cmd.en_us.yml +17 -0
  87. package/bin/commands/creative/make_video.cmd.js +54 -0
  88. package/bin/commands/creative/make_video.cmd.zh_cn.yml +16 -0
  89. package/bin/commands/creative/publish_collection.cmd.en_us.yml +10 -0
  90. package/bin/commands/creative/publish_collection.cmd.js +101 -0
  91. package/bin/commands/creative/publish_collection.cmd.zh_cn.yml +9 -0
  92. package/bin/commands/creative/remove_background.cmd.en_us.yml +10 -0
  93. package/bin/commands/creative/remove_background.cmd.js +74 -0
  94. package/bin/commands/creative/remove_background.cmd.zh_cn.yml +9 -0
  95. package/bin/commands/creative/request_character_or_elementum.cmd.en_us.yml +23 -0
  96. package/bin/commands/creative/request_character_or_elementum.cmd.js +108 -0
  97. package/bin/commands/creative/request_character_or_elementum.cmd.zh_cn.yml +22 -0
  98. package/bin/commands/creative/search_tcp.cmd.en_us.yml +16 -0
  99. package/bin/commands/creative/search_tcp.cmd.js +53 -0
  100. package/bin/commands/creative/search_tcp.cmd.zh_cn.yml +15 -0
  101. package/bin/commands/factory.js +15 -0
  102. package/bin/commands/load.js +157 -0
  103. package/bin/utils/errors.js +61 -0
  104. package/bin/utils/json.js +8 -0
  105. package/bin/utils/lang.js +8 -0
  106. package/bin/utils/parse_meta.js +16 -0
  107. package/bin/utils/polling.js +17 -0
  108. package/bin/utils/prompts.js +186 -0
  109. package/package.json +77 -0
  110. package/skills/neta/SKILL.md +119 -0
  111. package/skills/neta-community/SKILL.md +123 -0
  112. package/skills/neta-creative/SKILL.md +118 -0
  113. package/skills/neta-space/SKILL.md +129 -0
  114. package/skills/neta-suggest/SKILL.md +490 -0
  115. package/skills/zh_cn/neta/SKILL.md +111 -0
  116. package/skills/zh_cn/neta/references/character-search.md +234 -0
  117. package/skills/zh_cn/neta/references/collection-remix.md +40 -0
  118. package/skills/zh_cn/neta/references/community-exploration.md +636 -0
  119. package/skills/zh_cn/neta/references/hashtag-research.md +295 -0
  120. package/skills/zh_cn/neta/references/image-generation.md +121 -0
  121. package/skills/zh_cn/neta/references/interactive-feed.md +377 -0
  122. package/skills/zh_cn/neta/references/social-interactive.md +73 -0
  123. package/skills/zh_cn/neta/references/song-creation.md +247 -0
  124. package/skills/zh_cn/neta/references/song-mv.md +198 -0
  125. package/skills/zh_cn/neta/references/space.md +90 -0
  126. package/skills/zh_cn/neta/references/video-generation.md +221 -0
  127. package/skills/zh_cn/neta-community/SKILL.md +109 -0
  128. package/skills/zh_cn/neta-community/references/character-search.md +233 -0
  129. package/skills/zh_cn/neta-community/references/hashtag-research.md +295 -0
  130. package/skills/zh_cn/neta-community/references/interactive-feed.md +377 -0
  131. package/skills/zh_cn/neta-community/references/social-interactive.md +73 -0
  132. package/skills/zh_cn/neta-creative/SKILL.md +105 -0
  133. package/skills/zh_cn/neta-creative/references/character-search.md +233 -0
  134. package/skills/zh_cn/neta-creative/references/collection-remix.md +40 -0
  135. package/skills/zh_cn/neta-creative/references/image-generation.md +121 -0
  136. package/skills/zh_cn/neta-creative/references/song-creation.md +247 -0
  137. package/skills/zh_cn/neta-creative/references/song-mv.md +198 -0
  138. package/skills/zh_cn/neta-creative/references/video-generation.md +221 -0
  139. package/skills/zh_cn/neta-space/SKILL.md +126 -0
  140. package/skills/zh_cn/neta-suggest/SKILL.md +662 -0
@@ -0,0 +1,33 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ export const subscribeUserCmd = createCommand({
10
+ name: meta.name,
11
+ title: meta.title,
12
+ description: meta.description,
13
+ inputSchema: Type.Object({
14
+ user_uuid: Type.String(),
15
+ is_cancel: Type.Boolean({
16
+ default: false,
17
+ }),
18
+ }),
19
+ }, async ({ user_uuid, is_cancel }, { apis }) => {
20
+ const action = is_cancel ? "unsubscribe" : "subscribe";
21
+ const result = await apis.user.subscribeUser({
22
+ user_uuid,
23
+ is_cancel,
24
+ });
25
+ if (!result.success) {
26
+ throw new Error(`${action} fail`);
27
+ }
28
+ return {
29
+ success: true,
30
+ subscribe_status: result.subscribe_status,
31
+ message: `${action} success`,
32
+ };
33
+ });
@@ -0,0 +1,3 @@
1
+ name: subscribe_user
2
+ title: 关注用户&取消关注
3
+ description: 对用户进行关注或取消关注操作
@@ -0,0 +1,4 @@
1
+ name: suggest_categories
2
+ title: 📂 Suggest Category Hierarchy
3
+ description: Return navigation suggestions for the requested level in the content category hierarchy (category navigation suggestions).
4
+
@@ -0,0 +1,26 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ const suggestCategoriesV1Parameters = Type.Object({
10
+ level: Type.Integer({ minimum: 1, maximum: 5, default: 1 }),
11
+ parent_path: Type.Optional(Type.String()),
12
+ });
13
+ export const suggestCategories = createCommand({
14
+ name: meta.name,
15
+ title: meta.title,
16
+ description: meta.description,
17
+ inputSchema: suggestCategoriesV1Parameters,
18
+ }, async ({ level, parent_path }, { apis }) => {
19
+ const result = await apis.recsys.suggestCategories({
20
+ level,
21
+ parent_path,
22
+ });
23
+ return {
24
+ suggestions: result.suggestions || [],
25
+ };
26
+ });
@@ -0,0 +1,3 @@
1
+ name: suggest_categories
2
+ title: 📂 获取玩法分类层级的导航建议
3
+ description: 获取指定层级的分类导航建议(Category Navigation Suggestions)
@@ -0,0 +1,5 @@
1
+ name: suggest_content
2
+ title: 🧠 Content Suggestion Engine (Recommend/Search/Exact Modes)
3
+ description: |
4
+ Return a personalized content feed according to the specified intent and filters (content feed suggestion).
5
+
@@ -0,0 +1,59 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ // 创建扁平化的输入 schema(所有数组改为字符串,手动分割)
10
+ export const suggestContentInputSchema = Type.Object({
11
+ page_index: Type.Integer({ minimum: 0, default: 0 }),
12
+ page_size: Type.Integer({ minimum: 1, maximum: 40, default: 20 }),
13
+ scene: Type.String({ default: "agent_intent" }),
14
+ biz_trace_id: Type.Optional(Type.String()),
15
+ // 业务数据扁平化(使用逗号分隔的字符串)
16
+ intent: Type.Union([Type.Literal("recommend"), Type.Literal("search"), Type.Literal("exact")], { default: "recommend" }),
17
+ search_keywords: Type.String({ default: "" }),
18
+ tax_paths: Type.String({ default: "" }),
19
+ tax_primaries: Type.String({ default: "" }),
20
+ tax_secondaries: Type.String({ default: "" }),
21
+ tax_tertiaries: Type.String({ default: "" }),
22
+ exclude_keywords: Type.String({ default: "" }),
23
+ exclude_tax_paths: Type.String({ default: "" }),
24
+ });
25
+ export const suggestContent = createCommand({
26
+ name: meta.name,
27
+ title: meta.title,
28
+ description: meta.description,
29
+ inputSchema: suggestContentInputSchema,
30
+ }, async (params, { apis }) => {
31
+ // 将逗号分隔的字符串转换为数组
32
+ const parseArray = (str) => str
33
+ .split(",")
34
+ .map((s) => s.trim())
35
+ .filter(Boolean);
36
+ // 将扁平化参数转换为嵌套的 business_data 结构
37
+ const requestPayload = {
38
+ page_index: params.page_index,
39
+ page_size: params.page_size,
40
+ scene: params.scene,
41
+ biz_trace_id: params.biz_trace_id,
42
+ business_data: {
43
+ intent: params.intent,
44
+ search_keywords: parseArray(params.search_keywords),
45
+ tax_paths: parseArray(params.tax_paths),
46
+ tax_primaries: parseArray(params.tax_primaries),
47
+ tax_secondaries: parseArray(params.tax_secondaries),
48
+ tax_tertiaries: parseArray(params.tax_tertiaries),
49
+ exclude_keywords: parseArray(params.exclude_keywords),
50
+ exclude_tax_paths: parseArray(params.exclude_tax_paths),
51
+ },
52
+ };
53
+ const result = await apis.recsys.suggestContent(requestPayload);
54
+ // 将 API 返回结果转换为新结构
55
+ return {
56
+ module_list: result.module_list,
57
+ page_data: result.page_data,
58
+ };
59
+ });
@@ -0,0 +1,4 @@
1
+ name: suggest_content
2
+ title: 🧠 智能内容流引擎(支持推荐/搜索/精确筛选三模式)
3
+ description: |
4
+ 根据指定模式返回个性化的内容流(Content Feed Suggestion)
@@ -0,0 +1,4 @@
1
+ name: suggest_keywords
2
+ title: 🔍 Suggest Search Keywords
3
+ description: Return suggested search keywords based on a user‑provided prefix (search keyword autocomplete).
4
+
@@ -0,0 +1,26 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ const suggestKeywordsV1Parameters = Type.Object({
10
+ prefix: Type.String({ minLength: 1 }),
11
+ size: Type.Integer({ minimum: 1, maximum: 50, default: 10 }),
12
+ });
13
+ export const suggestKeywords = createCommand({
14
+ name: meta.name,
15
+ title: meta.title,
16
+ description: meta.description,
17
+ inputSchema: suggestKeywordsV1Parameters,
18
+ }, async ({ prefix, size }, { apis }) => {
19
+ const result = await apis.recsys.suggestKeywords({
20
+ prefix,
21
+ size,
22
+ });
23
+ return {
24
+ suggestions: result.suggestions || [],
25
+ };
26
+ });
@@ -0,0 +1,3 @@
1
+ name: suggest_keywords
2
+ title: 🔍 获取搜索关键词的自动补全建议
3
+ description: 基于用户输入的前缀,返回相关的搜索关键词建议(Search Keyword Autocomplete)
@@ -0,0 +1,4 @@
1
+ name: suggest_tags
2
+ title: 🏷️ Suggest Related Tags
3
+ description: Return related tag suggestions based on a full search keyword (tag matching suggestions).
4
+
@@ -0,0 +1,26 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ const suggestTagsV1Parameters = Type.Object({
10
+ keyword: Type.String({ minLength: 1 }),
11
+ size: Type.Integer({ minimum: 1, maximum: 50, default: 10 }),
12
+ });
13
+ export const suggestTags = createCommand({
14
+ name: meta.name,
15
+ title: meta.title,
16
+ description: meta.description,
17
+ inputSchema: suggestTagsV1Parameters,
18
+ }, async ({ keyword, size }, { apis }) => {
19
+ const result = await apis.recsys.suggestTags({
20
+ keyword,
21
+ size,
22
+ });
23
+ return {
24
+ suggestions: result.suggestions || [],
25
+ };
26
+ });
@@ -0,0 +1,3 @@
1
+ name: suggest_tags
2
+ title: 🏷️ 基于完整关键词获取相关标签建议
3
+ description: 基于完整的搜索关键词,返回相关的标签建议(Tag Matching Suggestions)
@@ -0,0 +1,4 @@
1
+ name: validate_tax_path
2
+ title: ✅ Validate Taxonomy Path
3
+ description: Validate whether a given taxonomy path string is valid (validate taxonomy path).
4
+
@@ -0,0 +1,24 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ }), import.meta);
9
+ const validateTaxPathV1Parameters = Type.Object({
10
+ tax_path: Type.String({ minLength: 1 }),
11
+ });
12
+ export const validateTaxPath = createCommand({
13
+ name: meta.name,
14
+ title: meta.title,
15
+ description: meta.description,
16
+ inputSchema: validateTaxPathV1Parameters,
17
+ }, async ({ tax_path }, { apis }) => {
18
+ const result = await apis.recsys.validateTaxPath({
19
+ tax_path,
20
+ });
21
+ return {
22
+ valid: result.valid || false,
23
+ };
24
+ });
@@ -0,0 +1,3 @@
1
+ name: validate_tax_path
2
+ title: ✅ 验证玩法标签路径是否有效
3
+ description: 验证指定的分类路径字符串是否有效(Validate Taxonomy Path)
@@ -0,0 +1,11 @@
1
+ name: edit_collection
2
+ title: Edit Collection
3
+ description: Edit an existing collection.
4
+ parameters:
5
+ uuid: Collection UUID.
6
+ name: Collection title.
7
+ description: Short description of the collection.
8
+ status: Publish status of the collection, either PRIVATE or PUBLISHED.
9
+ artifacts: List of collection assets, minimum 1 and maximum 12 items. Example picture_uuid,picture_uuid
10
+ hashtags: List of collection hashtags. Example hashtag_name,hashtag_name
11
+
@@ -0,0 +1,140 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { createCommand } from "../factory.js";
4
+ const meta = parseMeta(Type.Object({
5
+ name: Type.String(),
6
+ title: Type.String(),
7
+ description: Type.String(),
8
+ parameters: Type.Object({
9
+ uuid: Type.String(),
10
+ name: Type.String(),
11
+ description: Type.String(),
12
+ status: Type.String(),
13
+ artifacts: Type.String(),
14
+ hashtags: Type.String(),
15
+ }),
16
+ }), import.meta);
17
+ export const editCollection = createCommand({
18
+ name: meta.name,
19
+ title: meta.title,
20
+ description: meta.description,
21
+ inputSchema: Type.Object({
22
+ uuid: Type.String({ description: meta.parameters.uuid }),
23
+ name: Type.Optional(Type.String({ description: meta.parameters.name })),
24
+ description: Type.Optional(Type.String({ description: meta.parameters.description })),
25
+ status: Type.Optional(Type.Union([Type.Literal("PRIVATE"), Type.Literal("PUBLISHED")], {
26
+ description: meta.parameters.status,
27
+ })),
28
+ artifacts: Type.Optional(Type.String({ description: meta.parameters.artifacts })),
29
+ hashtags: Type.Optional(Type.String({ description: meta.parameters.hashtags })),
30
+ remix_instruct: Type.Optional(Type.String()),
31
+ }),
32
+ }, async ({ uuid, name, description, status, hashtags, artifacts, remix_instruct }, { apis }) => {
33
+ const [collection] = await apis.collection.collectionDetails([uuid]);
34
+ if (!collection) {
35
+ throw new Error(`collection ${uuid} not found`);
36
+ }
37
+ const payload = {
38
+ uuid,
39
+ name: collection.name,
40
+ description: collection.description ?? "",
41
+ status: collection.status,
42
+ hashtags: collection.hashtags,
43
+ displayData: collection.displayData,
44
+ editorData: collection.editorData,
45
+ picCount: collection.picCount,
46
+ coverUrl: collection.coverUrl,
47
+ shareUrl: collection.shareUrl,
48
+ aspect: collection.aspect,
49
+ activity: collection.activity,
50
+ extra_data: collection.extra_data,
51
+ bgm_uuid: collection.bgm_uuid,
52
+ video_uuid: collection.video_uuid,
53
+ is_interactive: collection.is_interactive,
54
+ };
55
+ if (name) {
56
+ payload.name = name;
57
+ }
58
+ if (description) {
59
+ payload.description = description;
60
+ }
61
+ if (status) {
62
+ payload.status = status;
63
+ }
64
+ if (hashtags) {
65
+ const tags = await Promise.all(hashtags?.split(",")?.map((tag) => apis.hashtag.createHashtag(tag)) ??
66
+ []);
67
+ const tagDetails = await Promise.all(tags.map((tag) => apis.hashtag.fetchHashtag(tag.name)));
68
+ const activity = tagDetails.find((tag) => tag?.activity_detail?.uuid) ?? null;
69
+ payload.hashtags = tagDetails.map((tag) => tag.name);
70
+ payload.activity = activity?.activity_detail?.uuid ?? null;
71
+ }
72
+ if (artifacts) {
73
+ const artifactDetails = await apis.artifact.artifactDetail(artifacts?.split(",") ?? []);
74
+ if (artifactDetails.length < 1 || artifactDetails.length > 12) {
75
+ throw new Error("artifacts must be between 1 and 12");
76
+ }
77
+ artifactDetails.forEach((artifact, index) => {
78
+ if (!artifact) {
79
+ throw new Error(`artifact ${artifacts[index]} not found`);
80
+ }
81
+ if (artifact.status !== "SUCCESS") {
82
+ throw new Error(`artifact ${artifacts[index]} status is not success`);
83
+ }
84
+ });
85
+ const coverArtifact = artifactDetails.find((artifact) => artifact.url) ?? null;
86
+ const aspect = (() => {
87
+ if (!coverArtifact)
88
+ return "3:4";
89
+ if (coverArtifact.modality === "PICTURE" &&
90
+ coverArtifact.image_detail) {
91
+ return `${coverArtifact.image_detail.width}:${coverArtifact.image_detail.height}`;
92
+ }
93
+ if (coverArtifact.modality === "VIDEO" && coverArtifact.video_detail) {
94
+ return `${coverArtifact.video_detail.width}:${coverArtifact.video_detail.height}`;
95
+ }
96
+ return "3:4";
97
+ })();
98
+ const data = {
99
+ pages: [
100
+ {
101
+ images: artifactDetails,
102
+ },
103
+ ],
104
+ };
105
+ const characters = new Map();
106
+ artifactDetails.forEach((artifact) => {
107
+ artifact.input?.rawPrompt?.forEach((p) => {
108
+ if (p?.type === "official_character_vtoken_adaptor" ||
109
+ p?.type === "oc_vtoken_adaptor") {
110
+ characters.set(p.value, {
111
+ type: "character",
112
+ name: p.name,
113
+ weight: p.weight,
114
+ value: p.value,
115
+ });
116
+ }
117
+ });
118
+ });
119
+ payload.displayData = data;
120
+ payload.editorData = data;
121
+ payload.picCount = artifactDetails.length;
122
+ payload.coverUrl = coverArtifact?.url ?? null;
123
+ payload.shareUrl = coverArtifact?.url ?? null;
124
+ payload.aspect = aspect;
125
+ payload.refCharacterTokens = Array.from(characters.values());
126
+ }
127
+ if (remix_instruct) {
128
+ if (payload.extra_data) {
129
+ payload.extra_data.remix_instruct = remix_instruct;
130
+ }
131
+ else {
132
+ payload.extra_data = {
133
+ remix_instruct,
134
+ };
135
+ }
136
+ }
137
+ const updated = await apis.collection.saveCollection(payload);
138
+ await apis.collection.publishCollection(uuid);
139
+ return updated;
140
+ });
@@ -0,0 +1,10 @@
1
+ name: edit_collection
2
+ title: 编辑作品
3
+ description: 编辑一个作品
4
+ parameters:
5
+ uuid: 作品 uuid
6
+ name: 作品标题
7
+ description: 作品简介
8
+ status: 作品发布状态 PRIVATE(私密) 或 PUBLISHED(公开)
9
+ artifacts: 作品素材列表, 最少1张, 最多12张, 示例, picture_uuid,picture_uuid
10
+ hashtags: 作品标签列表, 示例, hashtag_name,hashtag_name
@@ -0,0 +1,20 @@
1
+ name: make_image
2
+ title: Generate Image
3
+ description: Generate images from text prompts and/or reference images.
4
+ parameters:
5
+ prompt: |
6
+ The prompt for image generation.
7
+ - It can include:
8
+ - Characters: reference characters with @character_name; this includes the full character definition.
9
+ - Visual elements: reference style elements with /element_name, for example /MangaStyle.
10
+ - Reference images: reference existing images with the pattern ref_img-uuid, e.g. "ref_img-1234567890". At most 14 images are supported.
11
+ - Natural language phrases: describe the desired scene in detail. If you do not reference a character, you should describe the character’s appearance here.
12
+ - Notes:
13
+ - Provide as much context and intent as possible. Narrative descriptions of the scene almost always produce better and more coherent images than a flat list of disconnected keywords.
14
+ - Character references must appear in the form @character_name, e.g. @Neta.
15
+ - Element references must appear in the form /elementum_name, e.g. /MangaStyle.
16
+ - When referencing characters or elements, separate them with spaces or commas, for example: "@character_name, /elementum_name, walking on campus".
17
+ - For image editing or image‑to‑image tasks, always include the proper reference image variables.
18
+ - Example (character + element): @character_name, /elementum_name, ref_img-1234567890, ref_img-1234567891, keyword1, keyword2…
19
+ aspect: Image aspect ratio
20
+
@@ -0,0 +1,58 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { buildMakeImagePayload } from "../../apis/types.js";
3
+ import { parseMeta } from "../../utils/parse_meta.js";
4
+ import { polling } from "../../utils/polling.js";
5
+ import { createCommand } from "../factory.js";
6
+ const meta = parseMeta(Type.Object({
7
+ name: Type.String(),
8
+ title: Type.String(),
9
+ description: Type.String(),
10
+ parameters: Type.Object({
11
+ prompt: Type.String(),
12
+ aspect: Type.String(),
13
+ }),
14
+ }), import.meta);
15
+ const makeImageV1Parameters = Type.Object({
16
+ prompt: Type.String({ description: meta.parameters.prompt }),
17
+ aspect: Type.Union([
18
+ Type.Literal("3:4"),
19
+ Type.Literal("16:9"),
20
+ Type.Literal("4:3"),
21
+ Type.Literal("9:16"),
22
+ Type.Literal("1:1"),
23
+ ], {
24
+ default: "3:4",
25
+ description: meta.parameters.aspect,
26
+ }),
27
+ });
28
+ export const makeImage = createCommand({
29
+ name: meta.name,
30
+ title: meta.title,
31
+ description: meta.description,
32
+ inputSchema: makeImageV1Parameters,
33
+ }, async ({ prompt, aspect }, { log, apis }) => {
34
+ const createTask = async () => {
35
+ const vtokens = (await apis.prompt.parseVtokens(prompt)) ?? [];
36
+ const payload = buildMakeImagePayload(vtokens ?? [], {
37
+ make_image_aspect: aspect ?? "3:4",
38
+ context_model_series: "8_image_edit",
39
+ });
40
+ return await apis.artifact.makeImage(payload);
41
+ };
42
+ const task_uuid = await createTask();
43
+ log.debug("task: %s", task_uuid);
44
+ const timeout = 60 * 1000 * 10;
45
+ const res = await polling(() => apis.artifact.task(task_uuid), async (result) => {
46
+ log.debug("polling: %o", result);
47
+ return (result.task_status !== "PENDING" &&
48
+ result.task_status !== "MODERATION");
49
+ }, 2000, timeout);
50
+ if (res.isTimeout) {
51
+ return {
52
+ task_uuid,
53
+ task_status: "TIMEOUT",
54
+ artifacts: [],
55
+ };
56
+ }
57
+ return res.result;
58
+ });
@@ -0,0 +1,19 @@
1
+ name: make_image
2
+ title: 生成图片
3
+ description: 基于文本提示词或图片生成图片的工具
4
+ parameters:
5
+ prompt: |
6
+ 生图提示词。
7
+ - 可包括:
8
+ - 角色:通过 @character_name 来引用角色,这个引用会包含角色的完整形象信息;
9
+ - 画面元素:通过 /元素名称 格式引用风格元素,如 /漫画风格;
10
+ - 参考图:通过 参考图-uuid 格式引用已存在的图片作为参考图,如"参考图-1234567890"。最多能有 14 张图片;
11
+ - 中文词组:描述具体画面生成要求,如果没有引用角色,则需要在自然语言词组中描述角色形象;
12
+ - 注意:
13
+ - 提示词要多提供上下文和意图。详细描述场景,而不仅仅是列出关键字。与一连串不相关的字词相比,叙述性描述段落几乎总是能生成更好、更连贯的图片;
14
+ - 角色引用必须以 @角色名称 形式出现,如 @奈塔#996;
15
+ - 元素引用必须以 /元素名称 形式出现,如 /漫画风格;
16
+ - 引用角色或者元素的时候,前后要添加空格或逗号分隔,如:"@奈塔#996, /漫画风格, 在校园里散步"
17
+ - 对于修改图片等跟原图参考相关的生成,请一定引用上参考图变量
18
+ - 示例(引用角色和元素):@奈塔#996, /漫画风格, 参考图-1234567890, 参考图-1234567891, 词组1, 词组2…
19
+ aspect: 图片比例
@@ -0,0 +1,8 @@
1
+ name: make_song
2
+ title: Generate Song
3
+ description: Generate a song from lyrics and a high-level musical description.
4
+ parameters:
5
+ prompt: A description of the music, used to specify style, mood, and scenario. For example "Pop music, sad, suitable for a rainy night."
6
+ lyrics: |
7
+ The lyrics of the song. Use \n to separate each line. You can add structure tags such as [Intro], [Verse], [Pre Chorus], [Chorus], [Interlude], [Bridge], [Outro], [Post Chorus], [Transition], [Break], [Hook], [Build Up], [Inst], [Solo] to guide the musical structure.
8
+
@@ -0,0 +1,53 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { parseMeta } from "../../utils/parse_meta.js";
3
+ import { polling } from "../../utils/polling.js";
4
+ import { createCommand } from "../factory.js";
5
+ const meta = parseMeta(Type.Object({
6
+ name: Type.String(),
7
+ title: Type.String(),
8
+ description: Type.String(),
9
+ parameters: Type.Object({
10
+ prompt: Type.String(),
11
+ lyrics: Type.String(),
12
+ }),
13
+ }), import.meta);
14
+ const makeSongV1Parameters = Type.Object({
15
+ prompt: Type.String({
16
+ minLength: 10,
17
+ maxLength: 2000,
18
+ description: meta.parameters.prompt,
19
+ }),
20
+ lyrics: Type.String({
21
+ minLength: 10,
22
+ maxLength: 3500,
23
+ description: meta.parameters.lyrics,
24
+ }),
25
+ });
26
+ export const makeSong = createCommand({
27
+ name: meta.name,
28
+ title: meta.title,
29
+ description: meta.description,
30
+ inputSchema: makeSongV1Parameters,
31
+ }, async ({ prompt, lyrics }, { apis, log }) => {
32
+ const createTask = async () => {
33
+ return apis.artifact.makeSong(prompt, lyrics, {
34
+ entrance: "SONG,VERSE",
35
+ });
36
+ };
37
+ const task_uuid = await createTask();
38
+ log.debug("task: %s", task_uuid);
39
+ const timeout = 60 * 1000 * 5;
40
+ const res = await polling(() => apis.artifact.task(task_uuid), async (result) => {
41
+ log.debug("polling: %o", result);
42
+ return (result.task_status !== "PENDING" &&
43
+ result.task_status !== "MODERATION");
44
+ }, 2000, timeout);
45
+ if (res.isTimeout) {
46
+ return {
47
+ task_uuid,
48
+ task_status: "TIMEOUT",
49
+ artifacts: [],
50
+ };
51
+ }
52
+ return res.result;
53
+ });
@@ -0,0 +1,7 @@
1
+ name: make_song
2
+ title: 生成歌曲
3
+ description: 输入歌词和歌曲描述,进行歌曲生成
4
+ parameters:
5
+ prompt: 音乐的描述,用于指定风格、情绪和场景。例如"流行音乐, 难过, 适合在下雨的晚上"。
6
+ lyrics: |
7
+ 歌曲的歌词。使用 \n 分隔每行。你可以在歌词中加入 [Intro], [Verse], [Pre Chorus], [Chorus], [Interlude], [Bridge], [Outro], [Post Chorus], [Transition], [Break], [Hook], [Build Up], [Inst], [Solo] 等结构标签来优化生成的音乐结构。
@@ -0,0 +1,17 @@
1
+ name: make_video
2
+ title: Generate Video
3
+ description: Generate a video based on a single reference image and a detailed prompt.
4
+ parameters:
5
+ image_source: |
6
+ The image URL to use as the first frame of the video.
7
+ Only one image can be referenced. For multi‑character or multi‑shot scenarios, first use make_image to create a composite image and then use it as the video reference image.
8
+ prompt: |
9
+ A full natural language prompt that drives video generation.
10
+ Single‑shot scenes: include scene, characters, actions, style, camera movement, lighting, atmosphere, etc. Make sure character motion is natural and smooth.
11
+ Multi‑shot scenes: prompt structure = overall description + shot index + timestamp + shot content + aesthetic control + stylization + audio description (voice / sound effects / background music).
12
+ - Overall description: briefly summarize the whole video, including story theme, narrative style, main emotion or key events.
13
+ - Shot index: assign an index to each shot to distinguish different segments of the video.
14
+ - Timestamp: specify the time range of each shot in the video timeline to keep content aligned with time.
15
+ - Shot content: describe what key characters or objects are doing in each shot, including actions, dialogue, expressions, poses, etc.
16
+ model: Video generation model. Use model_w to generate 10‑second multi‑shot videos with audio, and model_s to generate 5‑second single‑shot videos without audio.
17
+