@linxin666/dsh-pet 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +12 -5
- package/README.zh.md +12 -5
- package/lib/client.js +134 -78
- package/lib/client.js.map +1 -1
- package/lib/index.js +100 -30
- package/lib/invariant.js +2 -2
- package/lib/state-Diiq8vjk.js +394 -0
- package/lib/types/affinity.d.ts +31 -3
- package/lib/types/affinity.d.ts.map +1 -1
- package/lib/types/affinity.js +21 -7
- package/lib/types/client/PetSettingsCard.d.ts +16 -5
- package/lib/types/client/PetSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PetSettingsCard.js +14 -1
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +8 -2
- package/lib/types/client/PluginSettingsCard.d.ts +11 -0
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PluginSettingsCard.js +11 -5
- package/lib/types/client/index.d.ts +3 -22
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +19 -12
- package/lib/types/client/locales.js +2 -2
- package/lib/types/client/settings-form.d.ts +8 -0
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/settings-form.js +15 -1
- package/lib/types/event-projection.d.ts.map +1 -1
- package/lib/types/event-projection.js +3 -1
- package/lib/types/index.d.ts +4 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +2 -1
- package/lib/types/ledger.d.ts +16 -1
- package/lib/types/ledger.d.ts.map +1 -1
- package/lib/types/ledger.js +29 -4
- package/lib/types/registry.d.ts +10 -0
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +3 -0
- package/lib/types/remarks.d.ts +56 -0
- package/lib/types/remarks.d.ts.map +1 -0
- package/lib/types/remarks.js +157 -0
- package/lib/types/service.d.ts +40 -3
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +90 -18
- package/lib/types/state.js +5 -5
- package/lib/types/treats.d.ts +3 -0
- package/lib/types/treats.d.ts.map +1 -1
- package/lib/types/treats.js +5 -2
- package/package.json +1 -1
- package/src/affinity.test.ts +19 -0
- package/src/affinity.ts +22 -7
- package/src/client/PetSettingsCard.tsx +35 -6
- package/src/client/PetSprite.test.tsx +33 -0
- package/src/client/PetSprite.tsx +16 -1
- package/src/client/PluginSettingsCard.tsx +50 -47
- package/src/client/index.ts +20 -30
- package/src/client/locales.ts +2 -2
- package/src/client/pet.module.css +19 -0
- package/src/client/settings-card.module.css +9 -0
- package/src/client/settings-form.ts +15 -1
- package/src/client/settings-section.module.css +5 -0
- package/src/event-projection.ts +3 -1
- package/src/index.ts +12 -1
- package/src/ledger.test.ts +40 -9
- package/src/ledger.ts +33 -4
- package/src/persist.test.ts +1 -1
- package/src/registry.test.ts +27 -0
- package/src/registry.ts +12 -0
- package/src/remarks.test.ts +89 -0
- package/src/remarks.ts +177 -0
- package/src/service.ts +116 -18
- package/src/state.test.ts +9 -0
- package/src/state.ts +5 -5
- package/src/treats.test.ts +13 -11
- package/src/treats.ts +5 -2
- package/lib/state-CFyJv0sQ.js +0 -213
|
@@ -28,6 +28,17 @@ export interface PluginSettingsCardProps<TKey extends string = string> {
|
|
|
28
28
|
onSave: () => void;
|
|
29
29
|
/** Drop every staged edit. */
|
|
30
30
|
onDiscard: () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Render the controls expanded on arrival (still collapsible). Defaults to
|
|
33
|
+
* true: promoted first-level sections show their settings immediately.
|
|
34
|
+
*/
|
|
35
|
+
defaultOpen?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Render without the collapse affordance: a static header and an always
|
|
38
|
+
* visible body. Used by first-level settings sections whose nav entry
|
|
39
|
+
* already provides the selection.
|
|
40
|
+
*/
|
|
41
|
+
alwaysOpen?: boolean;
|
|
31
42
|
/** The plugin's controls. */
|
|
32
43
|
children: ReactNode;
|
|
33
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAGnD,oGAAoG;AACpG,eAAO,MAAM,cAAc,kMAUjB,CAAA;AAEV,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzD,oEAAoE;AACpE,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,GAAG,WAAW,CAAA;AAE9E,wDAAwD;AACxD,MAAM,WAAW,uBAAuB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACnE,0CAA0C;IAC1C,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAA;IACnF,uCAAuC;IACvC,QAAQ,EAAE,IAAI,CAAA;IACd,4EAA4E;IAC5E,cAAc,EAAE,IAAI,CAAA;IACpB,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,IAAI,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,uBAAuB,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"PluginSettingsCard.d.ts","sourceRoot":"","sources":["../../../src/client/PluginSettingsCard.tsx"],"names":[],"mappings":"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"}
|
|
@@ -28,24 +28,30 @@ export const CARD_COPY_KEYS = [
|
|
|
28
28
|
* @returns the card, or nothing while the namespace is still loading.
|
|
29
29
|
*/
|
|
30
30
|
export function PluginSettingsCard(props) {
|
|
31
|
-
const [open, setOpen] = useState(
|
|
32
|
-
const { state } = props;
|
|
31
|
+
const [open, setOpen] = useState(props.defaultOpen ?? true);
|
|
32
|
+
const { state, alwaysOpen } = props;
|
|
33
33
|
if (!state.available)
|
|
34
34
|
return null;
|
|
35
35
|
const title = props.t(props.titleKey);
|
|
36
36
|
const description = props.t(props.descriptionKey);
|
|
37
37
|
const blocked = !state.dirty || state.invalid || state.saving;
|
|
38
|
-
const
|
|
38
|
+
const expanded = alwaysOpen === true || open;
|
|
39
|
+
const cardClass = expanded ? `${css.cardOpen} ${css.card}` : css.card;
|
|
40
|
+
// With alwaysOpen the nav entry already provides the selection, so the
|
|
41
|
+
// header is a static title row instead of a disclosure button.
|
|
42
|
+
const header = alwaysOpen === true
|
|
43
|
+
? (_jsxs("div", { className: css.headerStatic, children: [_jsxs("span", { className: css.headText, children: [_jsx("span", { className: css.name, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), children: props.t('settings.unsaved') }) : null] }))
|
|
44
|
+
: (_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, title: title, children: title }), _jsx("span", { className: css.description, title: description, children: description })] }), state.dirty ? _jsx("span", { className: css.pending, title: props.t('settings.unsaved'), 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" }) })] }));
|
|
39
45
|
// The namespace exists but the Host does not serve it to this client (the
|
|
40
46
|
// official settings allowlist omits third-party namespaces): show a card
|
|
41
47
|
// that explains the gap instead of vanishing, so a missing card never
|
|
42
48
|
// reads as a missing plugin.
|
|
43
49
|
if (!state.exposed) {
|
|
44
|
-
return (_jsxs("li", { className: cardClass, children: [
|
|
50
|
+
return (_jsxs("li", { className: cardClass, children: [header, expanded
|
|
45
51
|
? (_jsx("div", { className: css.body, children: _jsx("p", { className: css.notExposed, role: "status", children: props.t('settings.notExposed') }) }))
|
|
46
52
|
: null] }));
|
|
47
53
|
}
|
|
48
|
-
return (_jsxs("li", { className: cardClass, children: [
|
|
54
|
+
return (_jsxs("li", { className: cardClass, children: [header, expanded
|
|
49
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
|
|
50
56
|
? (_jsxs("p", { className: css.failed, role: "status", children: [props.t('settings.saveFailed'), state.failedReason ? ' - ' + state.failedReason : ''] }))
|
|
51
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') })] })] }))
|
|
@@ -18,27 +18,8 @@ export type { PetInjected, PetDockEntryProps } from './PetDockEntry.tsx';
|
|
|
18
18
|
export type { PetSpriteProps } from './PetSprite.tsx';
|
|
19
19
|
export type { PetUiState, PetFeedback } from './pet-store.ts';
|
|
20
20
|
export type { PetSettingsCardFace, PetSettingsCardState } from './PetSettingsCard.tsx';
|
|
21
|
+
export type { PetSettingsSectionProps } from './PetSettingsCard.tsx';
|
|
21
22
|
export type { PetDefinition } from '../registry.ts';
|
|
22
|
-
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
23
|
-
interface SlotMap {
|
|
24
|
-
/**
|
|
25
|
-
* The child slot the Web UI plugin group declares; this card registers
|
|
26
|
-
* into the group instead of the top-level 'settings.plugin.item' list.
|
|
27
|
-
* Spelled here with the same shape so this package can register without
|
|
28
|
-
* depending on the sibling UI package.
|
|
29
|
-
*/
|
|
30
|
-
'web-ui.plugin.item': {
|
|
31
|
-
kind: 'list';
|
|
32
|
-
scope: 'root';
|
|
33
|
-
owner: SettingsPluginItemOwnerProps;
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/** Owner share of a plugin card (the group card supplies nothing). */
|
|
38
|
-
export interface SettingsPluginItemOwnerProps {
|
|
39
|
-
/** Marker field: card owner props are intentionally empty. */
|
|
40
|
-
children?: never;
|
|
41
|
-
}
|
|
42
23
|
declare module '@deepseek-ai/cordis' {
|
|
43
24
|
interface Context {
|
|
44
25
|
/**
|
|
@@ -53,8 +34,8 @@ declare module '@deepseek-ai/cordis' {
|
|
|
53
34
|
}
|
|
54
35
|
/**
|
|
55
36
|
* Client plugin body: register dictionaries, mount the global pet entry and
|
|
56
|
-
* poll loop while the plugin is enabled, and seat the settings card
|
|
57
|
-
*
|
|
37
|
+
* poll loop while the plugin is enabled, and seat the settings card as a
|
|
38
|
+
* first-level settings section.
|
|
58
39
|
* @param ctx - client root context.
|
|
59
40
|
*/
|
|
60
41
|
export declare function apply(ctx: ClientContext): void;
|
|
@@ -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,
|
|
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,CA0L9C"}
|
|
@@ -14,7 +14,7 @@ import { createElement } from 'react';
|
|
|
14
14
|
import { createRoot } from 'react-dom/client';
|
|
15
15
|
import { createPetStore } from "./pet-store.js";
|
|
16
16
|
import { PetDockEntry } from "./PetDockEntry.js";
|
|
17
|
-
import {
|
|
17
|
+
import { PetSettingsSection, PetSettingsCardController } from "./PetSettingsCard.js";
|
|
18
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) {
|
|
@@ -48,8 +48,8 @@ const PET_SETTINGS_NS = 'pet';
|
|
|
48
48
|
export const inject = ['slots', 'locale', 'connection', 'settingsScope', 'remote'];
|
|
49
49
|
/**
|
|
50
50
|
* Client plugin body: register dictionaries, mount the global pet entry and
|
|
51
|
-
* poll loop while the plugin is enabled, and seat the settings card
|
|
52
|
-
*
|
|
51
|
+
* poll loop while the plugin is enabled, and seat the settings card as a
|
|
52
|
+
* first-level settings section.
|
|
53
53
|
* @param ctx - client root context.
|
|
54
54
|
*/
|
|
55
55
|
export function apply(ctx) {
|
|
@@ -62,17 +62,24 @@ export function apply(ctx) {
|
|
|
62
62
|
? snapshot.value?.enabled ?? true
|
|
63
63
|
: snapshot.status === 'unavailable';
|
|
64
64
|
};
|
|
65
|
-
//
|
|
66
|
-
// namespace,
|
|
65
|
+
// First-level settings section: one staged form over the 'pet' settings
|
|
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('
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
+
});
|
|
76
83
|
// The global pet entry, its store, and the poll loop live while the plugin
|
|
77
84
|
// is enabled; toggling the setting off hides the pet and stops polling.
|
|
78
85
|
let disposeUi;
|
|
@@ -17,7 +17,7 @@ export const zh = {
|
|
|
17
17
|
'pet.treats': '小鱼干 ×{n}',
|
|
18
18
|
'pet.state.loading': '宠物正在赶来…',
|
|
19
19
|
'pet.state.error': '宠物迷路了(连接失败)',
|
|
20
|
-
//
|
|
20
|
+
// 一级设置页(settings.section 席位)。
|
|
21
21
|
'settings.title': '宠物',
|
|
22
22
|
'settings.description': '选择宠物并调整它的显示布局。',
|
|
23
23
|
'settings.pet': '宠物',
|
|
@@ -61,7 +61,7 @@ export const en = {
|
|
|
61
61
|
'pet.treats': 'Treats ×{n}',
|
|
62
62
|
'pet.state.loading': 'The pet is on its way…',
|
|
63
63
|
'pet.state.error': 'The pet is lost (connection failed)',
|
|
64
|
-
//
|
|
64
|
+
// First-level settings section (the `settings.section` seat).
|
|
65
65
|
'settings.title': 'Pet',
|
|
66
66
|
'settings.description': 'Pick a pet and tune its display layout.',
|
|
67
67
|
'settings.pet': 'Pet',
|
|
@@ -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) {
|
|
@@ -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,
|
|
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
|
-
|
|
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.
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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';
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,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,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,SAAc,GAAG,IAAI,CA+DhE"}
|
package/lib/types/index.js
CHANGED
|
@@ -16,10 +16,11 @@ import { PetService, PET_SETTINGS_NAMESPACE } from "./service.js";
|
|
|
16
16
|
import { makePetRoutes } from "./routes.js";
|
|
17
17
|
import { loadPetRegistry, petPackageRoot } from "./registry.js";
|
|
18
18
|
import { DISPLAY_INSET_MAX, DISPLAY_SIZE_MAX, DISPLAY_SIZE_MIN } from "./persist.js";
|
|
19
|
-
export { PetService } from "./service.js";
|
|
19
|
+
export { PetService, MAX_SESSION_BUBBLES } from "./service.js";
|
|
20
20
|
export { AFFINITY_MAX, AFFINITY_RANKS, applyInteraction, applyTurnReward, emptyAffinity, rankOf, } from "./affinity.js";
|
|
21
21
|
export { animationForPhase, PetStateMachine, rowOf, } from "./state.js";
|
|
22
22
|
export { consumeTreat, defaultTreatConfig, emptyTreatLedger, settleTreatGrants, } from "./treats.js";
|
|
23
|
+
export { BUILTIN_REMARKS, REMARK_KINDS, REMARK_LINE_MAX, REMARK_LINES_MAX, RemarkPicker, builtinRemark, normalizePetRemarks, } from "./remarks.js";
|
|
23
24
|
export { DEFAULT_PET_ID, DEFAULT_PET_NAME, PET_NAME_MAX_LENGTH, defaultDisplayConfig, emptyPersist, loadPetPersist, petHomeDir, savePetPersist, } from "./persist.js";
|
|
24
25
|
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.js";
|
|
25
26
|
export { makePetRoutes, PET_API_PREFIX, PET_ASSET_PREFIX, } from "./routes.js";
|
package/lib/types/ledger.d.ts
CHANGED
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type AffinityConfig, type PetAffinityView, type PetInteraction } from './affinity.ts';
|
|
10
10
|
import { type TreatConfig } from './treats.ts';
|
|
11
|
+
import { type PetRemarks } from './remarks.ts';
|
|
11
12
|
import type { PetDisplayConfig, PetPersist } from './persist.ts';
|
|
12
13
|
/** Tuning overrides for the affinity economy. */
|
|
13
14
|
export interface LedgerConfig {
|
|
14
15
|
affinity?: Partial<AffinityConfig>;
|
|
15
16
|
treats?: Partial<TreatConfig>;
|
|
17
|
+
/** Per-pet remark pools for the selected pet (custom slots override built-ins). */
|
|
18
|
+
remarks?: PetRemarks;
|
|
16
19
|
}
|
|
17
20
|
/** Result of one ledger interaction (the shape the pet RPC returns). */
|
|
18
21
|
export interface LedgerInteractionResult {
|
|
@@ -31,6 +34,8 @@ export interface LedgerInteractionResult {
|
|
|
31
34
|
export declare class PetLedger {
|
|
32
35
|
private readonly affinityConfig;
|
|
33
36
|
private readonly treatConfig;
|
|
37
|
+
/** Round-robin reaction picker; rebuilt when the selected pet changes. */
|
|
38
|
+
private picker;
|
|
34
39
|
private current;
|
|
35
40
|
/** Completed turns already rewarded, per session (turn numbers are per-session). */
|
|
36
41
|
private rewardedTurns;
|
|
@@ -45,16 +50,26 @@ export declare class PetLedger {
|
|
|
45
50
|
get treatMax(): number;
|
|
46
51
|
/** Consume the pending-write flag if any mutation occurred. */
|
|
47
52
|
takeDirty(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Drop a session's rewarded-turn bookkeeping once that session is disposed,
|
|
55
|
+
* so the per-session map does not grow without bound.
|
|
56
|
+
*/
|
|
57
|
+
forgetSession(sessionId: string): void;
|
|
48
58
|
/** Replace the display block (clamping stays a caller concern). */
|
|
49
59
|
setDisplay(display: PetDisplayConfig): void;
|
|
50
60
|
/** Replace the selected pet id (validation stays a caller concern). */
|
|
51
61
|
setPetId(petId: string): void;
|
|
52
62
|
/** Replace one pet's display name (validation stays a caller concern). */
|
|
53
63
|
setPetName(petId: string, name: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Swap the reaction pools to another pet's custom remarks (called on pet
|
|
66
|
+
* selection). Slots the pet does not declare fall back to built-ins.
|
|
67
|
+
*/
|
|
68
|
+
setRemarks(remarks?: PetRemarks): void;
|
|
54
69
|
/**
|
|
55
70
|
* Settle the treat economy (work + time output since the last settlement).
|
|
56
71
|
* A zero-gain first settlement still starts the time clock (anchor write),
|
|
57
|
-
* which is how the
|
|
72
|
+
* which is how the time output can ever accrue. Returns true when
|
|
58
73
|
* the in-memory ledger changed and should be persisted.
|
|
59
74
|
*/
|
|
60
75
|
settleTreats(nowMs: number): boolean;
|
|
@@ -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,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;
|
|
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;gBAET,OAAO,EAAE,UAAU,EAAE,MAAM,GAAE,YAAiB;IAO1D,iDAAiD;IACjD,IAAI,QAAQ,IAAI,cAAc,CAE7B;IAED,qEAAqE;IACrE,IAAI,QAAQ,IAAI,UAAU,CAEzB;IAED,qCAAqC;IACrC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,+DAA+D;IAC/D,SAAS,IAAI,OAAO;IAMpB;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAItC,mEAAmE;IACnE,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAK3C,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,0EAA0E;IAC1E,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK7C;;;OAGG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAItC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAapC;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IASnE,8EAA8E;IAC9E,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IASxC,OAAO,CAAC,eAAe;IASvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB;IAgCtE,kDAAkD;IAClD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe;CAG7C"}
|
package/lib/types/ledger.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { applyInteraction, affinityViewOf, applyTurnReward, defaultAffinityConfig, } from "./affinity.js";
|
|
10
10
|
import { consumeTreat, defaultTreatConfig, settleTreatGrants, } from "./treats.js";
|
|
11
|
+
import { RemarkPicker } from "./remarks.js";
|
|
11
12
|
/**
|
|
12
13
|
* Holds the current persistence snapshot and all economy bookkeeping. Every
|
|
13
14
|
* mutating call flags takeDirty so the facade persists exactly once per
|
|
@@ -16,6 +17,8 @@ import { consumeTreat, defaultTreatConfig, settleTreatGrants, } from "./treats.j
|
|
|
16
17
|
export class PetLedger {
|
|
17
18
|
affinityConfig;
|
|
18
19
|
treatConfig;
|
|
20
|
+
/** Round-robin reaction picker; rebuilt when the selected pet changes. */
|
|
21
|
+
picker;
|
|
19
22
|
current;
|
|
20
23
|
/** Completed turns already rewarded, per session (turn numbers are per-session). */
|
|
21
24
|
rewardedTurns = new Map();
|
|
@@ -24,6 +27,7 @@ export class PetLedger {
|
|
|
24
27
|
constructor(persist, config = {}) {
|
|
25
28
|
this.affinityConfig = { ...defaultAffinityConfig, ...(config.affinity ?? {}) };
|
|
26
29
|
this.treatConfig = { ...defaultTreatConfig, ...(config.treats ?? {}) };
|
|
30
|
+
this.picker = new RemarkPicker(config.remarks);
|
|
27
31
|
this.current = persist;
|
|
28
32
|
}
|
|
29
33
|
/** Affinity cooldown/rank tuning (read-only). */
|
|
@@ -44,6 +48,13 @@ export class PetLedger {
|
|
|
44
48
|
this.dirty = false;
|
|
45
49
|
return was;
|
|
46
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Drop a session's rewarded-turn bookkeeping once that session is disposed,
|
|
53
|
+
* so the per-session map does not grow without bound.
|
|
54
|
+
*/
|
|
55
|
+
forgetSession(sessionId) {
|
|
56
|
+
this.rewardedTurns.delete(sessionId);
|
|
57
|
+
}
|
|
47
58
|
/** Replace the display block (clamping stays a caller concern). */
|
|
48
59
|
setDisplay(display) {
|
|
49
60
|
this.current = { ...this.current, display };
|
|
@@ -61,10 +72,17 @@ export class PetLedger {
|
|
|
61
72
|
this.current = { ...this.current, names: { ...this.current.names, [petId]: name } };
|
|
62
73
|
this.dirty = true;
|
|
63
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Swap the reaction pools to another pet's custom remarks (called on pet
|
|
77
|
+
* selection). Slots the pet does not declare fall back to built-ins.
|
|
78
|
+
*/
|
|
79
|
+
setRemarks(remarks) {
|
|
80
|
+
this.picker = new RemarkPicker(remarks);
|
|
81
|
+
}
|
|
64
82
|
/**
|
|
65
83
|
* Settle the treat economy (work + time output since the last settlement).
|
|
66
84
|
* A zero-gain first settlement still starts the time clock (anchor write),
|
|
67
|
-
* which is how the
|
|
85
|
+
* which is how the time output can ever accrue. Returns true when
|
|
68
86
|
* the in-memory ledger changed and should be persisted.
|
|
69
87
|
*/
|
|
70
88
|
settleTreats(nowMs) {
|
|
@@ -118,14 +136,17 @@ export class PetLedger {
|
|
|
118
136
|
if (kind === 'feed')
|
|
119
137
|
this.settleTreats(nowMs);
|
|
120
138
|
const outcome = applyInteraction(this.current.affinity, kind, nowMs, this.affinityConfig);
|
|
139
|
+
// Reactions come from the picker pools (custom per-pet slots override
|
|
140
|
+
// the built-in library per slot); outcome.reaction stays the fallback
|
|
141
|
+
// copy for direct applyInteraction callers.
|
|
121
142
|
if (kind === 'feed' && !outcome.accepted) {
|
|
122
|
-
return { reaction:
|
|
143
|
+
return { reaction: this.picker.pick('feedCooldown'), delta: 0, affinity: this.affinityView(nowMs) };
|
|
123
144
|
}
|
|
124
145
|
if (kind === 'feed') {
|
|
125
146
|
const consume = consumeTreat(this.current.treats);
|
|
126
147
|
if (!consume.ok) {
|
|
127
148
|
return {
|
|
128
|
-
reaction: '
|
|
149
|
+
reaction: this.picker.pick('noTreats'),
|
|
129
150
|
delta: 0,
|
|
130
151
|
affinity: this.affinityView(nowMs),
|
|
131
152
|
};
|
|
@@ -137,7 +158,11 @@ export class PetLedger {
|
|
|
137
158
|
this.current = { ...this.current, affinity: outcome.affinity };
|
|
138
159
|
this.dirty = true;
|
|
139
160
|
}
|
|
140
|
-
return {
|
|
161
|
+
return {
|
|
162
|
+
reaction: this.picker.pick(outcome.accepted ? kind : 'petCooldown'),
|
|
163
|
+
delta: outcome.delta,
|
|
164
|
+
affinity: this.affinityView(nowMs),
|
|
165
|
+
};
|
|
141
166
|
}
|
|
142
167
|
/** Current affinity view for the RPC snapshot. */
|
|
143
168
|
affinityView(nowMs) {
|
package/lib/types/registry.d.ts
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* @module @linxin666/dsh-pet/registry
|
|
18
18
|
*/
|
|
19
19
|
import type { PetAnimation } from './state.ts';
|
|
20
|
+
import { type PetRemarks, type PetRemarksManifest } from './remarks.ts';
|
|
20
21
|
/** Fixed row order of the 9-state animation contract. */
|
|
21
22
|
export declare const PET_ROW_ORDER: readonly PetAnimation[];
|
|
22
23
|
/** Atlas cell size in px. */
|
|
@@ -80,6 +81,13 @@ export interface PetManifest {
|
|
|
80
81
|
frames?: number[];
|
|
81
82
|
/** Optional per-track rhythm overrides; omitted tracks use the defaults. */
|
|
82
83
|
tracks?: Partial<Record<PetAnimation, PetTrackOverride>>;
|
|
84
|
+
/**
|
|
85
|
+
* Optional witty-remark overrides the pet speaks on interactions
|
|
86
|
+
* (community contributions use this to give their pet its own voice).
|
|
87
|
+
* Each slot accepts one line or a pool of lines; a slot replaces the
|
|
88
|
+
* built-in default pool for that slot only.
|
|
89
|
+
*/
|
|
90
|
+
remarks?: PetRemarksManifest;
|
|
83
91
|
}
|
|
84
92
|
/** Per-track rhythm overrides a manifest may carry. */
|
|
85
93
|
export interface PetTrackOverride {
|
|
@@ -114,6 +122,8 @@ export interface PetEntry extends PetDefinition {
|
|
|
114
122
|
dir: string;
|
|
115
123
|
/** Atlas path relative to 'dir' (declared by the manifest). */
|
|
116
124
|
spritesheetPath: string;
|
|
125
|
+
/** Normalized per-pet remark pools (manifest 'remarks'), when declared. */
|
|
126
|
+
remarks?: PetRemarks;
|
|
117
127
|
}
|
|
118
128
|
/** Registry load result: resolved entries plus load warnings. */
|
|
119
129
|
export interface PetRegistry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"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"}
|
package/lib/types/registry.js
CHANGED
|
@@ -20,6 +20,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
|
20
20
|
import { homedir } from 'node:os';
|
|
21
21
|
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { normalizePetRemarks } from "./remarks.js";
|
|
23
24
|
/** Fixed row order of the 9-state animation contract. */
|
|
24
25
|
export const PET_ROW_ORDER = [
|
|
25
26
|
'idle',
|
|
@@ -129,6 +130,7 @@ export function resolvePetManifest(raw, dir, options = {}) {
|
|
|
129
130
|
const value = Array.isArray(source.frames) ? source.frames[index] : undefined;
|
|
130
131
|
return finiteInt(value, fallback, columns);
|
|
131
132
|
});
|
|
133
|
+
const remarks = normalizePetRemarks(source.remarks, message => warn('manifest ' + id + ': ' + message));
|
|
132
134
|
const trackOverrides = (typeof source.tracks === 'object' && source.tracks !== null ? source.tracks : {});
|
|
133
135
|
const tracks = {};
|
|
134
136
|
for (const [row, animation] of PET_ROW_ORDER.entries()) {
|
|
@@ -168,6 +170,7 @@ export function resolvePetManifest(raw, dir, options = {}) {
|
|
|
168
170
|
manifestUrl: assetUrl(assetPrefix, id, 'pet.json'),
|
|
169
171
|
dir,
|
|
170
172
|
spritesheetPath: spritesheetPath.join('/'),
|
|
173
|
+
...(remarks === undefined ? {} : { remarks }),
|
|
171
174
|
};
|
|
172
175
|
}
|
|
173
176
|
/** Scan one directory of pet folders; entries come back in name order. */
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pet remark (reaction copy) library — pure. Reaction bubbles the pet speaks
|
|
3
|
+
* on interaction events come from two layers:
|
|
4
|
+
* - the built-in default library below (a generous pool per event kind);
|
|
5
|
+
* - per-pet custom lines declared in a manifest's 'remarks' block, which
|
|
6
|
+
* community pet contributions (PRs) use to give their pet its own voice.
|
|
7
|
+
* A custom slot replaces the built-in pool for that slot only; the other
|
|
8
|
+
* slots keep the built-in lines. Picks cycle round-robin within a pool so
|
|
9
|
+
* repeated interactions stay varied while tests stay deterministic (no
|
|
10
|
+
* randomness, no clock).
|
|
11
|
+
* @module @linxin666/dsh-pet/remarks
|
|
12
|
+
*/
|
|
13
|
+
/** Interaction events a reaction line can accompany. */
|
|
14
|
+
export type RemarkKind = 'pet' | 'petCooldown' | 'feed' | 'feedCooldown' | 'noTreats';
|
|
15
|
+
/** Every remark slot, in a stable order. */
|
|
16
|
+
export declare const REMARK_KINDS: readonly RemarkKind[];
|
|
17
|
+
/** Per-pet remark overrides (normalized shape; each slot is a line pool). */
|
|
18
|
+
export type PetRemarks = Partial<Record<RemarkKind, string[]>>;
|
|
19
|
+
/** Raw manifest shape: each slot accepts one line or a pool of lines. */
|
|
20
|
+
export type PetRemarksManifest = Partial<Record<RemarkKind, string | string[]>>;
|
|
21
|
+
/** Longest accepted reaction line (characters, trimmed before slicing). */
|
|
22
|
+
export declare const REMARK_LINE_MAX = 120;
|
|
23
|
+
/** Longest accepted pool per slot. */
|
|
24
|
+
export declare const REMARK_LINES_MAX = 64;
|
|
25
|
+
/**
|
|
26
|
+
* Built-in default remark library. Every pool is plain zh copy in the
|
|
27
|
+
* whale-girl voice; the first line of each pool is the legacy reaction the
|
|
28
|
+
* plugin has always spoken, so existing installs and tests keep their
|
|
29
|
+
* wording while the pool adds variety. No emoji characters anywhere (the
|
|
30
|
+
* repo bans them); ~ is the whale-girl's signature.
|
|
31
|
+
*/
|
|
32
|
+
export declare const BUILTIN_REMARKS: Readonly<Record<RemarkKind, readonly string[]>>;
|
|
33
|
+
/** The legacy first line of one kind (direct callers' fallback copy). */
|
|
34
|
+
export declare function builtinRemark(kind: RemarkKind): string;
|
|
35
|
+
/**
|
|
36
|
+
* Normalize a manifest 'remarks' block into per-kind line pools. Unknown
|
|
37
|
+
* slots and non-string entries are skipped with a warning; empty pools are
|
|
38
|
+
* dropped so the built-in library takes the slot. Returns undefined when no
|
|
39
|
+
* usable slot remains.
|
|
40
|
+
*/
|
|
41
|
+
export declare function normalizePetRemarks(raw: unknown, onWarning?: (message: string) => void): PetRemarks | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Round-robin reaction picker over the effective pools (per-pet custom lines
|
|
44
|
+
* override the built-in pool per slot). Counters are per slot, so each slot
|
|
45
|
+
* cycles its own list independently and picks stay deterministic for tests.
|
|
46
|
+
*/
|
|
47
|
+
export declare class RemarkPicker {
|
|
48
|
+
private readonly counters;
|
|
49
|
+
private readonly pools;
|
|
50
|
+
constructor(overrides?: PetRemarks);
|
|
51
|
+
/** The effective pool for one slot (custom override or built-in). */
|
|
52
|
+
pool(kind: RemarkKind): readonly string[];
|
|
53
|
+
/** The next line for one slot (round-robin within its pool). */
|
|
54
|
+
pick(kind: RemarkKind): string;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=remarks.d.ts.map
|