@space3-npm/cybersoul-client 1.4.3 → 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +16 -0
- package/dist/client.js +32 -9
- package/dist/llm.provider.d.ts +3 -1
- package/dist/llm.provider.js +8 -3
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -42,6 +42,22 @@ export declare class CyberSoulClient {
|
|
|
42
42
|
* If the payload is already the inner args object (no voiceArgs wrapper), uses it as-is.
|
|
43
43
|
*/
|
|
44
44
|
private extractVoiceArgsFromLlmResponse;
|
|
45
|
+
/**
|
|
46
|
+
* Strip content the TTS engine can't speak naturally:
|
|
47
|
+
* - Stage-direction wrappers like (smiles), (挑眉), [pauses], 【动作】, *grins*
|
|
48
|
+
* — these slip through despite prompt instructions and the engine will
|
|
49
|
+
* literally read the brackets/asterisks if left in.
|
|
50
|
+
* - Emoji and emoji-component codepoints (Extended_Pictographic plus the
|
|
51
|
+
* ZWJ / variation-selector / skin-tone / regional-indicator scaffolding
|
|
52
|
+
* that builds composite emoji). TTS providers either read these aloud
|
|
53
|
+
* as the literal Unicode name ("face with tears of joy") or produce a
|
|
54
|
+
* glitchy artifact, both of which sound wrong.
|
|
55
|
+
*
|
|
56
|
+
* Collapses runs of whitespace introduced by removals and trims the result.
|
|
57
|
+
* Returns "" if everything gets stripped — callers should fall back to a
|
|
58
|
+
* neutral placeholder (e.g. "...") so the TTS call still has valid input.
|
|
59
|
+
*/
|
|
60
|
+
private sanitizeTextForVoice;
|
|
45
61
|
private formatHistoryEntries;
|
|
46
62
|
private buildHistoryTranscript;
|
|
47
63
|
interact(params: InteractParams): Promise<InteractResponse>;
|
package/dist/client.js
CHANGED
|
@@ -13,7 +13,7 @@ export class CyberSoulClient {
|
|
|
13
13
|
this.requestTimeoutMs = config.requestTimeoutMs ?? 120000;
|
|
14
14
|
this.maxRetries = Math.max(0, config.maxRetries ?? 1);
|
|
15
15
|
// Setup Provider
|
|
16
|
-
this.llm = new GenericLLMProvider(config.llmConfig, config.backendUrl, config.characterKey);
|
|
16
|
+
this.llm = new GenericLLMProvider(config.llmConfig, config.backendUrl, config.characterKey, config.fetchImpl);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Internal wrapper for fetch that automatically injects the backend URL and Character Auth token.
|
|
@@ -33,7 +33,8 @@ export class CyberSoulClient {
|
|
|
33
33
|
const controller = new AbortController();
|
|
34
34
|
const timeout = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
35
35
|
try {
|
|
36
|
-
const
|
|
36
|
+
const fetchFn = this.config.fetchImpl ?? fetch;
|
|
37
|
+
const response = await fetchFn(url, {
|
|
37
38
|
...options,
|
|
38
39
|
headers,
|
|
39
40
|
signal: controller.signal,
|
|
@@ -408,6 +409,32 @@ ${isProactive
|
|
|
408
409
|
}
|
|
409
410
|
return payload;
|
|
410
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Strip content the TTS engine can't speak naturally:
|
|
414
|
+
* - Stage-direction wrappers like (smiles), (挑眉), [pauses], 【动作】, *grins*
|
|
415
|
+
* — these slip through despite prompt instructions and the engine will
|
|
416
|
+
* literally read the brackets/asterisks if left in.
|
|
417
|
+
* - Emoji and emoji-component codepoints (Extended_Pictographic plus the
|
|
418
|
+
* ZWJ / variation-selector / skin-tone / regional-indicator scaffolding
|
|
419
|
+
* that builds composite emoji). TTS providers either read these aloud
|
|
420
|
+
* as the literal Unicode name ("face with tears of joy") or produce a
|
|
421
|
+
* glitchy artifact, both of which sound wrong.
|
|
422
|
+
*
|
|
423
|
+
* Collapses runs of whitespace introduced by removals and trims the result.
|
|
424
|
+
* Returns "" if everything gets stripped — callers should fall back to a
|
|
425
|
+
* neutral placeholder (e.g. "...") so the TTS call still has valid input.
|
|
426
|
+
*/
|
|
427
|
+
sanitizeTextForVoice(text) {
|
|
428
|
+
if (typeof text !== "string")
|
|
429
|
+
return "";
|
|
430
|
+
return text
|
|
431
|
+
// (parens), (全角), [brackets], 【全角】, *asterisks*
|
|
432
|
+
.replace(/[\((\[【\*].*?[\))\]】\*]/g, "")
|
|
433
|
+
// emoji + ZWJ + variation selectors + skin-tone modifiers + regional indicators
|
|
434
|
+
.replace(/[\p{Extended_Pictographic}\u200D\uFE0F\uFE0E\u{1F3FB}-\u{1F3FF}\u{1F1E6}-\u{1F1FF}]/gu, "")
|
|
435
|
+
.replace(/\s+/g, " ")
|
|
436
|
+
.trim();
|
|
437
|
+
}
|
|
411
438
|
formatHistoryEntries(history, userName, agentName, promptDirective = "") {
|
|
412
439
|
const contextLines = [];
|
|
413
440
|
for (let i = 0; i < history.length; i++) {
|
|
@@ -642,12 +669,8 @@ Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent",
|
|
|
642
669
|
const normalizedVoiceArgs = parsedIntent.voiceArgs && typeof parsedIntent.voiceArgs === "object"
|
|
643
670
|
? parsedIntent.voiceArgs
|
|
644
671
|
: {};
|
|
645
|
-
let textForVoice = resolvedTextResponse;
|
|
646
|
-
|
|
647
|
-
if (typeof textForVoice === "string") {
|
|
648
|
-
textForVoice = textForVoice.replace(/[\((\[【\*].*?[\))\]】\*]/g, '').trim();
|
|
649
|
-
}
|
|
650
|
-
if (typeof textForVoice !== "string" || textForVoice.trim().length === 0) {
|
|
672
|
+
let textForVoice = this.sanitizeTextForVoice(resolvedTextResponse);
|
|
673
|
+
if (textForVoice.length === 0) {
|
|
651
674
|
textForVoice = "...";
|
|
652
675
|
}
|
|
653
676
|
mediaTasks.push(this.generatePrimitive("voice", {
|
|
@@ -994,7 +1017,7 @@ Output strictly valid JSON ONLY. No markdown, no conversational filler. Return e
|
|
|
994
1017
|
dynamicArgs = {};
|
|
995
1018
|
}
|
|
996
1019
|
const res = await this.generatePrimitive("voice", {
|
|
997
|
-
text: params.text,
|
|
1020
|
+
text: this.sanitizeTextForVoice(params.text) || "...",
|
|
998
1021
|
dynamicArgs,
|
|
999
1022
|
});
|
|
1000
1023
|
return {
|
package/dist/llm.provider.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ export declare class GenericLLMProvider implements BaseLLMProvider {
|
|
|
3
3
|
private config;
|
|
4
4
|
private backendApiUrl;
|
|
5
5
|
private backendAuthToken?;
|
|
6
|
+
private fetchImpl?;
|
|
6
7
|
private static templateCache;
|
|
7
|
-
constructor(config: GenericLLMConfig, backendApiUrl: string, backendAuthToken?: string | undefined);
|
|
8
|
+
constructor(config: GenericLLMConfig, backendApiUrl: string, backendAuthToken?: string | undefined, fetchImpl?: typeof fetch | undefined);
|
|
9
|
+
private get fetchFn();
|
|
8
10
|
private fetchTemplate;
|
|
9
11
|
private extractResponse;
|
|
10
12
|
generate(messages: {
|
package/dist/llm.provider.js
CHANGED
|
@@ -2,11 +2,16 @@ export class GenericLLMProvider {
|
|
|
2
2
|
config;
|
|
3
3
|
backendApiUrl;
|
|
4
4
|
backendAuthToken;
|
|
5
|
+
fetchImpl;
|
|
5
6
|
static templateCache = new Map();
|
|
6
|
-
constructor(config, backendApiUrl, backendAuthToken) {
|
|
7
|
+
constructor(config, backendApiUrl, backendAuthToken, fetchImpl) {
|
|
7
8
|
this.config = config;
|
|
8
9
|
this.backendApiUrl = backendApiUrl;
|
|
9
10
|
this.backendAuthToken = backendAuthToken;
|
|
11
|
+
this.fetchImpl = fetchImpl;
|
|
12
|
+
}
|
|
13
|
+
get fetchFn() {
|
|
14
|
+
return this.fetchImpl ?? fetch;
|
|
10
15
|
}
|
|
11
16
|
async fetchTemplate() {
|
|
12
17
|
const cacheKey = `${this.config.provider}:${this.config.model}`;
|
|
@@ -24,7 +29,7 @@ export class GenericLLMProvider {
|
|
|
24
29
|
provider: this.config.provider,
|
|
25
30
|
model: this.config.model
|
|
26
31
|
});
|
|
27
|
-
const resp = await
|
|
32
|
+
const resp = await this.fetchFn(`${this.backendApiUrl}/api/v1/cyber-soul/llm-models/template?${qs.toString()}`, {
|
|
28
33
|
headers
|
|
29
34
|
});
|
|
30
35
|
if (!resp.ok) {
|
|
@@ -66,7 +71,7 @@ export class GenericLLMProvider {
|
|
|
66
71
|
if (!payload.messages || (Array.isArray(payload.messages) && payload.messages.length === 0)) {
|
|
67
72
|
payload.messages = messages;
|
|
68
73
|
}
|
|
69
|
-
const response = await
|
|
74
|
+
const response = await this.fetchFn(template.apiUrl, {
|
|
70
75
|
method: 'POST',
|
|
71
76
|
headers,
|
|
72
77
|
body: JSON.stringify(payload)
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,15 @@ export interface CyberSoulClientConfig {
|
|
|
10
10
|
llmConfig: GenericLLMConfig;
|
|
11
11
|
requestTimeoutMs?: number;
|
|
12
12
|
maxRetries?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Optional fetch override. When provided, the client uses this in
|
|
15
|
+
* place of the global `fetch` for every HTTP call (backend + LLM
|
|
16
|
+
* provider). Intended for environments where the global fetch is
|
|
17
|
+
* suspended by the host platform — e.g. React Native on Samsung
|
|
18
|
+
* BBA / Doze — and a native HTTP path must be used instead. Must
|
|
19
|
+
* conform to the standard `fetch` signature.
|
|
20
|
+
*/
|
|
21
|
+
fetchImpl?: typeof fetch;
|
|
13
22
|
}
|
|
14
23
|
export declare enum InteractRequestType {
|
|
15
24
|
AUTO = "auto",
|