@luv1211/dsh-pet 0.1.1-rc.2
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/LICENSE +22 -0
- package/README.i18n.yaml +6 -0
- package/README.md +35 -0
- package/README.zh.md +35 -0
- package/assets/deepseek-whale/pet.json +12 -0
- package/assets/deepseek-whale/spritesheet.webp +0 -0
- package/lib/index.js +1613 -0
- package/lib/invariant.js +19 -0
- package/lib/types/activity.d.ts +29 -0
- package/lib/types/activity.js +63 -0
- package/lib/types/catalog.d.ts +67 -0
- package/lib/types/catalog.js +258 -0
- package/lib/types/client.d.ts +13 -0
- package/lib/types/client.js +10 -0
- package/lib/types/host-image.d.ts +11 -0
- package/lib/types/host-image.js +48 -0
- package/lib/types/host-native.d.ts +17 -0
- package/lib/types/host-native.js +50 -0
- package/lib/types/index.d.ts +114 -0
- package/lib/types/index.js +631 -0
- package/lib/types/invariant.d.ts +9 -0
- package/lib/types/invariant.js +18 -0
- package/lib/types/path-opener.d.ts +50 -0
- package/lib/types/path-opener.js +161 -0
- package/lib/types/renderer.d.ts +42 -0
- package/lib/types/renderer.js +54 -0
- package/lib/types/runtime.d.ts +155 -0
- package/lib/types/runtime.js +314 -0
- package/lib/types/types.d.ts +147 -0
- package/lib/types/types.js +7 -0
- package/package.json +111 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform native path and text-document openers used by the local GUI
|
|
3
|
+
* carrier.
|
|
4
|
+
*
|
|
5
|
+
* The default intent prefers the default browser for documents it renders when
|
|
6
|
+
* the platform can name one, then falls back to the default application. WSL
|
|
7
|
+
* translates every path for the Windows desktop instead of assuming a Linux
|
|
8
|
+
* GUI. The text-editor intent never consults the browser.
|
|
9
|
+
*/
|
|
10
|
+
import { type NativeCommandRunner } from '@deepseek-ai/dsh-native-command';
|
|
11
|
+
/** Testable command boundary; native implementations never invoke a shell. */
|
|
12
|
+
export type PathOpenerRunner = NativeCommandRunner;
|
|
13
|
+
/** Injectable platform facts for deterministic adapter tests. */
|
|
14
|
+
export interface PathOpenerInternals {
|
|
15
|
+
platform?: NodeJS.Platform;
|
|
16
|
+
/** Kernel release override used to distinguish WSL from desktop Linux. */
|
|
17
|
+
osRelease?: string;
|
|
18
|
+
/** Environment used for WSL markers and the desktop Linux browser convention. */
|
|
19
|
+
env?: NodeJS.ProcessEnv;
|
|
20
|
+
run?: PathOpenerRunner;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether {@link openNativePath} plausibly reaches a desktop on this host.
|
|
24
|
+
*
|
|
25
|
+
* macOS and Windows always carry a desktop opener; Linux does when it is WSL
|
|
26
|
+
* (the Windows desktop takes the path) or a display server is announced.
|
|
27
|
+
* A headless or containerised Linux host answers false, which is what lets a
|
|
28
|
+
* surface show a path as text instead of offering a button that would spawn
|
|
29
|
+
* `xdg-open` into nothing.
|
|
30
|
+
* @param internals - platform and environment seam for deterministic tests.
|
|
31
|
+
* @returns true when handing a path to the native opener can work at all.
|
|
32
|
+
*/
|
|
33
|
+
export declare function canOpenNativePath(internals?: PathOpenerInternals): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Open a filesystem path with the operating system's default application, or
|
|
36
|
+
* with the default browser when the path names a document a browser renders.
|
|
37
|
+
* @param path - absolute or host-resolvable path (caller owns resolution).
|
|
38
|
+
* @param signal - caller/connection lifetime; abort terminates the native command.
|
|
39
|
+
* @param internals - Platform, environment, and runner hooks for deterministic tests.
|
|
40
|
+
*/
|
|
41
|
+
export declare function openNativePath(path: string, signal: AbortSignal, internals?: PathOpenerInternals): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Open a text document for editing; macOS bypasses the file-type association
|
|
44
|
+
* so a YAML association with a browser cannot consume the gesture.
|
|
45
|
+
* @param path - absolute or host-resolvable text-document path.
|
|
46
|
+
* @param signal - caller/connection lifetime; abort terminates the native command.
|
|
47
|
+
* @param internals - Platform and runner hooks for deterministic tests.
|
|
48
|
+
*/
|
|
49
|
+
export declare function openNativeTextFile(path: string, signal: AbortSignal, internals?: PathOpenerInternals): Promise<void>;
|
|
50
|
+
//# sourceMappingURL=path-opener.d.ts.map
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform native path and text-document openers used by the local GUI
|
|
3
|
+
* carrier.
|
|
4
|
+
*
|
|
5
|
+
* The default intent prefers the default browser for documents it renders when
|
|
6
|
+
* the platform can name one, then falls back to the default application. WSL
|
|
7
|
+
* translates every path for the Windows desktop instead of assuming a Linux
|
|
8
|
+
* GUI. The text-editor intent never consults the browser.
|
|
9
|
+
*/
|
|
10
|
+
import { release as osRelease } from 'node:os';
|
|
11
|
+
import { extname } from 'node:path';
|
|
12
|
+
import { runNativeCommand } from '@deepseek-ai/dsh-native-command';
|
|
13
|
+
/** Documents a browser renders, as opposed to ones an editor merely edits. */
|
|
14
|
+
const BROWSER_DOCUMENTS = new Set(['.html', '.htm', '.xhtml', '.svg']);
|
|
15
|
+
/**
|
|
16
|
+
* The macOS bundle registered for `https` — the default browser, as
|
|
17
|
+
* LaunchServices records it. The nested version dict is stripped first
|
|
18
|
+
* because it carries its own `LSHandlerRoleAll`.
|
|
19
|
+
*/
|
|
20
|
+
function macBundleForHttps(plist) {
|
|
21
|
+
const stripped = plist.replace(/LSHandlerPreferredVersions\s*=\s*\{[^}]*\};/g, '');
|
|
22
|
+
const block = /\{[^{}]*LSHandlerURLScheme\s*=\s*"?https"?;[^{}]*\}/.exec(stripped)?.[0];
|
|
23
|
+
if (block === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
return /LSHandlerRoleAll\s*=\s*"?([\w.-]+)"?;/.exec(block)?.[1];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Open one browser-renderable document with the default browser.
|
|
29
|
+
* @returns true when a browser took it; false when this platform cannot name
|
|
30
|
+
* one, or naming it failed — the caller then uses the default application.
|
|
31
|
+
*/
|
|
32
|
+
async function openInBrowser(path, signal, platform, run, env) {
|
|
33
|
+
if (platform === 'darwin') {
|
|
34
|
+
let bundle;
|
|
35
|
+
try {
|
|
36
|
+
const { stdout } = await run('defaults', ['read', 'com.apple.LaunchServices/com.apple.launchservices.secure'], signal);
|
|
37
|
+
bundle = macBundleForHttps(stdout);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// No LaunchServices record (a fresh account never changed a default):
|
|
41
|
+
// the content-type handler is then the system's own choice anyway.
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (bundle === undefined)
|
|
45
|
+
return false;
|
|
46
|
+
await run('open', ['-b', bundle, path], signal);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
if (platform === 'linux') {
|
|
50
|
+
// $BROWSER is the portable convention; desktop-entry resolution through
|
|
51
|
+
// xdg-settings needs a launcher this package has no business shipping.
|
|
52
|
+
const browser = env.BROWSER;
|
|
53
|
+
if (browser === undefined || browser === '')
|
|
54
|
+
return false;
|
|
55
|
+
await run(browser, [path], signal);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// Windows names no browser without reading the UserChoice registry, and its
|
|
59
|
+
// .html association is the browser in the ordinary case.
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/** PowerShell single-quoted literal (doubles embedded quotes). */
|
|
63
|
+
function powershellLiteral(path) {
|
|
64
|
+
return `'${path.replace(/'/g, "''")}'`;
|
|
65
|
+
}
|
|
66
|
+
/** Whether one environment marker is set to a non-empty value. */
|
|
67
|
+
function present(value) {
|
|
68
|
+
return value !== undefined && value !== '';
|
|
69
|
+
}
|
|
70
|
+
/** Distinguish WSL from desktop Linux using its process and kernel markers. */
|
|
71
|
+
function isWsl(internals) {
|
|
72
|
+
const env = internals.env ?? process.env;
|
|
73
|
+
if (present(env.WSL_DISTRO_NAME) || present(env.WSL_INTEROP))
|
|
74
|
+
return true;
|
|
75
|
+
return (internals.osRelease ?? osRelease()).toLowerCase().includes('microsoft');
|
|
76
|
+
}
|
|
77
|
+
/** Open one Windows-resolvable path through its registered desktop application. */
|
|
78
|
+
async function openWindowsPath(path, signal, run) {
|
|
79
|
+
await run('powershell.exe', [
|
|
80
|
+
'-NoProfile',
|
|
81
|
+
'-Command',
|
|
82
|
+
`Invoke-Item -LiteralPath ${powershellLiteral(path)}`,
|
|
83
|
+
], signal);
|
|
84
|
+
}
|
|
85
|
+
/** Translate a WSL path before handing it to the Windows desktop. */
|
|
86
|
+
async function openWslPath(path, signal, run) {
|
|
87
|
+
const translated = await run('wslpath', ['-w', path], signal);
|
|
88
|
+
signal.throwIfAborted();
|
|
89
|
+
const windowsPath = translated.stdout.replace(/[\r\n]+$/, '');
|
|
90
|
+
if (windowsPath === '')
|
|
91
|
+
throw new Error('wslpath returned no Windows path');
|
|
92
|
+
await openWindowsPath(windowsPath, signal, run);
|
|
93
|
+
}
|
|
94
|
+
/** Dispatch one shell-free platform command for the requested open intent. */
|
|
95
|
+
async function openNativePathWithIntent(path, signal, intent, internals = {}) {
|
|
96
|
+
const platform = internals.platform ?? process.platform;
|
|
97
|
+
const run = internals.run ?? runNativeCommand;
|
|
98
|
+
const env = internals.env ?? process.env;
|
|
99
|
+
const wsl = platform === 'linux' && isWsl(internals);
|
|
100
|
+
if (!wsl && intent === 'default' && BROWSER_DOCUMENTS.has(extname(path).toLowerCase())
|
|
101
|
+
&& await openInBrowser(path, signal, platform, run, env))
|
|
102
|
+
return;
|
|
103
|
+
if (platform === 'darwin') {
|
|
104
|
+
await run('open', intent === 'text-editor' ? ['-t', path] : [path], signal);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (platform === 'win32') {
|
|
108
|
+
await openWindowsPath(path, signal, run);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (platform === 'linux') {
|
|
112
|
+
if (wsl) {
|
|
113
|
+
await openWslPath(path, signal, run);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
await run('xdg-open', [path], signal);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`native path opener is unsupported on ${platform}`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Whether {@link openNativePath} plausibly reaches a desktop on this host.
|
|
123
|
+
*
|
|
124
|
+
* macOS and Windows always carry a desktop opener; Linux does when it is WSL
|
|
125
|
+
* (the Windows desktop takes the path) or a display server is announced.
|
|
126
|
+
* A headless or containerised Linux host answers false, which is what lets a
|
|
127
|
+
* surface show a path as text instead of offering a button that would spawn
|
|
128
|
+
* `xdg-open` into nothing.
|
|
129
|
+
* @param internals - platform and environment seam for deterministic tests.
|
|
130
|
+
* @returns true when handing a path to the native opener can work at all.
|
|
131
|
+
*/
|
|
132
|
+
export function canOpenNativePath(internals = {}) {
|
|
133
|
+
const platform = internals.platform ?? process.platform;
|
|
134
|
+
if (platform === 'darwin' || platform === 'win32')
|
|
135
|
+
return true;
|
|
136
|
+
if (platform !== 'linux')
|
|
137
|
+
return false;
|
|
138
|
+
const env = internals.env ?? process.env;
|
|
139
|
+
return isWsl(internals) || present(env.DISPLAY) || present(env.WAYLAND_DISPLAY);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Open a filesystem path with the operating system's default application, or
|
|
143
|
+
* with the default browser when the path names a document a browser renders.
|
|
144
|
+
* @param path - absolute or host-resolvable path (caller owns resolution).
|
|
145
|
+
* @param signal - caller/connection lifetime; abort terminates the native command.
|
|
146
|
+
* @param internals - Platform, environment, and runner hooks for deterministic tests.
|
|
147
|
+
*/
|
|
148
|
+
export function openNativePath(path, signal, internals = {}) {
|
|
149
|
+
return openNativePathWithIntent(path, signal, 'default', internals);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Open a text document for editing; macOS bypasses the file-type association
|
|
153
|
+
* so a YAML association with a browser cannot consume the gesture.
|
|
154
|
+
* @param path - absolute or host-resolvable text-document path.
|
|
155
|
+
* @param signal - caller/connection lifetime; abort terminates the native command.
|
|
156
|
+
* @param internals - Platform and runner hooks for deterministic tests.
|
|
157
|
+
*/
|
|
158
|
+
export function openNativeTextFile(path, signal, internals = {}) {
|
|
159
|
+
return openNativePathWithIntent(path, signal, 'text-editor', internals);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=path-opener.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Browser-safe sprite frame projection shared by Web and desktop documents. */
|
|
2
|
+
import { type PetAnimationState, type PetPresentation } from './runtime.ts';
|
|
3
|
+
import type { PetAnimation } from '@luv1211/dsh-pet-compat';
|
|
4
|
+
/** One CSS frame projection for the validated compatible atlas. */
|
|
5
|
+
export interface PetSpriteFrameStyle {
|
|
6
|
+
/** Logical CSS width of one atlas cell. */
|
|
7
|
+
readonly width: number;
|
|
8
|
+
/** Logical CSS height of one atlas cell. */
|
|
9
|
+
readonly height: number;
|
|
10
|
+
/** Origin-relative or otherwise validated sprite URL supplied by the caller. */
|
|
11
|
+
readonly backgroundImage: string;
|
|
12
|
+
/** CSS pixel offset of the selected atlas cell. */
|
|
13
|
+
readonly backgroundPosition: string;
|
|
14
|
+
/** Full atlas size in logical CSS pixels. */
|
|
15
|
+
readonly backgroundSize: string;
|
|
16
|
+
}
|
|
17
|
+
/** Resolve one elapsed presentation into a frame and CSS background projection.
|
|
18
|
+
* @param assetUrl - validated origin-relative sprite URL.
|
|
19
|
+
* @param sizePx - validated logical CSS cell height.
|
|
20
|
+
* @param presentation - renderer state selected for this update.
|
|
21
|
+
* @param elapsedMs - elapsed time since the selected state began.
|
|
22
|
+
* @param animations - validated package animation tracks, when available.
|
|
23
|
+
* @returns the selected atlas cell and its CSS background projection.
|
|
24
|
+
*/
|
|
25
|
+
export declare function petSpriteFrame(assetUrl: string, sizePx: number, presentation: PetPresentation, elapsedMs: number, animations?: Readonly<Record<string, PetAnimation>>): {
|
|
26
|
+
frame: {
|
|
27
|
+
state: PetAnimationState;
|
|
28
|
+
row: number;
|
|
29
|
+
column: number;
|
|
30
|
+
done: boolean;
|
|
31
|
+
};
|
|
32
|
+
style: PetSpriteFrameStyle;
|
|
33
|
+
};
|
|
34
|
+
/** Resolve the static first atlas cell into a CSS background projection at any display height.
|
|
35
|
+
* Unlike {@link petSpriteFrame} this projection is decoupled from the validated overlay size range,
|
|
36
|
+
* so fixed-size list avatars can render smaller than the wake-state minimum.
|
|
37
|
+
* @param assetUrl - validated origin-relative sprite URL.
|
|
38
|
+
* @param heightPx - display cell height in CSS pixels, chosen by the caller.
|
|
39
|
+
* @returns the frame-zero cell and its CSS background projection.
|
|
40
|
+
*/
|
|
41
|
+
export declare function petSpriteAvatar(assetUrl: string, heightPx: number): PetSpriteFrameStyle;
|
|
42
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Browser-safe sprite frame projection shared by Web and desktop documents. */
|
|
2
|
+
import { DEFAULT_PET_ANIMATIONS, frameAt } from '@luv1211/dsh-pet-compat';
|
|
3
|
+
import { PET_COMPAT_ATLAS, petWidthForSize, } from "./runtime.js";
|
|
4
|
+
/** Resolve one elapsed presentation into a frame and CSS background projection.
|
|
5
|
+
* @param assetUrl - validated origin-relative sprite URL.
|
|
6
|
+
* @param sizePx - validated logical CSS cell height.
|
|
7
|
+
* @param presentation - renderer state selected for this update.
|
|
8
|
+
* @param elapsedMs - elapsed time since the selected state began.
|
|
9
|
+
* @param animations - validated package animation tracks, when available.
|
|
10
|
+
* @returns the selected atlas cell and its CSS background projection.
|
|
11
|
+
*/
|
|
12
|
+
export function petSpriteFrame(assetUrl, sizePx, presentation, elapsedMs, animations) {
|
|
13
|
+
const frame = presentation.state === 'tucked'
|
|
14
|
+
? { state: 'idle', row: 0, column: 0, done: true }
|
|
15
|
+
: (() => {
|
|
16
|
+
const selection = frameAt(animations ?? DEFAULT_PET_ANIMATIONS, presentation.state, elapsedMs, !presentation.animate);
|
|
17
|
+
const spriteIndex = selection?.spriteIndex ?? 0;
|
|
18
|
+
return {
|
|
19
|
+
state: presentation.state,
|
|
20
|
+
row: Math.floor(spriteIndex / PET_COMPAT_ATLAS.columns),
|
|
21
|
+
column: spriteIndex % PET_COMPAT_ATLAS.columns,
|
|
22
|
+
done: selection?.animation === 'idle' && presentation.state !== 'idle',
|
|
23
|
+
};
|
|
24
|
+
})();
|
|
25
|
+
const width = petWidthForSize(sizePx);
|
|
26
|
+
return {
|
|
27
|
+
frame,
|
|
28
|
+
style: {
|
|
29
|
+
width,
|
|
30
|
+
height: sizePx,
|
|
31
|
+
backgroundImage: `url(${assetUrl})`,
|
|
32
|
+
backgroundPosition: `${-frame.column * width}px ${-frame.row * sizePx}px`,
|
|
33
|
+
backgroundSize: `${petWidthForSize(sizePx) * PET_COMPAT_ATLAS.columns}px ${sizePx * PET_COMPAT_ATLAS.rows}px`,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Resolve the static first atlas cell into a CSS background projection at any display height.
|
|
38
|
+
* Unlike {@link petSpriteFrame} this projection is decoupled from the validated overlay size range,
|
|
39
|
+
* so fixed-size list avatars can render smaller than the wake-state minimum.
|
|
40
|
+
* @param assetUrl - validated origin-relative sprite URL.
|
|
41
|
+
* @param heightPx - display cell height in CSS pixels, chosen by the caller.
|
|
42
|
+
* @returns the frame-zero cell and its CSS background projection.
|
|
43
|
+
*/
|
|
44
|
+
export function petSpriteAvatar(assetUrl, heightPx) {
|
|
45
|
+
const width = Math.round(heightPx * PET_COMPAT_ATLAS.cellWidth / PET_COMPAT_ATLAS.cellHeight);
|
|
46
|
+
return {
|
|
47
|
+
width,
|
|
48
|
+
height: heightPx,
|
|
49
|
+
backgroundImage: `url(${assetUrl})`,
|
|
50
|
+
backgroundPosition: '0px 0px',
|
|
51
|
+
backgroundSize: `${width * PET_COMPAT_ATLAS.columns}px ${heightPx * PET_COMPAT_ATLAS.rows}px`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** Browser-safe pet constants, validation, presentation selection, and timing. */
|
|
2
|
+
import type { PetActivityStatus, PetDescriptor, PetHostActivityRecord, PetPreference } from './types.ts';
|
|
3
|
+
import type { PetSessionActivity } from './types.ts';
|
|
4
|
+
/** Version of the durable pet preference document. */
|
|
5
|
+
export declare const PET_PREFERENCE_VERSION: 3;
|
|
6
|
+
/** Built-in identifier selected by a fresh preference document. */
|
|
7
|
+
export declare const DEFAULT_PET_ID = "deepseek-whale";
|
|
8
|
+
/** Default logical CSS height of one compatible atlas cell. */
|
|
9
|
+
export declare const DEFAULT_PET_SIZE_PX = 112;
|
|
10
|
+
/** Minimum logical CSS height accepted by the pet preference validator. */
|
|
11
|
+
export declare const MIN_PET_SIZE_PX = 80;
|
|
12
|
+
/** Maximum logical CSS height accepted by the pet preference validator. */
|
|
13
|
+
export declare const MAX_PET_SIZE_PX = 224;
|
|
14
|
+
/** Compatible atlas geometry owned by the DSH renderer. */
|
|
15
|
+
export declare const PET_COMPAT_ATLAS: Readonly<{
|
|
16
|
+
width: 1536;
|
|
17
|
+
height: 1872;
|
|
18
|
+
cellWidth: 192;
|
|
19
|
+
cellHeight: 208;
|
|
20
|
+
columns: 8;
|
|
21
|
+
rows: 9;
|
|
22
|
+
}>;
|
|
23
|
+
/** Base animation states with cells in rows 0 through 8. */
|
|
24
|
+
export type PetAnimationState = 'idle' | 'running-right' | 'running-left' | 'waving' | 'jumping' | 'failed' | 'waiting' | 'running' | 'review';
|
|
25
|
+
/** Horizontal movement direction accepted by the presentation selector. */
|
|
26
|
+
export type PetDragDirection = 'left' | 'right';
|
|
27
|
+
/** Relative pointer target used for the 16 look-direction bins. */
|
|
28
|
+
export interface PetLookTarget {
|
|
29
|
+
/** Horizontal target distance in CSS pixels. */
|
|
30
|
+
readonly x: number;
|
|
31
|
+
/** Vertical target distance in CSS pixels. */
|
|
32
|
+
readonly y: number;
|
|
33
|
+
}
|
|
34
|
+
/** Presentation input shared by the browser and Electron renderers. */
|
|
35
|
+
export interface PetPresentationInput {
|
|
36
|
+
/** Whether the companion is currently rendered. */
|
|
37
|
+
readonly awake: boolean;
|
|
38
|
+
/** Highest-priority host activity, or undefined for idle. */
|
|
39
|
+
readonly status?: PetActivityStatus;
|
|
40
|
+
/** Whether the pointer is hovering the companion. */
|
|
41
|
+
readonly hover: boolean;
|
|
42
|
+
/** Accepted horizontal drag direction, when the pointer is being dragged. */
|
|
43
|
+
readonly dragDirection?: PetDragDirection;
|
|
44
|
+
/** Whether animation timers must be suppressed. */
|
|
45
|
+
readonly reducedMotion: boolean;
|
|
46
|
+
/** Relative pointer target for look-direction selection. */
|
|
47
|
+
readonly lookTarget?: PetLookTarget;
|
|
48
|
+
}
|
|
49
|
+
/** Presentation state selected for one renderer update. */
|
|
50
|
+
export interface PetPresentation {
|
|
51
|
+
/** Domain-independent state used by CSS and animation lookup. */
|
|
52
|
+
readonly state: PetAnimationState | 'tucked';
|
|
53
|
+
/** Atlas row for the selected state. */
|
|
54
|
+
readonly row: number;
|
|
55
|
+
/** First frame column for the selected state. */
|
|
56
|
+
readonly frame: number;
|
|
57
|
+
/** One of the sixteen direction-row cells. */
|
|
58
|
+
readonly lookDirection: number;
|
|
59
|
+
/** Whether the frame renderer should use the direction rows for this state. */
|
|
60
|
+
readonly lookDirectionActive: boolean;
|
|
61
|
+
/** Whether the renderer should schedule future frames. */
|
|
62
|
+
readonly animate: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** Validation limits supplied by the owning host configuration. */
|
|
65
|
+
export interface PetPackageValidationOptions {
|
|
66
|
+
/** Optional origin-relative asset URL assigned by the catalog owner. */
|
|
67
|
+
readonly assetUrl?: string;
|
|
68
|
+
/** Maximum UTF-8 manifest size. */
|
|
69
|
+
readonly maxManifestBytes?: number;
|
|
70
|
+
/** Maximum spritesheet size. */
|
|
71
|
+
readonly maxSpriteBytes?: number;
|
|
72
|
+
}
|
|
73
|
+
/** Validation options that also name the catalog origin recorded on the descriptor. */
|
|
74
|
+
export interface PetPackageSourceOptions extends PetPackageValidationOptions {
|
|
75
|
+
/** Origin written verbatim onto the returned descriptor's `source`. */
|
|
76
|
+
readonly source: PetDescriptor['source'];
|
|
77
|
+
}
|
|
78
|
+
/** Stable validation error that callers can diagnose without parsing messages. */
|
|
79
|
+
export declare class PetValidationError extends TypeError {
|
|
80
|
+
/** Machine-readable validation category. */
|
|
81
|
+
readonly code = "invalid-pet-package";
|
|
82
|
+
constructor(message: string);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Sort activity records by user-action urgency, then newest state transition,
|
|
86
|
+
* then their stable opaque session ids.
|
|
87
|
+
* @param left - the first activity record.
|
|
88
|
+
* @param right - the second activity record.
|
|
89
|
+
* @returns a standard ascending sort comparison result.
|
|
90
|
+
*/
|
|
91
|
+
export declare function comparePetActivities(left: PetSessionActivity, right: PetSessionActivity): number;
|
|
92
|
+
/** Resolve a missing preference or validate a current preference document.
|
|
93
|
+
* @param value - decoded preference value from the settings provider.
|
|
94
|
+
* @returns the validated v3 preference.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolvePetPreference(value: unknown): PetPreference;
|
|
97
|
+
/** Return the fresh v3 preference defaults.
|
|
98
|
+
* @returns a new v3 preference document.
|
|
99
|
+
*/
|
|
100
|
+
export declare function defaultPetPreference(): PetPreference;
|
|
101
|
+
/** Validate one logical CSS height.
|
|
102
|
+
* @param sizePx - candidate logical CSS height.
|
|
103
|
+
* @returns the validated height.
|
|
104
|
+
*/
|
|
105
|
+
export declare function validatePetSize(sizePx: unknown): number;
|
|
106
|
+
/** Return true only after pointer movement exceeds the shared four-pixel drag threshold.
|
|
107
|
+
* @param deltaX - horizontal pointer displacement.
|
|
108
|
+
* @param deltaY - vertical pointer displacement.
|
|
109
|
+
* @param threshold - minimum Euclidean displacement.
|
|
110
|
+
* @returns whether the displacement is a drag.
|
|
111
|
+
*/
|
|
112
|
+
export declare function isDragMovement(deltaX: number, deltaY: number, threshold?: number): boolean;
|
|
113
|
+
/** Derive the logical CSS width from one validated atlas-cell height.
|
|
114
|
+
* @param sizePx - validated logical CSS height.
|
|
115
|
+
* @returns the corresponding logical CSS width.
|
|
116
|
+
*/
|
|
117
|
+
export declare function petWidthForSize(sizePx: number): number;
|
|
118
|
+
/** Pick one of sixteen clockwise look-direction cells from a relative target.
|
|
119
|
+
* @param target - relative pointer target, or `undefined` for neutral direction.
|
|
120
|
+
* @returns a direction index from zero through fifteen.
|
|
121
|
+
*/
|
|
122
|
+
export declare function selectLookDirection(target: PetLookTarget | undefined): number;
|
|
123
|
+
/** Select the state and first frame used to render one presentation update.
|
|
124
|
+
* @param input - current host, pointer, motion, and wake state.
|
|
125
|
+
* @returns the renderer-independent presentation selection.
|
|
126
|
+
*/
|
|
127
|
+
export declare function selectPetPresentation(input: PetPresentationInput): PetPresentation;
|
|
128
|
+
/** Validate a compatible manifest and its WebP dimensions without Node or filesystem APIs.
|
|
129
|
+
* @param manifestBytes - UTF-8 pet.json bytes.
|
|
130
|
+
* @param spritesheetBytes - WebP atlas bytes.
|
|
131
|
+
* @param options - catalog origin, optional asset URL, and byte limits.
|
|
132
|
+
* @returns a sanitized descriptor suitable for client transport.
|
|
133
|
+
*/
|
|
134
|
+
export declare function validatePetPackage(manifestBytes: Uint8Array, spritesheetBytes: Uint8Array, options: PetPackageSourceOptions): PetDescriptor;
|
|
135
|
+
/** Validate package bytes and retain the manifest-relative asset location for host storage.
|
|
136
|
+
* @param manifestBytes - UTF-8 pet.json bytes.
|
|
137
|
+
* @param spritesheetBytes - WebP atlas bytes.
|
|
138
|
+
* @param options - catalog origin, optional asset URL, and byte limits.
|
|
139
|
+
* @returns sanitized client metadata and the validated relative spritesheet path.
|
|
140
|
+
*/
|
|
141
|
+
export declare function validatePetPackageFiles(manifestBytes: Uint8Array, spritesheetBytes: Uint8Array, options: PetPackageSourceOptions): {
|
|
142
|
+
readonly descriptor: PetDescriptor;
|
|
143
|
+
readonly spritesheetPath: string;
|
|
144
|
+
};
|
|
145
|
+
/** Resolve the safe relative spritesheet location before reading the image file.
|
|
146
|
+
* @param manifestBytes - bounded UTF-8 pet.json bytes.
|
|
147
|
+
* @returns the manifest-relative spritesheet path.
|
|
148
|
+
*/
|
|
149
|
+
export declare function petSpritesheetPath(manifestBytes: Uint8Array): string;
|
|
150
|
+
/** Convert a host activity record into the pet's display status.
|
|
151
|
+
* @param record - detached host activity record.
|
|
152
|
+
* @returns the display status, or `undefined` when the record is idle.
|
|
153
|
+
*/
|
|
154
|
+
export declare function petStatusForHostActivity(record: PetHostActivityRecord): PetActivityStatus | undefined;
|
|
155
|
+
//# sourceMappingURL=runtime.d.ts.map
|