@linxin666/dsh-pet 0.1.11 → 0.1.13

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/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as AFFINITY_MAX, c as applyTurnReward, d as rankOf, i as rowOf, l as defaultAffinityConfig, n as animationForPhase, o as AFFINITY_RANKS, r as defaultPetStateConfig, s as applyInteraction, t as PetStateMachine, u as emptyAffinity } from "./state-IyVnKymD.js";
1
+ import { a as AFFINITY_MAX, c as applyTurnReward, d as rankOf, i as rowOf, l as defaultAffinityConfig, n as animationForPhase, o as AFFINITY_RANKS, r as defaultPetStateConfig, s as applyInteraction, t as PetStateMachine, u as emptyAffinity } from "./state-C9EyycwI.js";
2
2
  import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
3
3
  import z from "schemastery";
4
4
  import { Service } from "@deepseek-ai/cordis";
@@ -30,8 +30,12 @@ function cap(treats, max) {
30
30
  * time output counts whole periods since the time anchor
31
31
  * (`lastTreatGrantAt`) and advances only the time anchor. The two sources
32
32
  * are independent so a continuously working user still earns time treats.
33
- * 0 time history never backfills — the clock starts at the first settlement.
34
- * Both sources are clamped by the stock cap.
33
+ * 0 time history never backfills — the clock starts at the first settlement,
34
+ * and even a zero-gain first settlement writes the time anchor so the next
35
+ * elapsed period can accrue (anchor deadlock fix). Both sources are clamped
36
+ * by the stock cap. When the anchor is already set and nothing is due, the
37
+ * input ledger is returned unchanged (same object), so callers can skip
38
+ * persistence cheaply.
35
39
  */
36
40
  function settleTreatGrants(ledger, turns, nowMs, config = defaultTreatConfig) {
37
41
  const turnDelta = Math.max(0, turns - ledger.turnsAtLastTreatGrant);
@@ -39,10 +43,19 @@ function settleTreatGrants(ledger, turns, nowMs, config = defaultTreatConfig) {
39
43
  const timeAnchor = ledger.lastTreatGrantAt === 0 ? nowMs : ledger.lastTreatGrantAt;
40
44
  const timeGrants = Math.floor(Math.max(0, nowMs - timeAnchor) / config.timeTreatMs);
41
45
  const gained = workGrants + timeGrants;
42
- if (gained <= 0) return {
43
- ledger,
44
- gained: 0
45
- };
46
+ if (gained <= 0) {
47
+ if (ledger.lastTreatGrantAt === 0) return {
48
+ ledger: {
49
+ ...ledger,
50
+ lastTreatGrantAt: nowMs
51
+ },
52
+ gained: 0
53
+ };
54
+ return {
55
+ ledger,
56
+ gained: 0
57
+ };
58
+ }
46
59
  return {
47
60
  ledger: {
48
61
  treats: cap(ledger.treats + gained, config.maxTreats),
@@ -162,7 +175,8 @@ var PetService = class extends Service {
162
175
  treatConfig;
163
176
  persistDir;
164
177
  persist;
165
- lastTurnRewardAt = 0;
178
+ /** Completed turns already rewarded, per session (turn numbers are per-session). */
179
+ rewardedTurns = /* @__PURE__ */ new Map();
166
180
  enabled;
167
181
  disposeActivity;
168
182
  constructor(ctx, config = {}) {
@@ -212,25 +226,31 @@ var PetService = class extends Service {
212
226
  }
213
227
  if (!this.enabled) return;
214
228
  this.disposeActivity = (() => {
215
- const disposers = [this.ctx.on("session/event", (_session, event) => {
216
- if (event.type !== "activity/status") return;
217
- const payload = event.data ?? {};
218
- if (payload.phase === void 0) return;
219
- const phase = payload.phase;
220
- if (![
221
- "idle",
222
- "waiting",
223
- "thinking",
224
- "tool",
225
- "done"
226
- ].includes(phase)) return;
227
- this.machine.onActivityStatus({
228
- phase,
229
- ...typeof payload.line === "string" ? { line: payload.line } : {},
230
- ...typeof payload.phrase === "string" ? { phrase: payload.phrase } : {}
231
- });
232
- this.machine.onSessionActive();
233
- if (phase === "done") this.rewardTurn();
229
+ const disposers = [this.ctx.on("session/event", (session, event) => {
230
+ switch (event.type) {
231
+ case "turn/start":
232
+ this.machine.onSessionActive();
233
+ break;
234
+ case "step/start":
235
+ this.machine.onSessionActive();
236
+ this.machine.onActivityStatus({ phase: "thinking" });
237
+ break;
238
+ case "tool/call":
239
+ this.machine.onSessionActive();
240
+ this.machine.onActivityStatus({
241
+ phase: "tool",
242
+ line: "tool: " + event.data.name
243
+ });
244
+ break;
245
+ case "turn/end":
246
+ this.machine.onSessionActive();
247
+ if (event.data.reason.kind === "completed") {
248
+ this.machine.onActivityStatus({ phase: "done" });
249
+ this.rewardTurn(String(session.id), event.data.turn);
250
+ } else this.machine.onActivityStatus({ phase: "idle" });
251
+ break;
252
+ default: break;
253
+ }
234
254
  }), this.ctx.on("session/disposed", () => {
235
255
  this.machine.onSessionDisposed();
236
256
  })];
@@ -364,11 +384,10 @@ var PetService = class extends Service {
364
384
  name: this.persist.name
365
385
  }).catch(() => {});
366
386
  }
367
- /** Award the turn reward once per done phase (idempotent per transition). */
368
- rewardTurn() {
369
- const nowMs = Date.now();
370
- if (nowMs - this.lastTurnRewardAt < 5e3) return;
371
- this.lastTurnRewardAt = nowMs;
387
+ /** Award the turn reward once per completed turn (idempotent per session + turn). */
388
+ rewardTurn(sessionId, turn) {
389
+ if (turn <= (this.rewardedTurns.get(sessionId) ?? 0)) return;
390
+ this.rewardedTurns.set(sessionId, turn);
372
391
  this.persist = {
373
392
  ...this.persist,
374
393
  affinity: applyTurnReward(this.persist.affinity, this.affinityConfig)
@@ -376,12 +395,14 @@ var PetService = class extends Service {
376
395
  this.flush();
377
396
  }
378
397
  /**
379
- * Settle the treat economy (work + time output since the last
380
- * settlement); persists only when treats were actually granted.
398
+ * Settle the treat economy (work + time output since the last settlement)
399
+ * and persist whenever the ledger changed. A zero-gain first settlement
400
+ * still starts the time clock (anchor write), which is what lets the
401
+ * 30-minute time output ever accrue.
381
402
  */
382
403
  settleTreats(nowMs) {
383
404
  const settlement = settleTreatGrants(this.persist.treats, this.persist.affinity.turns, nowMs, this.treatConfig);
384
- if (settlement.gained > 0) {
405
+ if (settlement.ledger !== this.persist.treats) {
385
406
  this.persist = {
386
407
  ...this.persist,
387
408
  treats: settlement.ledger
package/lib/invariant.js CHANGED
@@ -1,4 +1,4 @@
1
- import { l as defaultAffinityConfig, n as animationForPhase, o as AFFINITY_RANKS } from "./state-IyVnKymD.js";
1
+ import { l as defaultAffinityConfig, n as animationForPhase, o as AFFINITY_RANKS } from "./state-C9EyycwI.js";
2
2
  //#region src/invariant.ts
3
3
  /**
4
4
  * Package invariants — cheap structural checks run at import time on the
@@ -159,7 +159,7 @@ var PetStateMachine = class {
159
159
  this.config = config;
160
160
  this.now = now;
161
161
  }
162
- /** Consume one `activity/status` session event. */
162
+ /** Consume one phase snapshot (fed by the service from session events). */
163
163
  onActivityStatus(input) {
164
164
  this.phase = input.phase;
165
165
  this.line = input.line;
@@ -1 +1 @@
1
- {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGnD,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAA;IACnC,uCAAuC;IACvC,QAAQ,EAAE,eAAe,CAAA;IACzB,4EAA4E;IAC5E,cAAc,EAAE,eAAe,CAAA;IAC/B,kFAAkF;IAClF,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,sCAiFhE;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAA;IACV,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,UAAU,EAAE,OAAO,CAAA;IACnB,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAA;IAChB,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAA;IACvB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAA;IACjB,wBAAwB;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,oEAAoE;IACpE,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,kHAAkH;AAClH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG;IAC7C,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,+BAqCA;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG;IAC/C,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAA;CACjB,+BAmCA"}
1
+ {"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGnD,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,CAAA;IACnC,uCAAuC;IACvC,QAAQ,EAAE,eAAe,CAAA;IACzB,4EAA4E;IAC5E,cAAc,EAAE,eAAe,CAAA;IAC/B,kFAAkF;IAClF,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,sCA0GhE;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAA;IACV,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,UAAU,EAAE,OAAO,CAAA;IACnB,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAA;IAChB,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAA;IACvB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAA;IACjB,wBAAwB;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,oEAAoE;IACpE,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,kHAAkH;AAClH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG;IAC7C,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,+BAqCA;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG;IAC/C,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAA;CACjB,+BAmCA"}
@@ -21,16 +21,17 @@ export function PluginSettingsCard(props) {
21
21
  return null;
22
22
  const title = props.t(props.titleKey);
23
23
  const blocked = !state.dirty || state.invalid || state.saving;
24
+ const cardClass = open ? `${css.cardOpen} ${css.card}` : css.card;
24
25
  // The namespace exists but the Host does not serve it to this client (the
25
26
  // official settings allowlist omits third-party namespaces): show a card
26
27
  // that explains the gap instead of vanishing, so a missing card never
27
28
  // reads as a missing plugin.
28
29
  if (!state.exposed) {
29
- return (_jsxs("li", { className: css.card, children: [_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, children: title }), _jsx("span", { className: css.description, children: props.t(props.descriptionKey) })] }), _jsx("span", { className: open ? css.chevronOpen : css.chevron, children: "\u25BE" })] }), open
30
+ return (_jsxs("li", { className: cardClass, children: [_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, children: title }), _jsx("span", { className: css.description, children: props.t(props.descriptionKey) })] }), _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.chevron} ${css.chevronOpen}` : css.chevron, children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }), open
30
31
  ? (_jsx("div", { className: css.body, children: _jsx("p", { className: css.notExposed, role: "status", children: props.t('settings.notExposed') }) }))
31
32
  : null] }));
32
33
  }
33
- return (_jsxs("li", { className: css.card, children: [_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, children: title }), _jsx("span", { className: css.description, children: props.t(props.descriptionKey) })] }), state.dirty ? _jsx("span", { className: css.pending, children: props.t('settings.unsaved') }) : null, _jsx("span", { className: open ? css.chevronOpen : css.chevron, children: "\u25BE" })] }), open
34
+ return (_jsxs("li", { className: cardClass, children: [_jsxs("button", { type: "button", className: css.header, "aria-expanded": open, "aria-label": `${props.t(open ? 'settings.collapse' : 'settings.expand')}: ${title}`, onClick: () => { setOpen(!open); }, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, children: title }), _jsx("span", { className: css.description, children: props.t(props.descriptionKey) })] }), state.dirty ? _jsx("span", { className: css.pending, children: props.t('settings.unsaved') }) : null, _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: open ? `${css.chevron} ${css.chevronOpen}` : css.chevron, children: _jsx("path", { d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z", fill: "currentColor" }) })] }), open
34
35
  ? (_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 ? _jsx("p", { className: css.failed, role: "status", children: props.t('settings.saveFailed') }) : 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') })] })] }))
35
36
  : null] }));
36
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WhalePet.d.ts","sourceRoot":"","sources":["../../../src/client/WhalePet.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAqC,WAAW,EAAE,MAAM,OAAO,CAAA;AAE3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAGjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,gCAAgC,CAAA;AAEhE,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,wBAAwB,CAAA;AAErD,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,qDAAqD;IACrD,OAAO,EAAE,gBAAgB,CAAA;IACzB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,kCAAkC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,+BAA+B;IAC/B,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD,8CAA8C;IAC9C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,2DAA2D;IAC3D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,+CAA+C;IAC/C,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;CAC1B;AAOD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,WAAW,CA8S1D"}
1
+ {"version":3,"file":"WhalePet.d.ts","sourceRoot":"","sources":["../../../src/client/WhalePet.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAqC,WAAW,EAAE,MAAM,OAAO,CAAA;AAE3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAGjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAGjC,iFAAiF;AACjF,eAAO,MAAM,mBAAmB,gCAAgC,CAAA;AAEhE,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,wBAAwB,CAAA;AAErD,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,qDAAqD;IACrD,OAAO,EAAE,gBAAgB,CAAA;IACzB,sCAAsC;IACtC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,kCAAkC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,+BAA+B;IAC/B,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD,8CAA8C;IAC9C,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,2DAA2D;IAC3D,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,+CAA+C;IAC/C,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;CAC1B;AAOD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,WAAW,CAmT1D"}
@@ -234,6 +234,12 @@ export function WhalePet(props) {
234
234
  // crossed the sliver between the sprite and the panel.
235
235
  clearHideTimer();
236
236
  }, 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) => {
237
+ // While an IME composition is active (e.g. selecting a
238
+ // Chinese candidate), Enter/Escape keydowns belong to the
239
+ // input method: ignore them so candidate selection can
240
+ // neither submit the draft nor close the rename box.
241
+ if (e.nativeEvent.isComposing)
242
+ return;
237
243
  if (e.key === 'Enter') {
238
244
  const trimmed = nameDraft.trim();
239
245
  if (trimmed !== '') {
@@ -9,7 +9,7 @@
9
9
  * fixed-position summon button.
10
10
  * @module @linxin666/dsh-pet/client
11
11
  */
12
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
12
+ import type { ClientContext, SettingsScope, SettingsScopeSpec } from '@deepseek-ai/dsh-client-runtime/client';
13
13
  /** Required services. */
14
14
  export declare const inject: string[];
15
15
  /** Re-exported for consumers that type against the injected face. */
@@ -36,6 +36,18 @@ export interface SettingsPluginItemOwnerProps {
36
36
  /** Marker field: card owner props are intentionally empty. */
37
37
  children?: never;
38
38
  }
39
+ declare module '@deepseek-ai/cordis' {
40
+ interface Context {
41
+ /**
42
+ * Optional rc.6 compatibility binder provided by dsh-web-ui-settings;
43
+ * absent when that group plugin is not installed, so callers fall back to
44
+ * the official settings scope.
45
+ */
46
+ webUiSettings?: {
47
+ bind<S>(spec: SettingsScopeSpec<S>): SettingsScope<S>;
48
+ };
49
+ }
50
+ }
39
51
  /**
40
52
  * Client plugin body: register dictionaries, mount the global pet entry and
41
53
  * poll loop while the plugin is enabled, and seat the settings card in the
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAwD3E,yBAAyB;AACzB,eAAO,MAAM,MAAM,UAA+D,CAAA;AAElF,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEtF,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,OAAO;QACf;;;;;WAKG;QACH,oBAAoB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,4BAA4B,CAAA;SAAE,CAAA;KAC3F;CACF;AAED,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAmK9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAwD7G,yBAAyB;AACzB,eAAO,MAAM,MAAM,UAA+D,CAAA;AAElF,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEtF,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,OAAO;QACf;;;;;WAKG;QACH,oBAAoB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,4BAA4B,CAAA;SAAE,CAAA;KAC3F;CACF;AAED,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf;;;;WAIG;QACH,aAAa,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;SAAE,CAAA;KAC1E;CACF;AAGD;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAoK9C"}
@@ -51,7 +51,8 @@ export const inject = ['slots', 'locale', 'connection', 'settingsScope', 'remote
51
51
  */
52
52
  export function apply(ctx) {
53
53
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'pet: dictionaries');
54
- const settingsScope = ctx.settingsScope.bind({ namespace: PET_SETTINGS_NS });
54
+ const binder = ctx.get('webUiSettings') ?? ctx.settingsScope;
55
+ const settingsScope = binder.bind({ namespace: PET_SETTINGS_NS });
55
56
  const enabled = () => {
56
57
  const snapshot = settingsScope.getSnapshot();
57
58
  return snapshot.status === 'ready'
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Pet host service — the `pet.*` RPC domain. Owns the state machine wiring
3
- * (consumes `activity/status` session events and session lifecycle), the
4
- * affinity ledger, and the persisted display config. The API gateway maps
5
- * this service's methods onto `pet.state` / `pet.interact` /
6
- * `pet.setVisible` / `pet.setConfig` for browser consumers.
3
+ * (maps core rc.6 session events turn/step/tool boundaries — and the
4
+ * session lifecycle onto the pet phases), the affinity ledger, and the
5
+ * persisted display config. The API gateway maps this service's methods onto
6
+ * `pet.state` / `pet.interact` / `pet.setVisible` / `pet.setConfig`
7
+ * for browser consumers.
7
8
  * @module @linxin666/dsh-pet/service
8
9
  */
9
10
  import { Context, Service } from '@deepseek-ai/cordis';
@@ -103,7 +104,8 @@ export declare class PetService extends Service {
103
104
  private readonly treatConfig;
104
105
  private readonly persistDir;
105
106
  private persist;
106
- private lastTurnRewardAt;
107
+ /** Completed turns already rewarded, per session (turn numbers are per-session). */
108
+ private rewardedTurns;
107
109
  private enabled;
108
110
  private disposeActivity;
109
111
  constructor(ctx: Context, config?: PetConfig);
@@ -147,11 +149,13 @@ export declare class PetService extends Service {
147
149
  applySettingsSection(section: PetSettingsSection): void;
148
150
  /** Mirror the persisted display config into the settings document (best-effort). */
149
151
  private syncSettingsFromPet;
150
- /** Award the turn reward once per done phase (idempotent per transition). */
152
+ /** Award the turn reward once per completed turn (idempotent per session + turn). */
151
153
  private rewardTurn;
152
154
  /**
153
- * Settle the treat economy (work + time output since the last
154
- * settlement); persists only when treats were actually granted.
155
+ * Settle the treat economy (work + time output since the last settlement)
156
+ * and persist whenever the ledger changed. A zero-gain first settlement
157
+ * still starts the time clock (anchor write), which is what lets the
158
+ * 30-minute time output ever accrue.
155
159
  */
156
160
  private settleTreats;
157
161
  private view;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Pet host service — the `pet.*` RPC domain. Owns the state machine wiring
3
- * (consumes `activity/status` session events and session lifecycle), the
4
- * affinity ledger, and the persisted display config. The API gateway maps
5
- * this service's methods onto `pet.state` / `pet.interact` /
6
- * `pet.setVisible` / `pet.setConfig` for browser consumers.
3
+ * (maps core rc.6 session events turn/step/tool boundaries — and the
4
+ * session lifecycle onto the pet phases), the affinity ledger, and the
5
+ * persisted display config. The API gateway maps this service's methods onto
6
+ * `pet.state` / `pet.interact` / `pet.setVisible` / `pet.setConfig`
7
+ * for browser consumers.
7
8
  * @module @linxin666/dsh-pet/service
8
9
  */
9
10
  import { Service } from '@deepseek-ai/cordis';
@@ -26,7 +27,8 @@ export class PetService extends Service {
26
27
  treatConfig;
27
28
  persistDir;
28
29
  persist;
29
- lastTurnRewardAt = 0;
30
+ /** Completed turns already rewarded, per session (turn numbers are per-session). */
31
+ rewardedTurns = new Map();
30
32
  enabled;
31
33
  disposeActivity;
32
34
  constructor(ctx, config = {}) {
@@ -72,24 +74,37 @@ export class PetService extends Service {
72
74
  return;
73
75
  this.disposeActivity = (() => {
74
76
  const disposers = [
75
- this.ctx.on('session/event', (_session, event) => {
76
- if (event.type !== 'activity/status')
77
- return;
78
- const payload = (event.data ?? {});
79
- if (payload.phase === undefined)
80
- return;
81
- const phase = payload.phase;
82
- // Guard against unknown phases from newer activity trackers.
83
- if (!['idle', 'waiting', 'thinking', 'tool', 'done'].includes(phase))
84
- return;
85
- this.machine.onActivityStatus({
86
- phase,
87
- ...(typeof payload.line === 'string' ? { line: payload.line } : {}),
88
- ...(typeof payload.phrase === 'string' ? { phrase: payload.phrase } : {}),
89
- });
90
- this.machine.onSessionActive();
91
- if (phase === 'done')
92
- this.rewardTurn();
77
+ this.ctx.on('session/event', (session, event) => {
78
+ // rc.6 publishes no 'activity/status' event (the working-activity
79
+ // tracker is gone), so the pet derives its phases from the core
80
+ // session vocabulary instead.
81
+ switch (event.type) {
82
+ case 'turn/start':
83
+ this.machine.onSessionActive();
84
+ break;
85
+ case 'step/start':
86
+ this.machine.onSessionActive();
87
+ this.machine.onActivityStatus({ phase: 'thinking' });
88
+ break;
89
+ case 'tool/call':
90
+ this.machine.onSessionActive();
91
+ this.machine.onActivityStatus({ phase: 'tool', line: 'tool: ' + event.data.name });
92
+ break;
93
+ case 'turn/end':
94
+ this.machine.onSessionActive();
95
+ if (event.data.reason.kind === 'completed') {
96
+ this.machine.onActivityStatus({ phase: 'done' });
97
+ this.rewardTurn(String(session.id), event.data.turn);
98
+ }
99
+ else {
100
+ // Aborted / failed turns clear the working pose instead of
101
+ // freezing the pet on its last phase.
102
+ this.machine.onActivityStatus({ phase: 'idle' });
103
+ }
104
+ break;
105
+ default:
106
+ break;
107
+ }
93
108
  }),
94
109
  this.ctx.on('session/disposed', () => {
95
110
  this.machine.onSessionDisposed();
@@ -191,23 +206,24 @@ export class PetService extends Service {
191
206
  // A settings write failure must not break the pet's own persistence.
192
207
  });
193
208
  }
194
- /** Award the turn reward once per done phase (idempotent per transition). */
195
- rewardTurn() {
196
- const nowMs = Date.now();
197
- // A done phase can repeat while celebrating; only reward the first.
198
- if (nowMs - this.lastTurnRewardAt < 5_000)
209
+ /** Award the turn reward once per completed turn (idempotent per session + turn). */
210
+ rewardTurn(sessionId, turn) {
211
+ const last = this.rewardedTurns.get(sessionId) ?? 0;
212
+ if (turn <= last)
199
213
  return;
200
- this.lastTurnRewardAt = nowMs;
214
+ this.rewardedTurns.set(sessionId, turn);
201
215
  this.persist = { ...this.persist, affinity: applyTurnReward(this.persist.affinity, this.affinityConfig) };
202
216
  this.flush();
203
217
  }
204
218
  /**
205
- * Settle the treat economy (work + time output since the last
206
- * settlement); persists only when treats were actually granted.
219
+ * Settle the treat economy (work + time output since the last settlement)
220
+ * and persist whenever the ledger changed. A zero-gain first settlement
221
+ * still starts the time clock (anchor write), which is what lets the
222
+ * 30-minute time output ever accrue.
207
223
  */
208
224
  settleTreats(nowMs) {
209
225
  const settlement = settleTreatGrants(this.persist.treats, this.persist.affinity.turns, nowMs, this.treatConfig);
210
- if (settlement.gained > 0) {
226
+ if (settlement.ledger !== this.persist.treats) {
211
227
  this.persist = { ...this.persist, treats: settlement.ledger };
212
228
  this.flush();
213
229
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Pet state machine — pure, clock-injected. Maps the DSH `activity/status`
3
- * phase vocabulary (session events) onto the 9-state Codex pet
4
- * animation contract, plus the session lifecycle transitions the web UI
5
- * exposes (turn end celebration, no-session idle).
2
+ * Pet state machine — pure, clock-injected. Maps the pet's working-phase
3
+ * vocabulary (the service derives it from core session events) onto the
4
+ * 9-state Codex pet animation contract, plus the session lifecycle
5
+ * transitions the web UI exposes (turn end celebration, no-session idle).
6
6
  *
7
7
  * The machine is deliberately dumb: it holds the last input phase, the
8
8
  * animation decision, and a one-shot "celebration" window after `done` so the
@@ -10,13 +10,13 @@
10
10
  * function of (input, nowMs); persistence and RPC live in the service.
11
11
  * @module @linxin666/dsh-pet/state
12
12
  */
13
- /** The DSH `activity/status` phase vocabulary (wire contract of session events). */
13
+ /** The pet's working-phase vocabulary (derived from core session events by the service). */
14
14
  export type ActivityPhase = 'idle' | 'waiting' | 'thinking' | 'tool' | 'done';
15
15
  /** The Codex-compatible 9-state animation contract (spritesheet rows). */
16
16
  export type PetAnimation = 'idle' | 'running-right' | 'running-left' | 'waving' | 'jumping' | 'failed' | 'waiting' | 'running' | 'review';
17
17
  /** One input snapshot consumed by the machine. */
18
18
  export interface PetStateInput {
19
- /** Current activity/status phase of the active session. */
19
+ /** Current working phase of the active session. */
20
20
  phase: ActivityPhase;
21
21
  /** Human-readable status line (plain text). */
22
22
  line?: string;
@@ -68,7 +68,7 @@ export declare class PetStateMachine {
68
68
  private sessionActive;
69
69
  private doneAt;
70
70
  constructor(config?: PetStateConfig, now?: () => number);
71
- /** Consume one `activity/status` session event. */
71
+ /** Consume one phase snapshot (fed by the service from session events). */
72
72
  onActivityStatus(input: PetStateInput): void;
73
73
  /** A session became the active one (or a fresh session started). */
74
74
  onSessionActive(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,oFAAoF;AACpF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAE7E,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,eAAe,GACf,cAAc,GACd,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,CAAA;AAEZ,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,KAAK,EAAE,aAAa,CAAA;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,SAAS,EAAE,YAAY,CAAA;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAA;IACpB,0DAA0D;IAC1D,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAsC,CAAA;AAE1E;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAQpE;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAarD;AAED;;;GAGG;AACH,qBAAa,eAAe;IAQxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAoB;gBAGf,MAAM,GAAE,cAAsC,EAC9C,GAAG,GAAE,MAAM,MAAiB;IAG/C,mDAAmD;IACnD,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAO5C,oEAAoE;IACpE,eAAe,IAAI,IAAI;IAIvB,sDAAsD;IACtD,iBAAiB,IAAI,IAAI;IAQzB,6CAA6C;IAC7C,MAAM,IAAI,gBAAgB;CAoB3B"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAE7E,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,eAAe,GACf,cAAc,GACd,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,CAAA;AAEZ,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,KAAK,EAAE,aAAa,CAAA;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,SAAS,EAAE,YAAY,CAAA;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAA;IACpB,0DAA0D;IAC1D,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAsC,CAAA;AAE1E;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAQpE;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAarD;AAED;;;GAGG;AACH,qBAAa,eAAe;IAQxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAoB;gBAGf,MAAM,GAAE,cAAsC,EAC9C,GAAG,GAAE,MAAM,MAAiB;IAG/C,2EAA2E;IAC3E,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAO5C,oEAAoE;IACpE,eAAe,IAAI,IAAI;IAIvB,sDAAsD;IACtD,iBAAiB,IAAI,IAAI;IAQzB,6CAA6C;IAC7C,MAAM,IAAI,gBAAgB;CAoB3B"}
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Pet state machine — pure, clock-injected. Maps the DSH `activity/status`
3
- * phase vocabulary (session events) onto the 9-state Codex pet
4
- * animation contract, plus the session lifecycle transitions the web UI
5
- * exposes (turn end celebration, no-session idle).
2
+ * Pet state machine — pure, clock-injected. Maps the pet's working-phase
3
+ * vocabulary (the service derives it from core session events) onto the
4
+ * 9-state Codex pet animation contract, plus the session lifecycle
5
+ * transitions the web UI exposes (turn end celebration, no-session idle).
6
6
  *
7
7
  * The machine is deliberately dumb: it holds the last input phase, the
8
8
  * animation decision, and a one-shot "celebration" window after `done` so the
@@ -61,7 +61,7 @@ export class PetStateMachine {
61
61
  this.config = config;
62
62
  this.now = now;
63
63
  }
64
- /** Consume one `activity/status` session event. */
64
+ /** Consume one phase snapshot (fed by the service from session events). */
65
65
  onActivityStatus(input) {
66
66
  this.phase = input.phase;
67
67
  this.line = input.line;
@@ -42,8 +42,12 @@ export interface TreatSettlement {
42
42
  * time output counts whole periods since the time anchor
43
43
  * (`lastTreatGrantAt`) and advances only the time anchor. The two sources
44
44
  * are independent so a continuously working user still earns time treats.
45
- * 0 time history never backfills — the clock starts at the first settlement.
46
- * Both sources are clamped by the stock cap.
45
+ * 0 time history never backfills — the clock starts at the first settlement,
46
+ * and even a zero-gain first settlement writes the time anchor so the next
47
+ * elapsed period can accrue (anchor deadlock fix). Both sources are clamped
48
+ * by the stock cap. When the anchor is already set and nothing is due, the
49
+ * input ledger is returned unchanged (same object), so callers can skip
50
+ * persistence cheaply.
47
51
  */
48
52
  export declare function settleTreatGrants(ledger: TreatLedger, turns: number, nowMs: number, config?: TreatConfig): TreatSettlement;
49
53
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"treats.d.ts","sourceRoot":"","sources":["../../src/treats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAA;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,gBAAgB,EAAE,MAAM,CAAA;IACxB,8EAA8E;IAC9E,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,MAAM,EAAE,WAAW,CAAA;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;CACf;AAMD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,WAAgC,GACvC,eAAe,CAqBjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAGnD"}
1
+ {"version":3,"file":"treats.d.ts","sourceRoot":"","sources":["../../src/treats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,4BAA4B;AAC5B,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAA;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,gBAAgB,EAAE,MAAM,CAAA;IACxB,8EAA8E;IAC9E,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,MAAM,EAAE,WAAW,CAAA;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;CACf;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,WAAgC,GACvC,eAAe,CA6BjB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAGnD"}
@@ -26,8 +26,12 @@ function cap(treats, max) {
26
26
  * time output counts whole periods since the time anchor
27
27
  * (`lastTreatGrantAt`) and advances only the time anchor. The two sources
28
28
  * are independent so a continuously working user still earns time treats.
29
- * 0 time history never backfills — the clock starts at the first settlement.
30
- * Both sources are clamped by the stock cap.
29
+ * 0 time history never backfills — the clock starts at the first settlement,
30
+ * and even a zero-gain first settlement writes the time anchor so the next
31
+ * elapsed period can accrue (anchor deadlock fix). Both sources are clamped
32
+ * by the stock cap. When the anchor is already set and nothing is due, the
33
+ * input ledger is returned unchanged (same object), so callers can skip
34
+ * persistence cheaply.
31
35
  */
32
36
  export function settleTreatGrants(ledger, turns, nowMs, config = defaultTreatConfig) {
33
37
  const turnDelta = Math.max(0, turns - ledger.turnsAtLastTreatGrant);
@@ -37,8 +41,15 @@ export function settleTreatGrants(ledger, turns, nowMs, config = defaultTreatCon
37
41
  const timeAnchor = ledger.lastTreatGrantAt === 0 ? nowMs : ledger.lastTreatGrantAt;
38
42
  const timeGrants = Math.floor(Math.max(0, nowMs - timeAnchor) / config.timeTreatMs);
39
43
  const gained = workGrants + timeGrants;
40
- if (gained <= 0)
44
+ if (gained <= 0) {
45
+ if (ledger.lastTreatGrantAt === 0) {
46
+ // Zero-gain first settlement: persist the clock start anyway, so the
47
+ // 30-minute time output can begin. Before this fix the anchor stayed 0
48
+ // forever (the deadlock: no grant means no anchor write means no grant).
49
+ return { ledger: { ...ledger, lastTreatGrantAt: nowMs }, gained: 0 };
50
+ }
41
51
  return { ledger, gained: 0 };
52
+ }
42
53
  return {
43
54
  ledger: {
44
55
  treats: cap(ledger.treats + gained, config.maxTreats),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@linxin666/dsh-pet",
3
3
  "description": "鲸鱼娘宠物插件 for the dsh web GUI: a soft healing whale-girl companion that reacts to model activity (idle/waiting/thinking/tool/done), with petting/feeding interactions and an affinity score",
4
- "version": "0.1.11",
4
+ "version": "0.1.13",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "^22.19.0 || >=24.0.0"
@@ -33,7 +33,7 @@
33
33
  "cordis.patch.yml",
34
34
  "assets"
35
35
  ],
36
- "license": "BSD-3-Clause",
36
+ "license": "Apache-2.0",
37
37
  "dsh": {
38
38
  "bundle": {
39
39
  "patch": "./cordis.patch.yml"
@@ -53,16 +53,6 @@
53
53
  "schemastery": "^3.18.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
57
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
58
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
59
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
60
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
61
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
62
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
63
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
64
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
65
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
66
56
  "react": "^18.2.0",
67
57
  "react-dom": "^18.2.0"
68
58
  },