@linxin666/dsh-pet 0.1.18 → 0.1.20

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 (90) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +12 -5
  3. package/README.zh.md +12 -5
  4. package/lib/client.js +95 -26
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +144 -31
  7. package/lib/invariant.js +2 -2
  8. package/lib/state-Diiq8vjk.js +394 -0
  9. package/lib/types/affinity.d.ts +39 -11
  10. package/lib/types/affinity.d.ts.map +1 -1
  11. package/lib/types/affinity.js +21 -7
  12. package/lib/types/client/PetDockEntry.d.ts +2 -0
  13. package/lib/types/client/PetDockEntry.d.ts.map +1 -1
  14. package/lib/types/client/PetDockEntry.js +2 -2
  15. package/lib/types/client/PetSettingsCard.d.ts +5 -0
  16. package/lib/types/client/PetSettingsCard.d.ts.map +1 -1
  17. package/lib/types/client/PetSettingsCard.js +9 -2
  18. package/lib/types/client/PetSprite.d.ts +2 -0
  19. package/lib/types/client/PetSprite.d.ts.map +1 -1
  20. package/lib/types/client/PetSprite.js +22 -15
  21. package/lib/types/client/PluginSettingsCard.d.ts +1 -1
  22. package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
  23. package/lib/types/client/index.d.ts +1 -1
  24. package/lib/types/client/index.d.ts.map +1 -1
  25. package/lib/types/client/index.js +45 -14
  26. package/lib/types/client/locales.d.ts +82 -80
  27. package/lib/types/client/locales.d.ts.map +1 -1
  28. package/lib/types/client/locales.js +2 -0
  29. package/lib/types/client/settings-form.d.ts +8 -0
  30. package/lib/types/client/settings-form.d.ts.map +1 -1
  31. package/lib/types/client/settings-form.js +15 -1
  32. package/lib/types/client/spritesheet.d.ts +1 -1
  33. package/lib/types/client/spritesheet.d.ts.map +1 -1
  34. package/lib/types/client/spritesheet.js +3 -12
  35. package/lib/types/event-projection.d.ts.map +1 -1
  36. package/lib/types/event-projection.js +3 -1
  37. package/lib/types/index.d.ts +6 -3
  38. package/lib/types/index.d.ts.map +1 -1
  39. package/lib/types/index.js +15 -12
  40. package/lib/types/invariant.js +2 -2
  41. package/lib/types/ledger.d.ts +16 -1
  42. package/lib/types/ledger.d.ts.map +1 -1
  43. package/lib/types/ledger.js +31 -6
  44. package/lib/types/mount-once.d.ts +25 -0
  45. package/lib/types/mount-once.d.ts.map +1 -0
  46. package/lib/types/mount-once.js +42 -0
  47. package/lib/types/persist.js +3 -3
  48. package/lib/types/registry.d.ts +10 -0
  49. package/lib/types/registry.d.ts.map +1 -1
  50. package/lib/types/registry.js +3 -0
  51. package/lib/types/remarks.d.ts +56 -0
  52. package/lib/types/remarks.d.ts.map +1 -0
  53. package/lib/types/remarks.js +157 -0
  54. package/lib/types/routes.js +2 -2
  55. package/lib/types/service.d.ts +44 -3
  56. package/lib/types/service.d.ts.map +1 -1
  57. package/lib/types/service.js +100 -23
  58. package/lib/types/state.d.ts.map +1 -1
  59. package/lib/types/state.js +5 -5
  60. package/lib/types/treats.d.ts +3 -0
  61. package/lib/types/treats.d.ts.map +1 -1
  62. package/lib/types/treats.js +5 -2
  63. package/package.json +1 -1
  64. package/src/affinity.test.ts +19 -0
  65. package/src/affinity.ts +22 -7
  66. package/src/client/PetDockEntry.tsx +3 -0
  67. package/src/client/PetSettingsCard.tsx +8 -0
  68. package/src/client/PetSprite.test.tsx +89 -3
  69. package/src/client/PetSprite.tsx +36 -12
  70. package/src/client/index.ts +40 -11
  71. package/src/client/locales.ts +2 -0
  72. package/src/client/pet.module.css +52 -10
  73. package/src/client/settings-form.ts +15 -1
  74. package/src/client/spritesheet.ts +3 -13
  75. package/src/event-projection.ts +3 -1
  76. package/src/index.ts +16 -2
  77. package/src/ledger.test.ts +40 -9
  78. package/src/ledger.ts +33 -4
  79. package/src/mount-once.ts +48 -0
  80. package/src/persist.test.ts +1 -1
  81. package/src/registry.test.ts +27 -0
  82. package/src/registry.ts +12 -0
  83. package/src/remarks.test.ts +89 -0
  84. package/src/remarks.ts +177 -0
  85. package/src/service.ts +124 -18
  86. package/src/state.test.ts +9 -0
  87. package/src/state.ts +5 -5
  88. package/src/treats.test.ts +13 -11
  89. package/src/treats.ts +5 -2
  90. package/lib/state-CFyJv0sQ.js +0 -213
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
3
  * Pet sprite companion component — the browser half's centerpiece. Renders a
4
4
  * fixed-position floating sprite (React portal onto document.body), plays
@@ -12,7 +12,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  import { useEffect, useRef, useState } from 'react';
13
13
  import { createPortal } from 'react-dom';
14
14
  import clsx from 'clsx';
15
- import { framePosition, rowOfTrack, trimTrack } from "./spritesheet.js";
15
+ import { framePosition, rowOfTrack, trimTrack } from './spritesheet.js';
16
16
  import styles from './pet.module.css';
17
17
  /** Clamp a drag offset inside the viewport with a margin. */
18
18
  function clampOffset(value, max) {
@@ -88,10 +88,9 @@ export function PetSprite(props) {
88
88
  const tick = (ts) => {
89
89
  const delta = ts - last;
90
90
  last = ts;
91
- // Trim the track to the row's real frame count (transparent cells
92
- // would render as a vanishing pet).
93
- const row = rowOfTrack(animation);
94
- const track = trimTrack(tracks[animation], rows[row] ?? tracks[animation].frames.length);
91
+ // row/track come from the effect scope: they were computed once above
92
+ // and this effect re-runs when animation/tracks/rows change, so the
93
+ // per-frame recompute (trimTrack slices fresh arrays) is pure waste.
95
94
  const st = frameRef.current;
96
95
  if (st.track !== animation) {
97
96
  st.track = animation;
@@ -174,19 +173,27 @@ export function PetSprite(props) {
174
173
  const pos = dragPos ?? { right: display.right, bottom: display.bottom };
175
174
  const spriteWidth = Math.round(cell.width * spriteScale);
176
175
  const spriteHeight = Math.round(cell.height * spriteScale);
177
- const statusBubble = feedback === null && !hovered ? snapshot?.bubble : undefined;
176
+ // Concurrent sessions each render their own bubble (stacked above the
177
+ // 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.
180
+ const sessionBubbles = snapshot?.sessions ?? [];
181
+ const statusBubble = feedback === null && sessionBubbles.length === 0
182
+ ? snapshot?.bubble
183
+ : undefined;
178
184
  const displayName = snapshot?.name ?? definition.displayName;
179
185
  const float = (_jsxs("div", { ref: floatRef, className: styles.float, style: { right: pos.right, bottom: pos.bottom, zIndex: 2147483000 }, onPointerEnter: () => {
180
186
  clearHideTimer();
181
187
  setHovered(true);
182
188
  }, onPointerLeave: (e) => {
183
- // The panel and bubble render OUTSIDE the container's box (absolute,
184
- // above the sprite), so moving onto them fires pointerleave on the
185
- // container. Treat a target still inside the container's DOM (the
186
- // overflowed panel) as "still hovering"; otherwise give the pointer a
187
- // short grace period to reach the panel across the gap above it. The
188
- // bridge ('.panel::after') keeps the pointer inside the hit area, and
189
- // the grace period covers a slow mouse crossing the remaining sliver.
189
+ // The panel renders OUTSIDE the container's box (absolute, beside
190
+ // the sprite), so moving onto it fires pointerleave on the container.
191
+ // Treat a target still inside the container's DOM (the overflowed
192
+ // panel) as "still hovering"; otherwise give the pointer a short
193
+ // grace period to reach the panel across the gap beside the sprite.
194
+ // The bridge ('.panel::after') keeps the pointer inside the hit
195
+ // area, and the grace period covers a slow mouse crossing the
196
+ // remaining sliver.
190
197
  const next = e.relatedTarget;
191
198
  if (next instanceof Node && floatRef.current?.contains(next))
192
199
  return;
@@ -206,7 +213,7 @@ export function PetSprite(props) {
206
213
  if (draggedRef.current)
207
214
  return;
208
215
  props.onPet();
209
- }, 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)), 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: () => {
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: () => {
210
217
  // Reaching the panel (or its bridge) must cancel any hide timer
211
218
  // the container's pointerleave may have armed while the pointer
212
219
  // crossed the sliver between the sprite and the panel.
@@ -9,7 +9,7 @@
9
9
  import { type ReactNode } from 'react';
10
10
  import type { CardShell } from './settings-form.ts';
11
11
  /** Copy keys the card chrome itself reads; every consumer locale carries this shared vocabulary. */
12
- export declare const CARD_COPY_KEYS: readonly ["settings.collapse", "settings.expand", "settings.notExposed", "settings.unsaved", "settings.readOnly", "settings.saveFailed", "settings.discard", "settings.save", "settings.saving"];
12
+ export declare const CARD_COPY_KEYS: readonly ['settings.collapse', 'settings.expand', 'settings.notExposed', 'settings.unsaved', 'settings.readOnly', 'settings.saveFailed', 'settings.discard', 'settings.save', 'settings.saving'];
13
13
  /** Copy key the card chrome itself reads. */
14
14
  export type CardCopyKey = (typeof CARD_COPY_KEYS)[number];
15
15
  /** Key domain for the plugin's own copy (inferred per consumer). */
@@ -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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"}
@@ -11,7 +11,7 @@
11
11
  * @module @linxin666/dsh-pet/client
12
12
  */
13
13
  import type { ClientContext, SettingsScope, SettingsScopeSpec } from '@deepseek-ai/dsh-client-runtime/client';
14
- /** Required services. */
14
+ /** Required services (sessions powers bubble-to-session navigation). */
15
15
  export declare const inject: string[];
16
16
  /** Re-exported for consumers that type against the injected face. */
17
17
  export type { PetInjected, PetDockEntryProps } from './PetDockEntry.tsx';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AA6D7G,yBAAyB;AACzB,eAAO,MAAM,MAAM,UAA+D,CAAA;AAElF,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,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;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAoL9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAwB,aAAa,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AA6DnI,wEAAwE;AACxE,eAAO,MAAM,MAAM,UAA2E,CAAA;AAE9F,qEAAqE;AACrE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACtF,YAAY,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,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;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAiN9C"}
@@ -12,10 +12,10 @@
12
12
  */
13
13
  import { createElement } from 'react';
14
14
  import { createRoot } from 'react-dom/client';
15
- import { createPetStore } from "./pet-store.js";
16
- import { PetDockEntry } from "./PetDockEntry.js";
17
- import { PetSettingsSection, PetSettingsCardController } from "./PetSettingsCard.js";
18
- import { NS, en, zh, t } from "./locales.js";
15
+ import { createPetStore } from './pet-store.js';
16
+ import { PetDockEntry } from './PetDockEntry.js';
17
+ import { PetSettingsSection, PetSettingsCardController } from './PetSettingsCard.js';
18
+ import { NS, en, zh, t } from './locales.js';
19
19
  /** Same-origin JSON fetch helper (GET without body, POST with JSON body). */
20
20
  async function petFetch(path, body) {
21
21
  const response = await fetch(path, body === undefined
@@ -44,8 +44,8 @@ const petApi = {
44
44
  const POLL_MS = 2000;
45
45
  /** Settings namespace the pet settings card edits (the Host plugin registers it). */
46
46
  const PET_SETTINGS_NS = 'pet';
47
- /** Required services. */
48
- export const inject = ['slots', 'locale', 'connection', 'settingsScope', 'remote'];
47
+ /** Required services (sessions powers bubble-to-session navigation). */
48
+ export const inject = ['slots', 'locale', 'connection', 'settingsScope', 'remote', 'sessions'];
49
49
  /**
50
50
  * Client plugin body: register dictionaries, mount the global pet entry and
51
51
  * poll loop while the plugin is enabled, and seat the settings card as a
@@ -66,14 +66,20 @@ export function apply(ctx) {
66
66
  // namespace, registered as a top-level settings page. The controller loads
67
67
  // the petId choices from the registry endpoint itself.
68
68
  const petSettings = new PetSettingsCardController(settingsScope);
69
- ctx.slots.inject('settings.section', () => ctx.slots.register({
70
- name: 'settings.section',
71
- id: 'pet',
72
- order: 130,
73
- label: () => ctx.locale.bind('pet')('settings.title'),
74
- locale: 'pet',
75
- inject: () => petSettings.inject(),
76
- }, PetSettingsSection));
69
+ ctx.slots.inject('settings.section', () => {
70
+ const unregister = ctx.slots.register({
71
+ name: 'settings.section',
72
+ id: 'pet',
73
+ order: 130,
74
+ label: () => ctx.locale.bind('pet')('settings.title'),
75
+ locale: 'pet',
76
+ inject: () => petSettings.inject(),
77
+ }, PetSettingsSection);
78
+ return () => {
79
+ petSettings.dispose();
80
+ unregister();
81
+ };
82
+ });
77
83
  // The global pet entry, its store, and the poll loop live while the plugin
78
84
  // is enabled; toggling the setting off hides the pet and stops polling.
79
85
  let disposeUi;
@@ -94,6 +100,11 @@ export function apply(ctx) {
94
100
  // tick tries again. After it lands, one list feeds both the sprite and
95
101
  // the settings card's choices.
96
102
  let petsLoaded = false;
103
+ // Latest-wins guard: the 2s tick, visibility recovery, and
104
+ // interaction-triggered refreshes can overlap; only the newest
105
+ // response may publish, so a slow older one can never roll the
106
+ // snapshot back.
107
+ let stateSeq = 0;
97
108
  const pollNow = () => {
98
109
  if (!petsLoaded) {
99
110
  petApi.pets().then((list) => {
@@ -103,9 +114,15 @@ export function apply(ctx) {
103
114
  // Retry on the next poll tick.
104
115
  });
105
116
  }
117
+ const seq = stateSeq + 1;
118
+ stateSeq = seq;
106
119
  petApi.state().then((snapshot) => {
120
+ if (seq !== stateSeq)
121
+ return;
107
122
  setSnapshot(snapshot);
108
123
  }, () => {
124
+ if (seq !== stateSeq)
125
+ return;
109
126
  setState('error', 'pet.state transport error');
110
127
  });
111
128
  };
@@ -143,9 +160,23 @@ export function apply(ctx) {
143
160
  document.removeEventListener('visibilitychange', onVisibility);
144
161
  };
145
162
  }, 'pet: poll');
163
+ // Clicking a session bubble jumps the GUI to that session. A bubble
164
+ // can outlive its disposed session by one poll tick, and the sessions
165
+ // service fails loud on unknown ids, so consult the live list first.
166
+ // The pet's type program also loads the host-side dsh-session package
167
+ // through the service types, whose Context merge declares a different
168
+ // 'sessions' face; pin the browser runtime's outward face here.
169
+ const sessions = ctx.sessions;
170
+ const openSession = (sessionId) => {
171
+ const list = sessions.list.getSnapshot();
172
+ if (list.byId[sessionId] === undefined)
173
+ return;
174
+ sessions.open(sessionId);
175
+ };
146
176
  const injected = () => ({
147
177
  store: petStore,
148
178
  ensure: pollNow,
179
+ openSession,
149
180
  pet: () => {
150
181
  petApi.interact('pet').then((result) => {
151
182
  setFeedback({
@@ -6,89 +6,91 @@
6
6
  export declare const NS = "pet";
7
7
  /** Chinese copy. */
8
8
  export declare const zh: {
9
- readonly 'pet.feed': "喂食";
10
- readonly 'pet.hide': "隐藏";
11
- readonly 'pet.rename': "改名";
12
- readonly 'pet.confirm': "确定";
13
- readonly 'pet.namePlaceholder': "输入新名字";
14
- readonly 'pet.summon': "召唤{name}";
15
- readonly 'pet.rank': "亲密度 {rank}";
16
- readonly 'pet.points': "{points} 点";
17
- readonly 'pet.treats': "小鱼干 ×{n}";
18
- readonly 'pet.state.loading': "宠物正在赶来…";
19
- readonly 'pet.state.error': "宠物迷路了(连接失败)";
20
- readonly 'settings.title': "宠物";
21
- readonly 'settings.description': "选择宠物并调整它的显示布局。";
22
- readonly 'settings.pet': "宠物";
23
- readonly 'settings.petHint': "选择显示哪只宠物;每只宠物独立命名,可在宠物悬浮面板改名。";
24
- readonly 'settings.enabled': "启用宠物";
25
- readonly 'settings.enabledHint': "关闭后隐藏宠物并停止轮询,可在设置里重新启用。";
26
- readonly 'settings.visible': "显示宠物";
27
- readonly 'settings.visibleHint': "关闭后宠物隐藏,可从聊天输入区重新召唤。";
28
- readonly 'settings.size': "大小(px)";
29
- readonly 'settings.sizeHint': "精灵单元高度,范围 32–512。";
30
- readonly 'settings.right': "距右侧(px)";
31
- readonly 'settings.rightHint': "距视口右边缘的水平内缩距离。";
32
- readonly 'settings.bottom': "距底部(px)";
33
- readonly 'settings.bottomHint': "距视口底边的垂直内缩距离。";
34
- readonly 'settings.inherit': "继承";
35
- readonly 'settings.on': "开";
36
- readonly 'settings.off': "关";
37
- readonly 'settings.overridden': "已覆盖";
38
- readonly 'settings.reset': "恢复默认";
39
- readonly 'settings.notExposed': "当前 DSH 版本未向设置页暴露本插件的配置命名空间,表单不可用。可编辑 ~/.dsh/settings.yaml 直接配置,或为 dsh-host-apiproxy 的 WEB_SETTINGS_NAMESPACES 白名单补充本命名空间后重启。";
40
- readonly 'settings.readOnly': "当前部署的设置只读。";
41
- readonly 'settings.expand': "展开设置";
42
- readonly 'settings.collapse': "收起设置";
43
- readonly 'settings.save': "保存";
44
- readonly 'settings.saving': "保存中…";
45
- readonly 'settings.discard': "放弃";
46
- readonly 'settings.unsaved': "未保存";
47
- readonly 'settings.saveFailed': "部署未接受这些值,已保留供你修改。";
48
- readonly 'settings.invalidNumber': "请输入数字,留空则使用默认值。";
9
+ readonly 'pet.feed': '喂食';
10
+ readonly 'pet.hide': '隐藏';
11
+ readonly 'pet.rename': '改名';
12
+ readonly 'pet.confirm': '确定';
13
+ readonly 'pet.namePlaceholder': '输入新名字';
14
+ readonly 'pet.summon': '召唤{name}';
15
+ readonly 'pet.rank': '亲密度 {rank}';
16
+ readonly 'pet.points': '{points} 点';
17
+ readonly 'pet.treats': '小鱼干 ×{n}';
18
+ readonly 'pet.state.loading': '宠物正在赶来…';
19
+ readonly 'pet.state.error': '宠物迷路了(连接失败)';
20
+ readonly 'pet.openSessionHint': '点击跳转到对应会话';
21
+ readonly 'settings.title': '宠物';
22
+ readonly 'settings.description': '选择宠物并调整它的显示布局。';
23
+ readonly 'settings.pet': '宠物';
24
+ readonly 'settings.petHint': '选择显示哪只宠物;每只宠物独立命名,可在宠物悬浮面板改名。';
25
+ readonly 'settings.enabled': '启用宠物';
26
+ readonly 'settings.enabledHint': '关闭后隐藏宠物并停止轮询,可在设置里重新启用。';
27
+ readonly 'settings.visible': '显示宠物';
28
+ readonly 'settings.visibleHint': '关闭后宠物隐藏,可从聊天输入区重新召唤。';
29
+ readonly 'settings.size': '大小(px)';
30
+ readonly 'settings.sizeHint': '精灵单元高度,范围 32–512。';
31
+ readonly 'settings.right': '距右侧(px)';
32
+ readonly 'settings.rightHint': '距视口右边缘的水平内缩距离。';
33
+ readonly 'settings.bottom': '距底部(px)';
34
+ readonly 'settings.bottomHint': '距视口底边的垂直内缩距离。';
35
+ readonly 'settings.inherit': '继承';
36
+ readonly 'settings.on': '开';
37
+ readonly 'settings.off': '关';
38
+ readonly 'settings.overridden': '已覆盖';
39
+ readonly 'settings.reset': '恢复默认';
40
+ readonly 'settings.notExposed': '当前 DSH 版本未向设置页暴露本插件的配置命名空间,表单不可用。可编辑 ~/.dsh/settings.yaml 直接配置,或为 dsh-host-apiproxy 的 WEB_SETTINGS_NAMESPACES 白名单补充本命名空间后重启。';
41
+ readonly 'settings.readOnly': '当前部署的设置只读。';
42
+ readonly 'settings.expand': '展开设置';
43
+ readonly 'settings.collapse': '收起设置';
44
+ readonly 'settings.save': '保存';
45
+ readonly 'settings.saving': '保存中…';
46
+ readonly 'settings.discard': '放弃';
47
+ readonly 'settings.unsaved': '未保存';
48
+ readonly 'settings.saveFailed': '部署未接受这些值,已保留供你修改。';
49
+ readonly 'settings.invalidNumber': '请输入数字,留空则使用默认值。';
49
50
  };
50
51
  /** English copy. */
51
52
  export declare const en: {
52
- readonly 'pet.feed': "Feed";
53
- readonly 'pet.hide': "Hide";
54
- readonly 'pet.rename': "Rename";
55
- readonly 'pet.confirm': "OK";
56
- readonly 'pet.namePlaceholder': "Enter a new name";
57
- readonly 'pet.summon': "Summon {name}";
58
- readonly 'pet.rank': "Affinity {rank}";
59
- readonly 'pet.points': "{points} pts";
60
- readonly 'pet.treats': "Treats ×{n}";
61
- readonly 'pet.state.loading': "The pet is on its way…";
62
- readonly 'pet.state.error': "The pet is lost (connection failed)";
63
- readonly 'settings.title': "Pet";
64
- readonly 'settings.description': "Pick a pet and tune its display layout.";
65
- readonly 'settings.pet': "Pet";
66
- readonly 'settings.petHint': "Choose which pet shows. Names are stored per pet; rename from the pet hover panel.";
67
- readonly 'settings.enabled': "Enable the pet";
68
- readonly 'settings.enabledHint': "When off, the pet hides and polling stops; re-enable it here.";
69
- readonly 'settings.visible': "Show the pet";
70
- readonly 'settings.visibleHint': "When off, the pet hides; summon it again from the input row.";
71
- readonly 'settings.size': "Size (px)";
72
- readonly 'settings.sizeHint': "Sprite cell height, 32–512.";
73
- readonly 'settings.right': "Right inset (px)";
74
- readonly 'settings.rightHint': "Horizontal inset from the viewport right edge.";
75
- readonly 'settings.bottom': "Bottom inset (px)";
76
- readonly 'settings.bottomHint': "Vertical inset from the viewport bottom edge.";
77
- readonly 'settings.inherit': "Inherit";
78
- readonly 'settings.on': "On";
79
- readonly 'settings.off': "Off";
80
- readonly 'settings.overridden': "Overridden";
81
- readonly 'settings.reset': "Reset to default";
82
- readonly 'settings.notExposed': "This DSH version does not expose this plugin's settings namespace to the configuration page, so the form is unavailable. Edit ~/.dsh/settings.yaml directly, or add the namespace to dsh-host-apiproxy's WEB_SETTINGS_NAMESPACES allowlist and restart.";
83
- readonly 'settings.readOnly': "This deployment stores settings read-only.";
84
- readonly 'settings.expand': "Show settings";
85
- readonly 'settings.collapse': "Hide settings";
86
- readonly 'settings.save': "Save";
87
- readonly 'settings.saving': "Saving…";
88
- readonly 'settings.discard': "Discard";
89
- readonly 'settings.unsaved': "Unsaved";
90
- readonly 'settings.saveFailed': "The deployment did not accept these values; they were left for you to correct.";
91
- readonly 'settings.invalidNumber': "Enter a number, or leave blank to use the default.";
53
+ readonly 'pet.feed': 'Feed';
54
+ readonly 'pet.hide': 'Hide';
55
+ readonly 'pet.rename': 'Rename';
56
+ readonly 'pet.confirm': 'OK';
57
+ readonly 'pet.namePlaceholder': 'Enter a new name';
58
+ readonly 'pet.summon': 'Summon {name}';
59
+ readonly 'pet.rank': 'Affinity {rank}';
60
+ readonly 'pet.points': '{points} pts';
61
+ readonly 'pet.treats': 'Treats ×{n}';
62
+ readonly 'pet.state.loading': 'The pet is on its way…';
63
+ readonly 'pet.state.error': 'The pet is lost (connection failed)';
64
+ readonly 'pet.openSessionHint': 'Click to jump to this session';
65
+ readonly 'settings.title': 'Pet';
66
+ readonly 'settings.description': 'Pick a pet and tune its display layout.';
67
+ readonly 'settings.pet': 'Pet';
68
+ readonly 'settings.petHint': 'Choose which pet shows. Names are stored per pet; rename from the pet hover panel.';
69
+ readonly 'settings.enabled': 'Enable the pet';
70
+ readonly 'settings.enabledHint': 'When off, the pet hides and polling stops; re-enable it here.';
71
+ readonly 'settings.visible': 'Show the pet';
72
+ readonly 'settings.visibleHint': 'When off, the pet hides; summon it again from the input row.';
73
+ readonly 'settings.size': 'Size (px)';
74
+ readonly 'settings.sizeHint': 'Sprite cell height, 32–512.';
75
+ readonly 'settings.right': 'Right inset (px)';
76
+ readonly 'settings.rightHint': 'Horizontal inset from the viewport right edge.';
77
+ readonly 'settings.bottom': 'Bottom inset (px)';
78
+ readonly 'settings.bottomHint': 'Vertical inset from the viewport bottom edge.';
79
+ readonly 'settings.inherit': 'Inherit';
80
+ readonly 'settings.on': 'On';
81
+ readonly 'settings.off': 'Off';
82
+ readonly 'settings.overridden': 'Overridden';
83
+ readonly 'settings.reset': 'Reset to default';
84
+ readonly 'settings.notExposed': 'This DSH version does not expose this plugin\'s settings namespace to the configuration page, so the form is unavailable. Edit ~/.dsh/settings.yaml directly, or add the namespace to dsh-host-apiproxy\'s WEB_SETTINGS_NAMESPACES allowlist and restart.';
85
+ readonly 'settings.readOnly': 'This deployment stores settings read-only.';
86
+ readonly 'settings.expand': 'Show settings';
87
+ readonly 'settings.collapse': 'Hide settings';
88
+ readonly 'settings.save': 'Save';
89
+ readonly 'settings.saving': 'Saving…';
90
+ readonly 'settings.discard': 'Discard';
91
+ readonly 'settings.unsaved': 'Unsaved';
92
+ readonly 'settings.saveFailed': 'The deployment did not accept these values; they were left for you to correct.';
93
+ readonly 'settings.invalidNumber': 'Enter a number, or leave blank to use the default.';
92
94
  };
93
95
  /** Key union for this namespace. */
94
96
  export type PetKey = keyof typeof zh;
@@ -1 +1 @@
1
- {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mDAAmD;AACnD,eAAO,MAAM,EAAE,QAAQ,CAAA;AAEvB,oBAAoB;AACpB,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CL,CAAA;AAEV,oBAAoB;AACpB,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CL,CAAA;AAEV,oCAAoC;AACpC,MAAM,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAA;AAEpC,qDAAqD;AACrD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAA;AAEpC;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAGnD;AAED;;;;;;;GAOG;AACH,wBAAgB,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAQvE;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,uBAAuB;QACvB,GAAG,EAAE,MAAM,CAAA;KACZ;CACF"}
1
+ {"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ export const zh = {
17
17
  'pet.treats': '小鱼干 ×{n}',
18
18
  'pet.state.loading': '宠物正在赶来…',
19
19
  'pet.state.error': '宠物迷路了(连接失败)',
20
+ 'pet.openSessionHint': '点击跳转到对应会话',
20
21
  // 一级设置页(settings.section 席位)。
21
22
  'settings.title': '宠物',
22
23
  'settings.description': '选择宠物并调整它的显示布局。',
@@ -61,6 +62,7 @@ export const en = {
61
62
  'pet.treats': 'Treats ×{n}',
62
63
  'pet.state.loading': 'The pet is on its way…',
63
64
  'pet.state.error': 'The pet is lost (connection failed)',
65
+ 'pet.openSessionHint': 'Click to jump to this session',
64
66
  // First-level settings section (the `settings.section` seat).
65
67
  'settings.title': 'Pet',
66
68
  'settings.description': 'Pick a pet and tune its display layout.',
@@ -149,11 +149,19 @@ export declare class CardForm<T> {
149
149
  private readonly specs;
150
150
  private readonly staged;
151
151
  private readonly listeners;
152
+ /** The scope subscription installed in the constructor; released by dispose(). */
153
+ private readonly disposeScope;
154
+ private disposed;
152
155
  private saving;
153
156
  private failed;
154
157
  private failedReason;
155
158
  /** @param scope - the bound settings scope for this card's namespace. */
156
159
  constructor(scope: SettingsScope<T>, specs: FieldSpec[]);
160
+ /**
161
+ * Release the scope subscription and every bound store listener. The card
162
+ * must call this on teardown; later calls are no-ops.
163
+ */
164
+ dispose(): void;
157
165
  /** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */
158
166
  bind<S>(project: () => S): SnapshotStore<S>;
159
167
  /** Read the card-level state: what the Host serves, and what a save would do. */
@@ -1 +1 @@
1
- {"version":3,"file":"settings-form.d.ts","sourceRoot":"","sources":["../../../src/client/settings-form.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings-form.d.ts","sourceRoot":"","sources":["../../../src/client/settings-form.ts"],"names":[],"mappings":"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"}
@@ -91,6 +91,9 @@ export class CardForm {
91
91
  specs;
92
92
  staged = new Map();
93
93
  listeners = new Set();
94
+ /** The scope subscription installed in the constructor; released by dispose(). */
95
+ disposeScope;
96
+ disposed = false;
94
97
  saving = false;
95
98
  failed = false;
96
99
  failedReason;
@@ -98,7 +101,18 @@ export class CardForm {
98
101
  constructor(scope, specs) {
99
102
  this.scope = scope;
100
103
  this.specs = new Map(specs.map(spec => [spec.field, spec]));
101
- scope.subscribe(() => { this.publish(); });
104
+ this.disposeScope = scope.subscribe(() => { this.publish(); });
105
+ }
106
+ /**
107
+ * Release the scope subscription and every bound store listener. The card
108
+ * must call this on teardown; later calls are no-ops.
109
+ */
110
+ dispose() {
111
+ if (this.disposed)
112
+ return;
113
+ this.disposed = true;
114
+ this.disposeScope();
115
+ this.listeners.clear();
102
116
  }
103
117
  /** Publish a projection of this form, rebuilt whenever the scope or a draft changes. */
104
118
  bind(project) {
@@ -6,7 +6,7 @@
6
6
  * guard track lengths, and map the fixed 9-row animation contract.
7
7
  * @module @linxin666/dsh-pet/client/spritesheet
8
8
  */
9
- import type { PetAnimation } from '../state.ts';
9
+ import { type PetAnimation } from '../state.ts';
10
10
  import type { PetCell, PetTrackDef } from '../registry.ts';
11
11
  /** Animation track shape the frame loop consumes. */
12
12
  export type TrackDef = PetTrackDef;
@@ -1 +1 @@
1
- {"version":3,"file":"spritesheet.d.ts","sourceRoot":"","sources":["../../../src/client/spritesheet.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE1D,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAa1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAE3H;AAED,uCAAuC;AACvC,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,CAQvE"}
1
+ {"version":3,"file":"spritesheet.d.ts","sourceRoot":"","sources":["../../../src/client/spritesheet.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE1D,qDAAqD;AACrD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAG1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAE3H;AAED,uCAAuC;AACvC,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,QAAQ,CAQvE"}
@@ -6,20 +6,11 @@
6
6
  * guard track lengths, and map the fixed 9-row animation contract.
7
7
  * @module @linxin666/dsh-pet/client/spritesheet
8
8
  */
9
+ import { rowOf } from '../state.js';
9
10
  /** Row index of one animation track (the fixed 9-row contract). */
10
11
  export function rowOfTrack(animation) {
11
- const rows = {
12
- idle: 0,
13
- 'running-right': 1,
14
- 'running-left': 2,
15
- waving: 3,
16
- jumping: 4,
17
- failed: 5,
18
- waiting: 6,
19
- running: 7,
20
- review: 8,
21
- };
22
- return rows[animation];
12
+ // The table itself lives in state.ts (rowOf) — the single source of truth.
13
+ return rowOf(animation);
23
14
  }
24
15
  /**
25
16
  * Background-position (px) of one frame cell within the scaled atlas.
@@ -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,CAyEnC"}
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"}
@@ -85,7 +85,9 @@ export function projectOfficialEvent(event, runtime) {
85
85
  case 'blocked':
86
86
  return { input: { phase: 'waiting', line: '等待继续' } };
87
87
  case 'aborted':
88
- return { input: { phase: 'idle', line: '已停止' } };
88
+ // A stopped session settles to idle without a bubble: the pet
89
+ // visibly calms down and the session drops out of the bubble stack.
90
+ return { input: { phase: 'idle' } };
89
91
  default:
90
92
  // TurnEndReasonMap is merge-extensible; a newer ending must not
91
93
  // leave the pet showing stale in-progress work.
@@ -13,14 +13,16 @@
13
13
  import { Context } from '@deepseek-ai/cordis';
14
14
  import z from 'schemastery';
15
15
  import { type PetConfig } from './service.ts';
16
- export { PetService } from './service.ts';
17
- export type { PetConfig, PetInteractResult, PetSettingsSection, PetStateView, } from './service.ts';
16
+ export { PetService, MAX_SESSION_BUBBLES } from './service.ts';
17
+ export type { PetConfig, PetInteractResult, PetSettingsSection, PetSessionView, PetStateView, } from './service.ts';
18
18
  export { AFFINITY_MAX, AFFINITY_RANKS, applyInteraction, applyTurnReward, emptyAffinity, rankOf, } from './affinity.ts';
19
19
  export type { AffinityConfig, AffinityState, InteractionOutcome, PetInteraction, } from './affinity.ts';
20
20
  export { animationForPhase, PetStateMachine, rowOf, } from './state.ts';
21
21
  export type { ActivityPhase, PetAnimation, PetStateConfig, PetStateInput, PetStateSnapshot, } from './state.ts';
22
22
  export { consumeTreat, defaultTreatConfig, emptyTreatLedger, settleTreatGrants, } from './treats.ts';
23
23
  export type { TreatConfig, TreatLedger, TreatSettlement } from './treats.ts';
24
+ export { BUILTIN_REMARKS, REMARK_KINDS, REMARK_LINE_MAX, REMARK_LINES_MAX, RemarkPicker, builtinRemark, normalizePetRemarks, } from './remarks.ts';
25
+ export type { PetRemarks, PetRemarksManifest, RemarkKind } from './remarks.ts';
24
26
  export { DEFAULT_PET_ID, DEFAULT_PET_NAME, PET_NAME_MAX_LENGTH, defaultDisplayConfig, emptyPersist, loadPetPersist, petHomeDir, savePetPersist, } from './persist.ts';
25
27
  export type { PetDisplayConfig, PetPersist } from './persist.ts';
26
28
  export { DEFAULT_FRAME_COUNTS, DEFAULT_PET_CELL, DEFAULT_PET_COLUMNS, DEFAULT_PET_ROW_COUNT, DEFAULT_TRACK_PATTERNS, PET_ROW_ORDER, codexPetsDir, loadPetRegistry, petEntryView, petPackageRoot, resolvePetManifest, } from './registry.ts';
@@ -54,5 +56,6 @@ export declare function makePetSettingsSchema(fallbackPetId: string): z<Schemast
54
56
  enabled: z<boolean, boolean>;
55
57
  }>>;
56
58
  /** Register the pet service and its API + asset routes on the context. */
57
- export declare function apply(ctx: Context, config?: PetConfig): void;
59
+ export declare const apply: typeof applyImpl;
60
+ declare function applyImpl(ctx: Context, config?: PetConfig): void;
58
61
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C,OAAO,CAAC,MAAM,aAAa,CAAA;AAC3B,OAAO,EAAsC,KAAK,SAAS,EAA2B,MAAM,cAAc,CAAA;AAK1G,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,GACb,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,MAAM,GACP,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,GACN,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACf,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,aAAa,EACb,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,sEAAsE;AACtE,eAAO,MAAM,IAAI,QAAQ,CAAA;AAEzB,+DAA+D;AAC/D,eAAO,MAAM,MAAM,UAAgB,CAAA;AAEnC;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM;;;;;;;;;;;;;;IAS1D;AAED,0EAA0E;AAC1E,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,SAAc,GAAG,IAAI,CA+DhE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C,OAAO,CAAC,MAAM,aAAa,CAAA;AAC3B,OAAO,EAAsC,KAAK,SAAS,EAA2B,MAAM,cAAc,CAAA;AAM1G,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC9D,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,MAAM,GACP,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,GACN,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,gBAAgB,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,eAAe,EACf,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9E,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACf,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAChE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,aAAa,EACb,QAAQ,EACR,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,sEAAsE;AACtE,eAAO,MAAM,IAAI,QAAQ,CAAA;AAEzB,+DAA+D;AAC/D,eAAO,MAAM,MAAM,UAAgB,CAAA;AAEnC;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM;;;;;;;;;;;;;;IAS1D;AAED,0EAA0E;AAC1E,eAAO,MAAM,KAAK,kBAA6C,CAAA;AAE/D,iBAAS,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,SAAc,GAAG,IAAI,CA+D7D"}