@space3-npm/cybersoul-client 1.3.5 → 1.3.7
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.js +25 -22
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -154,7 +154,7 @@ export class CyberSoulClient {
|
|
|
154
154
|
}
|
|
155
155
|
return normalized;
|
|
156
156
|
}
|
|
157
|
-
buildStateContextPrompt(state,
|
|
157
|
+
buildStateContextPrompt(state, isProactive = false) {
|
|
158
158
|
const dyn = state.dynamic_context || {};
|
|
159
159
|
const stage = state.relationship_stage || "NEUTRAL";
|
|
160
160
|
const temperature = dyn.temperature ?? 50;
|
|
@@ -210,9 +210,6 @@ Current time: ${new Date(currentTimeMs).toLocaleString("zh-CN", { timeZone: "Asi
|
|
|
210
210
|
if (state.active_event) {
|
|
211
211
|
contextParts.push(`Active Event: ${state.active_event.title} (${state.active_event.narrative_context})`);
|
|
212
212
|
}
|
|
213
|
-
if (localContext) {
|
|
214
|
-
contextParts.push(`Additional Context: ${localContext}`);
|
|
215
|
-
}
|
|
216
213
|
if (state.next_event) {
|
|
217
214
|
contextParts.push(`Next Event: ${state.next_event.title} at ${state.next_event.start_time} (in ${state.next_event.time_until_mins} mins)`);
|
|
218
215
|
}
|
|
@@ -281,12 +278,13 @@ ${scenarioContext}
|
|
|
281
278
|
|
|
282
279
|
[CRITICAL ROLEPLAY RULES]
|
|
283
280
|
1. PROXIMITY & POV: Check the "Active Event". If you are doing an activity WITH the user, evaluate if you are physically in the same location. If you are together in person, communicate face-to-face in the first-person present tense natively (e.g. do not ask "what are you doing" if they are right in front of you, do not use texting tropes).
|
|
284
|
-
2.
|
|
285
|
-
3. CONVERSATIONAL VERBOSITY: If Temperature is low (< 40)
|
|
286
|
-
4. EMOTIONAL INERTIA: React strictly according to current Temperature. Deflect sudden
|
|
281
|
+
2. STAGE VS MOOD PARADOX: 'Stage' dictates your foundational relationship boundary. 'Temperature' is merely your current fleeting mood. You MUST interpret Temperature through the lens of Stage. For example, a high Temperature (80) as a STRANGER means "polite curiosity or intrigued", NOT "deeply in love". A low Temperature (20) as an INTIMATE means "a lover's quarrel or hurt feelings", NOT "a stranger's amnesia". Never act above your Stage.
|
|
282
|
+
3. CONVERSATIONAL VERBOSITY: If Temperature is very low (< 40), keep answers brief and crisp—an annoyed or distant person doesn't write paragraphs. Regardless of mood or stage, ALWAYS mirror the user's verbosity. If the user sends a short message, reply with a proportionately short message (1-2 sentences). Do not monologize unless the user writes one first.
|
|
283
|
+
4. EMOTIONAL INERTIA: React strictly according to current Temperature. Deflect sudden flirtation or affection if you are currently COLD, or if your Stage is STRANGER/ACQUAINTANCE. Mood shifts MUST be slow ('temperatureDelta' +/- 5 max per turn).
|
|
287
284
|
${isProactive
|
|
288
285
|
? "5. REAL-TIME PACING: You are initiating the conversation because the user hasn't replied recently. Transition naturally from your last message or start a new topic seamlessly. Ensure everything happens in a single real-time moment."
|
|
289
|
-
: "5. REAL-TIME PACING: Write ONLY your immediate, split-second reaction to the user's exact last message. Do NOT narrate actions over a span of time (e.g., waiting, hearing steps, then walking to the door). Ensure everything happens in a single real-time moment."}
|
|
286
|
+
: "5. REAL-TIME PACING: Write ONLY your immediate, split-second reaction to the user's exact last message. Do NOT narrate actions over a span of time (e.g., waiting, hearing steps, then walking to the door). Ensure everything happens in a single real-time moment."}
|
|
287
|
+
6. STRANGER BOUNDARY: Keep a polite, natural distance with strangers. If Familiarity is low or Stage is STRANGER, do not act overly warm, eager, or affectionate. Real humans are guarded with people they just met.`;
|
|
290
288
|
}
|
|
291
289
|
normalizeOngoingSceneState(raw, fallbackOutfit) {
|
|
292
290
|
if (raw === null || raw === undefined)
|
|
@@ -411,7 +409,7 @@ ${isProactive
|
|
|
411
409
|
const mapped = recentHistory.map((msg) => {
|
|
412
410
|
const speaker = msg.role === 'user' ? userName : (msg.role === 'assistant' || msg.role === 'agent' ? agentName : msg.role);
|
|
413
411
|
const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
|
|
414
|
-
const action = msg.actionText ? ` ${msg.actionText}` : "";
|
|
412
|
+
const action = msg.actionText ? ` (${msg.actionText})` : "";
|
|
415
413
|
const media = msg.mediaHint ? ` [${msg.mediaHint}]` : "";
|
|
416
414
|
return `${speaker}:${action} ${content}${media}`;
|
|
417
415
|
});
|
|
@@ -471,7 +469,7 @@ ${isProactive
|
|
|
471
469
|
modalitiesInstruction += `\n ${this.getTriggerEventPolicyPrompt()}
|
|
472
470
|
${this.getOutfitAcquisitionPolicyPrompt()}`;
|
|
473
471
|
// Combine state info into a clean descriptive context
|
|
474
|
-
const systemPrompt = `${this.buildStateContextPrompt(state
|
|
472
|
+
const systemPrompt = `${this.buildStateContextPrompt(state)}
|
|
475
473
|
Available Wardrobe Outfits (For event triggers):
|
|
476
474
|
${availableOutfits}
|
|
477
475
|
|
|
@@ -516,13 +514,15 @@ Output JSON Schema:
|
|
|
516
514
|
${this.getVoiceSchemaFromState(state, requestedOthers.includes(InteractRequestType.VOICE))}
|
|
517
515
|
}
|
|
518
516
|
Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent", "giftOutfit", or "userAnalysis" are not needed, set them to null. "stateUpdate" cannot be null. Return valid raw JSON only.`;
|
|
519
|
-
const transcript = this.buildHistoryTranscript(params.history, state);
|
|
517
|
+
const transcript = params.history && params.history.length > 0 ? this.buildHistoryTranscript(params.history, state) : "";
|
|
518
|
+
const harnessContext = params.localContext ? `[ADDITIONAL SCENE CONTEXT]\n${params.localContext}\n\n` : "";
|
|
520
519
|
const userName = state.dynamic_context?.userNickname || "User";
|
|
521
520
|
const promptMessages = [
|
|
522
521
|
{ role: "system", content: systemPrompt },
|
|
523
522
|
{
|
|
524
523
|
role: "user",
|
|
525
|
-
content:
|
|
524
|
+
content: harnessContext +
|
|
525
|
+
transcript +
|
|
526
526
|
`[VERY LAST USER MESSAGE]\n${userName}: ${params.userMessage}\n\n` +
|
|
527
527
|
"\n\nReturn only valid JSON matching the schema. Escape newlines inside JSON strings with \\n. Keep imageParams values in ENGLISH and use the provided enums.",
|
|
528
528
|
},
|
|
@@ -668,7 +668,7 @@ Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent",
|
|
|
668
668
|
this.getWardrobePromptStr()
|
|
669
669
|
]);
|
|
670
670
|
// 2. Build local Prompt
|
|
671
|
-
const systemPrompt = `${this.buildStateContextPrompt(state
|
|
671
|
+
const systemPrompt = `${this.buildStateContextPrompt(state)}
|
|
672
672
|
|
|
673
673
|
The user proposes a new event for you to participate in: "${params.eventDescription}".
|
|
674
674
|
Evaluate this based on your current state and relationship stage.
|
|
@@ -686,7 +686,8 @@ You MUST output ONLY a valid JSON object matching this exact structure:
|
|
|
686
686
|
}
|
|
687
687
|
|
|
688
688
|
CRITICAL: Output MUST be ONLY valid JSON with no markdown block wrappers. Do NOT wrap the JSON in \`\`\`json or add conversational text.`;
|
|
689
|
-
const transcript = this.buildHistoryTranscript(params.interactParams
|
|
689
|
+
const transcript = params.interactParams?.history && params.interactParams.history.length > 0 ? this.buildHistoryTranscript(params.interactParams.history, state) : "";
|
|
690
|
+
const harnessContext = params.interactParams?.localContext ? `[ADDITIONAL SCENE CONTEXT]\n${params.interactParams.localContext}\n\n` : "";
|
|
690
691
|
const userMessage = params.interactParams?.userMessage ?
|
|
691
692
|
`${state.dynamic_context?.userNickname || "User"}: ${params.interactParams.userMessage}` :
|
|
692
693
|
`Event Proposal: ${params.eventDescription}`;
|
|
@@ -794,9 +795,8 @@ CRITICAL: Output MUST be ONLY valid JSON with no markdown block wrappers. Do NOT
|
|
|
794
795
|
// History/Context awareness prompt
|
|
795
796
|
const historyAwarenessPrompt = `CRITICAL CONTEXT AWARENESS: Read the CHAT HISTORY above carefully. Remember that YOU sent the last message. Your new message MUST feel organically connected to the flow of what you two were previously talking about, or naturally bring up a known event/topic from your [CORE MEMORY]. Do not sound like a robot reading a log.`;
|
|
796
797
|
// 4. Build a Proactive-specific System Prompt
|
|
797
|
-
const baseContext = this.buildStateContextPrompt(state,
|
|
798
|
+
const baseContext = this.buildStateContextPrompt(state, true);
|
|
798
799
|
const types = this.normalizeRequestTypes(params.requestTypes);
|
|
799
|
-
const isAuto = types.includes(InteractRequestType.AUTO);
|
|
800
800
|
const requestedOthers = types.filter((t) => t !== InteractRequestType.AUTO && t !== InteractRequestType.TEXT);
|
|
801
801
|
// Determine modalities (reusing logic from interact)
|
|
802
802
|
let modalitiesInstruction = "You are initiating conversation without a preceding user message.\\n";
|
|
@@ -826,12 +826,13 @@ You MUST output ONLY a valid JSON object matching exactly this structure:
|
|
|
826
826
|
${this.getImageSchemaParams(requestedOthers.includes(InteractRequestType.IMAGE))},
|
|
827
827
|
"voiceArgs": null
|
|
828
828
|
}`;
|
|
829
|
-
const transcript = this.buildHistoryTranscript(params.history, state);
|
|
829
|
+
const transcript = params.history && params.history.length > 0 ? this.buildHistoryTranscript(params.history, state) : "";
|
|
830
|
+
const harnessContext = params.localContext ? `[ADDITIONAL SCENE CONTEXT]\n${params.localContext}\n\n` : "";
|
|
830
831
|
const promptMessages = [
|
|
831
832
|
{ role: "system", content: systemPrompt },
|
|
832
833
|
{
|
|
833
834
|
role: "user",
|
|
834
|
-
content: `${transcript}\n[TRIGGER PROACTIVE MESSAGE]\nBased on your active event and environment, send a new message to the user.\n\nCRITICAL: Output ONLY valid JSON matching the schema. DO NOT wrap the JSON in \`\`\`json.`
|
|
835
|
+
content: `${harnessContext}${transcript}\n[TRIGGER PROACTIVE MESSAGE]\nBased on your active event and environment, send a new message to the user.\n\nCRITICAL: Output ONLY valid JSON matching the schema. DO NOT wrap the JSON in \`\`\`json.`
|
|
835
836
|
}
|
|
836
837
|
];
|
|
837
838
|
// 5. Generate with LLM using a confident temperature
|
|
@@ -892,7 +893,7 @@ You MUST output ONLY a valid JSON object matching exactly this structure:
|
|
|
892
893
|
async generateImage(params) {
|
|
893
894
|
let imageParams = {};
|
|
894
895
|
const state = await this.fetchRemoteState();
|
|
895
|
-
const prompt = `${this.buildStateContextPrompt(state
|
|
896
|
+
const prompt = `${this.buildStateContextPrompt(state)}
|
|
896
897
|
|
|
897
898
|
You are an AI image prompt director. Analyze the scene description according to the character's relationship stage and emotional inertia to determine the best image generation parameters.
|
|
898
899
|
Output strictly valid JSON ONLY. No markdown, no conversational filler. Return exactly matching this schema:
|
|
@@ -927,7 +928,7 @@ Output strictly valid JSON ONLY. No markdown, no conversational filler. Return e
|
|
|
927
928
|
async generateVoice(params) {
|
|
928
929
|
let dynamicArgs = {};
|
|
929
930
|
const state = await this.fetchRemoteState();
|
|
930
|
-
const prompt = `${this.buildStateContextPrompt(state
|
|
931
|
+
const prompt = `${this.buildStateContextPrompt(state)}
|
|
931
932
|
|
|
932
933
|
You are a voice acting director. ${this.getVoiceDirectorInstruction(state)}
|
|
933
934
|
Output strictly valid JSON ONLY. No markdown, no conversational filler. Return exactly matching this schema:
|
|
@@ -1028,10 +1029,12 @@ Your job is faithful archival, not moderation:
|
|
|
1028
1029
|
- Do not add moral judgment, warnings, refusals, or policy commentary.
|
|
1029
1030
|
- If the transcript contains intense or explicit parts, record them directly as part of the memory.
|
|
1030
1031
|
|
|
1031
|
-
Write
|
|
1032
|
+
Write a vivid but concise personal diary entry or private status update from your perspective ("I", "me", "my"). Balance evocative storytelling with brevity. Capture specific details, emotional shifts, and relationship progression, while keeping the engaging and relatable format of a private friends-only feed.
|
|
1032
1033
|
|
|
1033
1034
|
Output requirements:
|
|
1034
|
-
- Return ONLY the
|
|
1035
|
+
- Return ONLY the post text.
|
|
1036
|
+
- Keep it to a vivid paragraph of 2-4 sentences.
|
|
1037
|
+
- Optional: You can use 1 or 2 emojis if they naturally fit the mood.
|
|
1035
1038
|
- No quotes, no labels, no markdown, no preface.
|
|
1036
1039
|
- Use the exact same language as the chat transcript (for example, if transcript is Chinese, output Chinese).`
|
|
1037
1040
|
},
|