@linxin666/dsh-pet 0.1.3 → 0.1.6
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/client.js +44 -44
- package/lib/types/index.d.ts +14 -13
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/lib/state-7ChK99mH.js +0 -217
- package/lib/state-CKh9f_dF.js +0 -196
- package/lib/state-DMgOYVFT.js +0 -198
- package/lib/types/client/DockPetDockEntry.d.ts +0 -23
- package/lib/types/client/DockPetDockEntry.d.ts.map +0 -1
- package/lib/types/client/DockPetDockEntry.js +0 -10
package/lib/client.js
CHANGED
|
@@ -303,8 +303,8 @@ window.__ModuleLoader__.load({
|
|
|
303
303
|
};
|
|
304
304
|
}
|
|
305
305
|
//#endregion
|
|
306
|
-
//#region \0dsh-css:/
|
|
307
|
-
const css$1 = ".
|
|
306
|
+
//#region \0dsh-css:/home/runner/work/dsh-web-ui/dsh-web-ui/packages/dsh-pet/src/client/pet.module.css.mjs
|
|
307
|
+
const css$1 = ".l0P8iq_float{pointer-events:auto;-webkit-user-select:none;user-select:none;flex-direction:column;align-items:center;display:flex;position:fixed}.l0P8iq_sprite{image-rendering:auto;touch-action:none;position:relative}.l0P8iq_bubble{white-space:nowrap;color:#fff;pointer-events:none;border-radius:999px;margin-bottom:6px;padding:4px 10px;font-size:12px;line-height:1.4;animation:2.6s ease-out forwards l0P8iq_pet-bubble-pop;position:absolute;bottom:100%;box-shadow:0 2px 8px #00000040}.l0P8iq_bubblePet{background:#f472b6eb}.l0P8iq_bubbleFeed{background:#38bdf8eb}@keyframes l0P8iq_pet-bubble-pop{0%{opacity:0;transform:translateY(6px)scale(.85)}15%{opacity:1;transform:translateY(0)scale(1.05)}25%{transform:translateY(0)scale(1)}75%{opacity:1}to{opacity:0;transform:translateY(-8px)scale(.95)}}.l0P8iq_panel{color:#e2e8f0;backdrop-filter:blur(6px);background:#0f172aeb;border:1px solid #94a3b859;border-radius:10px;flex-direction:column;gap:6px;min-width:132px;padding:8px 10px;font-size:12px;display:flex;position:absolute;bottom:calc(100% + 4px);box-shadow:0 4px 16px #00000059}.l0P8iq_rankRow{white-space:nowrap;justify-content:space-between;gap:10px;display:flex}.l0P8iq_nameCell{font-weight:600}.l0P8iq_renameRow{align-items:center;gap:6px;display:flex}.l0P8iq_nameInput{color:#e2e8f0;background:#1e293be6;border:1px solid #7dd3fc80;border-radius:6px;outline:none;flex:1;min-width:0;padding:3px 6px;font-size:12px}.l0P8iq_nameInput:focus{border-color:#38bdf8;box-shadow:0 0 0 2px #38bdf873}.l0P8iq_actions{gap:6px;display:flex}.l0P8iq_action{cursor:pointer;color:#0f172a;background:linear-gradient(#7dd3fc,#38bdf8);border:none;border-radius:6px;flex:1;padding:4px 8px;font-size:12px;transition:filter .12s,box-shadow .12s}.l0P8iq_action:hover{filter:brightness(1.08)}.l0P8iq_action:active{filter:brightness(.94)}.l0P8iq_action:focus-visible{outline:none;box-shadow:0 0 0 2px #38bdf8d9}.l0P8iq_summon{color:#7dd3fc;cursor:pointer;background:#0f172abf;border:1px dashed #7dd3fc99;border-radius:999px;padding:2px 10px;font-size:11px;transition:border-color .12s,color .12s,background .12s,box-shadow .12s}.l0P8iq_summon:hover{color:#bae6fd;background:#0f172ae6;border-color:#7dd3fcf2}.l0P8iq_summon:active{color:#7dd3fc;border-color:#7dd3fccc}.l0P8iq_summon:focus-visible{outline:none;box-shadow:0 0 0 2px #38bdf8d9}@media (prefers-reduced-motion:reduce){.l0P8iq_bubble{opacity:1;animation:none}.l0P8iq_action,.l0P8iq_summon{transition:none}}";
|
|
308
308
|
const tagId$1 = "@linxin666/dsh-pet/pet.module.css";
|
|
309
309
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
310
310
|
const tag = document.createElement("style");
|
|
@@ -314,20 +314,20 @@ window.__ModuleLoader__.load({
|
|
|
314
314
|
document.head.appendChild(tag);
|
|
315
315
|
}
|
|
316
316
|
var pet_module_css_default = {
|
|
317
|
-
"action": "
|
|
318
|
-
"actions": "
|
|
319
|
-
"bubble": "
|
|
320
|
-
"bubbleFeed": "
|
|
321
|
-
"bubblePet": "
|
|
322
|
-
"float": "
|
|
323
|
-
"nameCell": "
|
|
324
|
-
"nameInput": "
|
|
325
|
-
"panel": "
|
|
326
|
-
"pet-bubble-pop": "
|
|
327
|
-
"rankRow": "
|
|
328
|
-
"renameRow": "
|
|
329
|
-
"sprite": "
|
|
330
|
-
"summon": "
|
|
317
|
+
"action": "l0P8iq_action",
|
|
318
|
+
"actions": "l0P8iq_actions",
|
|
319
|
+
"bubble": "l0P8iq_bubble",
|
|
320
|
+
"bubbleFeed": "l0P8iq_bubbleFeed",
|
|
321
|
+
"bubblePet": "l0P8iq_bubblePet",
|
|
322
|
+
"float": "l0P8iq_float",
|
|
323
|
+
"nameCell": "l0P8iq_nameCell",
|
|
324
|
+
"nameInput": "l0P8iq_nameInput",
|
|
325
|
+
"panel": "l0P8iq_panel",
|
|
326
|
+
"pet-bubble-pop": "l0P8iq_pet-bubble-pop",
|
|
327
|
+
"rankRow": "l0P8iq_rankRow",
|
|
328
|
+
"renameRow": "l0P8iq_renameRow",
|
|
329
|
+
"sprite": "l0P8iq_sprite",
|
|
330
|
+
"summon": "l0P8iq_summon"
|
|
331
331
|
};
|
|
332
332
|
//#endregion
|
|
333
333
|
//#region src/client/WhalePet.tsx
|
|
@@ -652,8 +652,8 @@ window.__ModuleLoader__.load({
|
|
|
652
652
|
});
|
|
653
653
|
}
|
|
654
654
|
//#endregion
|
|
655
|
-
//#region \0dsh-css:/
|
|
656
|
-
const css = ".
|
|
655
|
+
//#region \0dsh-css:/home/runner/work/dsh-web-ui/dsh-web-ui/packages/dsh-pet/src/client/settings-card.module.css.mjs
|
|
656
|
+
const css = ".bDVnfa_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:8px;list-style:none;transition:border-color .16s,background .16s;overflow:hidden}.bDVnfa_cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.bDVnfa_header{cursor:pointer;text-align:left;width:100%;font:inherit;background:0 0;border:0;align-items:center;gap:8px;padding:10px 14px;transition:background .12s;display:flex}.bDVnfa_header:hover{background:var(--dsw-alias-interactive-bg-hover)}.bDVnfa_header:active{background:var(--dsw-alias-interactive-bg-hover-solid)}.bDVnfa_header:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-alias-button-info-fill);outline:none}.bDVnfa_headText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.bDVnfa_name{color:var(--dsw-alias-label-primary);font-weight:600}.bDVnfa_description{color:var(--dsw-alias-label-tertiary);font-size:12px}.bDVnfa_pending{color:var(--dsw-alias-state-warn-primary);font-size:12px}.bDVnfa_chevron{color:var(--dsw-alias-label-tertiary);transition:transform .12s}.bDVnfa_chevronOpen{transform:rotate(180deg)}.bDVnfa_body{flex-direction:column;gap:14px;padding:0 14px 14px;display:flex}.bDVnfa_readOnly{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px}.bDVnfa_footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}.bDVnfa_failed{color:var(--dsw-alias-state-error-primary);margin:0 auto 0 0;font-size:12px}.bDVnfa_discard,.bDVnfa_save{font:inherit;cursor:pointer;border-radius:6px;padding:5px 12px;font-size:13px;transition:color .12s,border-color .12s,background .12s,box-shadow .12s}.bDVnfa_discard{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.bDVnfa_discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}.bDVnfa_discard:active:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.bDVnfa_save{border:1px solid var(--dsw-alias-button-info-fill);background:var(--dsw-alias-button-info-fill);color:var(--dsw-alias-label-primary-foreground)}.bDVnfa_save:hover:not(:disabled){border-color:var(--dsw-alias-button-info-hover);background:var(--dsw-alias-button-info-hover)}.bDVnfa_save:active:not(:disabled){filter:brightness(.94)}.bDVnfa_discard:focus-visible:not(:disabled),.bDVnfa_save:focus-visible:not(:disabled){box-shadow:0 0 0 2px var(--dsw-alias-button-info-fill);outline:none}.bDVnfa_discard:disabled,.bDVnfa_save:disabled{opacity:.5;cursor:default}.bDVnfa_field{flex-direction:column;gap:4px;display:flex}.bDVnfa_head{align-items:center;gap:8px;display:flex}.bDVnfa_label{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.bDVnfa_badges{align-items:center;gap:6px;display:flex}.bDVnfa_badge{background:var(--dsw-alias-interactive-bg-hover-accent);color:var(--dsw-alias-state-business-primary);border-radius:999px;padding:1px 6px;font-size:11px}.bDVnfa_reset{color:var(--dsw-alias-state-business-primary);cursor:pointer;background:0 0;border:0;border-radius:3px;padding:0;font-size:11px;transition:color .12s,box-shadow .12s}.bDVnfa_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary-bluish);text-decoration:underline}.bDVnfa_reset:active:not(:disabled){color:var(--dsw-alias-state-business-primary)}.bDVnfa_reset:focus-visible:not(:disabled){box-shadow:0 0 0 2px var(--dsw-alias-button-info-fill);outline:none}.bDVnfa_reset:disabled{opacity:.5;cursor:default}.bDVnfa_input,.bDVnfa_select{border:1px solid var(--dsw-alias-border-l2);font:inherit;color:var(--dsw-alias-label-primary);background:var(--dsw-specific-input-major);border-radius:6px;padding:6px 8px;font-size:13px}.bDVnfa_inputInvalid{border:1px solid var(--dsw-alias-state-error-primary);font:inherit;color:var(--dsw-alias-label-primary);border-radius:6px;padding:6px 8px;font-size:13px}.bDVnfa_input:disabled,.bDVnfa_select:disabled{opacity:.6}.bDVnfa_input:focus,.bDVnfa_select:focus{border-color:var(--dsw-alias-button-info-fill);box-shadow:0 0 0 2px var(--dsw-alias-button-info-fill);outline:none}.bDVnfa_inputInvalid:focus{box-shadow:0 0 0 2px var(--dsw-alias-state-error-primary);outline:none}.bDVnfa_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:12px}.bDVnfa_invalid{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px}@media (prefers-reduced-motion:reduce){.bDVnfa_card,.bDVnfa_header,.bDVnfa_chevron,.bDVnfa_chevronOpen,.bDVnfa_reset,.bDVnfa_discard,.bDVnfa_save{transition:none}}";
|
|
657
657
|
const tagId = "@linxin666/dsh-pet/settings-card.module.css";
|
|
658
658
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
659
659
|
const tag = document.createElement("style");
|
|
@@ -663,32 +663,32 @@ window.__ModuleLoader__.load({
|
|
|
663
663
|
document.head.appendChild(tag);
|
|
664
664
|
}
|
|
665
665
|
var settings_card_module_css_default = {
|
|
666
|
-
"badge": "
|
|
667
|
-
"badges": "
|
|
668
|
-
"body": "
|
|
669
|
-
"card": "
|
|
670
|
-
"cardOpen": "
|
|
671
|
-
"chevron": "
|
|
672
|
-
"chevronOpen": "
|
|
673
|
-
"description": "
|
|
674
|
-
"discard": "
|
|
675
|
-
"failed": "
|
|
676
|
-
"field": "
|
|
677
|
-
"footer": "
|
|
678
|
-
"head": "
|
|
679
|
-
"headText": "
|
|
680
|
-
"header": "
|
|
681
|
-
"hint": "
|
|
682
|
-
"input": "
|
|
683
|
-
"inputInvalid": "
|
|
684
|
-
"invalid": "
|
|
685
|
-
"label": "
|
|
686
|
-
"name": "
|
|
687
|
-
"pending": "
|
|
688
|
-
"readOnly": "
|
|
689
|
-
"reset": "
|
|
690
|
-
"save": "
|
|
691
|
-
"select": "
|
|
666
|
+
"badge": "bDVnfa_badge",
|
|
667
|
+
"badges": "bDVnfa_badges",
|
|
668
|
+
"body": "bDVnfa_body",
|
|
669
|
+
"card": "bDVnfa_card",
|
|
670
|
+
"cardOpen": "bDVnfa_cardOpen",
|
|
671
|
+
"chevron": "bDVnfa_chevron",
|
|
672
|
+
"chevronOpen": "bDVnfa_chevronOpen",
|
|
673
|
+
"description": "bDVnfa_description",
|
|
674
|
+
"discard": "bDVnfa_discard",
|
|
675
|
+
"failed": "bDVnfa_failed",
|
|
676
|
+
"field": "bDVnfa_field",
|
|
677
|
+
"footer": "bDVnfa_footer",
|
|
678
|
+
"head": "bDVnfa_head",
|
|
679
|
+
"headText": "bDVnfa_headText",
|
|
680
|
+
"header": "bDVnfa_header",
|
|
681
|
+
"hint": "bDVnfa_hint",
|
|
682
|
+
"input": "bDVnfa_input",
|
|
683
|
+
"inputInvalid": "bDVnfa_inputInvalid",
|
|
684
|
+
"invalid": "bDVnfa_invalid",
|
|
685
|
+
"label": "bDVnfa_label",
|
|
686
|
+
"name": "bDVnfa_name",
|
|
687
|
+
"pending": "bDVnfa_pending",
|
|
688
|
+
"readOnly": "bDVnfa_readOnly",
|
|
689
|
+
"reset": "bDVnfa_reset",
|
|
690
|
+
"save": "bDVnfa_save",
|
|
691
|
+
"select": "bDVnfa_select"
|
|
692
692
|
};
|
|
693
693
|
//#endregion
|
|
694
694
|
//#region src/client/PluginSettingsCard.tsx
|
package/lib/types/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module @linxin666/dsh-pet
|
|
8
8
|
*/
|
|
9
9
|
import { Context } from '@deepseek-ai/cordis';
|
|
10
|
+
import z from 'schemastery';
|
|
10
11
|
import { type PetConfig } from './service.ts';
|
|
11
12
|
export { PetService } from './service.ts';
|
|
12
13
|
export type { PetConfig, PetInteractResult, PetStateView, } from './service.ts';
|
|
@@ -24,20 +25,20 @@ export declare const name = "pet";
|
|
|
24
25
|
/** Services required before the pet can mount its surfaces. */
|
|
25
26
|
export declare const inject: string[];
|
|
26
27
|
/** Settings section schema: the display fields and name the web settings surface edits. */
|
|
27
|
-
export declare const PET_SETTINGS_SCHEMA:
|
|
28
|
-
visible:
|
|
29
|
-
size:
|
|
30
|
-
right:
|
|
31
|
-
bottom:
|
|
32
|
-
name:
|
|
33
|
-
enabled:
|
|
28
|
+
export declare const PET_SETTINGS_SCHEMA: z<Schemastery.ObjectS<{
|
|
29
|
+
visible: z<boolean, boolean>;
|
|
30
|
+
size: z<number, number>;
|
|
31
|
+
right: z<number, number>;
|
|
32
|
+
bottom: z<number, number>;
|
|
33
|
+
name: z<string, string>;
|
|
34
|
+
enabled: z<boolean, boolean>;
|
|
34
35
|
}>, Schemastery.ObjectT<{
|
|
35
|
-
visible:
|
|
36
|
-
size:
|
|
37
|
-
right:
|
|
38
|
-
bottom:
|
|
39
|
-
name:
|
|
40
|
-
enabled:
|
|
36
|
+
visible: z<boolean, boolean>;
|
|
37
|
+
size: z<number, number>;
|
|
38
|
+
right: z<number, number>;
|
|
39
|
+
bottom: z<number, number>;
|
|
40
|
+
name: z<string, string>;
|
|
41
|
+
enabled: z<boolean, boolean>;
|
|
41
42
|
}>>;
|
|
42
43
|
/** Register the pet service and its API + asset routes on the context. */
|
|
43
44
|
export declare function apply(ctx: Context, config?: PetConfig): void;
|
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;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG7C,OAAO,CAAC,MAAM,aAAa,CAAA;AAC3B,OAAO,EAAsC,KAAK,SAAS,EAA2B,MAAM,cAAc,CAAA;AAU1G,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,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,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACf,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEhE,OAAO,EACL,aAAa,EACb,cAAc,EACd,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,2FAA2F;AAC3F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;GAO9B,CAAA;AAEF,0EAA0E;AAC1E,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,SAAc,GAAG,IAAI,CAoDhE"}
|
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.
|
|
4
|
+
"version": "0.1.6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
package/lib/state-7ChK99mH.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
//#region lib/types/affinity.js
|
|
2
|
-
/**
|
|
3
|
-
* Affinity score — pure, clock-injected. The pet grows closer the more you
|
|
4
|
-
* work together and care for it: every completed turn earns a small reward,
|
|
5
|
-
* petting earns a tiny one (cooldown-gated), feeding earns the most.
|
|
6
|
-
* Persistence lives in the service; this module only computes transitions.
|
|
7
|
-
* @module @deepseek-ai/dsh-pet/affinity
|
|
8
|
-
*/
|
|
9
|
-
const AFFINITY_MAX = 100;
|
|
10
|
-
/** Affinity ranks by points; the pet visibly grows with its rank. */
|
|
11
|
-
const AFFINITY_RANKS = [
|
|
12
|
-
{
|
|
13
|
-
min: 0,
|
|
14
|
-
name: "幼鲸",
|
|
15
|
-
emoji: "🐣"
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
min: 25,
|
|
19
|
-
name: "伙伴",
|
|
20
|
-
emoji: "🐬"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
min: 50,
|
|
24
|
-
name: "挚友",
|
|
25
|
-
emoji: "🐳"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
min: 80,
|
|
29
|
-
name: "深海羁绊",
|
|
30
|
-
emoji: "💙"
|
|
31
|
-
}
|
|
32
|
-
];
|
|
33
|
-
const defaultAffinityConfig = {
|
|
34
|
-
turnReward: 1,
|
|
35
|
-
petReward: 1,
|
|
36
|
-
petCooldownMs: 1e4,
|
|
37
|
-
feedReward: 5,
|
|
38
|
-
feedCooldownMs: 3e4
|
|
39
|
-
};
|
|
40
|
-
function emptyAffinity() {
|
|
41
|
-
return {
|
|
42
|
-
points: 0,
|
|
43
|
-
lastPetAt: 0,
|
|
44
|
-
lastFeedAt: 0,
|
|
45
|
-
pets: 0,
|
|
46
|
-
feeds: 0,
|
|
47
|
-
turns: 0
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
/** Rank for a point total. */
|
|
51
|
-
function rankOf(points) {
|
|
52
|
-
let rank = AFFINITY_RANKS[0];
|
|
53
|
-
for (const candidate of AFFINITY_RANKS) if (points >= candidate.min) rank = candidate;
|
|
54
|
-
return rank;
|
|
55
|
-
}
|
|
56
|
-
function clamp(points) {
|
|
57
|
-
return Math.min(100, Math.max(0, points));
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Apply one interaction to a copy of the state (immutable style: returns a
|
|
61
|
-
* new object; the caller replaces the persisted state). Cooldowns only
|
|
62
|
-
* apply once the pet has been interacted with at least once (last*At === 0
|
|
63
|
-
* means "never", so the first pet/feed always lands).
|
|
64
|
-
*/
|
|
65
|
-
function applyInteraction(state, kind, nowMs, config = defaultAffinityConfig) {
|
|
66
|
-
const next = { ...state };
|
|
67
|
-
if (kind === "pet") {
|
|
68
|
-
if (state.lastPetAt !== 0 && nowMs - state.lastPetAt < config.petCooldownMs) return {
|
|
69
|
-
affinity: state,
|
|
70
|
-
delta: 0,
|
|
71
|
-
reaction: "摸过头啦,让鲸鱼娘歇口气~",
|
|
72
|
-
accepted: false
|
|
73
|
-
};
|
|
74
|
-
next.lastPetAt = nowMs;
|
|
75
|
-
next.pets += 1;
|
|
76
|
-
next.points = clamp(state.points + config.petReward);
|
|
77
|
-
return {
|
|
78
|
-
affinity: next,
|
|
79
|
-
delta: config.petReward,
|
|
80
|
-
reaction: "咕噜咕噜~被摸摸好舒服!",
|
|
81
|
-
accepted: true
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (kind === "feed") {
|
|
85
|
-
if (state.lastFeedAt !== 0 && nowMs - state.lastFeedAt < config.feedCooldownMs) return {
|
|
86
|
-
affinity: state,
|
|
87
|
-
delta: 0,
|
|
88
|
-
reaction: "吃饱啦,晚点再喂~",
|
|
89
|
-
accepted: false
|
|
90
|
-
};
|
|
91
|
-
next.lastFeedAt = nowMs;
|
|
92
|
-
next.feeds += 1;
|
|
93
|
-
next.points = clamp(state.points + config.feedReward);
|
|
94
|
-
return {
|
|
95
|
-
affinity: next,
|
|
96
|
-
delta: config.feedReward,
|
|
97
|
-
reaction: "呜哇!小鱼干好好吃!",
|
|
98
|
-
accepted: true
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
affinity: state,
|
|
103
|
-
delta: 0,
|
|
104
|
-
reaction: "",
|
|
105
|
-
accepted: false
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
/** Reward one completed turn (called by the host on `done`). */
|
|
109
|
-
function applyTurnReward(state, config = defaultAffinityConfig) {
|
|
110
|
-
const next = { ...state };
|
|
111
|
-
next.turns += 1;
|
|
112
|
-
next.points = clamp(state.points + config.turnReward);
|
|
113
|
-
return next;
|
|
114
|
-
}
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region lib/types/state.js
|
|
117
|
-
/**
|
|
118
|
-
* Pet state machine — pure, clock-injected. Maps the DSH `activity/status`
|
|
119
|
-
* phase vocabulary (session events) onto the 9-state Codex pet
|
|
120
|
-
* animation contract, plus the session lifecycle transitions the web UI
|
|
121
|
-
* exposes (turn end celebration, no-session idle).
|
|
122
|
-
*
|
|
123
|
-
* The machine is deliberately dumb: it holds the last input phase, the
|
|
124
|
-
* animation decision, and a one-shot "celebration" window after `done` so the
|
|
125
|
-
* pet visibly jumps before settling back to idle. Everything here is a pure
|
|
126
|
-
* function of (input, nowMs); persistence and RPC live in the service.
|
|
127
|
-
* @module @deepseek-ai/dsh-pet/state
|
|
128
|
-
*/
|
|
129
|
-
const defaultPetStateConfig = { celebrateMs: 2400 };
|
|
130
|
-
/**
|
|
131
|
-
* Map one activity phase onto the animation contract.
|
|
132
|
-
* - thinking / tool → `running` (focused work), with `running-right` as the
|
|
133
|
-
* side-alternating variant the client may use for tool activity.
|
|
134
|
-
* - waiting → `waiting` (expectant pose, needs user input).
|
|
135
|
-
* - done → `jumping` (celebration), then back to `idle` after the window.
|
|
136
|
-
* - idle → `idle` (calm breathing loop).
|
|
137
|
-
* `failed` has no DSH phase source yet; the machine keeps the mapping table
|
|
138
|
-
* so a future error event can light it up.
|
|
139
|
-
*/
|
|
140
|
-
function animationForPhase(phase) {
|
|
141
|
-
switch (phase) {
|
|
142
|
-
case "thinking": return "running";
|
|
143
|
-
case "tool": return "running-right";
|
|
144
|
-
case "waiting": return "waiting";
|
|
145
|
-
case "done": return "jumping";
|
|
146
|
-
case "idle": return "idle";
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/** The spritesheet row index for one animation track. */
|
|
150
|
-
function rowOf(animation) {
|
|
151
|
-
return {
|
|
152
|
-
"idle": 0,
|
|
153
|
-
"running-right": 1,
|
|
154
|
-
"running-left": 2,
|
|
155
|
-
"waving": 3,
|
|
156
|
-
"jumping": 4,
|
|
157
|
-
"failed": 5,
|
|
158
|
-
"waiting": 6,
|
|
159
|
-
"running": 7,
|
|
160
|
-
"review": 8
|
|
161
|
-
}[animation];
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* PetStateMachine — one instance per host process. Holds only the latest
|
|
165
|
-
* input snapshot and the celebration timing; no storage, no side effects.
|
|
166
|
-
*/
|
|
167
|
-
var PetStateMachine = class {
|
|
168
|
-
config;
|
|
169
|
-
now;
|
|
170
|
-
phase = "idle";
|
|
171
|
-
line;
|
|
172
|
-
phrase;
|
|
173
|
-
sessionActive = false;
|
|
174
|
-
doneAt;
|
|
175
|
-
constructor(config = defaultPetStateConfig, now = Date.now) {
|
|
176
|
-
this.config = config;
|
|
177
|
-
this.now = now;
|
|
178
|
-
}
|
|
179
|
-
/** Consume one `activity/status` session event. */
|
|
180
|
-
onActivityStatus(input) {
|
|
181
|
-
this.phase = input.phase;
|
|
182
|
-
this.line = input.line;
|
|
183
|
-
this.phrase = input.phrase;
|
|
184
|
-
if (input.phase === "done") this.doneAt = this.now();
|
|
185
|
-
}
|
|
186
|
-
/** A session became the active one (or a fresh session started). */
|
|
187
|
-
onSessionActive() {
|
|
188
|
-
this.sessionActive = true;
|
|
189
|
-
}
|
|
190
|
-
/** The active session was disposed (or none left). */
|
|
191
|
-
onSessionDisposed() {
|
|
192
|
-
this.sessionActive = false;
|
|
193
|
-
this.phase = "idle";
|
|
194
|
-
this.line = void 0;
|
|
195
|
-
this.phrase = void 0;
|
|
196
|
-
this.doneAt = void 0;
|
|
197
|
-
}
|
|
198
|
-
/** Render the current animation decision. */
|
|
199
|
-
render() {
|
|
200
|
-
const nowMs = this.now();
|
|
201
|
-
let animation = animationForPhase(this.phase);
|
|
202
|
-
if (this.phase === "done" && this.doneAt !== void 0) {
|
|
203
|
-
if (nowMs - this.doneAt < this.config.celebrateMs) animation = "jumping";
|
|
204
|
-
else animation = "idle";
|
|
205
|
-
}
|
|
206
|
-
const bubble = this.phrase ?? this.line;
|
|
207
|
-
return {
|
|
208
|
-
animation,
|
|
209
|
-
...bubble === void 0 ? {} : { bubble },
|
|
210
|
-
animationStartedAt: nowMs,
|
|
211
|
-
phase: this.phase,
|
|
212
|
-
sessionActive: this.sessionActive
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
//#endregion
|
|
217
|
-
export { AFFINITY_MAX as a, applyTurnReward as c, rankOf as d, rowOf as i, defaultAffinityConfig as l, animationForPhase as n, AFFINITY_RANKS as o, defaultPetStateConfig as r, applyInteraction as s, PetStateMachine as t, emptyAffinity as u };
|
package/lib/state-CKh9f_dF.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
//#region src/affinity.ts
|
|
2
|
-
const AFFINITY_MAX = 100;
|
|
3
|
-
/** Affinity ranks by points; the pet visibly grows with its rank. */
|
|
4
|
-
const AFFINITY_RANKS = [
|
|
5
|
-
{
|
|
6
|
-
min: 0,
|
|
7
|
-
name: "幼鲸",
|
|
8
|
-
emoji: "🐣"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
min: 25,
|
|
12
|
-
name: "伙伴",
|
|
13
|
-
emoji: "🐬"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
min: 50,
|
|
17
|
-
name: "挚友",
|
|
18
|
-
emoji: "🐳"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
min: 80,
|
|
22
|
-
name: "深海羁绊",
|
|
23
|
-
emoji: "💙"
|
|
24
|
-
}
|
|
25
|
-
];
|
|
26
|
-
const defaultAffinityConfig = {
|
|
27
|
-
turnReward: 1,
|
|
28
|
-
petReward: 1,
|
|
29
|
-
petCooldownMs: 1e4,
|
|
30
|
-
feedReward: 5,
|
|
31
|
-
feedCooldownMs: 3e4
|
|
32
|
-
};
|
|
33
|
-
function emptyAffinity() {
|
|
34
|
-
return {
|
|
35
|
-
points: 0,
|
|
36
|
-
lastPetAt: 0,
|
|
37
|
-
lastFeedAt: 0,
|
|
38
|
-
pets: 0,
|
|
39
|
-
feeds: 0,
|
|
40
|
-
turns: 0
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
/** Rank for a point total. */
|
|
44
|
-
function rankOf(points) {
|
|
45
|
-
let rank = AFFINITY_RANKS[0];
|
|
46
|
-
for (const candidate of AFFINITY_RANKS) if (points >= candidate.min) rank = candidate;
|
|
47
|
-
return rank;
|
|
48
|
-
}
|
|
49
|
-
function clamp(points) {
|
|
50
|
-
return Math.min(100, Math.max(0, points));
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Apply one interaction to a copy of the state (immutable style: returns a
|
|
54
|
-
* new object; the caller replaces the persisted state). Cooldowns only
|
|
55
|
-
* apply once the pet has been interacted with at least once (last*At === 0
|
|
56
|
-
* means "never", so the first pet/feed always lands).
|
|
57
|
-
*/
|
|
58
|
-
function applyInteraction(state, kind, nowMs, config = defaultAffinityConfig) {
|
|
59
|
-
const next = { ...state };
|
|
60
|
-
if (kind === "pet") {
|
|
61
|
-
if (state.lastPetAt !== 0 && nowMs - state.lastPetAt < config.petCooldownMs) return {
|
|
62
|
-
affinity: state,
|
|
63
|
-
delta: 0,
|
|
64
|
-
reaction: "摸过头啦,让鲸鱼娘歇口气~",
|
|
65
|
-
accepted: false
|
|
66
|
-
};
|
|
67
|
-
next.lastPetAt = nowMs;
|
|
68
|
-
next.pets += 1;
|
|
69
|
-
next.points = clamp(state.points + config.petReward);
|
|
70
|
-
return {
|
|
71
|
-
affinity: next,
|
|
72
|
-
delta: config.petReward,
|
|
73
|
-
reaction: "咕噜咕噜~被摸摸好舒服!",
|
|
74
|
-
accepted: true
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (kind === "feed") {
|
|
78
|
-
if (state.lastFeedAt !== 0 && nowMs - state.lastFeedAt < config.feedCooldownMs) return {
|
|
79
|
-
affinity: state,
|
|
80
|
-
delta: 0,
|
|
81
|
-
reaction: "吃饱啦,晚点再喂~",
|
|
82
|
-
accepted: false
|
|
83
|
-
};
|
|
84
|
-
next.lastFeedAt = nowMs;
|
|
85
|
-
next.feeds += 1;
|
|
86
|
-
next.points = clamp(state.points + config.feedReward);
|
|
87
|
-
return {
|
|
88
|
-
affinity: next,
|
|
89
|
-
delta: config.feedReward,
|
|
90
|
-
reaction: "呜哇!小鱼干好好吃!",
|
|
91
|
-
accepted: true
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
affinity: state,
|
|
96
|
-
delta: 0,
|
|
97
|
-
reaction: "",
|
|
98
|
-
accepted: false
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/** Reward one completed turn (called by the host on `done`). */
|
|
102
|
-
function applyTurnReward(state, config = defaultAffinityConfig) {
|
|
103
|
-
const next = { ...state };
|
|
104
|
-
next.turns += 1;
|
|
105
|
-
next.points = clamp(state.points + config.turnReward);
|
|
106
|
-
return next;
|
|
107
|
-
}
|
|
108
|
-
//#endregion
|
|
109
|
-
//#region src/state.ts
|
|
110
|
-
const defaultPetStateConfig = { celebrateMs: 2400 };
|
|
111
|
-
/**
|
|
112
|
-
* Map one activity phase onto the animation contract.
|
|
113
|
-
* - thinking / tool → `running` (focused work), with `running-right` as the
|
|
114
|
-
* side-alternating variant the client may use for tool activity.
|
|
115
|
-
* - waiting → `waiting` (expectant pose, needs user input).
|
|
116
|
-
* - done → `jumping` (celebration), then back to `idle` after the window.
|
|
117
|
-
* - idle → `idle` (calm breathing loop).
|
|
118
|
-
* `failed` has no DSH phase source yet; the machine keeps the mapping table
|
|
119
|
-
* so a future error event can light it up.
|
|
120
|
-
*/
|
|
121
|
-
function animationForPhase(phase) {
|
|
122
|
-
switch (phase) {
|
|
123
|
-
case "thinking": return "running";
|
|
124
|
-
case "tool": return "running-right";
|
|
125
|
-
case "waiting": return "waiting";
|
|
126
|
-
case "done": return "jumping";
|
|
127
|
-
case "idle": return "idle";
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/** The spritesheet row index for one animation track. */
|
|
131
|
-
function rowOf(animation) {
|
|
132
|
-
return {
|
|
133
|
-
"idle": 0,
|
|
134
|
-
"running-right": 1,
|
|
135
|
-
"running-left": 2,
|
|
136
|
-
"waving": 3,
|
|
137
|
-
"jumping": 4,
|
|
138
|
-
"failed": 5,
|
|
139
|
-
"waiting": 6,
|
|
140
|
-
"running": 7,
|
|
141
|
-
"review": 8
|
|
142
|
-
}[animation];
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* PetStateMachine — one instance per host process. Holds only the latest
|
|
146
|
-
* input snapshot and the celebration timing; no storage, no side effects.
|
|
147
|
-
*/
|
|
148
|
-
var PetStateMachine = class {
|
|
149
|
-
config;
|
|
150
|
-
now;
|
|
151
|
-
phase = "idle";
|
|
152
|
-
line;
|
|
153
|
-
phrase;
|
|
154
|
-
sessionActive = false;
|
|
155
|
-
doneAt;
|
|
156
|
-
constructor(config = defaultPetStateConfig, now = Date.now) {
|
|
157
|
-
this.config = config;
|
|
158
|
-
this.now = now;
|
|
159
|
-
}
|
|
160
|
-
/** Consume one `activity/status` session event. */
|
|
161
|
-
onActivityStatus(input) {
|
|
162
|
-
this.phase = input.phase;
|
|
163
|
-
this.line = input.line;
|
|
164
|
-
this.phrase = input.phrase;
|
|
165
|
-
if (input.phase === "done") this.doneAt = this.now();
|
|
166
|
-
}
|
|
167
|
-
/** A session became the active one (or a fresh session started). */
|
|
168
|
-
onSessionActive() {
|
|
169
|
-
this.sessionActive = true;
|
|
170
|
-
}
|
|
171
|
-
/** The active session was disposed (or none left). */
|
|
172
|
-
onSessionDisposed() {
|
|
173
|
-
this.sessionActive = false;
|
|
174
|
-
this.phase = "idle";
|
|
175
|
-
this.line = void 0;
|
|
176
|
-
this.phrase = void 0;
|
|
177
|
-
this.doneAt = void 0;
|
|
178
|
-
}
|
|
179
|
-
/** Render the current animation decision. */
|
|
180
|
-
render() {
|
|
181
|
-
const nowMs = this.now();
|
|
182
|
-
let animation = animationForPhase(this.phase);
|
|
183
|
-
if (this.phase === "done" && this.doneAt !== void 0) if (nowMs - this.doneAt < this.config.celebrateMs) animation = "jumping";
|
|
184
|
-
else animation = "idle";
|
|
185
|
-
const bubble = this.phrase ?? this.line;
|
|
186
|
-
return {
|
|
187
|
-
animation,
|
|
188
|
-
...bubble === void 0 ? {} : { bubble },
|
|
189
|
-
animationStartedAt: nowMs,
|
|
190
|
-
phase: this.phase,
|
|
191
|
-
sessionActive: this.sessionActive
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
//#endregion
|
|
196
|
-
export { AFFINITY_MAX as a, applyTurnReward as c, rankOf as d, rowOf as i, defaultAffinityConfig as l, animationForPhase as n, AFFINITY_RANKS as o, defaultPetStateConfig as r, applyInteraction as s, PetStateMachine as t, emptyAffinity as u };
|
package/lib/state-DMgOYVFT.js
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
//#region src/affinity.ts
|
|
2
|
-
const AFFINITY_MAX = 100;
|
|
3
|
-
/** Affinity ranks by points; the pet visibly grows with its rank. */
|
|
4
|
-
const AFFINITY_RANKS = [
|
|
5
|
-
{
|
|
6
|
-
min: 0,
|
|
7
|
-
name: "幼鲸",
|
|
8
|
-
emoji: "🐣"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
min: 25,
|
|
12
|
-
name: "伙伴",
|
|
13
|
-
emoji: "🐬"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
min: 50,
|
|
17
|
-
name: "挚友",
|
|
18
|
-
emoji: "🐳"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
min: 80,
|
|
22
|
-
name: "深海羁绊",
|
|
23
|
-
emoji: "💙"
|
|
24
|
-
}
|
|
25
|
-
];
|
|
26
|
-
const defaultAffinityConfig = {
|
|
27
|
-
turnReward: 1,
|
|
28
|
-
petReward: 1,
|
|
29
|
-
petCooldownMs: 1e4,
|
|
30
|
-
feedReward: 5,
|
|
31
|
-
feedCooldownMs: 3e4
|
|
32
|
-
};
|
|
33
|
-
function emptyAffinity() {
|
|
34
|
-
return {
|
|
35
|
-
points: 0,
|
|
36
|
-
lastPetAt: 0,
|
|
37
|
-
lastFeedAt: 0,
|
|
38
|
-
pets: 0,
|
|
39
|
-
feeds: 0,
|
|
40
|
-
turns: 0
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
/** Rank for a point total. */
|
|
44
|
-
function rankOf(points) {
|
|
45
|
-
let rank = AFFINITY_RANKS[0];
|
|
46
|
-
for (const candidate of AFFINITY_RANKS) if (points >= candidate.min) rank = candidate;
|
|
47
|
-
return rank;
|
|
48
|
-
}
|
|
49
|
-
function clamp(points) {
|
|
50
|
-
return Math.min(100, Math.max(0, points));
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Apply one interaction to a copy of the state (immutable style: returns a
|
|
54
|
-
* new object; the caller replaces the persisted state). Cooldowns only
|
|
55
|
-
* apply once the pet has been interacted with at least once (last*At === 0
|
|
56
|
-
* means "never", so the first pet/feed always lands).
|
|
57
|
-
*/
|
|
58
|
-
function applyInteraction(state, kind, nowMs, config = defaultAffinityConfig) {
|
|
59
|
-
const next = { ...state };
|
|
60
|
-
if (kind === "pet") {
|
|
61
|
-
if (state.lastPetAt !== 0 && nowMs - state.lastPetAt < config.petCooldownMs) return {
|
|
62
|
-
affinity: state,
|
|
63
|
-
delta: 0,
|
|
64
|
-
reaction: "摸过头啦,让鲸鱼娘歇口气~",
|
|
65
|
-
accepted: false
|
|
66
|
-
};
|
|
67
|
-
next.lastPetAt = nowMs;
|
|
68
|
-
next.pets += 1;
|
|
69
|
-
next.points = clamp(state.points + config.petReward);
|
|
70
|
-
return {
|
|
71
|
-
affinity: next,
|
|
72
|
-
delta: config.petReward,
|
|
73
|
-
reaction: "咕噜咕噜~被摸摸好舒服!",
|
|
74
|
-
accepted: true
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (kind === "feed") {
|
|
78
|
-
if (state.lastFeedAt !== 0 && nowMs - state.lastFeedAt < config.feedCooldownMs) return {
|
|
79
|
-
affinity: state,
|
|
80
|
-
delta: 0,
|
|
81
|
-
reaction: "吃饱啦,晚点再喂~",
|
|
82
|
-
accepted: false
|
|
83
|
-
};
|
|
84
|
-
next.lastFeedAt = nowMs;
|
|
85
|
-
next.feeds += 1;
|
|
86
|
-
next.points = clamp(state.points + config.feedReward);
|
|
87
|
-
return {
|
|
88
|
-
affinity: next,
|
|
89
|
-
delta: config.feedReward,
|
|
90
|
-
reaction: "呜哇!小鱼干好好吃!",
|
|
91
|
-
accepted: true
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
affinity: state,
|
|
96
|
-
delta: 0,
|
|
97
|
-
reaction: "",
|
|
98
|
-
accepted: false
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
/** Reward one completed turn (called by the host on `done`). */
|
|
102
|
-
function applyTurnReward(state, config = defaultAffinityConfig) {
|
|
103
|
-
const next = { ...state };
|
|
104
|
-
next.turns += 1;
|
|
105
|
-
next.points = clamp(state.points + config.turnReward);
|
|
106
|
-
return next;
|
|
107
|
-
}
|
|
108
|
-
//#endregion
|
|
109
|
-
//#region src/state.ts
|
|
110
|
-
const defaultPetStateConfig = { celebrateMs: 2400 };
|
|
111
|
-
/**
|
|
112
|
-
* Map one activity phase onto the animation contract.
|
|
113
|
-
* - thinking / tool → `running` (focused work), with `running-right` as the
|
|
114
|
-
* side-alternating variant the client may use for tool activity.
|
|
115
|
-
* - waiting → `waiting` (expectant pose, needs user input).
|
|
116
|
-
* - done → `jumping` (celebration), then back to `idle` after the window.
|
|
117
|
-
* - idle → `idle` (calm breathing loop).
|
|
118
|
-
* `failed` has no DSH phase source yet; the machine keeps the mapping table
|
|
119
|
-
* so a future error event can light it up.
|
|
120
|
-
*/
|
|
121
|
-
function animationForPhase(phase) {
|
|
122
|
-
switch (phase) {
|
|
123
|
-
case "thinking": return "running";
|
|
124
|
-
case "tool": return "running-right";
|
|
125
|
-
case "waiting": return "waiting";
|
|
126
|
-
case "done": return "jumping";
|
|
127
|
-
case "idle": return "idle";
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/** The spritesheet row index for one animation track. */
|
|
131
|
-
function rowOf(animation) {
|
|
132
|
-
return {
|
|
133
|
-
"idle": 0,
|
|
134
|
-
"running-right": 1,
|
|
135
|
-
"running-left": 2,
|
|
136
|
-
"waving": 3,
|
|
137
|
-
"jumping": 4,
|
|
138
|
-
"failed": 5,
|
|
139
|
-
"waiting": 6,
|
|
140
|
-
"running": 7,
|
|
141
|
-
"review": 8
|
|
142
|
-
}[animation];
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* PetStateMachine — one instance per host process. Holds only the latest
|
|
146
|
-
* input snapshot and the celebration timing; no storage, no side effects.
|
|
147
|
-
*/
|
|
148
|
-
var PetStateMachine = class {
|
|
149
|
-
config;
|
|
150
|
-
now;
|
|
151
|
-
phase = "idle";
|
|
152
|
-
line;
|
|
153
|
-
phrase;
|
|
154
|
-
sessionActive = false;
|
|
155
|
-
doneAt;
|
|
156
|
-
constructor(config = defaultPetStateConfig, now = Date.now) {
|
|
157
|
-
this.config = config;
|
|
158
|
-
this.now = now;
|
|
159
|
-
}
|
|
160
|
-
/** Consume one `activity/status` session event. */
|
|
161
|
-
onActivityStatus(input) {
|
|
162
|
-
this.phase = input.phase;
|
|
163
|
-
this.line = input.line;
|
|
164
|
-
this.phrase = input.phrase;
|
|
165
|
-
if (input.phase === "done") this.doneAt = this.now();
|
|
166
|
-
}
|
|
167
|
-
/** A session became the active one (or a fresh session started). */
|
|
168
|
-
onSessionActive() {
|
|
169
|
-
this.sessionActive = true;
|
|
170
|
-
}
|
|
171
|
-
/** The active session was disposed (or none left). */
|
|
172
|
-
onSessionDisposed() {
|
|
173
|
-
this.sessionActive = false;
|
|
174
|
-
this.phase = "idle";
|
|
175
|
-
this.line = void 0;
|
|
176
|
-
this.phrase = void 0;
|
|
177
|
-
this.doneAt = void 0;
|
|
178
|
-
}
|
|
179
|
-
/** Render the current animation decision. */
|
|
180
|
-
render() {
|
|
181
|
-
const nowMs = this.now();
|
|
182
|
-
let animation = animationForPhase(this.phase);
|
|
183
|
-
if (this.phase === "done" && this.doneAt !== void 0) {
|
|
184
|
-
if (nowMs - this.doneAt < this.config.celebrateMs) animation = "jumping";
|
|
185
|
-
else animation = "idle";
|
|
186
|
-
}
|
|
187
|
-
const bubble = this.phrase ?? this.line;
|
|
188
|
-
return {
|
|
189
|
-
animation,
|
|
190
|
-
...bubble === void 0 ? {} : { bubble },
|
|
191
|
-
animationStartedAt: nowMs,
|
|
192
|
-
phase: this.phase,
|
|
193
|
-
sessionActive: this.sessionActive
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
//#endregion
|
|
198
|
-
export { AFFINITY_MAX as a, applyTurnReward as c, rankOf as d, rowOf as i, defaultAffinityConfig as l, animationForPhase as n, AFFINITY_RANKS as o, defaultPetStateConfig as r, applyInteraction as s, PetStateMachine as t, emptyAffinity as u };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dock-band fallback seat for the pet.
|
|
3
|
-
*
|
|
4
|
-
* Current dsh web shells declare `conversation.input.dock` (the composer dock
|
|
5
|
-
* band, a list slot) instead of the legacy `conversation.input.selector.context`
|
|
6
|
-
* hole this plugin was written against. The dock band renders only for an
|
|
7
|
-
* active session, so on shells that carry it the pet follows the session seat
|
|
8
|
-
* — an acceptable degradation until the upstream shell restores the context
|
|
9
|
-
* hole. The underlying entry ignores owner props (it reads only injected
|
|
10
|
-
* actions and the locale), so this wrapper is a pure props re-cast.
|
|
11
|
-
*/
|
|
12
|
-
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
13
|
-
import { type PetInjected } from './PetDockEntry.tsx';
|
|
14
|
-
import { NS } from './locales.ts';
|
|
15
|
-
/** Composed props of the dock-band fallback seat. */
|
|
16
|
-
export type DockPetDockEntryProps = PropsRuntime<'conversation.input.dock'> & PetInjected & PropsLocale<typeof NS>;
|
|
17
|
-
/**
|
|
18
|
-
* Render the pet dock from the composer dock band.
|
|
19
|
-
* @param props - composed slot props (dock band seat).
|
|
20
|
-
* @returns the dock entry element tree.
|
|
21
|
-
*/
|
|
22
|
-
export declare function DockPetDockEntry(props: DockPetDockEntryProps): import("react").JSX.Element;
|
|
23
|
-
//# sourceMappingURL=DockPetDockEntry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DockPetDockEntry.d.ts","sourceRoot":"","sources":["../../../src/client/DockPetDockEntry.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEjF,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC3F,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAA;AAEjC,qDAAqD;AACrD,MAAM,MAAM,qBAAqB,GAAG,YAAY,CAAC,yBAAyB,CAAC,GAAG,WAAW,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAA;AAElH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,+BAE5D"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { PetDockEntry } from "./PetDockEntry.js";
|
|
3
|
-
/**
|
|
4
|
-
* Render the pet dock from the composer dock band.
|
|
5
|
-
* @param props - composed slot props (dock band seat).
|
|
6
|
-
* @returns the dock entry element tree.
|
|
7
|
-
*/
|
|
8
|
-
export function DockPetDockEntry(props) {
|
|
9
|
-
return _jsx(PetDockEntry, { ...props });
|
|
10
|
-
}
|