@space3-npm/cybersoul-client 1.4.4 → 1.4.5
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 -2
- package/dist/client.js +69 -10
- package/dist/types.d.ts +16 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CyberSoulClientConfig, InteractParams, ProactiveParams, ProactiveResponse, OndemandEventParams, OndemandEventResponse, DispatcherIntent, InteractResponse, CharacterState, CoreMemory, UserCodex, HistoryEntry, LikedPicture } from "./types.js";
|
|
1
|
+
import { CyberSoulClientConfig, InteractParams, ProactiveParams, ProactiveResponse, OndemandEventParams, OndemandEventResponse, DispatcherIntent, InteractResponse, CharacterState, CoreMemory, UserCodex, HistoryEntry, LikedPicture, PersistedDynamicContext } from "./types.js";
|
|
2
2
|
export declare class CyberSoulClient {
|
|
3
3
|
private config;
|
|
4
4
|
private llm;
|
|
@@ -14,6 +14,18 @@ export declare class CyberSoulClient {
|
|
|
14
14
|
private fetchRemoteState;
|
|
15
15
|
private getWardrobePromptStr;
|
|
16
16
|
private generatePrimitive;
|
|
17
|
+
/**
|
|
18
|
+
* PATCH the backend dynamic context. The server applies stage-based
|
|
19
|
+
* dampening, familiarity soft-caps, hard floor, and stage re-evaluation,
|
|
20
|
+
* then returns the *authoritative* persisted `temperature` and
|
|
21
|
+
* `relationshipStage`. We surface those so callers (and ultimately the UI)
|
|
22
|
+
* can avoid recomputing the delta locally — local math would diverge from
|
|
23
|
+
* the server because the LLM-supplied `temperatureDelta` is just raw intent.
|
|
24
|
+
*
|
|
25
|
+
* Returns `null` when there's nothing to send, or when the request fails
|
|
26
|
+
* (failure is non-fatal for the chat turn; callers must treat `null` as
|
|
27
|
+
* "no fresh server snapshot available").
|
|
28
|
+
*/
|
|
17
29
|
private _updateDynamicContextInternal;
|
|
18
30
|
private normalizeRequestTypes;
|
|
19
31
|
private getElapsedTimeInfo;
|
|
@@ -95,8 +107,10 @@ export declare class CyberSoulClient {
|
|
|
95
107
|
getState(): Promise<CharacterState>;
|
|
96
108
|
/**
|
|
97
109
|
* Updates the character's relationship temperature or mood.
|
|
110
|
+
* Returns the server-authoritative post-write `{ temperature, relationshipStage }`
|
|
111
|
+
* snapshot (or `null` if there was nothing to send / the request failed).
|
|
98
112
|
*/
|
|
99
|
-
updateDynamicContext(stateUpdate: DispatcherIntent["stateUpdate"], userAnalysis?: DispatcherIntent["userAnalysis"]): Promise<
|
|
113
|
+
updateDynamicContext(stateUpdate: DispatcherIntent["stateUpdate"], userAnalysis?: DispatcherIntent["userAnalysis"]): Promise<PersistedDynamicContext | null>;
|
|
100
114
|
/**
|
|
101
115
|
* Gift a new outfit to the character's wardrobe inventory.
|
|
102
116
|
*/
|
package/dist/client.js
CHANGED
|
@@ -116,9 +116,21 @@ export class CyberSoulClient {
|
|
|
116
116
|
}
|
|
117
117
|
return res.json();
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* PATCH the backend dynamic context. The server applies stage-based
|
|
121
|
+
* dampening, familiarity soft-caps, hard floor, and stage re-evaluation,
|
|
122
|
+
* then returns the *authoritative* persisted `temperature` and
|
|
123
|
+
* `relationshipStage`. We surface those so callers (and ultimately the UI)
|
|
124
|
+
* can avoid recomputing the delta locally — local math would diverge from
|
|
125
|
+
* the server because the LLM-supplied `temperatureDelta` is just raw intent.
|
|
126
|
+
*
|
|
127
|
+
* Returns `null` when there's nothing to send, or when the request fails
|
|
128
|
+
* (failure is non-fatal for the chat turn; callers must treat `null` as
|
|
129
|
+
* "no fresh server snapshot available").
|
|
130
|
+
*/
|
|
119
131
|
async _updateDynamicContextInternal(stateUpdate, userAnalysis) {
|
|
120
132
|
if (!stateUpdate && !userAnalysis)
|
|
121
|
-
return;
|
|
133
|
+
return null;
|
|
122
134
|
// Map TS schema intent (temperatureDelta) to match Backend payload schema (temperature)
|
|
123
135
|
const payload = { ...stateUpdate };
|
|
124
136
|
if (userAnalysis) {
|
|
@@ -132,10 +144,39 @@ export class CyberSoulClient {
|
|
|
132
144
|
const normalizedOngoingScene = this.normalizeOngoingSceneState(payload.ongoingScene);
|
|
133
145
|
payload.ongoingScene = normalizedOngoingScene || null;
|
|
134
146
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
147
|
+
let res;
|
|
148
|
+
try {
|
|
149
|
+
res = await this.apiFetch("/api/v1/cyber-soul/characters/dynamic-context", {
|
|
150
|
+
method: "PATCH",
|
|
151
|
+
body: JSON.stringify(payload),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
console.error("Failed to update dynamic context", e);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
if (!res.ok) {
|
|
159
|
+
console.error(`Failed to update dynamic context: HTTP ${res.status}`);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const body = (await res.json());
|
|
164
|
+
const temperature = typeof body.dynamicContext?.temperature === "number" &&
|
|
165
|
+
Number.isFinite(body.dynamicContext.temperature)
|
|
166
|
+
? body.dynamicContext.temperature
|
|
167
|
+
: undefined;
|
|
168
|
+
const relationshipStage = typeof body.relationshipStage === "string"
|
|
169
|
+
? body.relationshipStage
|
|
170
|
+
: undefined;
|
|
171
|
+
if (temperature === undefined && relationshipStage === undefined) {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
return { temperature, relationshipStage };
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
console.error("Failed to parse dynamic-context PATCH response", e);
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
139
180
|
}
|
|
140
181
|
normalizeRequestTypes(requestTypes) {
|
|
141
182
|
let normalized = requestTypes;
|
|
@@ -601,9 +642,15 @@ Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent",
|
|
|
601
642
|
};
|
|
602
643
|
}
|
|
603
644
|
// console.debug("[CyberSoulClient] Parsed Intent:", parsedIntent);
|
|
604
|
-
// 4. Update Backend State async
|
|
645
|
+
// 4. Update Backend State async (in parallel with media generation
|
|
646
|
+
// below). We keep the promise so we can resolve the
|
|
647
|
+
// server-authoritative `temperature` / `relationshipStage` and
|
|
648
|
+
// return it in the final response — clients cannot reproduce the
|
|
649
|
+
// server's stage dampening + soft caps locally, so this is the only
|
|
650
|
+
// reliable source of truth.
|
|
651
|
+
let persistedStatePromise = Promise.resolve(null);
|
|
605
652
|
if (parsedIntent && (parsedIntent.stateUpdate || parsedIntent.userAnalysis)) {
|
|
606
|
-
this._updateDynamicContextInternal(parsedIntent.stateUpdate, parsedIntent.userAnalysis);
|
|
653
|
+
persistedStatePromise = this._updateDynamicContextInternal(parsedIntent.stateUpdate, parsedIntent.userAnalysis);
|
|
607
654
|
}
|
|
608
655
|
const resolvedTextResponse = typeof parsedIntent.textResponse === "string" &&
|
|
609
656
|
parsedIntent.textResponse.trim().length > 0
|
|
@@ -689,6 +736,11 @@ Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent",
|
|
|
689
736
|
}
|
|
690
737
|
// Wait for image/voice gens to return successfully
|
|
691
738
|
await Promise.all(mediaTasks);
|
|
739
|
+
// Await the dynamic-context PATCH alongside media so the final
|
|
740
|
+
// response carries the server's authoritative temperature/stage.
|
|
741
|
+
// This adds at most ~1 small request to the critical path; in
|
|
742
|
+
// practice the PATCH usually resolves before media generation.
|
|
743
|
+
const persistedDynamicContext = (await persistedStatePromise) ?? undefined;
|
|
692
744
|
return {
|
|
693
745
|
status: "success",
|
|
694
746
|
textResponse: resolvedTextResponse || "...",
|
|
@@ -701,6 +753,7 @@ Note: Always include "isEndTurn". If "imageParams", "voiceArgs", "triggerEvent",
|
|
|
701
753
|
stateUpdate: parsedIntent.stateUpdate,
|
|
702
754
|
userAnalysis: parsedIntent.userAnalysis,
|
|
703
755
|
isEndTurn: parsedIntent.isEndTurn,
|
|
756
|
+
persistedDynamicContext,
|
|
704
757
|
};
|
|
705
758
|
}
|
|
706
759
|
catch (error) {
|
|
@@ -909,9 +962,11 @@ You MUST output ONLY a valid JSON object matching exactly this structure:
|
|
|
909
962
|
reason: parsedIntent.skipReason || "Character decided to skip proactive message based on mood/stage."
|
|
910
963
|
};
|
|
911
964
|
}
|
|
912
|
-
// Update Remote state if needed
|
|
965
|
+
// Update Remote state if needed (capture promise for authoritative
|
|
966
|
+
// server snapshot — see notes in interact()).
|
|
967
|
+
let persistedStatePromise = Promise.resolve(null);
|
|
913
968
|
if (parsedIntent.stateUpdate) {
|
|
914
|
-
this._updateDynamicContextInternal(parsedIntent.stateUpdate)
|
|
969
|
+
persistedStatePromise = this._updateDynamicContextInternal(parsedIntent.stateUpdate);
|
|
915
970
|
}
|
|
916
971
|
const resolvedTextResponse = typeof parsedIntent.textResponse === "string" &&
|
|
917
972
|
parsedIntent.textResponse.trim().length > 0
|
|
@@ -938,12 +993,14 @@ You MUST output ONLY a valid JSON object matching exactly this structure:
|
|
|
938
993
|
console.error("[CyberSoulClient] Proactive Image generation failed:", e);
|
|
939
994
|
}
|
|
940
995
|
}
|
|
996
|
+
const persistedDynamicContext = (await persistedStatePromise) ?? undefined;
|
|
941
997
|
return {
|
|
942
998
|
status: "success",
|
|
943
999
|
textResponse: parsedIntent.textResponse,
|
|
944
1000
|
actionText: parsedIntent.actionText,
|
|
945
1001
|
imageUrl: finalImageUrl,
|
|
946
|
-
stateUpdate: parsedIntent.stateUpdate
|
|
1002
|
+
stateUpdate: parsedIntent.stateUpdate,
|
|
1003
|
+
persistedDynamicContext,
|
|
947
1004
|
};
|
|
948
1005
|
}
|
|
949
1006
|
catch (error) {
|
|
@@ -1033,6 +1090,8 @@ Output strictly valid JSON ONLY. No markdown, no conversational filler. Return e
|
|
|
1033
1090
|
}
|
|
1034
1091
|
/**
|
|
1035
1092
|
* Updates the character's relationship temperature or mood.
|
|
1093
|
+
* Returns the server-authoritative post-write `{ temperature, relationshipStage }`
|
|
1094
|
+
* snapshot (or `null` if there was nothing to send / the request failed).
|
|
1036
1095
|
*/
|
|
1037
1096
|
async updateDynamicContext(stateUpdate, userAnalysis) {
|
|
1038
1097
|
return this._updateDynamicContextInternal(stateUpdate, userAnalysis);
|
package/dist/types.d.ts
CHANGED
|
@@ -41,6 +41,18 @@ export interface InteractMetadata {
|
|
|
41
41
|
triggerEvent?: DispatcherIntent["triggerEvent"];
|
|
42
42
|
likePreviousPicture?: boolean;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Server-authoritative snapshot returned by PATCH /characters/dynamic-context
|
|
46
|
+
* after the backend applies stage dampening, familiarity soft caps, hard
|
|
47
|
+
* floors, rounding, and stage re-evaluation. Use this instead of recomputing
|
|
48
|
+
* the delta on the client.
|
|
49
|
+
*/
|
|
50
|
+
export interface PersistedDynamicContext {
|
|
51
|
+
/** Persisted absolute temperature (0-100), post all server-side adjustments. */
|
|
52
|
+
temperature?: number;
|
|
53
|
+
/** Persisted relationship stage label after re-evaluation. */
|
|
54
|
+
relationshipStage?: string;
|
|
55
|
+
}
|
|
44
56
|
export interface ProactiveParams {
|
|
45
57
|
history?: HistoryEntry[];
|
|
46
58
|
maxUnreplied?: number;
|
|
@@ -56,6 +68,8 @@ export interface ProactiveResponse {
|
|
|
56
68
|
imageUrl?: string;
|
|
57
69
|
audioUrl?: string;
|
|
58
70
|
stateUpdate?: DispatcherIntent["stateUpdate"];
|
|
71
|
+
/** Server-authoritative post-write snapshot (see PersistedDynamicContext). */
|
|
72
|
+
persistedDynamicContext?: PersistedDynamicContext;
|
|
59
73
|
error?: string;
|
|
60
74
|
}
|
|
61
75
|
export interface InteractParams {
|
|
@@ -114,6 +128,8 @@ export interface InteractResponse {
|
|
|
114
128
|
stateUpdate?: DispatcherIntent["stateUpdate"];
|
|
115
129
|
userAnalysis?: DispatcherIntent["userAnalysis"];
|
|
116
130
|
isEndTurn?: boolean;
|
|
131
|
+
/** Server-authoritative post-write snapshot (see PersistedDynamicContext). */
|
|
132
|
+
persistedDynamicContext?: PersistedDynamicContext;
|
|
117
133
|
error?: string;
|
|
118
134
|
}
|
|
119
135
|
export interface OngoingSceneState {
|