@linxin666/dsh-pet 0.3.19 → 0.3.21
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/README.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +191 -53
- package/lib/client.js.map +1 -1
- package/lib/index.js +174 -61
- package/lib/types/client/gameplay-hud.d.ts +15 -0
- package/lib/types/client/gameplay-hud.d.ts.map +1 -1
- package/lib/types/client/gameplay-hud.js +48 -6
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +21 -13
- package/lib/types/client/renderers/Frames2dVisualMount.d.ts.map +1 -1
- package/lib/types/client/renderers/Frames2dVisualMount.js +5 -0
- package/lib/types/client/renderers/frames2d.d.ts +5 -4
- package/lib/types/client/renderers/frames2d.d.ts.map +1 -1
- package/lib/types/client/renderers/frames2d.js +96 -39
- package/lib/types/client/work-tick-gate.d.ts +40 -0
- package/lib/types/client/work-tick-gate.d.ts.map +1 -0
- package/lib/types/client/work-tick-gate.js +49 -0
- package/lib/types/event-projection.d.ts +14 -0
- package/lib/types/event-projection.d.ts.map +1 -1
- package/lib/types/event-projection.js +32 -18
- package/lib/types/gameplay.d.ts +4 -0
- package/lib/types/gameplay.d.ts.map +1 -1
- package/lib/types/gameplay.js +11 -2
- package/lib/types/ledger.d.ts +8 -0
- package/lib/types/ledger.d.ts.map +1 -1
- package/lib/types/ledger.js +25 -0
- package/lib/types/persist.d.ts +6 -0
- package/lib/types/persist.d.ts.map +1 -1
- package/lib/types/persist.js +25 -1
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +6 -0
- package/lib/types/service.d.ts +24 -0
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +43 -1
- package/package.json +14 -14
- package/src/client/PetDockEntry.test.tsx +1 -0
- package/src/client/gameplay-hud.test.tsx +165 -2
- package/src/client/gameplay-hud.tsx +62 -6
- package/src/client/index.ts +23 -13
- package/src/client/pet.module.css +1 -1
- package/src/client/renderers/Frames2dVisualMount.test.tsx +73 -0
- package/src/client/renderers/Frames2dVisualMount.tsx +4 -0
- package/src/client/renderers/frames2d.test.ts +129 -7
- package/src/client/renderers/frames2d.ts +94 -36
- package/src/client/work-tick-gate.test.ts +53 -0
- package/src/client/work-tick-gate.ts +63 -0
- package/src/event-projection.ts +37 -18
- package/src/gameplay.test.ts +36 -0
- package/src/gameplay.ts +14 -2
- package/src/ledger.test.ts +19 -0
- package/src/ledger.ts +24 -0
- package/src/persist.test.ts +13 -0
- package/src/persist.ts +29 -1
- package/src/routes.ts +5 -0
- package/src/service.ts +49 -0
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
* Frame presentation has two modes picked once at mount by capability
|
|
13
13
|
* probing:
|
|
14
14
|
* - Canvas bitmap buffer (default where createImageBitmap/fetch/2D context
|
|
15
|
-
* exist):
|
|
16
|
-
* the
|
|
17
|
-
* zero DOM mutations and zero
|
|
18
|
-
* <img>.src per frame drove image
|
|
15
|
+
* exist): frames are decoded once into an ImageBitmap on demand, with a
|
|
16
|
+
* bounded look-ahead window over the playing track, and drawn onto one
|
|
17
|
+
* <canvas> - steady-state playback issues zero DOM mutations and zero
|
|
18
|
+
* re-decodes (measured hotspot: swapping <img>.src per frame drove image
|
|
19
|
+
* decode + invalidation every tick).
|
|
19
20
|
* - Classic <img> fallback (jsdom/tests or missing APIs): identical to the
|
|
20
21
|
* historical behavior - cache-warm Image elements plus guarded src swaps,
|
|
21
22
|
* so environments without modern decoding keep working unchanged.
|
|
@@ -159,39 +160,98 @@ export const frames2dRenderer = {
|
|
|
159
160
|
// the last painted frame instead of breaking playback).
|
|
160
161
|
const decoding = new Map();
|
|
161
162
|
const decodedAll = [];
|
|
162
|
-
|
|
163
|
+
// All frame fetches funnel through a small pool. Full-library warm passes
|
|
164
|
+
// on large pets fire 1100+ requests at once, which trips the browser's
|
|
165
|
+
// in-flight request limit (net::ERR_INSUFFICIENT_RESOURCES) and fails
|
|
166
|
+
// whole batches of frames while starving the rest of the page. Playback
|
|
167
|
+
// demand jumps ahead of the warm backlog.
|
|
168
|
+
const FRAME_POOL_LIMIT = 8;
|
|
169
|
+
const frameQueue = [];
|
|
170
|
+
let activeFrames = 0;
|
|
171
|
+
const decodeFrame = async (url) => {
|
|
172
|
+
try {
|
|
173
|
+
const response = await fetch(url);
|
|
174
|
+
if (!response.ok)
|
|
175
|
+
throw new Error('http ' + response.status);
|
|
176
|
+
const bitmap = await createImageBitmap(await response.blob());
|
|
177
|
+
return { source: bitmap, width: bitmap.width, height: bitmap.height };
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Fail-open: classic Image decode keeps non-modern runtimes alive.
|
|
181
|
+
return await new Promise((resolve) => {
|
|
182
|
+
try {
|
|
183
|
+
const pre = new Image();
|
|
184
|
+
pre.onload = () => {
|
|
185
|
+
resolve(pre.naturalWidth > 0 ? { source: pre, width: pre.naturalWidth, height: pre.naturalHeight } : undefined);
|
|
186
|
+
};
|
|
187
|
+
pre.onerror = () => resolve(undefined);
|
|
188
|
+
pre.src = url;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
resolve(undefined);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
const pumpFrames = () => {
|
|
197
|
+
while (activeFrames < FRAME_POOL_LIMIT && frameQueue.length > 0) {
|
|
198
|
+
const queued = frameQueue.shift();
|
|
199
|
+
activeFrames += 1;
|
|
200
|
+
queued.release();
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const loadFrame = (url, jump = false) => {
|
|
204
|
+
// Jump first: warm-enqueued frames already carry their memo, so a
|
|
205
|
+
// playback demand must reorder the unstarted entry before the cache
|
|
206
|
+
// lookup short-circuits.
|
|
207
|
+
if (jump) {
|
|
208
|
+
const index = frameQueue.findIndex((queued) => queued.url === url);
|
|
209
|
+
if (index > 0)
|
|
210
|
+
frameQueue.unshift(frameQueue.splice(index, 1)[0]);
|
|
211
|
+
}
|
|
163
212
|
const cached = decoding.get(url);
|
|
164
213
|
if (cached !== undefined)
|
|
165
214
|
return cached;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// Fail-open: classic Image decode keeps non-modern runtimes alive.
|
|
176
|
-
return await new Promise((resolve) => {
|
|
177
|
-
try {
|
|
178
|
-
const pre = new Image();
|
|
179
|
-
pre.onload = () => {
|
|
180
|
-
resolve(pre.naturalWidth > 0 ? { source: pre, width: pre.naturalWidth, height: pre.naturalHeight } : undefined);
|
|
181
|
-
};
|
|
182
|
-
pre.onerror = () => resolve(undefined);
|
|
183
|
-
pre.src = url;
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
resolve(undefined);
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
})();
|
|
215
|
+
let release;
|
|
216
|
+
const gate = new Promise((resolve) => { release = resolve; });
|
|
217
|
+
const job = gate.then(() => (disposed ? undefined : decodeFrame(url)));
|
|
218
|
+
job.then((frame) => { if (frame === undefined)
|
|
219
|
+
decoding.delete(url); }, () => decoding.delete(url));
|
|
220
|
+
void job.finally(() => {
|
|
221
|
+
activeFrames -= 1;
|
|
222
|
+
pumpFrames();
|
|
223
|
+
});
|
|
191
224
|
decoding.set(url, job);
|
|
192
225
|
decodedAll.push(job.then(() => undefined, () => undefined));
|
|
226
|
+
const entry = { url, release };
|
|
227
|
+
if (jump)
|
|
228
|
+
frameQueue.unshift(entry);
|
|
229
|
+
else
|
|
230
|
+
frameQueue.push(entry);
|
|
231
|
+
pumpFrames();
|
|
193
232
|
return job;
|
|
194
233
|
};
|
|
234
|
+
/**
|
|
235
|
+
* Bounded look-ahead window: decode only the frames playback is about to
|
|
236
|
+
* need. The historical warm pass decoded every frame of every track up
|
|
237
|
+
* front - a shipped pet carries ~1.1k 512x683 frames, so that pass pulls
|
|
238
|
+
* tens of megabytes and retains every decoded bitmap for the life of the
|
|
239
|
+
* page. Prefetching the playing track's next frames keeps loops and phase
|
|
240
|
+
* switches warm while unplayed tracks (and every unselected skin's
|
|
241
|
+
* frames) stay on demand, where playback jumps the queue anyway.
|
|
242
|
+
*/
|
|
243
|
+
const PREFETCH_AHEAD = 12;
|
|
244
|
+
const prefetchAhead = (trackId, index) => {
|
|
245
|
+
const def = config.tracks[trackId];
|
|
246
|
+
if (def === undefined)
|
|
247
|
+
return;
|
|
248
|
+
const end = Math.min(def.frames.length, index + 1 + PREFETCH_AHEAD);
|
|
249
|
+
for (let ahead = index + 1; ahead < end; ahead += 1) {
|
|
250
|
+
const url = def.frames[ahead];
|
|
251
|
+
if (url !== undefined)
|
|
252
|
+
void loadFrame(url);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
195
255
|
let disposed = false;
|
|
196
256
|
let timer;
|
|
197
257
|
let watchdog;
|
|
@@ -217,7 +277,7 @@ export const frames2dRenderer = {
|
|
|
217
277
|
if (context2d === null || canvas === null)
|
|
218
278
|
return;
|
|
219
279
|
const myToken = ++drawToken;
|
|
220
|
-
void loadFrame(url).then((frame) => {
|
|
280
|
+
void loadFrame(url, true).then((frame) => {
|
|
221
281
|
if (disposed || frame === undefined || myToken !== drawToken)
|
|
222
282
|
return;
|
|
223
283
|
if (lastDrawnUrl === url)
|
|
@@ -239,6 +299,7 @@ export const frames2dRenderer = {
|
|
|
239
299
|
const url = def?.frames[index];
|
|
240
300
|
if (url === undefined)
|
|
241
301
|
return;
|
|
302
|
+
prefetchAhead(trackId, index);
|
|
242
303
|
if (img !== null) {
|
|
243
304
|
if (img.getAttribute('src') !== url)
|
|
244
305
|
img.src = url;
|
|
@@ -320,13 +381,6 @@ export const frames2dRenderer = {
|
|
|
320
381
|
tick();
|
|
321
382
|
}, WATCHDOG_MS);
|
|
322
383
|
}
|
|
323
|
-
// Warm pass: decode every frame up front (tiny same-origin webp files)
|
|
324
|
-
// so loops and phase switches never wait on a first decode - same intent
|
|
325
|
-
// as the historical Image-cache warm loop, now feeding the decode cache.
|
|
326
|
-
for (const warmTrack of Object.values(config.tracks)) {
|
|
327
|
-
for (const warmUrl of warmTrack.frames)
|
|
328
|
-
void loadFrame(warmUrl);
|
|
329
|
-
}
|
|
330
384
|
play(track);
|
|
331
385
|
let disposedOnce = false;
|
|
332
386
|
const dispose = () => {
|
|
@@ -340,7 +394,10 @@ export const frames2dRenderer = {
|
|
|
340
394
|
if (watchdog !== undefined)
|
|
341
395
|
clearInterval(watchdog);
|
|
342
396
|
// Release decoded bitmaps after pending decodes settle; close() is
|
|
343
|
-
// browser-only, so guard it for exotic hosts.
|
|
397
|
+
// browser-only, so guard it for exotic hosts. Queued-but-unstarted
|
|
398
|
+
// frames release immediately as no-ops so the settle barrier drains.
|
|
399
|
+
for (const queued of frameQueue.splice(0))
|
|
400
|
+
queued.release();
|
|
344
401
|
void Promise.allSettled(decodedAll).then(() => {
|
|
345
402
|
for (const job of decoding.values()) {
|
|
346
403
|
void job.then((frame) => {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page-wide work-tick gate for the pet's work mode. Hot reloads can leave
|
|
3
|
+
* several GameplayHud instances alive, each running its own work interval;
|
|
4
|
+
* without a shared gate every interval would call workTick and each stale call
|
|
5
|
+
* re-rolls, re-grants treats and re-plays the success/fail track, so the
|
|
6
|
+
* outcome appears to play several times per window. The gate accepts the first
|
|
7
|
+
* adjudication of a window and silently suppresses the duplicates that follow.
|
|
8
|
+
*
|
|
9
|
+
* The window is the active pet's own `gameplay.work.tickMs`, not a constant: a
|
|
10
|
+
* pet configured with a shorter cadence must actually adjudicate that often,
|
|
11
|
+
* while a fixed window would downgrade it without saying so (#1494).
|
|
12
|
+
* @module @linxin666/dsh-pet/client/work-tick-gate
|
|
13
|
+
*/
|
|
14
|
+
/** Window used when the active pet declares no work cadence. */
|
|
15
|
+
export declare const DEFAULT_WORK_TICK_MS = 10000;
|
|
16
|
+
/**
|
|
17
|
+
* The gate window for one pet: its configured cadence, clamped to the manifest's
|
|
18
|
+
* own bounds so a malformed registry entry cannot disable or flood the gate.
|
|
19
|
+
* @param tickMs - the active definition's `gameplay.work.tickMs`, when it has one.
|
|
20
|
+
* @returns the window in milliseconds.
|
|
21
|
+
*/
|
|
22
|
+
export declare function workTickWindowMs(tickMs: number | undefined): number;
|
|
23
|
+
/** The shared work-tick gate. */
|
|
24
|
+
export interface WorkTickGate {
|
|
25
|
+
/**
|
|
26
|
+
* Admit one adjudication for the current window.
|
|
27
|
+
* @param tickMs - the active pet's configured work cadence.
|
|
28
|
+
* @returns true when this call may adjudicate, false for a duplicate.
|
|
29
|
+
*/
|
|
30
|
+
allow: (tickMs: number | undefined) => boolean;
|
|
31
|
+
/** Forget the last adjudication (used when work mode is entered). */
|
|
32
|
+
reset: () => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Create a gate.
|
|
36
|
+
* @param now - the clock, injectable so tests control the window.
|
|
37
|
+
* @returns the gate over that clock.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createWorkTickGate(now?: () => number): WorkTickGate;
|
|
40
|
+
//# sourceMappingURL=work-tick-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"work-tick-gate.d.ts","sourceRoot":"","sources":["../../../src/client/work-tick-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,QAAS,CAAA;AAM1C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGnE;AAED,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAA;IAC9C,qEAAqE;IACrE,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,MAAiB,GAAG,YAAY,CAa7E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page-wide work-tick gate for the pet's work mode. Hot reloads can leave
|
|
3
|
+
* several GameplayHud instances alive, each running its own work interval;
|
|
4
|
+
* without a shared gate every interval would call workTick and each stale call
|
|
5
|
+
* re-rolls, re-grants treats and re-plays the success/fail track, so the
|
|
6
|
+
* outcome appears to play several times per window. The gate accepts the first
|
|
7
|
+
* adjudication of a window and silently suppresses the duplicates that follow.
|
|
8
|
+
*
|
|
9
|
+
* The window is the active pet's own `gameplay.work.tickMs`, not a constant: a
|
|
10
|
+
* pet configured with a shorter cadence must actually adjudicate that often,
|
|
11
|
+
* while a fixed window would downgrade it without saying so (#1494).
|
|
12
|
+
* @module @linxin666/dsh-pet/client/work-tick-gate
|
|
13
|
+
*/
|
|
14
|
+
/** Window used when the active pet declares no work cadence. */
|
|
15
|
+
export const DEFAULT_WORK_TICK_MS = 10_000;
|
|
16
|
+
/** Manifest bounds for `gameplay.work.tickMs` (src/gameplay.ts). */
|
|
17
|
+
const MIN_WORK_TICK_MS = 1_000;
|
|
18
|
+
const MAX_WORK_TICK_MS = 60_000;
|
|
19
|
+
/**
|
|
20
|
+
* The gate window for one pet: its configured cadence, clamped to the manifest's
|
|
21
|
+
* own bounds so a malformed registry entry cannot disable or flood the gate.
|
|
22
|
+
* @param tickMs - the active definition's `gameplay.work.tickMs`, when it has one.
|
|
23
|
+
* @returns the window in milliseconds.
|
|
24
|
+
*/
|
|
25
|
+
export function workTickWindowMs(tickMs) {
|
|
26
|
+
if (typeof tickMs !== 'number' || !Number.isFinite(tickMs))
|
|
27
|
+
return DEFAULT_WORK_TICK_MS;
|
|
28
|
+
return Math.min(MAX_WORK_TICK_MS, Math.max(MIN_WORK_TICK_MS, tickMs));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a gate.
|
|
32
|
+
* @param now - the clock, injectable so tests control the window.
|
|
33
|
+
* @returns the gate over that clock.
|
|
34
|
+
*/
|
|
35
|
+
export function createWorkTickGate(now = Date.now) {
|
|
36
|
+
let lastAdjudicatedAt = 0;
|
|
37
|
+
return {
|
|
38
|
+
allow: (tickMs) => {
|
|
39
|
+
const at = now();
|
|
40
|
+
if (at - lastAdjudicatedAt < workTickWindowMs(tickMs))
|
|
41
|
+
return false;
|
|
42
|
+
lastAdjudicatedAt = at;
|
|
43
|
+
return true;
|
|
44
|
+
},
|
|
45
|
+
reset: () => {
|
|
46
|
+
lastAdjudicatedAt = 0;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -11,8 +11,15 @@
|
|
|
11
11
|
* tool/result and turn/end — so the pet's inner voice always roughly knows
|
|
12
12
|
* what is going on and never mis-fires on output text. The wall clock is
|
|
13
13
|
* injected by the caller, keeping every projection reproducible.
|
|
14
|
+
*
|
|
15
|
+
* Since the 0.1.5-alpha.2 cohort the stream itself is no longer durable
|
|
16
|
+
* vocabulary: per-chunk phase input arrives through the process-local
|
|
17
|
+
* `agent/assistant-stream` publication ({@link projectAssistantStreamFrame}),
|
|
18
|
+
* while the durable log settles one `assistant/message` (or `assistant/attempt`)
|
|
19
|
+
* per attempt.
|
|
14
20
|
* @module @linxin666/dsh-pet/event-projection
|
|
15
21
|
*/
|
|
22
|
+
import type { AssistantStreamFrame } from '@deepseek-ai/dsh-agent';
|
|
16
23
|
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
17
24
|
import type { PetStateInput } from './state.ts';
|
|
18
25
|
import { StatusVoice, WhisperEngine, type VoicePoolsProvider } from './chatter.ts';
|
|
@@ -56,4 +63,11 @@ export declare function isActivityPhase(phase: string): phase is PetStateInput['
|
|
|
56
63
|
* @param nowMs - injected wall clock for copy rotation and whisper pacing.
|
|
57
64
|
*/
|
|
58
65
|
export declare function projectOfficialEvent(event: SessionEvent, runtime: ProjectionRuntime, nowMs?: number): PetActivityTransition | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Project one live `agent/assistant-stream` publication into the pet's visual
|
|
68
|
+
* phases. Chunk frames are the alpha.2 replacement for the retired durable
|
|
69
|
+
* `assistant/chunk` event: a reasoning delta keeps the pet thinking, a text
|
|
70
|
+
* delta moves it to review; start, end, and non-delta chunks change nothing.
|
|
71
|
+
*/
|
|
72
|
+
export declare function projectAssistantStreamFrame(frame: AssistantStreamFrame, runtime: ProjectionRuntime, nowMs?: number): PetActivityTransition | undefined;
|
|
59
73
|
//# sourceMappingURL=event-projection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-projection.d.ts","sourceRoot":"","sources":["../../src/event-projection.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"event-projection.d.ts","sourceRoot":"","sources":["../../src/event-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EACL,WAAW,EAGX,aAAa,EAGb,KAAK,kBAAkB,EACxB,MAAM,cAAc,CAAA;AAErB,2DAA2D;AAC3D,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,+EAA+E;IAC/E,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACtB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;IACvB,qEAAqE;IACrE,KAAK,EAAE,WAAW,CAAA;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CASpF;AAQD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,iBAAiB,EAC1B,KAAK,GAAE,MAAmB,GACzB,qBAAqB,GAAG,SAAS,CAiGnC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,EAAE,iBAAiB,EAC1B,KAAK,GAAE,MAAmB,GACzB,qBAAqB,GAAG,SAAS,CAkBnC"}
|
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
* tool/result and turn/end — so the pet's inner voice always roughly knows
|
|
12
12
|
* what is going on and never mis-fires on output text. The wall clock is
|
|
13
13
|
* injected by the caller, keeping every projection reproducible.
|
|
14
|
+
*
|
|
15
|
+
* Since the 0.1.5-alpha.2 cohort the stream itself is no longer durable
|
|
16
|
+
* vocabulary: per-chunk phase input arrives through the process-local
|
|
17
|
+
* `agent/assistant-stream` publication ({@link projectAssistantStreamFrame}),
|
|
18
|
+
* while the durable log settles one `assistant/message` (or `assistant/attempt`)
|
|
19
|
+
* per attempt.
|
|
14
20
|
* @module @linxin666/dsh-pet/event-projection
|
|
15
21
|
*/
|
|
16
22
|
import { StatusVoice, toolArgHint, toolCategory, WhisperEngine, whisperCategoryOf, looksLikeTestTool, } from "./chatter.js";
|
|
@@ -55,24 +61,6 @@ export function projectOfficialEvent(event, runtime, nowMs = Date.now()) {
|
|
|
55
61
|
runtime.activeTools.clear();
|
|
56
62
|
runtime.stepHadFailure = false;
|
|
57
63
|
return { input: { phase: 'waiting', line: runtime.voice.scene('waiting', nowMs) } };
|
|
58
|
-
case 'assistant/chunk': {
|
|
59
|
-
const { chunk } = event.data;
|
|
60
|
-
if (chunk.type === 'reasoning-delta' && chunk.text.length > 0) {
|
|
61
|
-
const whisper = runtime.whispers.feed('thinking', nowMs);
|
|
62
|
-
return {
|
|
63
|
-
input: { phase: 'thinking', line: runtime.voice.scene('thinking', nowMs) },
|
|
64
|
-
...(whisper === undefined ? {} : { whisper }),
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (chunk.type === 'text-delta' && chunk.text.length > 0) {
|
|
68
|
-
const whisper = runtime.whispers.feed('writing', nowMs);
|
|
69
|
-
return {
|
|
70
|
-
input: { phase: 'review', line: runtime.voice.scene('review', nowMs) },
|
|
71
|
-
...(whisper === undefined ? {} : { whisper }),
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
64
|
case 'assistant/message':
|
|
77
65
|
return { input: { phase: 'review', line: runtime.voice.scene('review', nowMs) } };
|
|
78
66
|
case 'tool/call': {
|
|
@@ -156,3 +144,29 @@ export function projectOfficialEvent(event, runtime, nowMs = Date.now()) {
|
|
|
156
144
|
return undefined;
|
|
157
145
|
}
|
|
158
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Project one live `agent/assistant-stream` publication into the pet's visual
|
|
149
|
+
* phases. Chunk frames are the alpha.2 replacement for the retired durable
|
|
150
|
+
* `assistant/chunk` event: a reasoning delta keeps the pet thinking, a text
|
|
151
|
+
* delta moves it to review; start, end, and non-delta chunks change nothing.
|
|
152
|
+
*/
|
|
153
|
+
export function projectAssistantStreamFrame(frame, runtime, nowMs = Date.now()) {
|
|
154
|
+
if (frame.type !== 'chunk')
|
|
155
|
+
return undefined;
|
|
156
|
+
const { chunk } = frame;
|
|
157
|
+
if (chunk.type === 'reasoning-delta' && chunk.text.length > 0) {
|
|
158
|
+
const whisper = runtime.whispers.feed('thinking', nowMs);
|
|
159
|
+
return {
|
|
160
|
+
input: { phase: 'thinking', line: runtime.voice.scene('thinking', nowMs) },
|
|
161
|
+
...(whisper === undefined ? {} : { whisper }),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (chunk.type === 'text-delta' && chunk.text.length > 0) {
|
|
165
|
+
const whisper = runtime.whispers.feed('writing', nowMs);
|
|
166
|
+
return {
|
|
167
|
+
input: { phase: 'review', line: runtime.voice.scene('review', nowMs) },
|
|
168
|
+
...(whisper === undefined ? {} : { whisper }),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
package/lib/types/gameplay.d.ts
CHANGED
|
@@ -150,6 +150,10 @@ export interface PetGameplayState {
|
|
|
150
150
|
mode: 'work' | 'sleep' | null;
|
|
151
151
|
/** Epoch ms of the last lazy settle. */
|
|
152
152
|
settledAt: number;
|
|
153
|
+
/** Accumulated remainder ms towards the next passive income tick. */
|
|
154
|
+
incomeCarryMs?: number;
|
|
155
|
+
/** Accumulated remainder ms towards the next sleep restore tick. */
|
|
156
|
+
restoreCarryMs?: number;
|
|
153
157
|
}
|
|
154
158
|
/** Fresh state for one pet: stats at their initial (default max), no currency. */
|
|
155
159
|
export declare function initialGameplayState(manifest: PetGameplayManifest, now: number): PetGameplayState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gameplay.d.ts","sourceRoot":"","sources":["../../src/gameplay.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"gameplay.d.ts","sourceRoot":"","sources":["../../src/gameplay.ts"],"names":[],"mappings":"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"}
|
package/lib/types/gameplay.js
CHANGED
|
@@ -555,7 +555,10 @@ export function settleGameplay(state, manifest, now, options) {
|
|
|
555
555
|
}
|
|
556
556
|
}
|
|
557
557
|
if (manifest.passiveIncome !== undefined) {
|
|
558
|
-
const
|
|
558
|
+
const incomeElapsed = elapsedMs + (state.incomeCarryMs ?? 0);
|
|
559
|
+
const interval = manifest.passiveIncome.intervalMs;
|
|
560
|
+
const ticks = Math.floor(incomeElapsed / interval);
|
|
561
|
+
state.incomeCarryMs = incomeElapsed % interval;
|
|
559
562
|
if (ticks > 0) {
|
|
560
563
|
const currency = manifest.passiveIncome.currency;
|
|
561
564
|
state.currencies[currency] = (state.currencies[currency] ?? 0) + ticks * manifest.passiveIncome.amount;
|
|
@@ -563,13 +566,19 @@ export function settleGameplay(state, manifest, now, options) {
|
|
|
563
566
|
}
|
|
564
567
|
}
|
|
565
568
|
if (state.mode === 'sleep' && manifest.sleep !== undefined) {
|
|
566
|
-
const
|
|
569
|
+
const restoreElapsed = elapsedMs + (state.restoreCarryMs ?? 0);
|
|
570
|
+
const interval = manifest.sleep.restore.intervalMs;
|
|
571
|
+
const ticks = Math.floor(restoreElapsed / interval);
|
|
572
|
+
state.restoreCarryMs = restoreElapsed % interval;
|
|
567
573
|
if (ticks > 0) {
|
|
568
574
|
const stat = manifest.sleep.restore.stat;
|
|
569
575
|
state.stats[stat] = (state.stats[stat] ?? 0) + ticks * manifest.sleep.restore.amount;
|
|
570
576
|
changed = true;
|
|
571
577
|
}
|
|
572
578
|
}
|
|
579
|
+
else {
|
|
580
|
+
state.restoreCarryMs = 0;
|
|
581
|
+
}
|
|
573
582
|
state.settledAt = now;
|
|
574
583
|
clampGameplay(state, manifest);
|
|
575
584
|
return changed;
|
package/lib/types/ledger.d.ts
CHANGED
|
@@ -66,6 +66,14 @@ export declare class PetLedger {
|
|
|
66
66
|
setGameplay(petId: string, gameplay: PetGameplayState): void;
|
|
67
67
|
/** Replace one pet's display name (validation stays a caller concern). */
|
|
68
68
|
setPetName(petId: string, name: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* Select one pet's frames2d skin; `undefined` clears the choice back to the
|
|
71
|
+
* pet's default look. Manifest validation stays a caller concern, exactly
|
|
72
|
+
* like setPetName's length check.
|
|
73
|
+
*/
|
|
74
|
+
setPetSkin(petId: string, skinId: string | undefined): void;
|
|
75
|
+
/** The persisted skin id for one pet (undefined = the pet's default look). */
|
|
76
|
+
petSkin(petId: string): string | undefined;
|
|
69
77
|
/**
|
|
70
78
|
* Swap the reaction pools to another pet's custom remarks (called on pet
|
|
71
79
|
* selection). Slots the pet does not declare fall back to voice packs or built-ins.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7B,mFAAmF;IACnF,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,UAAU,CAAA;CAC1B;AAED,wEAAwE;AACxE,MAAM,WAAW,uBAAuB;IACtC,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,6DAA6D;IAC7D,QAAQ,EAAE,eAAe,CAAA;CAC1B;AAED;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAY;IAC3B,oFAAoF;IACpF,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,sBAAsB,CAAI;IAClC,OAAO,CAAC,KAAK,CAAQ;gBAET,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,YAAiB;IAO1D,iDAAiD;IACjD,IAAI,QAAQ,IAAI,cAAc,CAE7B;IAED,qEAAqE;IACrE,IAAI,QAAQ,IAAI,UAAU,CAEzB;IAED,qCAAqC;IACrC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,+DAA+D;IAC/D,SAAS,IAAI,OAAO;IAMpB;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAItC,mEAAmE;IACnE,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAK3C,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,qFAAqF;IACrF,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAK5D,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK7C;;;OAGG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,UAAU,GAAG,IAAI;IAIjE;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAapC;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IASpC,8EAA8E;IAC9E,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE;IAQ5C;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IASnE,8EAA8E;IAC9E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IASxC,OAAO,CAAC,eAAe;IASvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB;IAwCtE,kDAAkD;IAClD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe;CAG7C"}
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/ledger.ts"],"names":[],"mappings":"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"}
|
package/lib/types/ledger.js
CHANGED
|
@@ -77,6 +77,31 @@ export class PetLedger {
|
|
|
77
77
|
this.current = { ...this.current, names: { ...this.current.names, [petId]: name } };
|
|
78
78
|
this.dirty = true;
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Select one pet's frames2d skin; `undefined` clears the choice back to the
|
|
82
|
+
* pet's default look. Manifest validation stays a caller concern, exactly
|
|
83
|
+
* like setPetName's length check.
|
|
84
|
+
*/
|
|
85
|
+
setPetSkin(petId, skinId) {
|
|
86
|
+
const skins = this.current.skins;
|
|
87
|
+
if (skinId === undefined) {
|
|
88
|
+
if (skins[petId] === undefined)
|
|
89
|
+
return;
|
|
90
|
+
const next = { ...skins };
|
|
91
|
+
delete next[petId];
|
|
92
|
+
this.current = { ...this.current, skins: next };
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (skins[petId] === skinId)
|
|
96
|
+
return;
|
|
97
|
+
this.current = { ...this.current, skins: { ...skins, [petId]: skinId } };
|
|
98
|
+
}
|
|
99
|
+
this.dirty = true;
|
|
100
|
+
}
|
|
101
|
+
/** The persisted skin id for one pet (undefined = the pet's default look). */
|
|
102
|
+
petSkin(petId) {
|
|
103
|
+
return this.current.skins[petId];
|
|
104
|
+
}
|
|
80
105
|
/**
|
|
81
106
|
* Swap the reaction pools to another pet's custom remarks (called on pet
|
|
82
107
|
* selection). Slots the pet does not declare fall back to voice packs or built-ins.
|
package/lib/types/persist.d.ts
CHANGED
|
@@ -33,6 +33,12 @@ export interface PetPersist {
|
|
|
33
33
|
* to its manifest displayName, so only user renames are stored here.
|
|
34
34
|
*/
|
|
35
35
|
names: Record<string, string>;
|
|
36
|
+
/**
|
|
37
|
+
* Per-pet selected frames2d skin id (keyed by pet id). Skin ids are manifest
|
|
38
|
+
* data, so a stale entry (skin renamed or removed, pet swapped) is ignored
|
|
39
|
+
* when the state view is built instead of pinning an unresolvable track.
|
|
40
|
+
*/
|
|
41
|
+
skins: Record<string, string>;
|
|
36
42
|
affinity: AffinityState;
|
|
37
43
|
/** Treat (小鱼干) stock ledger. */
|
|
38
44
|
treats: TreatLedger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAKlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../src/persist.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAC/E,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAEhE,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,oBAAoB,EAAE,gBAKlC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,gBAAgB,OAAO,CAAA;AACpC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,gCAAgC;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,EAAE,gBAAgB,CAAA;IACzB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;CAC3C;AAED,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CAUzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAmFD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAqDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
|
package/lib/types/persist.js
CHANGED
|
@@ -27,6 +27,7 @@ export function emptyPersist() {
|
|
|
27
27
|
return {
|
|
28
28
|
petId: DEFAULT_PET_ID,
|
|
29
29
|
names: {},
|
|
30
|
+
skins: {},
|
|
30
31
|
affinity: emptyAffinity(),
|
|
31
32
|
treats: emptyTreatLedger(),
|
|
32
33
|
display: { ...defaultDisplayConfig },
|
|
@@ -60,6 +61,21 @@ function loadPetNames(parsed) {
|
|
|
60
61
|
}
|
|
61
62
|
return names;
|
|
62
63
|
}
|
|
64
|
+
/** Sanitize the per-pet skin selection map (string keys, non-empty trimmed values). */
|
|
65
|
+
function loadPetSkins(parsed) {
|
|
66
|
+
const skins = {};
|
|
67
|
+
if (typeof parsed.skins !== 'object' || parsed.skins === null)
|
|
68
|
+
return skins;
|
|
69
|
+
for (const [id, value] of Object.entries(parsed.skins)) {
|
|
70
|
+
if (id === '' || typeof value !== 'string')
|
|
71
|
+
continue;
|
|
72
|
+
const skin = value.trim();
|
|
73
|
+
if (skin === '')
|
|
74
|
+
continue;
|
|
75
|
+
skins[id] = skin;
|
|
76
|
+
}
|
|
77
|
+
return skins;
|
|
78
|
+
}
|
|
63
79
|
/** Clamp one count/score into [0, max]. */
|
|
64
80
|
function clamp(value, max) {
|
|
65
81
|
return Math.min(max, Math.max(0, value));
|
|
@@ -92,12 +108,19 @@ function loadGameplay(parsed) {
|
|
|
92
108
|
currencies[key] = Math.min(GAMEPLAY_LOAD_CURRENCY_CAP, Math.max(0, Math.floor(value)));
|
|
93
109
|
}
|
|
94
110
|
}
|
|
95
|
-
|
|
111
|
+
const item = {
|
|
96
112
|
stats,
|
|
97
113
|
currencies,
|
|
98
114
|
mode: record.mode === 'work' || record.mode === 'sleep' ? record.mode : null,
|
|
99
115
|
settledAt: clamp(finiteNum(record.settledAt, 0), Number.MAX_SAFE_INTEGER),
|
|
100
116
|
};
|
|
117
|
+
if (typeof record.incomeCarryMs === 'number' && Number.isFinite(record.incomeCarryMs)) {
|
|
118
|
+
item.incomeCarryMs = Math.max(0, record.incomeCarryMs);
|
|
119
|
+
}
|
|
120
|
+
if (typeof record.restoreCarryMs === 'number' && Number.isFinite(record.restoreCarryMs)) {
|
|
121
|
+
item.restoreCarryMs = Math.max(0, record.restoreCarryMs);
|
|
122
|
+
}
|
|
123
|
+
result[petId] = item;
|
|
101
124
|
}
|
|
102
125
|
return result;
|
|
103
126
|
}
|
|
@@ -146,6 +169,7 @@ export function loadPetPersist(dir = petHomeDir()) {
|
|
|
146
169
|
return {
|
|
147
170
|
petId,
|
|
148
171
|
names,
|
|
172
|
+
skins: loadPetSkins(parsed),
|
|
149
173
|
affinity,
|
|
150
174
|
treats,
|
|
151
175
|
display,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAO9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB;;IAEzB,iDAAiD;;IAEjD,8EAA8E;;CAEtE,CAAA;AAEV,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcrF;AAqPD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA8B,CAAA;AAe7D,4EAA4E;AAC5E,eAAO,MAAM,eAAe,QAAmB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4MD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,GAAG,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAO9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB;;IAEzB,iDAAiD;;IAEjD,8EAA8E;;CAEtE,CAAA;AAEV,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAcrF;AAqPD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA8B,CAAA;AAe7D,4EAA4E;AAC5E,eAAO,MAAM,eAAe,QAAmB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4MD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,GAAG,QAAQ,EAAE,CAqFjI;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
|
package/lib/types/routes.js
CHANGED
|
@@ -586,6 +586,12 @@ export function makePetRoutes(deps) {
|
|
|
586
586
|
return Promise.reject(new Error('invalid-name'));
|
|
587
587
|
return service.setName(name);
|
|
588
588
|
}),
|
|
589
|
+
postRoute(ctx, PET_API_PREFIX + '/set-skin', (body) => {
|
|
590
|
+
const skin = body.skin;
|
|
591
|
+
if (skin !== undefined && typeof skin !== 'string')
|
|
592
|
+
return Promise.reject(new Error('invalid-skin'));
|
|
593
|
+
return service.setSkin(skin === undefined || skin === '' ? undefined : skin);
|
|
594
|
+
}),
|
|
589
595
|
postRoute(ctx, PET_API_PREFIX + '/set-pet', (body) => {
|
|
590
596
|
const petId = body.petId;
|
|
591
597
|
if (typeof petId !== 'string')
|