@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,157 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { readdir } from "node:fs/promises";
10
+ import { resolve } from "node:path";
11
+ import { pathToFileURL } from "node:url";
12
+ import { Option, } from "@commander-js/extra-typings";
13
+ import { Type } from "@sinclair/typebox";
14
+ import { Default, Value } from "@sinclair/typebox/value";
15
+ import { createApis } from "../apis/index.js";
16
+ import { ApiResponseError } from "../utils/errors.js";
17
+ import { getLocale, setLocale } from "../utils/parse_meta.js";
18
+ import { isCommand } from "./factory.js";
19
+ export const loadCommands = async (domains) => {
20
+ const cmdFiles = await Promise.all(domains.map(async (domain) => {
21
+ return readdir(resolve(import.meta.dirname, domain))
22
+ .then((files) => files
23
+ .filter((file) => file.endsWith(".cmd.ts") || file.endsWith(".cmd.js"))
24
+ .map((file) => resolve(import.meta.dirname, domain, file)))
25
+ .catch((_error) => {
26
+ return [];
27
+ });
28
+ })).then((files) => files.flat());
29
+ return await Promise.all(cmdFiles.map(async (file) => {
30
+ const module = await import(__rewriteRelativeImportExtension(pathToFileURL(file).href));
31
+ return Object.getOwnPropertyNames(module)
32
+ .filter((name) => {
33
+ const value = module[name];
34
+ return isCommand(value);
35
+ })
36
+ .map((name) => module[name]);
37
+ })).then((commands) => commands.flat());
38
+ };
39
+ const IS_DEV = process.env["NODE_ENV"] === "development";
40
+ const logger = console;
41
+ export const buildCommands = async (cli) => {
42
+ setLocale();
43
+ const commands = await loadCommands(["creative", "community"]);
44
+ return commands.map((cmd) => {
45
+ const command = cli.command(cmd.name);
46
+ command.description(cmd.title || cmd.description || "");
47
+ const inputSchema = cmd.inputSchema;
48
+ if (inputSchema && "properties" in inputSchema) {
49
+ const properties = inputSchema.properties;
50
+ if (!properties)
51
+ return command;
52
+ Object.entries(properties).forEach(([key, property]) => {
53
+ if (typeof property !== "object")
54
+ return;
55
+ const option = new Option(`--${key} <${property["type"]}>`, property.description);
56
+ if (property.default) {
57
+ option.default(property.default);
58
+ }
59
+ if (property["anyOf"]) {
60
+ option.choices(property["anyOf"].map((item) => item.const));
61
+ }
62
+ if (inputSchema.required?.includes(key) &&
63
+ property.default === undefined) {
64
+ option.makeOptionMandatory();
65
+ }
66
+ if (property.type === "boolean") {
67
+ option.argParser((value) => value === "true" || value === "1");
68
+ }
69
+ if (property.type === "number") {
70
+ option.argParser((value) => Number.parseFloat(value));
71
+ }
72
+ if (property.type === "integer") {
73
+ option.argParser((value) => Number.parseInt(value, 10));
74
+ }
75
+ if (property.type === "null") {
76
+ option.argParser(() => null);
77
+ }
78
+ command.addOption(option);
79
+ });
80
+ }
81
+ command.action(async (args) => {
82
+ const { api_base_url, token } = cli.opts();
83
+ const _locale = getLocale();
84
+ const baseUrl = typeof api_base_url === "string"
85
+ ? api_base_url
86
+ : (process.env["NETA_API_BASE_URL"] ??
87
+ (_locale === "zh_cn"
88
+ ? "https://api.talesofai.cn"
89
+ : "https://api.talesofai.com"));
90
+ const apis = createApis({
91
+ baseUrl,
92
+ headers: {
93
+ "x-token": typeof token === "string"
94
+ ? token
95
+ : (process.env["NETA_TOKEN"] ?? ""),
96
+ "x-platform": "nieta-app/web",
97
+ },
98
+ });
99
+ const user = await apis.user.me().catch((e) => {
100
+ if (e instanceof ApiResponseError) {
101
+ return null;
102
+ }
103
+ return null;
104
+ });
105
+ const type = cmd.inputSchema ?? Type.Object({});
106
+ const input = Value.Decode(type, Default(type, args));
107
+ if (IS_DEV) {
108
+ logger.debug("command: %s, params: %o", cmd.name, input);
109
+ }
110
+ const result = await cmd
111
+ .execute(input, {
112
+ apis,
113
+ user,
114
+ log: IS_DEV
115
+ ? logger
116
+ : {
117
+ error: () => { },
118
+ warn: () => { },
119
+ info: () => { },
120
+ debug: () => { },
121
+ },
122
+ })
123
+ .catch((e) => {
124
+ if (e instanceof ApiResponseError) {
125
+ logger.error({
126
+ error: {
127
+ type: e.name,
128
+ code: e.code,
129
+ message: e.message,
130
+ },
131
+ });
132
+ return null;
133
+ }
134
+ if (e instanceof Error) {
135
+ logger.error({
136
+ error: {
137
+ type: e.name,
138
+ message: e.message,
139
+ },
140
+ });
141
+ return null;
142
+ }
143
+ logger.error(e);
144
+ return null;
145
+ });
146
+ if (!result)
147
+ return;
148
+ if (IS_DEV) {
149
+ logger.debug(result);
150
+ }
151
+ else {
152
+ logger.info(JSON.stringify(result));
153
+ }
154
+ });
155
+ return command;
156
+ });
157
+ };
@@ -0,0 +1,61 @@
1
+ import { AxiosError } from "axios";
2
+ import { safeParseJson } from "./json.js";
3
+ export class ApiResponseError extends Error {
4
+ code;
5
+ message;
6
+ constructor(code, message, options) {
7
+ super(message, {
8
+ ...options,
9
+ });
10
+ this.code = code;
11
+ this.message = message;
12
+ this.name = "ApiResponseError";
13
+ }
14
+ }
15
+ export const catchErrorResponse = (data) => {
16
+ if (typeof data !== "string" && typeof data !== "object")
17
+ return String(data);
18
+ const parsedData = typeof data === "string" ? (safeParseJson(data) ?? {}) : data;
19
+ const detail = parsedData?.["detail"];
20
+ if (typeof detail === "string") {
21
+ return detail;
22
+ }
23
+ if (typeof detail === "object") {
24
+ if (Array.isArray(detail)) {
25
+ return detail.map(({ msg } = { msg: "" }) => msg).join(", ");
26
+ }
27
+ else {
28
+ return detail["message"] ?? detail["msg"] ?? JSON.stringify(detail);
29
+ }
30
+ }
31
+ const message = parsedData?.["message"] ??
32
+ parsedData?.["msg"] ??
33
+ JSON.stringify(parsedData);
34
+ return message;
35
+ };
36
+ export const handleAxiosError = (error) => {
37
+ if (error instanceof AxiosError) {
38
+ if (error.response?.status) {
39
+ let message = error.message;
40
+ if (error.response.status >= 400 && error.response.status < 500) {
41
+ message = catchErrorResponse(error.response.data);
42
+ }
43
+ throw new ApiResponseError(error.response.status, message, {
44
+ cause: error,
45
+ });
46
+ }
47
+ }
48
+ if (error instanceof Error) {
49
+ throw new ApiResponseError(-1, error.message, {
50
+ cause: error,
51
+ });
52
+ }
53
+ if (typeof error === "object" && error !== null) {
54
+ throw new ApiResponseError(-1, JSON.stringify(error), {
55
+ cause: error,
56
+ });
57
+ }
58
+ throw new ApiResponseError(-1, String(error), {
59
+ cause: error,
60
+ });
61
+ };
@@ -0,0 +1,8 @@
1
+ export function safeParseJson(json) {
2
+ try {
3
+ return JSON.parse(json);
4
+ }
5
+ catch {
6
+ return null;
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ import osLocale from "os-locale";
2
+ export const getLocale = () => {
3
+ const locale = osLocale();
4
+ if (locale.startsWith("zh")) {
5
+ return "zh_cn";
6
+ }
7
+ return "en_us";
8
+ };
@@ -0,0 +1,16 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { Value } from "@sinclair/typebox/value";
3
+ import yaml from "yaml";
4
+ import { getLocale as getLocaleFromLang } from "./lang.js";
5
+ let _locale = "en_us";
6
+ export const setLocale = (locale) => {
7
+ _locale = locale ?? getLocaleFromLang();
8
+ };
9
+ export const getLocale = () => {
10
+ return _locale;
11
+ };
12
+ export const parseMeta = (schema, importMeta) => {
13
+ const file = readFileSync(importMeta.filename.replace(/\.(ts|js)$/, `.${_locale}.yml`), "utf-8");
14
+ const data = yaml.parse(file);
15
+ return Value.Decode(schema, data);
16
+ };
@@ -0,0 +1,17 @@
1
+ export const polling = async (fn, condition, interval = 2000, timeout = 10 * 60 * 1000) => {
2
+ const startTime = Date.now();
3
+ while (Date.now() - startTime < timeout) {
4
+ const result = await fn();
5
+ if (await condition(result)) {
6
+ return {
7
+ result,
8
+ isTimeout: false,
9
+ };
10
+ }
11
+ await new Promise((resolve) => setTimeout(resolve, interval));
12
+ }
13
+ return {
14
+ result: null,
15
+ isTimeout: true,
16
+ };
17
+ };
@@ -0,0 +1,186 @@
1
+ export const mapTCP2Tag = (tcp, weight = 1) => {
2
+ if (tcp.type === "elementum") {
3
+ return {
4
+ uuid: tcp.uuid,
5
+ name: tcp.name,
6
+ value: tcp.uuid,
7
+ type: "elementum",
8
+ weight,
9
+ };
10
+ }
11
+ return {
12
+ uuid: tcp.uuid,
13
+ name: tcp.name,
14
+ value: tcp.uuid,
15
+ type: "oc_vtoken_adaptor",
16
+ weight,
17
+ };
18
+ };
19
+ export const SEPARATORS = [",", ",", "。", ";", ";", "!", "!", "?", "?"];
20
+ const parseSeparatedListOfString = (chars, getContent) => {
21
+ let offset = 0;
22
+ const pop = () => (offset >= chars.length ? null : (chars[offset++] ?? null));
23
+ const contents = [];
24
+ const separators = [];
25
+ let currentToken = "";
26
+ let startOffset = 0;
27
+ while (true) {
28
+ const next = pop();
29
+ if (!next) {
30
+ break;
31
+ }
32
+ else if (getContent(next) === "\\") {
33
+ const nextnext = pop();
34
+ if (nextnext) {
35
+ currentToken += getContent(nextnext);
36
+ }
37
+ else {
38
+ // is this valid?
39
+ currentToken += "\\";
40
+ }
41
+ }
42
+ else if (SEPARATORS.includes(getContent(next))) {
43
+ // we will insert a separator
44
+ contents.push({
45
+ parsedText: currentToken,
46
+ start: startOffset,
47
+ end: offset - 1,
48
+ });
49
+ separators.push({
50
+ parsedText: getContent(next),
51
+ start: offset - 1,
52
+ end: offset,
53
+ });
54
+ currentToken = "";
55
+ startOffset = offset;
56
+ }
57
+ else {
58
+ currentToken += getContent(next);
59
+ }
60
+ }
61
+ contents.push({
62
+ start: startOffset,
63
+ end: offset,
64
+ parsedText: currentToken,
65
+ });
66
+ if (contents.length - separators.length !== 1) {
67
+ throw new Error("Assertation failed: contents.length - separators.length !== 1");
68
+ }
69
+ return {
70
+ contents,
71
+ separators,
72
+ };
73
+ };
74
+ export const REF_IMG_PROMPT_PLACEHOLDER = "REF_IMG_PROMPT_PLACEHOLDER";
75
+ export const REF_IMG_PROMPT_INVALID = "REF_IMG_PROMPT_INVALID";
76
+ function stringToPrompt(promptString, options) {
77
+ const str = promptString.trim();
78
+ function extractWeight(str) {
79
+ const segs = str.split(":");
80
+ if (segs.length > 1) {
81
+ const f = parseFloat(segs[segs.length - 1] ?? "1");
82
+ return [
83
+ segs.slice(0, -1).join(":"),
84
+ Number.isNaN(f) ? 1 : Math.min(Math.max(0.1, f), 2),
85
+ ];
86
+ }
87
+ return [segs[0] ?? "", 1];
88
+ }
89
+ if (str.startsWith("@")) {
90
+ const [name, weight] = extractWeight(str.slice(1));
91
+ return { type: "character", name, weight, value: "" };
92
+ }
93
+ if (str.startsWith("/")) {
94
+ const [name, weight] = extractWeight(str.slice(1));
95
+ return { type: "elementum", name, weight };
96
+ }
97
+ if (str.startsWith("参考图-") || str.startsWith("图片捏-")) {
98
+ const [uuid, weight] = extractWeight(str.slice(4));
99
+ const refImageUrl = uuid ? options?.refImages?.[uuid] : undefined;
100
+ return {
101
+ name: "",
102
+ type: "ref_image",
103
+ value: refImageUrl ?? REF_IMG_PROMPT_PLACEHOLDER,
104
+ weight,
105
+ sub_type: "v1",
106
+ ref_img_uuid: uuid ?? null,
107
+ };
108
+ }
109
+ if (str.startsWith("ref_img-")) {
110
+ const [uuid, weight] = extractWeight(str.slice(8));
111
+ const refImageUrl = uuid ? options?.refImages?.[uuid] : undefined;
112
+ return {
113
+ name: "",
114
+ type: "ref_image",
115
+ value: refImageUrl ?? REF_IMG_PROMPT_PLACEHOLDER,
116
+ weight,
117
+ sub_type: "v1",
118
+ ref_img_uuid: uuid ?? null,
119
+ };
120
+ }
121
+ if ((str.startsWith("(参考图-") || str.startsWith("(图片捏-")) &&
122
+ str.endsWith(")")) {
123
+ const [uuid, weight] = extractWeight(str.slice(5, -1));
124
+ const refImageUrl = uuid ? options?.refImages?.[uuid] : undefined;
125
+ return {
126
+ name: "",
127
+ type: "ref_image",
128
+ value: refImageUrl ?? REF_IMG_PROMPT_PLACEHOLDER,
129
+ weight,
130
+ sub_type: "v1",
131
+ ref_img_uuid: uuid ?? null,
132
+ };
133
+ }
134
+ if (str.startsWith("(ref_img-") && str.endsWith(")")) {
135
+ const [uuid, weight] = extractWeight(str.slice(9, -1));
136
+ const refImageUrl = uuid ? options?.refImages?.[uuid] : undefined;
137
+ return {
138
+ name: "",
139
+ type: "ref_image",
140
+ value: refImageUrl ?? REF_IMG_PROMPT_PLACEHOLDER,
141
+ weight,
142
+ sub_type: "v1",
143
+ ref_img_uuid: uuid ?? null,
144
+ };
145
+ }
146
+ if (str.startsWith("(") && str.endsWith(")")) {
147
+ const [value, weight] = extractWeight(str.slice(1, -1));
148
+ return { type: "text", value, weight };
149
+ }
150
+ if (str === "参考图" || str === "图片捏") {
151
+ return {
152
+ name: "",
153
+ type: "ref_image",
154
+ value: REF_IMG_PROMPT_PLACEHOLDER,
155
+ weight: 1,
156
+ sub_type: "v1",
157
+ ref_img_uuid: null,
158
+ };
159
+ }
160
+ if (str === "ref_img") {
161
+ return {
162
+ name: "",
163
+ type: "ref_image",
164
+ value: REF_IMG_PROMPT_PLACEHOLDER,
165
+ weight: 1,
166
+ sub_type: "v1",
167
+ ref_img_uuid: null,
168
+ };
169
+ }
170
+ return {
171
+ type: "text",
172
+ value: str,
173
+ weight: 1,
174
+ };
175
+ }
176
+ export const splitPrompts = (str) => {
177
+ const { contents } = parseSeparatedListOfString([...str], (x) => x);
178
+ return contents.map((x) => x.parsedText.trim()).filter((x) => x !== "");
179
+ };
180
+ export function stringToPrompts(str, options) {
181
+ const { contents } = parseSeparatedListOfString([...str], (x) => x);
182
+ return contents
183
+ .map((x) => x.parsedText.trim())
184
+ .filter((x) => x !== "")
185
+ .map((text) => stringToPrompt(text, options));
186
+ }
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@talesofai/neta-skills",
3
+ "version": "0.6.0",
4
+ "description": "Neta API pi coding agent skills for interacting with Neta API to generate images, videos, songs, and manage characters/elements.",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/talesofai/neta-skills.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/talesofai/neta-skills/issues"
12
+ },
13
+ "homepage": "https://github.com/talesofai/neta-skills#readme",
14
+ "keywords": [
15
+ "neta",
16
+ "api",
17
+ "skill",
18
+ "pi-agent",
19
+ "image-generation",
20
+ "video-generation",
21
+ "ai"
22
+ ],
23
+ "author": "Neta Team",
24
+ "license": "MIT",
25
+ "engines": {
26
+ "node": ">=22.0.0"
27
+ },
28
+ "packageManager": "pnpm@10.25.0",
29
+ "bin": {
30
+ "neta-cli": "bin/cli.js"
31
+ },
32
+ "scripts": {
33
+ "lint": "biome check . --write --unsafe",
34
+ "validate": "skills-ref to-prompt ./skills/neta ./skills/neta-community ./skills/neta-creative ./skills/neta-suggest ./skills/neta-space",
35
+ "type-check": "tsc --noEmit",
36
+ "check": "pnpm lint && pnpm type-check && pnpm validate",
37
+ "changelog": "changeset",
38
+ "bump": "changeset version",
39
+ "prepare": "husky",
40
+ "build": "rimraf bin && tsc",
41
+ "postbuild": "node scripts/postbuild.js",
42
+ "dev": "NODE_ENV=development node src/cli.ts",
43
+ "start": "node bin/cli.js"
44
+ },
45
+ "dependencies": {
46
+ "@commander-js/extra-typings": "^14.0.0",
47
+ "@sinclair/typebox": "^0.34.48",
48
+ "axios": "^1.7.9",
49
+ "commander": "^14.0.0",
50
+ "dotenv": "^16.4.7",
51
+ "dotenv-flow": "^4.1.0",
52
+ "os-locale": "^8.0.0",
53
+ "qs": "^6.15.0",
54
+ "skills-ref": "^0.1.5",
55
+ "yaml": "^2.8.2"
56
+ },
57
+ "devDependencies": {
58
+ "@biomejs/biome": "2.3.8",
59
+ "@changesets/cli": "^2.29.8",
60
+ "@types/node": "^22.10.2",
61
+ "@types/qs": "^6.14.0",
62
+ "glob": "^13.0.6",
63
+ "husky": "^9.1.7",
64
+ "lint-staged": "^16.3.1",
65
+ "rimraf": "^6.1.3",
66
+ "typescript": "^5.9.3"
67
+ },
68
+ "files": [
69
+ "bin",
70
+ "skills",
71
+ "package.json",
72
+ "README.md",
73
+ "README.en.md",
74
+ "CHANGELOG.md",
75
+ "LICENSE"
76
+ ]
77
+ }
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: neta
3
+ description: Neta capability index and routing skill — help choose the appropriate Neta‑related skill (neta-space / neta-creative / neta-community / neta-suggest). Use this skill when you need to understand Neta’s overall capabilities, decide which skill fits the current task, or migrate from older documentation that referenced the monolithic neta skill.
4
+ ---
5
+
6
+ # Neta Skill
7
+
8
+ Used for **overview and routing** of Neta‑related skills, rather than executing concrete commands directly.
9
+
10
+ > This skill used to be a “kitchen‑sink” Neta interaction skill. It has now been split into multiple focused skills. Prefer using the skills listed below; use this skill only to understand the capability map or when migrating from older docs.
11
+
12
+ ## Installing sub‑skills
13
+
14
+ In environments that support `skills add`, install sub‑skills as needed:
15
+
16
+ ```bash
17
+ # Spaces and worldbuilding
18
+ npx skills add talesofai/neta-skills/skills/neta-space
19
+
20
+ # Creative content (images/videos/songs/MVs)
21
+ npx skills add talesofai/neta-skills/skills/neta-creative
22
+
23
+ # Community browsing and interactions
24
+ npx skills add talesofai/neta-skills/skills/neta-community
25
+
26
+ # Research and content suggestions
27
+ npx skills add talesofai/neta-skills/skills/neta-suggest
28
+ ```
29
+
30
+ ## Instructions
31
+
32
+ 1. **Identify the task type**: classify the user’s need as one of: “space exploration”, “content creation”, “community interaction”, or “research/recommendation”.
33
+ 2. **Choose the corresponding sub‑skill**:
34
+ - Spaces/worldbuilding/gameplay structure → use `neta-space`
35
+ - Image/video/song/MV creation and idea deconstruction → use `neta-creative`
36
+ - Browsing feeds, viewing collection details, liking/interacting, community‑centric views → use `neta-community`
37
+ - Keyword/tag/category research and recommendation, progressive exploration from broad to narrow → use `neta-suggest`
38
+ 3. Use this skill only when boundaries are unclear or when you need to explain which sub‑skill to pick.
39
+
40
+ ## Capability map and sub‑skill overview
41
+
42
+ ### 1. Spaces and worldbuilding: `neta-space`
43
+
44
+ Responsibilities:
45
+
46
+ - List all available spaces.
47
+ - Fetch worldbuilding (lore) for spaces/hashtags.
48
+ - Fetch sub‑spaces, characters, and gameplay collections within a space.
49
+
50
+ Use when:
51
+
52
+ - The user talks about “worlds/universes/spaces/scene settings”.
53
+ - They want to browse gameplay and content organized by spaces/activities.
54
+
55
+ See `skills/neta-space/SKILL.md` for full details.
56
+
57
+ ### 2. Content creation: `neta-creative`
58
+
59
+ Responsibilities:
60
+
61
+ - Generate images, videos, songs, and MVs.
62
+ - Remove image backgrounds.
63
+ - Search and inspect characters (in a creation context).
64
+ - Deconstruct creative ideas from existing collections via `read_collection`.
65
+
66
+ Use when:
67
+
68
+ - The user wants to “create/edit images/videos/songs/MVs”.
69
+ - They want to create based on character settings or stories.
70
+ - They want to analyze the creative intent behind an existing work.
71
+
72
+ See `skills/neta-creative/SKILL.md` for full details.
73
+
74
+ ### 3. Community browsing and interactions: `neta-community`
75
+
76
+ Responsibilities:
77
+
78
+ - Fetch interactive recommendation feeds.
79
+ - View collection details (in a community context).
80
+ - Like/unlike or otherwise interact with content.
81
+ - Browse community content grouped by tags or characters.
82
+
83
+ Use when:
84
+
85
+ - The user says “show me what people are doing”, “scroll the feed”.
86
+ - They want to like or interact with specific works.
87
+
88
+ See `skills/neta-community/SKILL.md` for full details.
89
+
90
+ ### 4. Research and recommendation engine: `neta-suggest`
91
+
92
+ Responsibilities:
93
+
94
+ - Keyword suggestions (`suggest_keywords`).
95
+ - Tag suggestions (`suggest_tags`).
96
+ - Category navigation and path validation (`suggest_categories` / `validate_tax_path`).
97
+ - Multi‑mode content feeds (`suggest_content`).
98
+
99
+ Use when:
100
+
101
+ - The user has no clear target and wants ideas/topics.
102
+ - They want to understand popular tags/category structure/content distribution.
103
+ - They need systematic research before creating content.
104
+
105
+ See `skills/neta-suggest/SKILL.md` for full details.
106
+
107
+ ## Migration notes (from legacy neta skill)
108
+
109
+ If you encounter older docs or scripts that call commands directly under `neta`, migrate them according to this table:
110
+
111
+ | Legacy capability | New skill |
112
+ |---------------------------------------------|------------------|
113
+ | Space/tag lore and space browsing | `neta-space` |
114
+ | Image/video/song/MV creation | `neta-creative` |
115
+ | Collection details, feeds, likes/interacts | `neta-community` |
116
+ | Keyword/tag/category/recommendation research| `neta-suggest` |
117
+
118
+ For new development, always prefer the focused sub‑skills and avoid adding new command examples directly to this skill.
119
+