@linxin666/dsh-pet 0.1.20 → 0.2.0

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.
Files changed (65) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +17 -10
  3. package/README.zh.md +17 -10
  4. package/assets/whale/pet.json +9 -0
  5. package/lib/client.js +158 -26
  6. package/lib/client.js.map +1 -1
  7. package/lib/index.js +853 -41
  8. package/lib/invariant.js +1 -1
  9. package/lib/{state-Diiq8vjk.js → state-Ch3f4luZ.js} +51 -23
  10. package/lib/types/affinity.d.ts +4 -0
  11. package/lib/types/affinity.d.ts.map +1 -1
  12. package/lib/types/affinity.js +32 -6
  13. package/lib/types/chatter.d.ts +111 -0
  14. package/lib/types/chatter.d.ts.map +1 -0
  15. package/lib/types/chatter.js +666 -0
  16. package/lib/types/client/PetSprite.d.ts.map +1 -1
  17. package/lib/types/client/PetSprite.js +88 -14
  18. package/lib/types/client/PluginSettingsCard.d.ts +6 -0
  19. package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
  20. package/lib/types/client/PluginSettingsCard.js +5 -3
  21. package/lib/types/client/sequences.d.ts +10 -0
  22. package/lib/types/client/sequences.d.ts.map +1 -0
  23. package/lib/types/client/sequences.js +20 -0
  24. package/lib/types/event-projection.d.ts +14 -1
  25. package/lib/types/event-projection.d.ts.map +1 -1
  26. package/lib/types/event-projection.js +38 -17
  27. package/lib/types/ledger.d.ts.map +1 -1
  28. package/lib/types/ledger.js +15 -7
  29. package/lib/types/persist.d.ts.map +1 -1
  30. package/lib/types/persist.js +3 -1
  31. package/lib/types/registry.d.ts +7 -1
  32. package/lib/types/registry.d.ts.map +1 -1
  33. package/lib/types/registry.js +36 -0
  34. package/lib/types/remarks.d.ts +2 -0
  35. package/lib/types/remarks.d.ts.map +1 -1
  36. package/lib/types/remarks.js +5 -0
  37. package/lib/types/service.d.ts +6 -0
  38. package/lib/types/service.d.ts.map +1 -1
  39. package/lib/types/service.js +15 -2
  40. package/lib/types/state.d.ts +7 -4
  41. package/lib/types/state.d.ts.map +1 -1
  42. package/lib/types/state.js +20 -20
  43. package/package.json +9 -9
  44. package/src/affinity.test.ts +4 -2
  45. package/src/affinity.ts +37 -6
  46. package/src/chatter.test.ts +154 -0
  47. package/src/chatter.ts +697 -0
  48. package/src/client/PetSprite.test.tsx +190 -1
  49. package/src/client/PetSprite.tsx +112 -25
  50. package/src/client/PluginSettingsCard.tsx +10 -0
  51. package/src/client/pet-css.test.ts +42 -0
  52. package/src/client/pet.module.css +154 -26
  53. package/src/client/sequences.test.ts +33 -0
  54. package/src/client/sequences.ts +33 -0
  55. package/src/event-projection.ts +49 -16
  56. package/src/ledger.test.ts +42 -1
  57. package/src/ledger.ts +15 -7
  58. package/src/persist.test.ts +18 -1
  59. package/src/persist.ts +3 -1
  60. package/src/registry.test.ts +50 -3
  61. package/src/registry.ts +47 -3
  62. package/src/remarks.ts +6 -0
  63. package/src/service.ts +27 -2
  64. package/src/state.test.ts +13 -0
  65. package/src/state.ts +24 -18
@@ -9,10 +9,12 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
9
9
  * pet id), so one component renders every registry entry.
10
10
  * @module @linxin666/dsh-pet/client/PetSprite
11
11
  */
12
- import { useEffect, useRef, useState } from 'react';
12
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
13
13
  import { createPortal } from 'react-dom';
14
14
  import clsx from 'clsx';
15
15
  import { framePosition, rowOfTrack, trimTrack } from './spritesheet.js';
16
+ import { sequenceFrameAt } from './sequences.js';
17
+ import { animationForPhase } from '../state.js';
16
18
  import styles from './pet.module.css';
17
19
  /** Clamp a drag offset inside the viewport with a margin. */
18
20
  function clampOffset(value, max) {
@@ -28,10 +30,22 @@ export function PetSprite(props) {
28
30
  const { snapshot, definition, display, feedback } = props;
29
31
  const spriteRef = useRef(null);
30
32
  const floatRef = useRef(null);
33
+ const panelRef = useRef(null);
34
+ // Whichever bubble surface is currently rendered (feedback, the session
35
+ // stack, or the legacy status bubble) — only one exists at a time.
36
+ const bubbleRef = useRef(null);
31
37
  const [imageReady, setImageReady] = useState(false);
32
38
  const [hovered, setHovered] = useState(false);
33
39
  const [renaming, setRenaming] = useState(false);
40
+ const [panelAbove, setPanelAbove] = useState(false);
41
+ // Extra margin-bottom for the above-panel so it stacks clear of the
42
+ // bubbles instead of overlapping them (both anchor at the sprite's top).
43
+ const [panelLift, setPanelLift] = useState(0);
34
44
  const [nameDraft, setNameDraft] = useState('');
45
+ // Explicit IME composition tracking: some input methods (WeChat IME on
46
+ // Windows) report keydowns with isComposing === false mid-composition, so
47
+ // the native flag alone is not a safe submit/cancel guard (#303).
48
+ const composingRef = useRef(false);
35
49
  const [dragPos, setDragPos] = useState(null);
36
50
  const dragRef = useRef(null);
37
51
  const hideTimerRef = useRef(null);
@@ -44,6 +58,7 @@ export function PetSprite(props) {
44
58
  const columns = definition.columns;
45
59
  const rows = definition.rows;
46
60
  const tracks = definition.tracks;
61
+ const sequences = definition.sequences;
47
62
  // Load the atlas once; the definition carries the authoritative per-row
48
63
  // frame counts and per-track durations, so nothing else is fetched.
49
64
  useEffect(() => {
@@ -66,14 +81,17 @@ export function PetSprite(props) {
66
81
  // its track's first frame instead of animating (presentation-only; the
67
82
  // animation state machine is untouched).
68
83
  const spriteScale = display.size / cell.height;
84
+ const phase = snapshot?.phase ?? 'idle';
69
85
  const animation = snapshot?.animation ?? 'idle';
70
86
  const scaleRef = useRef(spriteScale);
71
87
  scaleRef.current = spriteScale;
72
88
  useEffect(() => {
73
89
  const reduceMotion = typeof window !== 'undefined'
74
90
  && window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches === true;
75
- const row = rowOfTrack(animation);
76
- const track = trimTrack(tracks[animation], rows[row] ?? tracks[animation].frames.length);
91
+ const sequence = animation === animationForPhase(phase) ? sequences?.[phase] : undefined;
92
+ const leadAnimation = sequence?.[0] ?? animation;
93
+ const row = rowOfTrack(leadAnimation);
94
+ const track = trimTrack(tracks[leadAnimation], rows[row] ?? tracks[leadAnimation].frames.length);
77
95
  // Paint one static sprite frame up front either way, so the pet is never
78
96
  // blank while the loop heat-up runs.
79
97
  const leadCol = track.frames[0];
@@ -85,9 +103,23 @@ export function PetSprite(props) {
85
103
  return;
86
104
  let raf = 0;
87
105
  let last = performance.now();
106
+ let sequenceElapsed = 0;
88
107
  const tick = (ts) => {
89
108
  const delta = ts - last;
90
109
  last = ts;
110
+ if (sequence !== undefined) {
111
+ sequenceElapsed += delta;
112
+ const current = sequenceFrameAt(sequence, tracks, sequenceElapsed);
113
+ const currentRow = rowOfTrack(current.animation);
114
+ const currentTrack = trimTrack(tracks[current.animation], rows[currentRow] ?? tracks[current.animation].frames.length);
115
+ const col = currentTrack.frames[current.frameIndex];
116
+ const pos = framePosition(cell, columns, currentRow, col, scaleRef.current);
117
+ if (spriteRef.current !== null) {
118
+ spriteRef.current.style.backgroundPosition = pos.x + 'px ' + pos.y + 'px';
119
+ }
120
+ raf = requestAnimationFrame(tick);
121
+ return;
122
+ }
91
123
  // row/track come from the effect scope: they were computed once above
92
124
  // and this effect re-runs when animation/tracks/rows change, so the
93
125
  // per-frame recompute (trimTrack slices fresh arrays) is pure waste.
@@ -121,7 +153,7 @@ export function PetSprite(props) {
121
153
  };
122
154
  raf = requestAnimationFrame(tick);
123
155
  return () => cancelAnimationFrame(raf);
124
- }, [animation, cell, columns, rows, tracks]);
156
+ }, [animation, phase, cell, columns, rows, tracks, sequences]);
125
157
  // Auto-clear the feedback bubble after its CSS animation. The callback
126
158
  // rides a ref so re-renders never reset the timer: the 2s poll rebuilds
127
159
  // `props` every tick, and depending on it would starve the timeout.
@@ -175,35 +207,70 @@ export function PetSprite(props) {
175
207
  const spriteHeight = Math.round(cell.height * spriteScale);
176
208
  // Concurrent sessions each render their own bubble (stacked above the
177
209
  // sprite); the legacy single 'bubble' is the fallback when the host serves
178
- // no per-session list. The hover panel now sits beside the sprite, so the
179
- // bubbles stay visible and clickable while hovering — no region swap.
210
+ // no per-session list. The hover panel normally sits below the sprite, so
211
+ // the bubbles stay visible and clickable while hovering — no region swap.
180
212
  const sessionBubbles = snapshot?.sessions ?? [];
181
213
  const statusBubble = feedback === null && sessionBubbles.length === 0
182
214
  ? snapshot?.bubble
183
215
  : undefined;
216
+ // The display session's inner whisper (碎碎念) — short inner-voice copy
217
+ // woken by the model's output. Interaction feedback takes over the whole
218
+ // bubble area while it plays, so whispers yield to it like status copy.
219
+ const whisper = feedback === null ? snapshot?.whisper : undefined;
220
+ const bubblePresent = feedback !== null || sessionBubbles.length > 0 || statusBubble !== undefined || whisper !== undefined;
184
221
  const displayName = snapshot?.name ?? definition.displayName;
222
+ useLayoutEffect(() => {
223
+ if (!hovered) {
224
+ setPanelAbove(false);
225
+ setPanelLift(0);
226
+ return;
227
+ }
228
+ const updatePanelPlacement = () => {
229
+ const sprite = spriteRef.current;
230
+ const panel = panelRef.current;
231
+ if (sprite === null || panel === null)
232
+ return;
233
+ const availableBelow = window.innerHeight - sprite.getBoundingClientRect().bottom;
234
+ const above = availableBelow < panel.getBoundingClientRect().height + 8;
235
+ setPanelAbove(above);
236
+ // The fallback above-placement shares the sprite's top edge with the
237
+ // bubble(s); lift the panel by the bubble area's height so the two
238
+ // never overlap (8px base gap + 6px clearance above the top bubble).
239
+ const bubbleHeight = above ? bubbleRef.current?.getBoundingClientRect().height ?? 0 : 0;
240
+ setPanelLift(bubbleHeight > 0 ? Math.ceil(bubbleHeight) + 14 : 0);
241
+ };
242
+ updatePanelPlacement();
243
+ window.addEventListener('resize', updatePanelPlacement);
244
+ return () => window.removeEventListener('resize', updatePanelPlacement);
245
+ }, [hovered, renaming, pos.right, pos.bottom, display.size, bubblePresent, sessionBubbles.length, feedback]);
185
246
  const float = (_jsxs("div", { ref: floatRef, className: styles.float, style: { right: pos.right, bottom: pos.bottom, zIndex: 2147483000 }, onPointerEnter: () => {
186
247
  clearHideTimer();
187
248
  setHovered(true);
188
249
  }, onPointerLeave: (e) => {
189
- // The panel renders OUTSIDE the container's box (absolute, beside
250
+ // The panel renders OUTSIDE the container's box (absolute, below
190
251
  // the sprite), so moving onto it fires pointerleave on the container.
191
252
  // Treat a target still inside the container's DOM (the overflowed
192
253
  // panel) as "still hovering"; otherwise give the pointer a short
193
- // grace period to reach the panel across the gap beside the sprite.
254
+ // grace period to reach the panel across the gap below the sprite.
194
255
  // The bridge ('.panel::after') keeps the pointer inside the hit
195
256
  // area, and the grace period covers a slow mouse crossing the
196
257
  // remaining sliver.
197
258
  const next = e.relatedTarget;
198
259
  if (next instanceof Node && floatRef.current?.contains(next))
199
260
  return;
261
+ // Never auto-hide while the rename box is open: moving the pointer
262
+ // onto an IME candidate window (an OS-level window outside the
263
+ // webview) fires pointerleave, and unmounting the input mid-IME-
264
+ // composition crashes some input methods / the renderer (#303).
265
+ if (renaming)
266
+ return;
200
267
  clearHideTimer();
201
268
  hideTimerRef.current = window.setTimeout(() => setHovered(false), 300);
202
269
  }, children: [_jsx("div", { ref: spriteRef, className: styles.sprite, style: {
203
270
  width: spriteWidth,
204
271
  height: spriteHeight,
205
272
  backgroundImage: imageReady ? 'url(' + definition.atlasUrl + ')' : undefined,
206
- backgroundSize: (cell.width * columns * spriteScale) + 'px ' + (cell.height * rows.length * spriteScale) + 'px',
273
+ backgroundSize: (cell.width * columns * spriteScale) + 'px ' + (cell.height * (definition.atlasRows ?? rows.length) * spriteScale) + 'px',
207
274
  backgroundRepeat: 'no-repeat',
208
275
  backgroundPosition: '0 0',
209
276
  cursor: dragRef.current === null ? 'grab' : 'grabbing',
@@ -213,17 +280,21 @@ export function PetSprite(props) {
213
280
  if (draggedRef.current)
214
281
  return;
215
282
  props.onPet();
216
- }, role: "button", "aria-label": definition.displayName }), feedback !== null && (_jsx("div", { className: clsx(styles.bubble, feedback.kind === 'feed' ? styles.bubbleFeed : styles.bubblePet), children: feedback.text }, feedback.at)), feedback === null && sessionBubbles.length > 0 && (_jsx("div", { className: styles.bubbleStack, children: sessionBubbles.map(session => (_jsx("button", { type: "button", className: clsx(styles.bubble, styles.bubbleStatus, styles.bubbleClickable), title: props.t('pet.openSessionHint'), onClick: () => { props.onOpenSession(session.sessionId); }, children: session.bubble }, session.sessionId))) })), statusBubble !== undefined && (_jsx("div", { className: clsx(styles.bubble, styles.bubbleStatus), role: "status", "aria-live": "polite", children: statusBubble })), hovered && dragRef.current === null && (_jsx("div", { className: styles.panel, onPointerEnter: () => {
283
+ }, role: "button", "aria-label": definition.displayName }), feedback !== null && (_jsx("div", { ref: bubbleRef, className: clsx(styles.bubble, feedback.kind === 'feed' ? styles.bubbleFeed : styles.bubblePet), children: feedback.text }, feedback.at)), feedback === null && (sessionBubbles.length > 0 || statusBubble !== undefined || whisper !== undefined) && (_jsxs("div", { ref: bubbleRef, className: styles.bubbleStack, children: [sessionBubbles.map(session => (_jsx("button", { type: "button", className: clsx(styles.bubble, styles.bubbleStatus, styles.bubbleClickable), title: props.t('pet.openSessionHint'), onClick: () => { props.onOpenSession(session.sessionId); }, children: session.bubble }, session.sessionId))), sessionBubbles.length === 0 && statusBubble !== undefined && (_jsx("div", { className: clsx(styles.bubble, styles.bubbleStatus), role: "status", "aria-live": "polite", children: statusBubble })), whisper !== undefined && (_jsx("div", { className: styles.bubbleWhisper, children: whisper }, whisper))] })), hovered && dragRef.current === null && (_jsx("div", { ref: panelRef, className: clsx(styles.panel, panelAbove && styles.panelAbove), "data-placement": panelAbove ? 'above' : 'below', style: panelAbove && panelLift > 0
284
+ ? { marginBottom: panelLift }
285
+ : undefined, onPointerEnter: () => {
217
286
  // Reaching the panel (or its bridge) must cancel any hide timer
218
287
  // the container's pointerleave may have armed while the pointer
219
288
  // crossed the sliver between the sprite and the panel.
220
289
  clearHideTimer();
221
- }, children: renaming ? (_jsxs("div", { className: styles.renameRow, children: [_jsx("input", { className: styles.nameInput, value: nameDraft, maxLength: 20, placeholder: props.t('pet.namePlaceholder'), autoFocus: true, onChange: (e) => setNameDraft(e.target.value), onKeyDown: (e) => {
290
+ }, children: renaming ? (_jsxs("div", { className: styles.renameRow, children: [_jsx("input", { className: styles.nameInput, value: nameDraft, maxLength: 20, placeholder: props.t('pet.namePlaceholder'), autoFocus: true, onChange: (e) => setNameDraft(e.target.value), onCompositionStart: () => { composingRef.current = true; }, onCompositionEnd: () => { composingRef.current = false; }, onKeyDown: (e) => {
222
291
  // While an IME composition is active (e.g. selecting a
223
292
  // Chinese candidate), Enter/Escape keydowns belong to the
224
293
  // input method: ignore them so candidate selection can
225
- // neither submit the draft nor close the rename box.
226
- if (e.nativeEvent.isComposing)
294
+ // neither submit the draft nor close the rename box. The
295
+ // explicit ref and the 'Process' key cover IMEs that mark
296
+ // composition keydowns with isComposing === false (#303).
297
+ if (composingRef.current || e.nativeEvent.isComposing || e.key === 'Process')
227
298
  return;
228
299
  if (e.key === 'Enter') {
229
300
  const trimmed = nameDraft.trim();
@@ -241,7 +312,10 @@ export function PetSprite(props) {
241
312
  props.onRename(trimmed);
242
313
  setRenaming(false);
243
314
  }
244
- }, children: props.t('pet.confirm') })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.rankRow, children: [_jsx("span", { className: styles.nameCell, children: displayName }), _jsx("span", { children: props.t('pet.rank', { rank: snapshot?.affinity.rank ?? '?' }) })] }), _jsxs("div", { className: styles.rankRow, children: [_jsx("span", { children: props.t('pet.treats', { n: snapshot?.treats.stocked ?? 0 }) }), _jsx("span", { children: props.t('pet.points', { points: snapshot?.affinity.points ?? 0 }) })] }), _jsxs("div", { className: styles.actions, children: [_jsx("button", { type: "button", className: styles.action, onClick: props.onFeed, children: props.t('pet.feed') }), _jsx("button", { type: "button", className: styles.action, onClick: () => {
315
+ }, children: props.t('pet.confirm') })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.rankRow, children: [_jsx("span", { className: styles.nameCell, children: displayName }), _jsx("span", { className: styles.statRank, children: props.t('pet.rank', { rank: snapshot?.affinity.rank ?? '?' }) })] }), _jsxs("div", { className: styles.rankRow, children: [_jsx("span", { className: styles.statTreats, children: props.t('pet.treats', { n: snapshot?.treats.stocked ?? 0 }) }), _jsx("span", { className: styles.statPoints, children: props.t('pet.points', { points: snapshot?.affinity.points ?? 0 }) })] }), _jsxs("div", { className: styles.actions, children: [_jsx("button", { type: "button", className: styles.action, onClick: props.onFeed, children: props.t('pet.feed') }), _jsx("button", { type: "button", className: styles.action, onClick: () => {
316
+ // Cancel any pending hide so the rename box cannot
317
+ // unmount right as the user starts typing (#303).
318
+ clearHideTimer();
245
319
  setNameDraft(displayName);
246
320
  setRenaming(true);
247
321
  }, children: props.t('pet.rename') }), _jsx("button", { type: "button", className: styles.action, onClick: props.onHide, children: props.t('pet.hide') })] })] })) }))] }));
@@ -39,6 +39,12 @@ export interface PluginSettingsCardProps<TKey extends string = string> {
39
39
  * already provides the selection.
40
40
  */
41
41
  alwaysOpen?: boolean;
42
+ /**
43
+ * Hide the save/discard footer: cards whose body applies its own changes
44
+ * immediately (an embedded external settings section) have no staged
45
+ * edits, so the footer would sit there permanently disabled.
46
+ */
47
+ hideFooter?: boolean;
42
48
  /** The plugin's controls. */
43
49
  children: ReactNode;
44
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
@@ -52,9 +52,11 @@ export function PluginSettingsCard(props) {
52
52
  : null] }));
53
53
  }
54
54
  return (_jsxs("li", { className: cardClass, children: [header, expanded
55
- ? (_jsxs("div", { className: css.body, children: [!state.writable ? _jsx("p", { className: css.readOnly, role: "status", children: props.t('settings.readOnly') }) : null, props.children, _jsxs("div", { className: css.footer, children: [state.failed
56
- ? (_jsxs("p", { className: css.failed, role: "status", children: [props.t('settings.saveFailed'), state.failedReason ? ' - ' + state.failedReason : ''] }))
57
- : null, _jsx("button", { type: "button", className: css.discard, disabled: !state.dirty || state.saving, onClick: props.onDiscard, children: props.t('settings.discard') }), _jsx("button", { type: "button", className: css.save, disabled: blocked, onClick: props.onSave, children: props.t(!state.saving ? 'settings.save' : 'settings.saving') })] })] }))
55
+ ? (_jsxs("div", { className: css.body, children: [!state.writable ? _jsx("p", { className: css.readOnly, role: "status", children: props.t('settings.readOnly') }) : null, props.children, props.hideFooter === true
56
+ ? null
57
+ : (_jsxs("div", { className: css.footer, children: [state.failed
58
+ ? (_jsxs("p", { className: css.failed, role: "status", children: [props.t('settings.saveFailed'), state.failedReason ? ' - ' + state.failedReason : ''] }))
59
+ : null, _jsx("button", { type: "button", className: css.discard, disabled: !state.dirty || state.saving, onClick: props.onDiscard, children: props.t('settings.discard') }), _jsx("button", { type: "button", className: css.save, disabled: blocked, onClick: props.onSave, children: props.t(!state.saving ? 'settings.save' : 'settings.saving') })] }))] }))
58
60
  : null] }));
59
61
  }
60
62
  /** A staged value field. `numeric` only hints the keypad: which drafts a field accepts is decided by its spec. */
@@ -0,0 +1,10 @@
1
+ /** Pure timing helpers for manifest-defined scene animation sequences. */
2
+ import type { PetTrackDef } from '../registry.ts';
3
+ import type { PetAnimation } from '../state.ts';
4
+ export interface SequenceFrame {
5
+ animation: PetAnimation;
6
+ frameIndex: number;
7
+ }
8
+ /** Resolve the active track and frame after elapsed milliseconds of a looping sequence. */
9
+ export declare function sequenceFrameAt(sequence: readonly PetAnimation[], tracks: Record<PetAnimation, PetTrackDef>, elapsedMs: number): SequenceFrame;
10
+ //# sourceMappingURL=sequences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequences.d.ts","sourceRoot":"","sources":["../../../src/client/sequences.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,YAAY,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,EACzC,SAAS,EAAE,MAAM,GAChB,aAAa,CAiBf"}
@@ -0,0 +1,20 @@
1
+ /** Pure timing helpers for manifest-defined scene animation sequences. */
2
+ /** Resolve the active track and frame after elapsed milliseconds of a looping sequence. */
3
+ export function sequenceFrameAt(sequence, tracks, elapsedMs) {
4
+ const itemDurations = sequence.map(animation => tracks[animation].durations.reduce((sum, value) => sum + value, 0));
5
+ const sequenceDuration = itemDurations.reduce((sum, value) => sum + value, 0);
6
+ let offset = Math.max(0, elapsedMs) % sequenceDuration;
7
+ let itemIndex = 0;
8
+ while (itemIndex < sequence.length - 1 && offset >= itemDurations[itemIndex]) {
9
+ offset -= itemDurations[itemIndex];
10
+ itemIndex += 1;
11
+ }
12
+ const animation = sequence[itemIndex];
13
+ const track = tracks[animation];
14
+ let frameIndex = 0;
15
+ while (frameIndex < track.frames.length - 1 && offset >= track.durations[frameIndex]) {
16
+ offset -= track.durations[frameIndex];
17
+ frameIndex += 1;
18
+ }
19
+ return { animation, frameIndex };
20
+ }
@@ -3,10 +3,16 @@
3
3
  * vocabulary onto the pet's visual phases and carries an optional completed-
4
4
  * turn reward for the ledger. Holds no state of its own; callers keep a
5
5
  * {@link ProjectionRuntime} per session and feed events in arrival order.
6
+ *
7
+ * Status copy comes from the chatter voice (big rotating pools, per-tool
8
+ * families, real-argument hints), and streamed model output feeds the murmur
9
+ * engine so the pet can whisper its inner voice (碎碎念). The wall clock is
10
+ * injected by the caller, keeping every projection reproducible.
6
11
  * @module @linxin666/dsh-pet/event-projection
7
12
  */
8
13
  import type { SessionEvent } from '@deepseek-ai/dsh-session';
9
14
  import type { PetStateInput } from './state.ts';
15
+ import { StatusVoice, WhisperEngine } from './chatter.ts';
10
16
  /** Runtime shape of the optional legacy activity event. */
11
17
  export interface ActivityStatusEventLike {
12
18
  phase?: string;
@@ -18,11 +24,17 @@ export interface ProjectionRuntime {
18
24
  activeTools: Set<string>;
19
25
  officialEventsSeen: boolean;
20
26
  stepHadFailure: boolean;
27
+ /** Round-robin status copy voice (scene-stable, cadence-rotated). */
28
+ voice: StatusVoice;
29
+ /** Inner-whisper engine fed by the model's own streamed output. */
30
+ whispers: WhisperEngine;
21
31
  }
22
32
  /** One official event projection, optionally carrying a completed turn reward. */
23
33
  export interface PetActivityTransition {
24
34
  input: PetStateInput;
25
35
  completedTurn?: number;
36
+ /** A fresh inner whisper woken by this event's model output, when any. */
37
+ whisper?: string;
26
38
  }
27
39
  /** Fresh projection runtime for a newly seen session. */
28
40
  export declare function emptyProjectionRuntime(): ProjectionRuntime;
@@ -31,6 +43,7 @@ export declare function isActivityPhase(phase: string): phase is PetStateInput['
31
43
  /**
32
44
  * Project the durable DSH session vocabulary into the pet's visual phases.
33
45
  * Unknown and log-only events do not disturb the last meaningful activity.
46
+ * @param nowMs - injected wall clock for copy rotation and whisper pacing.
34
47
  */
35
- export declare function projectOfficialEvent(event: SessionEvent, runtime: ProjectionRuntime): PetActivityTransition | undefined;
48
+ export declare function projectOfficialEvent(event: SessionEvent, runtime: ProjectionRuntime, nowMs?: number): PetActivityTransition | undefined;
36
49
  //# 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;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,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,kBAAkB,EAAE,OAAO,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;CACxB;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,yDAAyD;AACzD,wBAAgB,sBAAsB,IAAI,iBAAiB,CAE1D;AAQD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,CAE9E;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,iBAAiB,GACzB,qBAAqB,GAAG,SAAS,CA2EnC"}
1
+ {"version":3,"file":"event-projection.d.ts","sourceRoot":"","sources":["../../src/event-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAe,aAAa,EAAE,MAAM,cAAc,CAAA;AAEtE,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,kBAAkB,EAAE,OAAO,CAAA;IAC3B,cAAc,EAAE,OAAO,CAAA;IACvB,qEAAqE;IACrE,KAAK,EAAE,WAAW,CAAA;IAClB,mEAAmE;IACnE,QAAQ,EAAE,aAAa,CAAA;CACxB;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,aAAa,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,yDAAyD;AACzD,wBAAgB,sBAAsB,IAAI,iBAAiB,CAQ1D;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,CAwFnC"}
@@ -3,16 +3,28 @@
3
3
  * vocabulary onto the pet's visual phases and carries an optional completed-
4
4
  * turn reward for the ledger. Holds no state of its own; callers keep a
5
5
  * {@link ProjectionRuntime} per session and feed events in arrival order.
6
+ *
7
+ * Status copy comes from the chatter voice (big rotating pools, per-tool
8
+ * families, real-argument hints), and streamed model output feeds the murmur
9
+ * engine so the pet can whisper its inner voice (碎碎念). The wall clock is
10
+ * injected by the caller, keeping every projection reproducible.
6
11
  * @module @linxin666/dsh-pet/event-projection
7
12
  */
13
+ import { StatusVoice, toolArgHint, WhisperEngine } from './chatter.js';
8
14
  /** Fresh projection runtime for a newly seen session. */
9
15
  export function emptyProjectionRuntime() {
10
- return { activeTools: new Set(), officialEventsSeen: false, stepHadFailure: false };
16
+ return {
17
+ activeTools: new Set(),
18
+ officialEventsSeen: false,
19
+ stepHadFailure: false,
20
+ voice: new StatusVoice(),
21
+ whispers: new WhisperEngine(),
22
+ };
11
23
  }
12
24
  /** Keep tool names readable inside the compact status bubble. */
13
25
  function displayToolName(name) {
14
26
  const compact = name.replace(/\s+/g, ' ').trim() || '工具';
15
- return compact.length <= 24 ? compact : `${compact.slice(0, 21)}...`;
27
+ return compact.length <= 24 ? compact : compact.slice(0, 21) + '...';
16
28
  }
17
29
  /** Whether a legacy phase is part of the pet's supported vocabulary. */
18
30
  export function isActivityPhase(phase) {
@@ -21,35 +33,44 @@ export function isActivityPhase(phase) {
21
33
  /**
22
34
  * Project the durable DSH session vocabulary into the pet's visual phases.
23
35
  * Unknown and log-only events do not disturb the last meaningful activity.
36
+ * @param nowMs - injected wall clock for copy rotation and whisper pacing.
24
37
  */
25
- export function projectOfficialEvent(event, runtime) {
38
+ export function projectOfficialEvent(event, runtime, nowMs = Date.now()) {
26
39
  switch (event.type) {
27
40
  case 'turn/start':
28
41
  runtime.activeTools.clear();
29
42
  runtime.stepHadFailure = false;
30
- return { input: { phase: 'waiting', line: '准备开始' } };
43
+ return { input: { phase: 'waiting', line: runtime.voice.scene('prepare', nowMs) } };
31
44
  case 'step/start':
32
45
  runtime.activeTools.clear();
33
46
  runtime.stepHadFailure = false;
34
- return { input: { phase: 'waiting', line: '等待模型响应' } };
47
+ return { input: { phase: 'waiting', line: runtime.voice.scene('waiting', nowMs) } };
35
48
  case 'assistant/chunk': {
36
49
  const { chunk } = event.data;
37
50
  if (chunk.type === 'reasoning-delta' && chunk.text.length > 0) {
38
- return { input: { phase: 'thinking', line: '正在思考' } };
51
+ const whisper = runtime.whispers.feed(chunk.text, nowMs);
52
+ return {
53
+ input: { phase: 'thinking', line: runtime.voice.scene('thinking', nowMs) },
54
+ ...(whisper === undefined ? {} : { whisper }),
55
+ };
39
56
  }
40
57
  if (chunk.type === 'text-delta' && chunk.text.length > 0) {
41
- return { input: { phase: 'review', line: '整理回复中' } };
58
+ const whisper = runtime.whispers.feed(chunk.text, nowMs);
59
+ return {
60
+ input: { phase: 'review', line: runtime.voice.scene('review', nowMs) },
61
+ ...(whisper === undefined ? {} : { whisper }),
62
+ };
42
63
  }
43
64
  return undefined;
44
65
  }
45
66
  case 'assistant/message':
46
- return { input: { phase: 'review', line: '整理回复中' } };
67
+ return { input: { phase: 'review', line: runtime.voice.scene('review', nowMs) } };
47
68
  case 'tool/call':
48
69
  runtime.activeTools.add(String(event.data.callId));
49
70
  return {
50
71
  input: {
51
72
  phase: 'tool',
52
- line: `正在使用 ${displayToolName(event.data.name)}`,
73
+ line: runtime.voice.tool(event.data.name, displayToolName(event.data.name), toolArgHint(event.data.name, event.data.arguments), nowMs),
53
74
  },
54
75
  };
55
76
  case 'tool/result': {
@@ -60,30 +81,30 @@ export function projectOfficialEvent(event, runtime) {
60
81
  return {
61
82
  input: {
62
83
  phase: 'tool',
63
- line: `还有 ${runtime.activeTools.size} 个工具运行中`,
84
+ line: runtime.voice.toolRemaining(runtime.activeTools.size, nowMs),
64
85
  },
65
86
  };
66
87
  }
67
88
  return runtime.stepHadFailure
68
- ? { input: { phase: 'failed', line: '工具执行失败' } }
69
- : { input: { phase: 'thinking', line: '处理工具结果' } };
89
+ ? { input: { phase: 'failed', line: runtime.voice.scene('toolFailed', nowMs) } }
90
+ : { input: { phase: 'thinking', line: runtime.voice.scene('toolResult', nowMs) } };
70
91
  }
71
92
  case 'turn/end': {
72
93
  runtime.activeTools.clear();
73
94
  switch (event.data.reason.kind) {
74
95
  case 'completed':
75
96
  return {
76
- input: { phase: 'done', line: '完成啦' },
97
+ input: { phase: 'done', line: runtime.voice.scene('done', nowMs) },
77
98
  completedTurn: event.data.turn,
78
99
  };
79
100
  case 'error':
80
- return { input: { phase: 'failed', line: '执行失败' } };
101
+ return { input: { phase: 'failed', line: runtime.voice.scene('failed', nowMs) } };
81
102
  case 'max-tokens':
82
- return { input: { phase: 'failed', line: '达到输出上限' } };
103
+ return { input: { phase: 'failed', line: runtime.voice.scene('maxTokens', nowMs) } };
83
104
  case 'interrupted':
84
- return { input: { phase: 'failed', line: '执行意外中断' } };
105
+ return { input: { phase: 'failed', line: runtime.voice.scene('interrupted', nowMs) } };
85
106
  case 'blocked':
86
- return { input: { phase: 'waiting', line: '等待继续' } };
107
+ return { input: { phase: 'waiting', line: runtime.voice.scene('blocked', nowMs) } };
87
108
  case 'aborted':
88
109
  // A stopped session settles to idle without a bubble: the pet
89
110
  // visibly calms down and the session drops out of the bubble stack.
@@ -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;AAEhE,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;CACrB;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;IAErB,YAAY,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,YAAiB,EAKzD;IAED,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,CAInB;IAED;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAErC;IAED,mEAAmE;IACnE,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAG1C;IAED,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI5B;IAED,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAG5C;IAED;;;OAGG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAErC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAWnC;IAED;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOlE;IAED,8EAA8E;IAC9E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOvC;IAED,OAAO,CAAC,eAAe;IASvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB,CA8BrE;IAED,kDAAkD;IAClD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAE3C;CACF"}
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;AAEhE,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;CACrB;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;IAErB,YAAY,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,YAAiB,EAKzD;IAED,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,CAInB;IAED;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAErC;IAED,mEAAmE;IACnE,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAG1C;IAED,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI5B;IAED,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAG5C;IAED;;;OAGG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAErC;IAED;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAWnC;IAED;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOlE;IAED,8EAA8E;IAC9E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOvC;IAED,OAAO,CAAC,eAAe;IASvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB,CAsCrE;IAED,kDAAkD;IAClD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAE3C;CACF"}
@@ -135,12 +135,19 @@ export class PetLedger {
135
135
  interact(kind, nowMs) {
136
136
  if (kind === 'feed')
137
137
  this.settleTreats(nowMs);
138
- const outcome = applyInteraction(this.current.affinity, kind, nowMs, this.affinityConfig);
138
+ const before = this.current.affinity;
139
+ const outcome = applyInteraction(before, kind, nowMs, this.affinityConfig);
139
140
  // Reactions come from the picker pools (custom per-pet slots override
140
141
  // the built-in library per slot); outcome.reaction stays the fallback
141
142
  // copy for direct applyInteraction callers.
142
143
  if (kind === 'feed' && !outcome.accepted) {
143
- return { reaction: this.picker.pick('feedCooldown'), delta: 0, affinity: this.affinityView(nowMs) };
144
+ this.current = { ...this.current, affinity: outcome.affinity };
145
+ this.dirty = true;
146
+ return {
147
+ reaction: this.picker.pickAt('feedCooldown', before.feedRejects),
148
+ delta: 0,
149
+ affinity: this.affinityView(nowMs),
150
+ };
144
151
  }
145
152
  if (kind === 'feed') {
146
153
  const consume = consumeTreat(this.current.treats);
@@ -154,12 +161,13 @@ export class PetLedger {
154
161
  this.current = { ...this.current, treats: consume.ledger };
155
162
  this.dirty = true;
156
163
  }
157
- if (outcome.accepted) {
158
- this.current = { ...this.current, affinity: outcome.affinity };
159
- this.dirty = true;
160
- }
164
+ this.current = { ...this.current, affinity: outcome.affinity };
165
+ this.dirty = true;
166
+ const count = kind === 'pet'
167
+ ? outcome.accepted ? before.pets : before.petRejects
168
+ : before.feeds;
161
169
  return {
162
- reaction: this.picker.pick(outcome.accepted ? kind : 'petCooldown'),
170
+ reaction: this.picker.pickAt(outcome.accepted ? kind : 'petCooldown', count),
163
171
  delta: outcome.delta,
164
172
  affinity: this.affinityView(nowMs),
165
173
  };
@@ -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,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,MAAM,CAAA;AACnC,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;CAC1B;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,eAAe,CAAA;AAE1C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,uBAAQ,CAAA;AAErC,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CAQzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AA4BD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAiDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
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,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,MAAM,CAAA;AACnC,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;CAC1B;AAED,qEAAqE;AACrE,eAAO,MAAM,cAAc,eAAe,CAAA;AAE1C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,uBAAQ,CAAA;AAErC,wBAAwB;AACxB,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,wBAAgB,YAAY,IAAI,UAAU,CAQzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AA4BD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAqB,GAAG,UAAU,CAmDrE;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,GAAE,MAAqB,GAAG,IAAI,CAMjF"}
@@ -13,7 +13,7 @@ export const defaultDisplayConfig = {
13
13
  visible: true,
14
14
  size: 160,
15
15
  right: 24,
16
- bottom: 20,
16
+ bottom: 120,
17
17
  };
18
18
  /** Display value bounds (shared by load-time validation and setConfig). */
19
19
  export const DISPLAY_SIZE_MIN = 32;
@@ -78,6 +78,8 @@ export function loadPetPersist(dir = petHomeDir()) {
78
78
  lastFeedAt: clamp(finiteNum(rawAffinity.lastFeedAt, 0), Number.MAX_SAFE_INTEGER),
79
79
  pets: clamp(finiteNum(rawAffinity.pets, 0), Number.MAX_SAFE_INTEGER),
80
80
  feeds: clamp(finiteNum(rawAffinity.feeds, 0), Number.MAX_SAFE_INTEGER),
81
+ petRejects: clamp(finiteNum(rawAffinity.petRejects, 0), Number.MAX_SAFE_INTEGER),
82
+ feedRejects: clamp(finiteNum(rawAffinity.feedRejects, 0), Number.MAX_SAFE_INTEGER),
81
83
  turns: clamp(finiteNum(rawAffinity.turns, 0), Number.MAX_SAFE_INTEGER),
82
84
  };
83
85
  const rawTreats = (parsed.treats ?? {});
@@ -16,7 +16,7 @@
16
16
  * whale-girl manifest overrides its own durations.
17
17
  * @module @linxin666/dsh-pet/registry
18
18
  */
19
- import type { PetAnimation } from './state.ts';
19
+ import type { ActivityPhase, PetAnimation } from './state.ts';
20
20
  import { type PetRemarks, type PetRemarksManifest } from './remarks.ts';
21
21
  /** Fixed row order of the 9-state animation contract. */
22
22
  export declare const PET_ROW_ORDER: readonly PetAnimation[];
@@ -81,6 +81,8 @@ export interface PetManifest {
81
81
  frames?: number[];
82
82
  /** Optional per-track rhythm overrides; omitted tracks use the defaults. */
83
83
  tracks?: Partial<Record<PetAnimation, PetTrackOverride>>;
84
+ /** Optional per-scene track sequences; every declared sequence has at least 5 items. */
85
+ sequences?: Partial<Record<ActivityPhase, PetAnimation[]>>;
84
86
  /**
85
87
  * Optional witty-remark overrides the pet speaks on interactions
86
88
  * (community contributions use this to give their pet its own voice).
@@ -109,8 +111,12 @@ export interface PetDefinition {
109
111
  columns: number;
110
112
  /** Per-row frame counts (length 9, row order above). */
111
113
  rows: number[];
114
+ /** Total atlas rows (9 for v1, 11 for v2 look-row atlases). */
115
+ atlasRows: number;
112
116
  /** Fully resolved animation tracks (frames + durations + loop/fallback). */
113
117
  tracks: Record<PetAnimation, PetTrackDef>;
118
+ /** Validated per-scene track sequences; omitted scenes keep single-track playback. */
119
+ sequences?: Partial<Record<ActivityPhase, PetAnimation[]>>;
114
120
  /** Browser URL of the atlas (served by the host asset route). */
115
121
  atlasUrl: string;
116
122
  /** Browser URL of the manifest (served by the host asset route). */
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}