@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.
- package/CHANGELOG.md +47 -0
- package/LICENSE +21 -0
- package/README.en.md +234 -0
- package/README.md +237 -0
- package/bin/apis/activity.js +14 -0
- package/bin/apis/artifact.js +64 -0
- package/bin/apis/audio.js +10 -0
- package/bin/apis/collection.js +87 -0
- package/bin/apis/config.js +49 -0
- package/bin/apis/feeds.js +34 -0
- package/bin/apis/gpt.js +10 -0
- package/bin/apis/hashtag.js +23 -0
- package/bin/apis/index.js +62 -0
- package/bin/apis/prompt.js +120 -0
- package/bin/apis/recsys.js +29 -0
- package/bin/apis/space.js +48 -0
- package/bin/apis/task.js +21 -0
- package/bin/apis/tcp.js +16 -0
- package/bin/apis/types.js +76 -0
- package/bin/apis/user.js +45 -0
- package/bin/apis/verse.js +18 -0
- package/bin/cli.js +16 -0
- package/bin/commands/community/create_comment.cmd.en_us.yml +4 -0
- package/bin/commands/community/create_comment.cmd.js +40 -0
- package/bin/commands/community/create_comment.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/favor_collection.cmd.en_us.yml +4 -0
- package/bin/commands/community/favor_collection.cmd.js +29 -0
- package/bin/commands/community/favor_collection.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/get_fan_list.cmd.en_us.yml +4 -0
- package/bin/commands/community/get_fan_list.cmd.js +36 -0
- package/bin/commands/community/get_fan_list.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/get_hashtag_characters.cmd.en_us.yml +4 -0
- package/bin/commands/community/get_hashtag_characters.cmd.js +46 -0
- package/bin/commands/community/get_hashtag_characters.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/get_hashtag_collections.cmd.en_us.yml +6 -0
- package/bin/commands/community/get_hashtag_collections.cmd.js +54 -0
- package/bin/commands/community/get_hashtag_collections.cmd.zh_cn.yml +5 -0
- package/bin/commands/community/get_hashtag_info.cmd.en_us.yml +4 -0
- package/bin/commands/community/get_hashtag_info.cmd.js +42 -0
- package/bin/commands/community/get_hashtag_info.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/get_subscribe_list.cmd.en_us.yml +4 -0
- package/bin/commands/community/get_subscribe_list.cmd.js +36 -0
- package/bin/commands/community/get_subscribe_list.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/like_collection.cmd.en_us.yml +4 -0
- package/bin/commands/community/like_collection.cmd.js +29 -0
- package/bin/commands/community/like_collection.cmd.zh_cn.yml +4 -0
- package/bin/commands/community/list_space_topics.cmd.en_us.yml +7 -0
- package/bin/commands/community/list_space_topics.cmd.js +39 -0
- package/bin/commands/community/list_space_topics.cmd.zh_cn.yml +6 -0
- package/bin/commands/community/list_spaces.cmd.en_us.yml +4 -0
- package/bin/commands/community/list_spaces.cmd.js +19 -0
- package/bin/commands/community/list_spaces.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/read_collection.cmd.en_us.yml +4 -0
- package/bin/commands/community/read_collection.cmd.js +83 -0
- package/bin/commands/community/read_collection.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/request_interactive_feed.cmd.en_us.yml +4 -0
- package/bin/commands/community/request_interactive_feed.cmd.js +54 -0
- package/bin/commands/community/request_interactive_feed.cmd.zh_cn.yml +5 -0
- package/bin/commands/community/subscribe_user.cmd.en_us.yml +4 -0
- package/bin/commands/community/subscribe_user.cmd.js +33 -0
- package/bin/commands/community/subscribe_user.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/suggest_categories.cmd.en_us.yml +4 -0
- package/bin/commands/community/suggest_categories.cmd.js +26 -0
- package/bin/commands/community/suggest_categories.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/suggest_content.cmd.en_us.yml +5 -0
- package/bin/commands/community/suggest_content.cmd.js +59 -0
- package/bin/commands/community/suggest_content.cmd.zh_cn.yml +4 -0
- package/bin/commands/community/suggest_keywords.cmd.en_us.yml +4 -0
- package/bin/commands/community/suggest_keywords.cmd.js +26 -0
- package/bin/commands/community/suggest_keywords.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/suggest_tags.cmd.en_us.yml +4 -0
- package/bin/commands/community/suggest_tags.cmd.js +26 -0
- package/bin/commands/community/suggest_tags.cmd.zh_cn.yml +3 -0
- package/bin/commands/community/validate_tax_path.cmd.en_us.yml +4 -0
- package/bin/commands/community/validate_tax_path.cmd.js +24 -0
- package/bin/commands/community/validate_tax_path.cmd.zh_cn.yml +3 -0
- package/bin/commands/creative/edit_colleciton.cmd.en_us.yml +11 -0
- package/bin/commands/creative/edit_colleciton.cmd.js +140 -0
- package/bin/commands/creative/edit_colleciton.cmd.zh_cn.yml +10 -0
- package/bin/commands/creative/make_image.cmd.en_us.yml +20 -0
- package/bin/commands/creative/make_image.cmd.js +58 -0
- package/bin/commands/creative/make_image.cmd.zh_cn.yml +19 -0
- package/bin/commands/creative/make_song.cmd.en_us.yml +8 -0
- package/bin/commands/creative/make_song.cmd.js +53 -0
- package/bin/commands/creative/make_song.cmd.zh_cn.yml +7 -0
- package/bin/commands/creative/make_video.cmd.en_us.yml +17 -0
- package/bin/commands/creative/make_video.cmd.js +54 -0
- package/bin/commands/creative/make_video.cmd.zh_cn.yml +16 -0
- package/bin/commands/creative/publish_collection.cmd.en_us.yml +10 -0
- package/bin/commands/creative/publish_collection.cmd.js +101 -0
- package/bin/commands/creative/publish_collection.cmd.zh_cn.yml +9 -0
- package/bin/commands/creative/remove_background.cmd.en_us.yml +10 -0
- package/bin/commands/creative/remove_background.cmd.js +74 -0
- package/bin/commands/creative/remove_background.cmd.zh_cn.yml +9 -0
- package/bin/commands/creative/request_character_or_elementum.cmd.en_us.yml +23 -0
- package/bin/commands/creative/request_character_or_elementum.cmd.js +108 -0
- package/bin/commands/creative/request_character_or_elementum.cmd.zh_cn.yml +22 -0
- package/bin/commands/creative/search_tcp.cmd.en_us.yml +16 -0
- package/bin/commands/creative/search_tcp.cmd.js +53 -0
- package/bin/commands/creative/search_tcp.cmd.zh_cn.yml +15 -0
- package/bin/commands/factory.js +15 -0
- package/bin/commands/load.js +157 -0
- package/bin/utils/errors.js +61 -0
- package/bin/utils/json.js +8 -0
- package/bin/utils/lang.js +8 -0
- package/bin/utils/parse_meta.js +16 -0
- package/bin/utils/polling.js +17 -0
- package/bin/utils/prompts.js +186 -0
- package/package.json +77 -0
- package/skills/neta/SKILL.md +119 -0
- package/skills/neta-community/SKILL.md +123 -0
- package/skills/neta-creative/SKILL.md +118 -0
- package/skills/neta-space/SKILL.md +129 -0
- package/skills/neta-suggest/SKILL.md +490 -0
- package/skills/zh_cn/neta/SKILL.md +111 -0
- package/skills/zh_cn/neta/references/character-search.md +234 -0
- package/skills/zh_cn/neta/references/collection-remix.md +40 -0
- package/skills/zh_cn/neta/references/community-exploration.md +636 -0
- package/skills/zh_cn/neta/references/hashtag-research.md +295 -0
- package/skills/zh_cn/neta/references/image-generation.md +121 -0
- package/skills/zh_cn/neta/references/interactive-feed.md +377 -0
- package/skills/zh_cn/neta/references/social-interactive.md +73 -0
- package/skills/zh_cn/neta/references/song-creation.md +247 -0
- package/skills/zh_cn/neta/references/song-mv.md +198 -0
- package/skills/zh_cn/neta/references/space.md +90 -0
- package/skills/zh_cn/neta/references/video-generation.md +221 -0
- package/skills/zh_cn/neta-community/SKILL.md +109 -0
- package/skills/zh_cn/neta-community/references/character-search.md +233 -0
- package/skills/zh_cn/neta-community/references/hashtag-research.md +295 -0
- package/skills/zh_cn/neta-community/references/interactive-feed.md +377 -0
- package/skills/zh_cn/neta-community/references/social-interactive.md +73 -0
- package/skills/zh_cn/neta-creative/SKILL.md +105 -0
- package/skills/zh_cn/neta-creative/references/character-search.md +233 -0
- package/skills/zh_cn/neta-creative/references/collection-remix.md +40 -0
- package/skills/zh_cn/neta-creative/references/image-generation.md +121 -0
- package/skills/zh_cn/neta-creative/references/song-creation.md +247 -0
- package/skills/zh_cn/neta-creative/references/song-mv.md +198 -0
- package/skills/zh_cn/neta-creative/references/video-generation.md +221 -0
- package/skills/zh_cn/neta-space/SKILL.md +126 -0
- package/skills/zh_cn/neta-suggest/SKILL.md +662 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { buildMakeVideoPayload } 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
|
+
image_source: Type.String(),
|
|
12
|
+
prompt: Type.String(),
|
|
13
|
+
model: Type.String(),
|
|
14
|
+
}),
|
|
15
|
+
}), import.meta);
|
|
16
|
+
const makeVideoV1Parameters = Type.Object({
|
|
17
|
+
image_source: Type.String({ description: meta.parameters.image_source }),
|
|
18
|
+
prompt: Type.String({ description: meta.parameters.prompt }),
|
|
19
|
+
model: Type.Union([Type.Literal("model_s"), Type.Literal("model_w")], {
|
|
20
|
+
description: meta.parameters.model,
|
|
21
|
+
}),
|
|
22
|
+
});
|
|
23
|
+
export const makeVideo = createCommand({
|
|
24
|
+
name: meta.name,
|
|
25
|
+
title: meta.title,
|
|
26
|
+
description: meta.description,
|
|
27
|
+
inputSchema: makeVideoV1Parameters,
|
|
28
|
+
}, async ({ image_source, prompt, model }, { log, apis }) => {
|
|
29
|
+
const MODEL_MAPPING = {
|
|
30
|
+
model_s: "volc_seedance_fast_i2v_upscale",
|
|
31
|
+
model_w: "wan26",
|
|
32
|
+
};
|
|
33
|
+
const work_flow_model = MODEL_MAPPING[model];
|
|
34
|
+
const createTask = async () => {
|
|
35
|
+
const payload = buildMakeVideoPayload(image_source, prompt, work_flow_model);
|
|
36
|
+
return await apis.artifact.makeVideo(payload);
|
|
37
|
+
};
|
|
38
|
+
const task_uuid = await createTask();
|
|
39
|
+
log.debug("task: %s", task_uuid);
|
|
40
|
+
const timeout = 60 * 1000 * 20;
|
|
41
|
+
const res = await polling(() => apis.artifact.task(task_uuid), async (result) => {
|
|
42
|
+
log.debug("polling: %o", result);
|
|
43
|
+
return (result.task_status !== "PENDING" &&
|
|
44
|
+
result.task_status !== "MODERATION");
|
|
45
|
+
}, 2000, timeout);
|
|
46
|
+
if (res.isTimeout) {
|
|
47
|
+
return {
|
|
48
|
+
task_uuid,
|
|
49
|
+
task_status: "TIMEOUT",
|
|
50
|
+
artifacts: [],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return res.result;
|
|
54
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: make_video
|
|
2
|
+
title: 生成视频
|
|
3
|
+
description: 基于一张图片来生成视频的工具
|
|
4
|
+
parameters:
|
|
5
|
+
image_source: |
|
|
6
|
+
支持图片URL作为视频的首帧。只能引用一张图,因此需要参考多角色/多分镜场景时先使用 make_image 生成一张多人/多分镜图片再作为视频参考图引用。
|
|
7
|
+
图片URL: 完整图片地址
|
|
8
|
+
prompt: |
|
|
9
|
+
用于驱动视频生成的完整自然语言提示词。
|
|
10
|
+
单分镜场景:需要包含场景、角色、动作、风格、镜头调度、光线、氛围等信息。提醒角色动作要自然流畅。
|
|
11
|
+
多分镜场景:提示词结构 = 总体描述 + 镜头序号 + 时间戳 + 分镜内容 + 美学控制 + 风格化 + 声音描述(人声/音效/背景音乐)
|
|
12
|
+
- 总体描述:简要概述整个视频内容,说明故事主题、叙述风格、主要情感或核心事件
|
|
13
|
+
- 镜头序号:为每个镜头分配编号,用于区分视频中不同的场景或段落顺序
|
|
14
|
+
- 时间戳:标明每个镜头在视频中的具体时间范围,确保镜头内容与视频时间线对应
|
|
15
|
+
- 分镜内容:详细描述每个分镜头中主要角色或物体的具体行为,包括动作、语言、表情、姿态等
|
|
16
|
+
model: 视频生成模型。model_w 用于带声音的 10s 多分镜音画同步的视频生成,model_s 用于 5s 单分镜无声音视频生成。
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
name: publish_collection
|
|
2
|
+
title: Publish Collection
|
|
3
|
+
description: Publish a collection.
|
|
4
|
+
parameters:
|
|
5
|
+
name: Collection title.
|
|
6
|
+
description: Short description of the collection.
|
|
7
|
+
status: Publish status of the collection, either PRIVATE or PUBLISHED.
|
|
8
|
+
artifacts: List of collection assets, minimum 1 and maximum 12 items. Example picture_uuid,picture_uuid
|
|
9
|
+
hashtags: List of collection hashtags. Example hashtag_name,hashtag_name
|
|
10
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
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
|
+
name: Type.String(),
|
|
10
|
+
description: Type.String(),
|
|
11
|
+
status: Type.String(),
|
|
12
|
+
artifacts: Type.String(),
|
|
13
|
+
hashtags: Type.String(),
|
|
14
|
+
}),
|
|
15
|
+
}), import.meta);
|
|
16
|
+
export const publishCollection = createCommand({
|
|
17
|
+
name: meta.name,
|
|
18
|
+
title: meta.title,
|
|
19
|
+
description: meta.description,
|
|
20
|
+
inputSchema: Type.Object({
|
|
21
|
+
name: Type.String({ description: meta.parameters.name }),
|
|
22
|
+
description: Type.String({ description: meta.parameters.description }),
|
|
23
|
+
status: Type.Union([Type.Literal("PRIVATE"), Type.Literal("PUBLISHED")], {
|
|
24
|
+
description: meta.parameters.status,
|
|
25
|
+
}),
|
|
26
|
+
artifacts: Type.String({ description: meta.parameters.artifacts }),
|
|
27
|
+
hashtags: Type.Optional(Type.String({ description: meta.parameters.hashtags })),
|
|
28
|
+
remix_instruct: Type.Optional(Type.String()),
|
|
29
|
+
}),
|
|
30
|
+
}, async ({ name, description, status, hashtags, artifacts, remix_instruct }, { apis }) => {
|
|
31
|
+
const tags = await Promise.all(hashtags?.split(",")?.map((tag) => apis.hashtag.createHashtag(tag)) ?? []);
|
|
32
|
+
const tagDetails = await Promise.all(tags.map((tag) => apis.hashtag.fetchHashtag(tag.name)));
|
|
33
|
+
const activity = tagDetails.find((tag) => tag?.activity_detail?.uuid) ?? null;
|
|
34
|
+
const artifactDetails = await apis.artifact.artifactDetail(artifacts.split(","));
|
|
35
|
+
if (artifactDetails.length < 1 || artifactDetails.length > 12) {
|
|
36
|
+
throw new Error("artifacts must be between 1 and 12");
|
|
37
|
+
}
|
|
38
|
+
artifactDetails.forEach((artifact, index) => {
|
|
39
|
+
if (!artifact) {
|
|
40
|
+
throw new Error(`artifact ${artifacts[index]} not found`);
|
|
41
|
+
}
|
|
42
|
+
if (artifact.status !== "SUCCESS") {
|
|
43
|
+
throw new Error(`artifact ${artifacts[index]} status is not success`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const uuid = await apis.collection.createCollection();
|
|
47
|
+
const data = {
|
|
48
|
+
pages: [
|
|
49
|
+
{
|
|
50
|
+
images: artifactDetails,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
};
|
|
54
|
+
const coverArtifact = artifactDetails.find((artifact) => artifact.url) ?? null;
|
|
55
|
+
const aspect = (() => {
|
|
56
|
+
if (!coverArtifact)
|
|
57
|
+
return "3:4";
|
|
58
|
+
if (coverArtifact.modality === "PICTURE" && coverArtifact.image_detail) {
|
|
59
|
+
return `${coverArtifact.image_detail.width}:${coverArtifact.image_detail.height}`;
|
|
60
|
+
}
|
|
61
|
+
if (coverArtifact.modality === "VIDEO" && coverArtifact.video_detail) {
|
|
62
|
+
return `${coverArtifact.video_detail.width}:${coverArtifact.video_detail.height}`;
|
|
63
|
+
}
|
|
64
|
+
return "3:4";
|
|
65
|
+
})();
|
|
66
|
+
const characters = new Map();
|
|
67
|
+
artifactDetails.forEach((artifact) => {
|
|
68
|
+
artifact.input?.rawPrompt?.forEach((p) => {
|
|
69
|
+
if (p?.type === "official_character_vtoken_adaptor" ||
|
|
70
|
+
p?.type === "oc_vtoken_adaptor") {
|
|
71
|
+
characters.set(p.value, {
|
|
72
|
+
type: "character",
|
|
73
|
+
name: p.name,
|
|
74
|
+
weight: p.weight,
|
|
75
|
+
value: p.value,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
const collection = await apis.collection.saveCollection({
|
|
81
|
+
uuid,
|
|
82
|
+
name,
|
|
83
|
+
description,
|
|
84
|
+
version: "3.0.0",
|
|
85
|
+
status,
|
|
86
|
+
hashtags: tagDetails.map((tag) => tag.name),
|
|
87
|
+
displayData: data,
|
|
88
|
+
editorData: data,
|
|
89
|
+
picCount: artifactDetails.length,
|
|
90
|
+
coverUrl: coverArtifact?.url ?? null,
|
|
91
|
+
shareUrl: coverArtifact?.url ?? null,
|
|
92
|
+
aspect,
|
|
93
|
+
activity: activity?.activity_detail?.uuid ?? null,
|
|
94
|
+
extra_data: {
|
|
95
|
+
remix_instruct,
|
|
96
|
+
},
|
|
97
|
+
refCharacterTokens: Array.from(characters.values()),
|
|
98
|
+
});
|
|
99
|
+
await apis.collection.publishCollection(uuid);
|
|
100
|
+
return collection;
|
|
101
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
name: publish_collection
|
|
2
|
+
title: 发布作品
|
|
3
|
+
description: 发布一个作品
|
|
4
|
+
parameters:
|
|
5
|
+
name: 作品标题
|
|
6
|
+
description: 作品简介
|
|
7
|
+
status: 作品发布状态 PRIVATE(私密) 或 PUBLISHED(公开)
|
|
8
|
+
artifacts: 作品素材列表, 最少1张, 最多12张, 示例, picture_uuid,picture_uuid
|
|
9
|
+
hashtags: 作品标签列表, 示例, hashtag_name,hashtag_name
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
remove_background:
|
|
2
|
+
name: remove_background
|
|
3
|
+
title: Remove Image Background
|
|
4
|
+
description: Remove the background of an input image while preserving the main subject, and return an image with a transparent background.
|
|
5
|
+
|
|
6
|
+
remove_background_nocrop:
|
|
7
|
+
name: remove_background_nocrop
|
|
8
|
+
title: Remove Image Background (No Cropping)
|
|
9
|
+
description: Remove the background of the input image and return a transparent‑background image without cropping transparent edges.
|
|
10
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
remove_background: Type.Object({
|
|
7
|
+
name: Type.String(),
|
|
8
|
+
title: Type.String(),
|
|
9
|
+
description: Type.String(),
|
|
10
|
+
}),
|
|
11
|
+
remove_background_nocrop: Type.Object({
|
|
12
|
+
name: Type.String(),
|
|
13
|
+
title: Type.String(),
|
|
14
|
+
description: Type.String(),
|
|
15
|
+
}),
|
|
16
|
+
}), import.meta);
|
|
17
|
+
const removeBackgroundV1Parameters = Type.Object({
|
|
18
|
+
input_image: Type.String(),
|
|
19
|
+
});
|
|
20
|
+
export const removeBackground = createCommand({
|
|
21
|
+
name: meta.remove_background.name,
|
|
22
|
+
title: meta.remove_background.title,
|
|
23
|
+
description: meta.remove_background.description,
|
|
24
|
+
inputSchema: removeBackgroundV1Parameters,
|
|
25
|
+
}, async ({ input_image }, { apis, log }) => {
|
|
26
|
+
const createTask = async () => {
|
|
27
|
+
return apis.artifact.postProcess(input_image, "0_null/抠图SEG", {
|
|
28
|
+
entrance: "PICTURE,PURE,VERSE",
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
const task_uuid = await createTask();
|
|
32
|
+
log.debug("task: %s", task_uuid);
|
|
33
|
+
const timeout = 60 * 1000 * 5;
|
|
34
|
+
const res = await polling(() => apis.artifact.task(task_uuid), async (result) => {
|
|
35
|
+
log.debug("polling: %o", result);
|
|
36
|
+
return (result.task_status !== "PENDING" &&
|
|
37
|
+
result.task_status !== "MODERATION");
|
|
38
|
+
}, 2000, timeout);
|
|
39
|
+
if (res.isTimeout) {
|
|
40
|
+
return {
|
|
41
|
+
task_uuid,
|
|
42
|
+
task_status: "TIMEOUT",
|
|
43
|
+
artifacts: [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return res.result;
|
|
47
|
+
});
|
|
48
|
+
export const removeBackgroundNoCrop = createCommand({
|
|
49
|
+
name: meta.remove_background_nocrop.name,
|
|
50
|
+
title: meta.remove_background_nocrop.title,
|
|
51
|
+
description: meta.remove_background_nocrop.description,
|
|
52
|
+
inputSchema: removeBackgroundV1Parameters,
|
|
53
|
+
}, async ({ input_image }, { apis, log }) => {
|
|
54
|
+
const createTask = async () => {
|
|
55
|
+
return apis.artifact.postProcess(input_image, "0_null/抠图SEG", {
|
|
56
|
+
entrance: "PICTURE,PURE,VERSE",
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const task_uuid = await createTask();
|
|
60
|
+
log.debug("task: %s", task_uuid);
|
|
61
|
+
const res = await polling(() => apis.artifact.task(task_uuid), (result) => {
|
|
62
|
+
log.debug("polling: %o", result);
|
|
63
|
+
return (result.task_status !== "PENDING" &&
|
|
64
|
+
result.task_status !== "MODERATION");
|
|
65
|
+
}, 2000, 60 * 1000 * 10);
|
|
66
|
+
if (res.isTimeout) {
|
|
67
|
+
return {
|
|
68
|
+
task_uuid,
|
|
69
|
+
task_status: "TIMEOUT",
|
|
70
|
+
artifacts: [],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return res.result;
|
|
74
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: request_character_or_elementum
|
|
2
|
+
title: Get Character or Elementum
|
|
3
|
+
description: Fetch detailed information about a character or elementum by exact name or UUID.
|
|
4
|
+
errors:
|
|
5
|
+
missing_id: Either name or uuid must be provided.
|
|
6
|
+
not_found: Character or elementum not found {identifier}
|
|
7
|
+
type_mismatch_character: The resolved type is "character", but parent_type="elementum" was specified. Please adjust parent_type or use a different name to search.
|
|
8
|
+
type_mismatch_elementum: The resolved type is "elementum", but parent_type="character" was specified. Please adjust parent_type or use a different name to search.
|
|
9
|
+
unknown_type: Unknown TCP type {type}
|
|
10
|
+
parameters:
|
|
11
|
+
name: |
|
|
12
|
+
Exact name of the character or elementum.
|
|
13
|
+
- When name is provided, the tool first searches for a matching character or elementum (using exact match), then fetches its details.
|
|
14
|
+
- Examples: "Neta", "Hatsune Miku", "Cyberpunk Style".
|
|
15
|
+
- Note: exact matching is used, so make sure the name matches exactly.
|
|
16
|
+
- If both name and uuid are provided, uuid takes precedence.
|
|
17
|
+
uuid: |
|
|
18
|
+
UUID of the character or elementum.
|
|
19
|
+
- When uuid is provided, details are fetched directly by UUID.
|
|
20
|
+
- You can obtain UUIDs via the search_character_or_elementum tool.
|
|
21
|
+
- If both name and uuid are provided, uuid takes precedence.
|
|
22
|
+
parent_type: The type of entity to resolve ("character", "elementum", or "both").
|
|
23
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
errors: Type.Object({
|
|
9
|
+
missing_id: Type.String(),
|
|
10
|
+
not_found: Type.String(),
|
|
11
|
+
type_mismatch_character: Type.String(),
|
|
12
|
+
type_mismatch_elementum: Type.String(),
|
|
13
|
+
unknown_type: Type.String(),
|
|
14
|
+
}),
|
|
15
|
+
parameters: Type.Object({
|
|
16
|
+
name: Type.String(),
|
|
17
|
+
uuid: Type.String(),
|
|
18
|
+
parent_type: Type.String(),
|
|
19
|
+
}),
|
|
20
|
+
}), import.meta);
|
|
21
|
+
const requestCharacterOrElementumV1Parameters = Type.Object({
|
|
22
|
+
name: Type.Optional(Type.String({ description: meta.parameters.name })),
|
|
23
|
+
uuid: Type.Optional(Type.String({ description: meta.parameters.uuid })),
|
|
24
|
+
parent_type: Type.Union([
|
|
25
|
+
Type.Literal("character"),
|
|
26
|
+
Type.Literal("elementum"),
|
|
27
|
+
Type.Literal("both"),
|
|
28
|
+
], { default: "both", description: meta.parameters.parent_type }),
|
|
29
|
+
});
|
|
30
|
+
export const requestCharacterOrElementum = createCommand({
|
|
31
|
+
name: meta.name,
|
|
32
|
+
title: meta.title,
|
|
33
|
+
description: meta.description,
|
|
34
|
+
inputSchema: requestCharacterOrElementumV1Parameters,
|
|
35
|
+
}, async ({ name, uuid, parent_type }, { log, apis }) => {
|
|
36
|
+
const targetType = parent_type === "both" ? ["character", "elementum"] : [parent_type];
|
|
37
|
+
const getTcp = async () => {
|
|
38
|
+
if (!uuid && !name) {
|
|
39
|
+
throw new Error(meta.errors.missing_id);
|
|
40
|
+
}
|
|
41
|
+
if (uuid) {
|
|
42
|
+
return await apis.tcp.tcpProfile(uuid);
|
|
43
|
+
}
|
|
44
|
+
if (name) {
|
|
45
|
+
const res = await apis.tcp.searchTCPs({
|
|
46
|
+
keywords: name,
|
|
47
|
+
page_index: 0,
|
|
48
|
+
page_size: 1,
|
|
49
|
+
sort_scheme: "exact",
|
|
50
|
+
parent_type: parent_type === "both"
|
|
51
|
+
? ["oc", "elementum"]
|
|
52
|
+
: parent_type === "character"
|
|
53
|
+
? "oc"
|
|
54
|
+
: "elementum",
|
|
55
|
+
});
|
|
56
|
+
if (!res)
|
|
57
|
+
return null;
|
|
58
|
+
if (res.list.length === 0)
|
|
59
|
+
return null;
|
|
60
|
+
const first = res.list[0];
|
|
61
|
+
if (!first)
|
|
62
|
+
return null;
|
|
63
|
+
return apis.tcp.tcpProfile(first.uuid);
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
};
|
|
67
|
+
const tcp = await getTcp();
|
|
68
|
+
if (!tcp) {
|
|
69
|
+
throw new Error(meta.errors.not_found.replace("{identifier}", String((name || uuid) ?? "").trim()));
|
|
70
|
+
}
|
|
71
|
+
if (tcp.type === "oc" || tcp.type === "official") {
|
|
72
|
+
if (!targetType.includes("character")) {
|
|
73
|
+
throw new Error(meta.errors.type_mismatch_character);
|
|
74
|
+
}
|
|
75
|
+
const assignValue = {
|
|
76
|
+
type: "character",
|
|
77
|
+
uuid: tcp.uuid,
|
|
78
|
+
name: tcp.name,
|
|
79
|
+
age: tcp.oc_bio.age,
|
|
80
|
+
interests: tcp.oc_bio.interests,
|
|
81
|
+
persona: tcp.oc_bio.persona,
|
|
82
|
+
description: tcp.oc_bio.description,
|
|
83
|
+
occupation: tcp.oc_bio.occupation,
|
|
84
|
+
avatar_img: tcp.config.avatar_img,
|
|
85
|
+
header_img: tcp.config.header_img,
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
detail: assignValue,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (tcp.type === "elementum") {
|
|
92
|
+
if (!targetType.includes("elementum")) {
|
|
93
|
+
throw new Error(meta.errors.type_mismatch_elementum);
|
|
94
|
+
}
|
|
95
|
+
const assignValue = {
|
|
96
|
+
type: "elementum",
|
|
97
|
+
uuid: tcp.uuid,
|
|
98
|
+
name: tcp.name,
|
|
99
|
+
description: tcp.oc_bio.description,
|
|
100
|
+
avatar_img: tcp.config.avatar_img,
|
|
101
|
+
};
|
|
102
|
+
return {
|
|
103
|
+
detail: assignValue,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
log.warn(`request_character_or_elementum: unknown tcp type: ${tcp.type}`);
|
|
107
|
+
throw new Error(meta.errors.unknown_type.replace("{type}", String(tcp.type)));
|
|
108
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: request_character_or_elementum
|
|
2
|
+
title: 请求角色或元素
|
|
3
|
+
description: 通过名称(精确匹配)或UUID获取角色或元素的详细信息
|
|
4
|
+
errors:
|
|
5
|
+
missing_id: 必须提供 name 或 uuid 参数之一
|
|
6
|
+
not_found: 未找到角色或元素 {identifier}
|
|
7
|
+
type_mismatch_character: 找到的类型为 "character"(角色),但指定了 parent_type="elementum"(风格元素)。请调整 parent_type 参数或使用不同的名称搜索。
|
|
8
|
+
type_mismatch_elementum: 找到的类型为 "elementum"(风格元素),但指定了 parent_type="character"(角色)。请调整 parent_type 参数或使用不同的名称搜索。
|
|
9
|
+
unknown_type: 未知 TCP 类型 {type}
|
|
10
|
+
parameters:
|
|
11
|
+
name: |
|
|
12
|
+
角色或元素的名称(精确匹配)
|
|
13
|
+
- 当提供name时,工具会先搜索匹配的角色或元素(使用精确匹配),然后获取详情
|
|
14
|
+
- 示例:"奈塔#996"、"初音未来"、"赛博朋克风格"
|
|
15
|
+
- 注意:使用精确匹配,确保名称完全一致
|
|
16
|
+
- 如果同时提供name和uuid,优先使用uuid
|
|
17
|
+
uuid: |
|
|
18
|
+
角色或元素的UUID
|
|
19
|
+
- 当提供uuid时,直接获取角色或元素详情
|
|
20
|
+
- 可以通过search_tcp工具获取UUID
|
|
21
|
+
- 如果同时提供name和uuid,优先使用uuid
|
|
22
|
+
parent_type: 指定搜索类型
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: search_character_or_elementum
|
|
2
|
+
title: Search Characters and Elementums
|
|
3
|
+
description: |
|
|
4
|
+
Search for characters and style elementums, supporting both exact and fuzzy matching.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
- Use this tool to fuzzily search and browse characters or style elementums.
|
|
8
|
+
- If you need to fetch full details of a character or elementum by name, use request_character_or_elementum instead.
|
|
9
|
+
|
|
10
|
+
Terminology:
|
|
11
|
+
- Character (character): people or characters such as "Neta", "Hatsune Miku", "Satoru Gojo".
|
|
12
|
+
- Elementum (elementum): also called "element"; includes concepts like art styles, world settings, memes, and story fragments, for example "manga style", "cyberpunk style", "school romance setting".
|
|
13
|
+
|
|
14
|
+
Search tips:
|
|
15
|
+
- You can first use search_character_or_elementum to find the exact name, then call request_character_or_elementum to get details.
|
|
16
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
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 searchCharacterOrElementumV1Parameters = Type.Object({
|
|
10
|
+
keywords: Type.String(),
|
|
11
|
+
parent_type: Type.Union([
|
|
12
|
+
Type.Literal("character"),
|
|
13
|
+
Type.Literal("elementum"),
|
|
14
|
+
Type.Literal("both"),
|
|
15
|
+
], { default: "both" }),
|
|
16
|
+
sort_scheme: Type.Union([Type.Literal("exact"), Type.Literal("best")], {
|
|
17
|
+
default: "best",
|
|
18
|
+
}),
|
|
19
|
+
page_index: Type.Integer({ minimum: 0, default: 0 }),
|
|
20
|
+
page_size: Type.Integer({ minimum: 1, maximum: 50, default: 10 }),
|
|
21
|
+
});
|
|
22
|
+
export const searchCharacterOrElementum = createCommand({
|
|
23
|
+
name: meta.name,
|
|
24
|
+
title: meta.title,
|
|
25
|
+
description: meta.description,
|
|
26
|
+
inputSchema: searchCharacterOrElementumV1Parameters,
|
|
27
|
+
}, async ({ keywords, parent_type, sort_scheme, page_index, page_size }, { apis }) => {
|
|
28
|
+
const result = await apis.tcp.searchTCPs({
|
|
29
|
+
keywords,
|
|
30
|
+
page_index,
|
|
31
|
+
page_size,
|
|
32
|
+
parent_type: parent_type === "both"
|
|
33
|
+
? ["oc", "elementum"]
|
|
34
|
+
: parent_type === "character"
|
|
35
|
+
? "oc"
|
|
36
|
+
: "elementum",
|
|
37
|
+
sort_scheme,
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
total: result.total,
|
|
41
|
+
page_index: result.page_index,
|
|
42
|
+
page_size: result.page_size,
|
|
43
|
+
list: result.list.map((res) => ({
|
|
44
|
+
uuid: res.uuid,
|
|
45
|
+
type: res.type === "oc" || res.type === "official"
|
|
46
|
+
? "character"
|
|
47
|
+
: "elementum",
|
|
48
|
+
name: res.name,
|
|
49
|
+
avatar_img: res.config?.avatar_img,
|
|
50
|
+
header_img: res.config?.header_img,
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: search_character_or_elementum
|
|
2
|
+
title: 搜索角色和元素
|
|
3
|
+
description: |
|
|
4
|
+
搜索角色和风格元素,支持精确和模糊查找
|
|
5
|
+
|
|
6
|
+
使用说明:
|
|
7
|
+
- 此工具用于模糊搜索和浏览角色或风格元素
|
|
8
|
+
- 如需通过名称精确获取角色或元素详情,请使用request_character_or_elementum工具
|
|
9
|
+
|
|
10
|
+
术语说明:
|
|
11
|
+
- 角色(character):人物、角色,如"奈塔#996"、"初音未来"、"五条悟"
|
|
12
|
+
- 风格元素(elementum):也称为"元素",包括绘画风格、世界观设定、梗图、故事片段等概念,如"漫画风格"、"赛博朋克风格"、"校园恋爱世界观"
|
|
13
|
+
|
|
14
|
+
搜索建议:
|
|
15
|
+
- 可以通过search_character_or_elementum搜索获取准确名称,然后使用request_character_or_elementum获取详情
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Type, } from "@sinclair/typebox";
|
|
2
|
+
export const Nullable = (schema) => Type.Unsafe({
|
|
3
|
+
...schema,
|
|
4
|
+
nullable: true,
|
|
5
|
+
});
|
|
6
|
+
export const createCommand = (command, execute) => {
|
|
7
|
+
return {
|
|
8
|
+
...command,
|
|
9
|
+
execute,
|
|
10
|
+
_IS_COMMAND__: true,
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export const isCommand = (value) => {
|
|
14
|
+
return (typeof value === "object" && value !== null && "_IS_COMMAND__" in value);
|
|
15
|
+
};
|