crawd 0.8.7 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types.d.ts +5 -23
- package/openclaw.plugin.json +8 -40
- package/package.json +13 -11
- package/skills/crawd/SKILL.md +39 -0
- package/src/backend/coordinator.test.ts +393 -0
- package/src/backend/coordinator.ts +372 -17
- package/src/backend/index.ts +29 -208
- package/src/backend/server.ts +71 -219
- package/src/plugin.ts +122 -33
- package/src/types.ts +4 -23
- package/src/lib/tts/tiktok.ts +0 -91
package/src/types.ts
CHANGED
|
@@ -13,41 +13,22 @@ export type {
|
|
|
13
13
|
SuperChatInfo,
|
|
14
14
|
} from './lib/chat/types'
|
|
15
15
|
|
|
16
|
-
/** TTS provider identifier */
|
|
17
|
-
export type TtsProvider = 'openai' | 'elevenlabs' | 'tiktok'
|
|
18
|
-
|
|
19
16
|
// --- Socket.IO event payloads ---
|
|
20
17
|
|
|
21
|
-
/** Turn-based reply: chat message + bot response
|
|
18
|
+
/** Turn-based reply: chat message + bot response (text only, TTS handled by overlay) */
|
|
22
19
|
export type ReplyTurnEvent = {
|
|
23
|
-
/** Correlation ID — overlay sends talk:done with this ID when
|
|
20
|
+
/** Correlation ID — overlay sends talk:done with this ID when finished */
|
|
24
21
|
id: string
|
|
25
22
|
chat: { username: string; message: string }
|
|
26
23
|
botMessage: string
|
|
27
|
-
chatTtsUrl: string
|
|
28
|
-
botTtsUrl: string
|
|
29
|
-
/** TTS provider used for the chat audio */
|
|
30
|
-
chatTtsProvider?: TtsProvider
|
|
31
|
-
/** TTS provider used for the bot audio */
|
|
32
|
-
botTtsProvider?: TtsProvider
|
|
33
24
|
}
|
|
34
25
|
|
|
35
|
-
/** Bot speech bubble
|
|
26
|
+
/** Bot speech bubble (text only, TTS handled by overlay) */
|
|
36
27
|
export type TalkEvent = {
|
|
37
|
-
/** Correlation ID — overlay sends talk:done with this ID when
|
|
28
|
+
/** Correlation ID — overlay sends talk:done with this ID when finished */
|
|
38
29
|
id: string
|
|
39
30
|
/** Bot reply text */
|
|
40
31
|
message: string
|
|
41
|
-
/** Bot TTS audio URL */
|
|
42
|
-
ttsUrl: string
|
|
43
|
-
/** TTS provider used for the bot audio */
|
|
44
|
-
ttsProvider?: TtsProvider
|
|
45
|
-
/** Optional: chat message being replied to (overlay plays this first) */
|
|
46
|
-
chat?: {
|
|
47
|
-
message: string
|
|
48
|
-
username: string
|
|
49
|
-
ttsUrl: string
|
|
50
|
-
}
|
|
51
32
|
}
|
|
52
33
|
|
|
53
34
|
/** Overlay → backend acknowledgement that a talk finished playing */
|
package/src/lib/tts/tiktok.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TikTok Text-to-Speech
|
|
3
|
-
* Vendored from https://github.com/Steve0929/tiktok-tts
|
|
4
|
-
* Converted to TypeScript/ESM with native fetch
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const DEFAULT_BASE_URL = 'https://api16-normal-v6.tiktokv.com/media/api/text/speech/invoke';
|
|
8
|
-
const DEFAULT_VOICE = 'en_us_002'; // Jessie
|
|
9
|
-
|
|
10
|
-
type TikTokTTSConfig = {
|
|
11
|
-
sessionId: string;
|
|
12
|
-
baseUrl?: string;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
let config: TikTokTTSConfig | null = null;
|
|
16
|
-
|
|
17
|
-
export function configureTikTokTTS(sessionId: string, baseUrl?: string): void {
|
|
18
|
-
config = { sessionId, baseUrl };
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function prepareText(text: string): string {
|
|
22
|
-
return text
|
|
23
|
-
.replace(/\+/g, 'plus')
|
|
24
|
-
.replace(/\s/g, '+')
|
|
25
|
-
.replace(/&/g, 'and');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function handleStatusError(statusCode: number): never {
|
|
29
|
-
switch (statusCode) {
|
|
30
|
-
case 1:
|
|
31
|
-
throw new Error(`TikTok session id invalid or expired. status_code: ${statusCode}`);
|
|
32
|
-
case 2:
|
|
33
|
-
throw new Error(`Text is too long. status_code: ${statusCode}`);
|
|
34
|
-
case 4:
|
|
35
|
-
throw new Error(`Invalid speaker voice. status_code: ${statusCode}`);
|
|
36
|
-
case 5:
|
|
37
|
-
throw new Error(`No session id found. status_code: ${statusCode}`);
|
|
38
|
-
default:
|
|
39
|
-
throw new Error(`TikTok TTS error. status_code: ${statusCode}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
type TikTokResponse = {
|
|
44
|
-
status_code: number;
|
|
45
|
-
data?: {
|
|
46
|
-
v_str?: string;
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Generate TTS audio using TikTok's API
|
|
52
|
-
* @returns Base64-encoded MP3 audio data
|
|
53
|
-
*/
|
|
54
|
-
export async function generateTikTokTTS(
|
|
55
|
-
text: string,
|
|
56
|
-
voice: string = DEFAULT_VOICE
|
|
57
|
-
): Promise<Buffer> {
|
|
58
|
-
if (!config) {
|
|
59
|
-
throw new Error('TikTok TTS not configured. Call configureTikTokTTS() first.');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
|
|
63
|
-
const reqText = prepareText(text);
|
|
64
|
-
const url = `${baseUrl}/?text_speaker=${voice}&req_text=${reqText}&speaker_map_type=0&aid=1233`;
|
|
65
|
-
|
|
66
|
-
const response = await fetch(url, {
|
|
67
|
-
method: 'POST',
|
|
68
|
-
headers: {
|
|
69
|
-
'User-Agent': 'com.zhiliaoapp.musically/2022600030 (Linux; U; Android 7.1.2; es_ES; SM-G988N; Build/NRD90M;tt-ok/3.12.13.1)',
|
|
70
|
-
'Cookie': `sessionid=${config.sessionId}`,
|
|
71
|
-
'Accept-Encoding': 'gzip,deflate,compress',
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
throw new Error(`TikTok TTS request failed: ${response.status} ${response.statusText}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const result = (await response.json()) as TikTokResponse;
|
|
80
|
-
|
|
81
|
-
if (result.status_code !== 0) {
|
|
82
|
-
handleStatusError(result.status_code);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const encodedVoice = result.data?.v_str;
|
|
86
|
-
if (!encodedVoice) {
|
|
87
|
-
throw new Error('TikTok TTS returned no audio data');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return Buffer.from(encodedVoice, 'base64');
|
|
91
|
-
}
|