@open-pets/plugin-sdk 2.1.1 → 3.3.0
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 +21 -0
- package/dist/check-plugin-sdk.d.ts +1 -23
- package/dist/check-plugin-sdk.d.ts.map +1 -1
- package/dist/check-plugin-sdk.js +91 -62
- package/dist/check-plugin-sdk.js.map +1 -1
- package/dist/index.d.ts +742 -62
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +255 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +671 -0
- package/dist/testing.js.map +1 -0
- package/package.json +10 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Type definitions for OpenPets plugins.
|
|
2
|
+
* Type definitions for OpenPets plugins — SDK v3 ("SuperPlugins").
|
|
3
3
|
*
|
|
4
4
|
* This package ships **types only**. There is no runtime to import — the
|
|
5
5
|
* OpenPets desktop app injects the `OpenPetsPlugin` global into the plugin
|
|
@@ -12,34 +12,484 @@
|
|
|
12
12
|
*
|
|
13
13
|
* OpenPetsPlugin.register({
|
|
14
14
|
* async start(ctx) {
|
|
15
|
-
* await ctx.
|
|
15
|
+
* const bubble = await ctx.ui.bubble({ text: "Hello!", sticky: true })
|
|
16
|
+
* bubble.onAction(() => bubble.dismiss())
|
|
16
17
|
* },
|
|
17
18
|
* })
|
|
18
19
|
* ```
|
|
19
20
|
*
|
|
21
|
+
* SDK v3 reframes a pet as a programmable surface: the API is organized into
|
|
22
|
+
* subsystems (`ui`, `pets`, `events`, `audio`, `ai`, …) instead of one flat
|
|
23
|
+
* `ctx.pet` namespace. The v2 surface (`ctx.pet.speak`, `ctx.http.fetch`, …)
|
|
24
|
+
* keeps working unchanged.
|
|
25
|
+
*
|
|
20
26
|
* @packageDocumentation
|
|
21
27
|
*/
|
|
22
28
|
/** Capabilities a plugin can request in its manifest's `permissions` array. */
|
|
23
|
-
export type OpenPetsPermission = "pet:speak" | "pet:reaction" | "pet:move" | "schedule" | "storage" | "status" | "commands" | "network";
|
|
29
|
+
export type OpenPetsPermission = "pet:speak" | "pet:reaction" | "pet:move" | "schedule" | "storage" | "status" | "commands" | "network" | "pet:interact" | "pet:pin" | "pet:animate" | "pet:speak:dynamic" | "pet:drop" | "pets:read" | "pets:manage" | "audio" | "events" | "ui:toast" | "ui:panel" | "ui:delivery" | "notify" | "bus" | "ai" | "secrets" | "voice:speak" | "voice:listen" | "auth" | "files" | "system:openExternal" | "system:metrics" | "clipboard" | "network:write";
|
|
24
30
|
/**
|
|
25
|
-
* Reaction name passed to {@link
|
|
31
|
+
* Reaction name passed to {@link OpenPetsPetHandle.react}. Common values are
|
|
26
32
|
* listed for autocomplete; any string the host accepts is allowed.
|
|
27
33
|
*/
|
|
28
34
|
export type OpenPetsReaction = "idle" | "thinking" | "working" | "editing" | "running" | "testing" | "waiting" | "waving" | "success" | "error" | "celebrating" | (string & {});
|
|
29
|
-
/** Tone shown alongside a plugin's status line
|
|
35
|
+
/** Tone shown alongside a plugin's status line or bubble. */
|
|
30
36
|
export type OpenPetsStatusTone = "info" | "success" | "warning" | "error";
|
|
31
37
|
/** A status line, either a bare string or text plus a {@link OpenPetsStatusTone}. */
|
|
32
38
|
export type OpenPetsStatus = string | {
|
|
33
39
|
text: string;
|
|
34
40
|
tone?: OpenPetsStatusTone;
|
|
35
41
|
};
|
|
36
|
-
/** A
|
|
42
|
+
/** A point in screen coordinates. */
|
|
43
|
+
export interface OpenPetsPoint {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
}
|
|
47
|
+
/** A rectangle in screen coordinates. */
|
|
48
|
+
export interface OpenPetsRect {
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* An opaque reference to an asset bundled with the plugin and declared in the
|
|
56
|
+
* manifest's `assets` block. Obtained from {@link OpenPetsAssetsApi}; never
|
|
57
|
+
* constructed by hand. Plugins pass references, never raw bytes or markup.
|
|
58
|
+
*/
|
|
59
|
+
export interface OpenPetsAssetRef {
|
|
60
|
+
readonly kind: "icon" | "image" | "svg" | "sprite" | "sound";
|
|
61
|
+
readonly name: string;
|
|
62
|
+
}
|
|
63
|
+
/** A named host icon (curated set) or a bundled icon asset reference. */
|
|
64
|
+
export type OpenPetsIconRef = string | OpenPetsAssetRef;
|
|
65
|
+
/** A JSON-safe reference to a user-imported sound. */
|
|
66
|
+
export interface OpenPetsUserSoundRef {
|
|
67
|
+
readonly kind: "user-sound";
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly name?: string;
|
|
70
|
+
}
|
|
71
|
+
/** A named host sound, bundled sound asset, or user-imported sound reference. */
|
|
72
|
+
export type OpenPetsSoundRef = string | OpenPetsAssetRef | OpenPetsUserSoundRef;
|
|
73
|
+
/** Resolve manifest-declared assets to opaque references. */
|
|
74
|
+
export interface OpenPetsAssetsApi {
|
|
75
|
+
/** Resolve a manifest-declared icon. */
|
|
76
|
+
icon(name: string): OpenPetsAssetRef;
|
|
77
|
+
/** Resolve a manifest-declared raster image. */
|
|
78
|
+
image(name: string): OpenPetsAssetRef;
|
|
79
|
+
/** Resolve a manifest-declared, install-time-sanitized SVG. */
|
|
80
|
+
svg(name: string): OpenPetsAssetRef;
|
|
81
|
+
/** Resolve a manifest-declared spritesheet. */
|
|
82
|
+
sprite(name: string): OpenPetsAssetRef;
|
|
83
|
+
/** Resolve a manifest-declared sound. */
|
|
84
|
+
sound(name: string): OpenPetsAssetRef;
|
|
85
|
+
}
|
|
86
|
+
/** A button rendered inside a bubble. Requires `pet:interact`. */
|
|
87
|
+
export interface OpenPetsBubbleAction {
|
|
88
|
+
/** Short, stable id (`[A-Za-z0-9._:-]`, 1–64 chars). */
|
|
89
|
+
id: string;
|
|
90
|
+
label: string;
|
|
91
|
+
style?: "default" | "primary" | "danger";
|
|
92
|
+
icon?: OpenPetsIconRef;
|
|
93
|
+
/** Dismiss the bubble when this action fires. Default true. */
|
|
94
|
+
dismissesBubble?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/** An inline input rendered inside a bubble. Requires `pet:interact`. */
|
|
97
|
+
export interface OpenPetsBubbleInput {
|
|
98
|
+
id: string;
|
|
99
|
+
type: "text" | "number" | "select";
|
|
100
|
+
placeholder?: string;
|
|
101
|
+
default?: string | number;
|
|
102
|
+
/** Options for `select` inputs. */
|
|
103
|
+
options?: Array<{
|
|
104
|
+
value: string;
|
|
105
|
+
label: string;
|
|
106
|
+
}>;
|
|
107
|
+
submitLabel?: string;
|
|
108
|
+
}
|
|
109
|
+
/** A HUD item shown in the host-rendered pinned mini-HUD bubble. */
|
|
110
|
+
export interface OpenPetsBubbleHudItem {
|
|
111
|
+
/** Named host icon or bundled icon asset reference. */
|
|
112
|
+
icon: OpenPetsIconRef;
|
|
113
|
+
/** Numeric value between 0 and 100 inclusive. */
|
|
114
|
+
value: number;
|
|
115
|
+
/** Optional short display label. */
|
|
116
|
+
label?: string;
|
|
117
|
+
/** Optional theme color tone for the bar/indicator. */
|
|
118
|
+
tone?: "amber" | "blue" | "green" | "pink" | "slate" | "red";
|
|
119
|
+
}
|
|
120
|
+
/** Descriptor for a host-rendered mini HUD layout, used in pinned bubbles. */
|
|
121
|
+
export interface OpenPetsBubbleHud {
|
|
122
|
+
/** List of HUD items (usually up to 4 items). */
|
|
123
|
+
items: OpenPetsBubbleHudItem[];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A structured, host-rendered bubble descriptor. The plugin describes; the
|
|
127
|
+
* host renders — no raw HTML or live DOM ever crosses the SDK boundary.
|
|
128
|
+
*/
|
|
129
|
+
export interface OpenPetsBubble {
|
|
130
|
+
/** Host-rendered mini HUD layout for pinned bubbles. */
|
|
131
|
+
hud?: OpenPetsBubbleHud;
|
|
132
|
+
/** Plain text, length-capped, content-filtered. */
|
|
133
|
+
text?: string;
|
|
134
|
+
/** Limited markdown (bold/italic/code/line breaks), host-sanitized. */
|
|
135
|
+
markdown?: string;
|
|
136
|
+
/** Named host icon or a bundled icon asset. Body media is icon-only; use `indicator` for icon + message. */
|
|
137
|
+
icon?: OpenPetsIconRef;
|
|
138
|
+
/** Bundled, install-time-sanitized SVG. Body media is icon-only; use `indicator` for icon + message. */
|
|
139
|
+
svg?: OpenPetsAssetRef;
|
|
140
|
+
/** Bundled raster image. Body media is icon-only; use `indicator` for icon + message. */
|
|
141
|
+
image?: OpenPetsAssetRef;
|
|
142
|
+
tone?: OpenPetsStatusTone;
|
|
143
|
+
/** Optional top-row indicator/header. Intended primarily for alerts. */
|
|
144
|
+
indicator?: OpenPetsAlertIndicator | false;
|
|
145
|
+
/** Theme-token name, not a raw color string. */
|
|
146
|
+
accent?: string;
|
|
147
|
+
/**
|
|
148
|
+
* Marks content as model-generated. Requires `pet:speak:dynamic` and the
|
|
149
|
+
* global "allow AI speech" setting; uses the relaxed dynamic screen instead
|
|
150
|
+
* of the static ambient filter (§13.1).
|
|
151
|
+
*/
|
|
152
|
+
dynamic?: boolean;
|
|
153
|
+
/** Auto-dismiss after N ms; omit for the host default. */
|
|
154
|
+
durationMs?: number;
|
|
155
|
+
/** Ignore duration; stay until dismissed or replaced. */
|
|
156
|
+
sticky?: boolean;
|
|
157
|
+
/** Occupy the persistent pinned slot (max 1 per pet). Requires `pet:pin`. */
|
|
158
|
+
pin?: boolean;
|
|
159
|
+
dismissOn?: Array<"timeout" | "click" | "petClick" | "action" | "outsideClick">;
|
|
160
|
+
/** Feeds the bubble arbiter. Default "normal". */
|
|
161
|
+
priority?: "low" | "normal" | "high" | "urgent";
|
|
162
|
+
actions?: OpenPetsBubbleAction[];
|
|
163
|
+
input?: OpenPetsBubbleInput;
|
|
164
|
+
}
|
|
165
|
+
/** Why a bubble went away. */
|
|
166
|
+
export type OpenPetsBubbleDismissReason = "timeout" | "click" | "replaced" | "manual" | "unpinned";
|
|
167
|
+
/**
|
|
168
|
+
* Live handle to a shown bubble. Lets the plugin update it in place
|
|
169
|
+
* (progress, countdowns, streamed tokens) and receive interaction callbacks.
|
|
170
|
+
*/
|
|
171
|
+
export interface OpenPetsBubbleHandle {
|
|
172
|
+
readonly id: string;
|
|
173
|
+
update(patch: Partial<OpenPetsBubble>): Promise<void>;
|
|
174
|
+
dismiss(): Promise<void>;
|
|
175
|
+
/** Promote this bubble to the pinned slot (§1.5). Requires `pet:pin`. */
|
|
176
|
+
pin(): Promise<void>;
|
|
177
|
+
/** Release the pinned slot. */
|
|
178
|
+
unpin(): Promise<void>;
|
|
179
|
+
onAction(handler: (actionId: string) => void | Promise<void>): void;
|
|
180
|
+
onSubmit(handler: (values: Record<string, string | number>) => void | Promise<void>): void;
|
|
181
|
+
onDismiss(handler: (reason: OpenPetsBubbleDismissReason) => void): void;
|
|
182
|
+
}
|
|
183
|
+
/** Options for opening a sandboxed plugin panel (§7.2). Requires `ui:panel`. */
|
|
184
|
+
export interface OpenPetsPanelOptions {
|
|
185
|
+
/** Name of a manifest-declared panel page (`panels` block). */
|
|
186
|
+
panel: string;
|
|
187
|
+
title?: string;
|
|
188
|
+
width?: number;
|
|
189
|
+
height?: number;
|
|
190
|
+
}
|
|
191
|
+
/** Handle to a sandboxed plugin panel window. */
|
|
192
|
+
export interface OpenPetsPanelHandle {
|
|
193
|
+
readonly id: string;
|
|
194
|
+
show(): Promise<void>;
|
|
195
|
+
hide(): Promise<void>;
|
|
196
|
+
/** Host -> panel. Payload must be clone-safe data. */
|
|
197
|
+
postMessage(msg: unknown): Promise<void>;
|
|
198
|
+
/** Panel -> plugin, clone-safe. */
|
|
199
|
+
onMessage(handler: (msg: unknown) => void): void;
|
|
200
|
+
close(): Promise<void>;
|
|
201
|
+
}
|
|
202
|
+
/** Descriptor for a host-owned, display-level delivery surface. Requires `ui:delivery`. */
|
|
203
|
+
export interface OpenPetsDelivery {
|
|
204
|
+
/** Stable, plugin-scoped id (`[A-Za-z0-9._:-]`, 1–96 chars). */
|
|
205
|
+
key: string;
|
|
206
|
+
/** A manifest-declared courier spritesheet (`ctx.assets.sprite(name)`). */
|
|
207
|
+
courier: OpenPetsAssetRef;
|
|
208
|
+
/** Plain-text title (1–160 characters). */
|
|
209
|
+
title: string;
|
|
210
|
+
/** Optional plain-text detail (0–200 characters). */
|
|
211
|
+
detail: string;
|
|
212
|
+
/** Finite epoch milliseconds, in the next seven days. */
|
|
213
|
+
expiresAt: number;
|
|
214
|
+
}
|
|
215
|
+
export type OpenPetsDeliveryDismissReason = "click" | "manual" | "expired" | "plugin-stopped";
|
|
216
|
+
/** Opaque handle for a host-owned delivery surface. */
|
|
217
|
+
export interface OpenPetsDeliveryHandle {
|
|
218
|
+
dismiss(): Promise<void>;
|
|
219
|
+
onDismiss(handler: (reason: OpenPetsDeliveryDismissReason) => void): void;
|
|
220
|
+
}
|
|
221
|
+
/** Alert header indicator rendered above alert text. Custom art must be a manifest-declared asset. */
|
|
222
|
+
export interface OpenPetsAlertIndicator {
|
|
223
|
+
/** Visible/accessibility label shown next to the icon. */
|
|
224
|
+
label?: string;
|
|
225
|
+
/** Named host icon or manifest-declared icon asset (`ctx.assets.icon(...)`). */
|
|
226
|
+
icon?: OpenPetsIconRef;
|
|
227
|
+
/** Manifest-declared sanitized SVG asset (`ctx.assets.svg(...)`). */
|
|
228
|
+
svg?: OpenPetsAssetRef;
|
|
229
|
+
/** Manifest-declared raster/icon image asset. */
|
|
230
|
+
image?: OpenPetsAssetRef;
|
|
231
|
+
tone?: OpenPetsStatusTone;
|
|
232
|
+
/** Safe CSS color for the icon/SVG (`#hex`, `rgb(a)`, or `hsl(a)`). */
|
|
233
|
+
color?: string;
|
|
234
|
+
/** Safe CSS background color for the circular icon well. */
|
|
235
|
+
background?: string;
|
|
236
|
+
/** Alias for `background`. */
|
|
237
|
+
backgroundColor?: string;
|
|
238
|
+
/** Safe CSS border color for the circular icon well. */
|
|
239
|
+
borderColor?: string;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Must-not-miss pet alert. Alerts render as sticky high-priority bubbles and
|
|
243
|
+
* may also request best-effort sound and OS notification delivery.
|
|
244
|
+
*/
|
|
245
|
+
export interface OpenPetsAlert extends Omit<OpenPetsBubble, "sticky" | "priority"> {
|
|
246
|
+
/** Optional sound to play with the alert. Requires `audio` only when set. */
|
|
247
|
+
sound?: OpenPetsSoundRef;
|
|
248
|
+
/** Optional OS notification. Requires `notify` only when set. */
|
|
249
|
+
notify?: {
|
|
250
|
+
title: string;
|
|
251
|
+
body?: string;
|
|
252
|
+
sound?: boolean;
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/** Handle to a live alert bubble. */
|
|
256
|
+
export interface OpenPetsAlertHandle extends OpenPetsBubbleHandle {
|
|
257
|
+
/** Mark the alert acknowledged and dismiss it. */
|
|
258
|
+
acknowledge(): Promise<void>;
|
|
259
|
+
}
|
|
260
|
+
/** Bubbles, toasts, panels, and the dynamic context-menu section. */
|
|
261
|
+
export interface OpenPetsUiApi {
|
|
262
|
+
/** Show a bubble on the default pet. Requires `pet:speak`. */
|
|
263
|
+
bubble(spec: string | OpenPetsBubble): Promise<OpenPetsBubbleHandle>;
|
|
264
|
+
/** Show a transient host toast. Requires `ui:toast`. */
|
|
265
|
+
toast(spec: {
|
|
266
|
+
text: string;
|
|
267
|
+
tone?: OpenPetsStatusTone;
|
|
268
|
+
durationMs?: number;
|
|
269
|
+
}): Promise<void>;
|
|
270
|
+
/** Show a sticky high-priority alert bubble. Requires `pet:speak`. */
|
|
271
|
+
alert(spec: OpenPetsAlert): Promise<OpenPetsAlertHandle>;
|
|
272
|
+
/** Open a sandboxed plugin webview panel. Requires `ui:panel`. */
|
|
273
|
+
panel(spec: OpenPetsPanelOptions): Promise<OpenPetsPanelHandle>;
|
|
274
|
+
/** Show a host-owned delivery surface on the cursor display. Requires `ui:delivery`. */
|
|
275
|
+
delivery(spec: OpenPetsDelivery): Promise<OpenPetsDeliveryHandle>;
|
|
276
|
+
/** Fully dynamic context-menu section. Requires `commands`. */
|
|
277
|
+
menu: OpenPetsMenuApi;
|
|
278
|
+
}
|
|
279
|
+
/** OS notifications. Requires `notify`. */
|
|
280
|
+
export interface OpenPetsNotifyApi {
|
|
281
|
+
notify(spec: {
|
|
282
|
+
title: string;
|
|
283
|
+
body?: string;
|
|
284
|
+
sound?: boolean;
|
|
285
|
+
}): Promise<void>;
|
|
286
|
+
}
|
|
287
|
+
/** Play named host sounds or bundled plugin sounds. Requires `audio`. */
|
|
288
|
+
export interface OpenPetsAudioApi {
|
|
289
|
+
/**
|
|
290
|
+
* Play a sound. Named host sounds (`"chime"`, `"pop"`, `"nom"`, `"alert"`,
|
|
291
|
+
* `"level-up"`) need no assets; bundled sounds come from
|
|
292
|
+
* {@link OpenPetsAssetsApi.sound}. Gated by the global sound toggle and
|
|
293
|
+
* quiet hours.
|
|
294
|
+
*/
|
|
295
|
+
play(sound: OpenPetsSoundRef, options?: {
|
|
296
|
+
volume?: number;
|
|
297
|
+
}): Promise<void>;
|
|
298
|
+
/** Import a user-picked sound into plugin-owned host storage. Requires `audio` and `files`. */
|
|
299
|
+
importUserSound(file: OpenPetsPickedFile, opts?: {
|
|
300
|
+
name?: string;
|
|
301
|
+
}): Promise<OpenPetsUserSoundRef>;
|
|
302
|
+
/** Forget a previously imported user sound. Requires `audio`. */
|
|
303
|
+
forgetUserSound(ref: OpenPetsUserSoundRef): Promise<void>;
|
|
304
|
+
stop(handle?: string): Promise<void>;
|
|
305
|
+
}
|
|
306
|
+
/** Curated, read-only host event names. */
|
|
307
|
+
export type OpenPetsEventName = "pet:clicked" | "pet:doubleClicked" | "pet:dragStart" | "pet:dragEnd" | "pet:hover" | "pet:drop" | "idle:enter" | "idle:exit" | "agent:activity" | "config:changed" | "screen:locked" | "screen:unlocked" | "power:battery-low" | "power:charging" | "display:changed" | "online" | "offline" | "day:partChanged";
|
|
308
|
+
/** A file delivered by an explicit user drop onto the pet (§13.7). */
|
|
309
|
+
export interface OpenPetsDroppedFile {
|
|
310
|
+
name: string;
|
|
311
|
+
sizeBytes: number;
|
|
312
|
+
/** One-shot, size-capped read of the dropped file's text content. */
|
|
313
|
+
readText(): Promise<string>;
|
|
314
|
+
}
|
|
315
|
+
/** Payload for `pet:drop`. */
|
|
316
|
+
export interface OpenPetsDropEvent {
|
|
317
|
+
kind: "text" | "files";
|
|
318
|
+
text?: string;
|
|
319
|
+
files?: OpenPetsDroppedFile[];
|
|
320
|
+
petId: string;
|
|
321
|
+
}
|
|
322
|
+
/** Payload shapes per event. Unlisted events carry a small data record. */
|
|
323
|
+
export interface OpenPetsEventPayloads {
|
|
324
|
+
"pet:clicked": {
|
|
325
|
+
petId: string;
|
|
326
|
+
};
|
|
327
|
+
"pet:doubleClicked": {
|
|
328
|
+
petId: string;
|
|
329
|
+
};
|
|
330
|
+
"pet:dragStart": {
|
|
331
|
+
petId: string;
|
|
332
|
+
};
|
|
333
|
+
"pet:dragEnd": {
|
|
334
|
+
petId: string;
|
|
335
|
+
};
|
|
336
|
+
"pet:hover": {
|
|
337
|
+
petId: string;
|
|
338
|
+
};
|
|
339
|
+
"pet:drop": OpenPetsDropEvent;
|
|
340
|
+
"idle:enter": {
|
|
341
|
+
idleSeconds: number;
|
|
342
|
+
};
|
|
343
|
+
"idle:exit": {
|
|
344
|
+
idleSeconds: number;
|
|
345
|
+
};
|
|
346
|
+
"agent:activity": {
|
|
347
|
+
kind: string;
|
|
348
|
+
reaction?: string;
|
|
349
|
+
active: boolean;
|
|
350
|
+
petId: string;
|
|
351
|
+
};
|
|
352
|
+
"config:changed": Record<string, unknown>;
|
|
353
|
+
"screen:locked": Record<string, never>;
|
|
354
|
+
"screen:unlocked": Record<string, never>;
|
|
355
|
+
"power:battery-low": {
|
|
356
|
+
percent?: number;
|
|
357
|
+
};
|
|
358
|
+
"power:charging": {
|
|
359
|
+
charging: boolean;
|
|
360
|
+
};
|
|
361
|
+
"display:changed": {
|
|
362
|
+
displays: number;
|
|
363
|
+
};
|
|
364
|
+
online: Record<string, never>;
|
|
365
|
+
offline: Record<string, never>;
|
|
366
|
+
"day:partChanged": {
|
|
367
|
+
part: "morning" | "afternoon" | "evening" | "night";
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
export type OpenPetsEvent<E extends OpenPetsEventName> = OpenPetsEventPayloads[E];
|
|
371
|
+
/**
|
|
372
|
+
* Subscribe to the curated host event stream. Requires `events`
|
|
373
|
+
* (`pet:drop` additionally requires `pet:drop`).
|
|
374
|
+
*
|
|
375
|
+
* The event set is explicitly bounded: no keystrokes, no screen contents, no
|
|
376
|
+
* other apps' window titles, no clipboard, no ambient filesystem watching.
|
|
377
|
+
*/
|
|
378
|
+
export interface OpenPetsEventsApi {
|
|
379
|
+
on<E extends OpenPetsEventName>(event: E, handler: (e: OpenPetsEvent<E>) => void): () => void;
|
|
380
|
+
}
|
|
381
|
+
/** Options for {@link OpenPetsPetHandle.moveBy}. */
|
|
382
|
+
export interface OpenPetsMoveByOptions {
|
|
383
|
+
x: number;
|
|
384
|
+
y: number;
|
|
385
|
+
durationMs?: number;
|
|
386
|
+
}
|
|
387
|
+
/** Options for {@link OpenPetsPetHandle.wander}. */
|
|
388
|
+
export interface OpenPetsWanderOptions {
|
|
389
|
+
distance?: number;
|
|
390
|
+
durationMs?: number;
|
|
391
|
+
}
|
|
392
|
+
/** Beyond named reactions: a bundled spritesheet animation (§5). */
|
|
393
|
+
export type OpenPetsAnimationState = OpenPetsReaction | {
|
|
394
|
+
sprite: OpenPetsAssetRef;
|
|
395
|
+
loop?: boolean;
|
|
396
|
+
fps?: number;
|
|
397
|
+
};
|
|
398
|
+
/** Self-perception snapshot returned by {@link OpenPetsPetHandle.getState}. */
|
|
399
|
+
export interface OpenPetsPetState {
|
|
400
|
+
position: OpenPetsPoint;
|
|
401
|
+
bounds: OpenPetsRect;
|
|
402
|
+
currentAnimation: string;
|
|
403
|
+
visible: boolean;
|
|
404
|
+
dragging: boolean;
|
|
405
|
+
}
|
|
406
|
+
export interface OpenPetsPetInfo {
|
|
407
|
+
id: string;
|
|
408
|
+
name: string;
|
|
409
|
+
kind: "default" | "agent" | "plugin";
|
|
410
|
+
visible: boolean;
|
|
411
|
+
}
|
|
412
|
+
export interface OpenPetsReactOptions {
|
|
413
|
+
/** Set false to animate without showing the built-in reaction/status message. */
|
|
414
|
+
showMessage?: boolean;
|
|
415
|
+
}
|
|
416
|
+
/** Addressable handle to a single pet. */
|
|
417
|
+
export interface OpenPetsPetHandle {
|
|
418
|
+
readonly id: string;
|
|
419
|
+
/** Requires `pet:speak`. Accepts plain text or a full bubble descriptor. */
|
|
420
|
+
speak(spec: string | OpenPetsBubble): Promise<OpenPetsBubbleHandle>;
|
|
421
|
+
/** Requires `pet:reaction`. */
|
|
422
|
+
react(reaction: OpenPetsReaction, options?: OpenPetsReactOptions): Promise<void>;
|
|
423
|
+
/** Requires `pet:animate` for sprite states; named reactions need `pet:reaction`. */
|
|
424
|
+
setAnimation(state: OpenPetsAnimationState): Promise<void>;
|
|
425
|
+
/** Bounded by the host (0.5–2). Requires `pet:animate`. */
|
|
426
|
+
setScale(scale: number): Promise<void>;
|
|
427
|
+
/** Show a status reaction (or clear with null). Requires `pet:reaction`. */
|
|
428
|
+
setStatusReaction(reaction: OpenPetsReaction | null): Promise<void>;
|
|
429
|
+
/** Requires `pet:move`. Movement is bounded to the work area. */
|
|
430
|
+
moveBy(options: OpenPetsMoveByOptions): Promise<void>;
|
|
431
|
+
/** Requires `pet:move`. */
|
|
432
|
+
wander(options?: OpenPetsWanderOptions): Promise<void>;
|
|
433
|
+
/** Requires `pet:move`. */
|
|
434
|
+
moveToHome(): Promise<void>;
|
|
435
|
+
/** Animated absolute move. Requires `pet:move`. */
|
|
436
|
+
moveTo(point: OpenPetsPoint, opts?: {
|
|
437
|
+
durationMs?: number;
|
|
438
|
+
easing?: string;
|
|
439
|
+
}): Promise<void>;
|
|
440
|
+
/** Continuous cursor following with lag. Requires `pet:move`. */
|
|
441
|
+
followCursor(opts?: {
|
|
442
|
+
enabled: boolean;
|
|
443
|
+
lag?: number;
|
|
444
|
+
}): Promise<void>;
|
|
445
|
+
/** Lightweight physics (gravity/bounce). Requires `pet:move`. */
|
|
446
|
+
physics(opts?: {
|
|
447
|
+
gravity?: boolean;
|
|
448
|
+
bounce?: number;
|
|
449
|
+
climbEdges?: boolean;
|
|
450
|
+
}): Promise<void>;
|
|
451
|
+
/**
|
|
452
|
+
* Continuous behavior loop — host-driven, throttled, auto-paused while the
|
|
453
|
+
* pet is hidden or being dragged. The brain loop for "alive" pets.
|
|
454
|
+
* Requires `events`. Returns an unsubscribe function.
|
|
455
|
+
*/
|
|
456
|
+
onTick(handler: (dtMs: number) => void): () => void;
|
|
457
|
+
/** Self-perception. Requires `pets:read`. */
|
|
458
|
+
getState(): Promise<OpenPetsPetState>;
|
|
459
|
+
/** Requires `pets:manage`. */
|
|
460
|
+
show(): Promise<void>;
|
|
461
|
+
/** Requires `pets:manage`. */
|
|
462
|
+
hide(): Promise<void>;
|
|
463
|
+
/** Close an ephemeral/spawned pet. Requires `pets:manage`. */
|
|
464
|
+
close(): Promise<void>;
|
|
465
|
+
}
|
|
466
|
+
/** Multi-pet registry: list, target, spawn. */
|
|
467
|
+
export interface OpenPetsPetsApi {
|
|
468
|
+
readonly default: OpenPetsPetHandle;
|
|
469
|
+
/** Requires `pets:read`. */
|
|
470
|
+
list(): Promise<OpenPetsPetInfo[]>;
|
|
471
|
+
get(petId: string): OpenPetsPetHandle;
|
|
472
|
+
/** Spawn an ephemeral pet window. Requires `pets:manage`. */
|
|
473
|
+
spawn(spec: {
|
|
474
|
+
petId: string;
|
|
475
|
+
name?: string;
|
|
476
|
+
position?: OpenPetsPoint;
|
|
477
|
+
ephemeral?: boolean;
|
|
478
|
+
}): Promise<OpenPetsPetHandle>;
|
|
479
|
+
/** Requires `pets:read`. Returns an unsubscribe function. */
|
|
480
|
+
onChange(handler: (pets: OpenPetsPetInfo[]) => void): () => void;
|
|
481
|
+
}
|
|
482
|
+
/** A single field in a command's input form (extended in v3, §8.1). */
|
|
37
483
|
export interface OpenPetsCommandFormField {
|
|
38
484
|
/** Identifier for this field; the submitted value is keyed by it. */
|
|
39
485
|
id: string;
|
|
40
|
-
type: "text" | "textarea" | "number";
|
|
486
|
+
type: "text" | "textarea" | "number" | "boolean" | "select" | "multiselect" | "time" | "date" | "list";
|
|
41
487
|
label: string;
|
|
42
|
-
default?: string | number;
|
|
488
|
+
default?: string | number | boolean | string[];
|
|
489
|
+
options?: Array<{
|
|
490
|
+
label: string;
|
|
491
|
+
value: string;
|
|
492
|
+
}>;
|
|
43
493
|
/** Minimum value (number fields only). */
|
|
44
494
|
min?: number;
|
|
45
495
|
/** Maximum value (number fields only). */
|
|
@@ -59,55 +509,48 @@ export interface OpenPetsCommand {
|
|
|
59
509
|
id: string;
|
|
60
510
|
title: string;
|
|
61
511
|
description?: string;
|
|
512
|
+
icon?: OpenPetsIconRef;
|
|
62
513
|
/** When present, the host opens a dialog and passes validated values to the handler. */
|
|
63
514
|
form?: OpenPetsCommandForm;
|
|
515
|
+
/** Top-level item vs grouped plugin submenu. Default "submenu". */
|
|
516
|
+
placement?: "top" | "submenu";
|
|
517
|
+
/** Ordering within its group (higher first). */
|
|
518
|
+
priority?: number;
|
|
519
|
+
featured?: boolean;
|
|
520
|
+
/** Maximum time the host waits for this command (1 second to 5 minutes). Defaults to 5 seconds. */
|
|
521
|
+
timeoutMs?: number;
|
|
522
|
+
}
|
|
523
|
+
/** A dynamic context-menu item set via {@link OpenPetsMenuApi.setItems}. */
|
|
524
|
+
export interface OpenPetsMenuItem {
|
|
525
|
+
id: string;
|
|
526
|
+
title: string;
|
|
527
|
+
enabled?: boolean;
|
|
528
|
+
checked?: boolean;
|
|
529
|
+
}
|
|
530
|
+
/** Fully dynamic context-menu section. Requires `commands`. */
|
|
531
|
+
export interface OpenPetsMenuApi {
|
|
532
|
+
setItems(items: OpenPetsMenuItem[]): Promise<void>;
|
|
533
|
+
onSelect(handler: (id: string) => void | Promise<void>): () => void;
|
|
534
|
+
}
|
|
535
|
+
/** Handler invoked when a command runs, with validated form values when present. */
|
|
536
|
+
export type OpenPetsCommandHandler = (values?: Record<string, unknown>) => void | Promise<void>;
|
|
537
|
+
/** Register right-click pet actions. Requires `commands`. */
|
|
538
|
+
export interface OpenPetsCommandsApi {
|
|
539
|
+
register(command: OpenPetsCommand, handler: OpenPetsCommandHandler): Promise<void>;
|
|
540
|
+
unregister(id: string): Promise<void>;
|
|
64
541
|
}
|
|
65
542
|
/** A daily schedule time, optionally restricted to specific weekdays. */
|
|
66
543
|
export type OpenPetsDailySpec = string | {
|
|
67
544
|
time: string;
|
|
68
545
|
days?: number[];
|
|
69
546
|
};
|
|
70
|
-
/** Options for {@link OpenPetsPetApi.moveBy}. */
|
|
71
|
-
export interface OpenPetsMoveByOptions {
|
|
72
|
-
x: number;
|
|
73
|
-
y: number;
|
|
74
|
-
durationMs?: number;
|
|
75
|
-
}
|
|
76
|
-
/** Options for {@link OpenPetsPetApi.wander}. */
|
|
77
|
-
export interface OpenPetsWanderOptions {
|
|
78
|
-
distance?: number;
|
|
79
|
-
durationMs?: number;
|
|
80
|
-
}
|
|
81
|
-
/** Options for {@link OpenPetsHttpApi.fetch}. GET-only by design. */
|
|
82
|
-
export interface OpenPetsHttpOptions {
|
|
83
|
-
method?: "GET";
|
|
84
|
-
headers?: Record<string, string>;
|
|
85
|
-
timeoutMs?: number;
|
|
86
|
-
}
|
|
87
|
-
/** Response returned by {@link OpenPetsHttpApi.fetch}. */
|
|
88
|
-
export interface OpenPetsHttpResponse {
|
|
89
|
-
status: number;
|
|
90
|
-
ok: boolean;
|
|
91
|
-
headers: Record<string, string>;
|
|
92
|
-
text: string;
|
|
93
|
-
json?: unknown;
|
|
94
|
-
}
|
|
95
|
-
/** Make the default pet speak, react, or move. */
|
|
96
|
-
export interface OpenPetsPetApi {
|
|
97
|
-
/** Requires `pet:speak`. Messages are capped at 140 chars and content-filtered. */
|
|
98
|
-
speak(message: string): Promise<void>;
|
|
99
|
-
/** Requires `pet:reaction`. */
|
|
100
|
-
react(reaction: OpenPetsReaction): Promise<void>;
|
|
101
|
-
/** Requires `pet:move`. Movement is bounded to the work area. */
|
|
102
|
-
moveBy(options: OpenPetsMoveByOptions): Promise<void>;
|
|
103
|
-
/** Requires `pet:move`. */
|
|
104
|
-
wander(options?: OpenPetsWanderOptions): Promise<void>;
|
|
105
|
-
/** Requires `pet:move`. */
|
|
106
|
-
moveToHome(): Promise<void>;
|
|
107
|
-
}
|
|
108
547
|
/** A callback fired by a schedule. */
|
|
109
548
|
export type OpenPetsScheduleHandler = () => void | Promise<void>;
|
|
110
|
-
/**
|
|
549
|
+
/**
|
|
550
|
+
* Run callbacks once, on an interval, daily, on a cron expression, or at an
|
|
551
|
+
* absolute time. Wall-clock aware: schedules re-arm after sleep/wake.
|
|
552
|
+
* Requires `schedule`.
|
|
553
|
+
*/
|
|
111
554
|
export interface OpenPetsScheduleApi {
|
|
112
555
|
/** Fire once after `delayMs`. */
|
|
113
556
|
once(id: string, delayMs: number, handler: OpenPetsScheduleHandler): Promise<void>;
|
|
@@ -115,14 +558,25 @@ export interface OpenPetsScheduleApi {
|
|
|
115
558
|
every(id: string, intervalMs: number, handler: OpenPetsScheduleHandler): Promise<void>;
|
|
116
559
|
/** Fire daily at `HH:mm`, optionally only on the given weekdays (0–6, Sunday = 0). */
|
|
117
560
|
daily(id: string, spec: OpenPetsDailySpec, handler: OpenPetsScheduleHandler): Promise<void>;
|
|
561
|
+
/** Fire on a 5-field cron expression (`m h dom mon dow`). */
|
|
562
|
+
cron(id: string, expr: string, handler: OpenPetsScheduleHandler): Promise<void>;
|
|
563
|
+
/** Fire once at an absolute ISO-8601 timestamp. Past timestamps fire immediately. */
|
|
564
|
+
at(id: string, isoTimestamp: string, handler: OpenPetsScheduleHandler): Promise<void>;
|
|
565
|
+
list(): Promise<Array<{
|
|
566
|
+
id: string;
|
|
567
|
+
nextRunMs: number;
|
|
568
|
+
}>>;
|
|
118
569
|
cancel(id: string): Promise<void>;
|
|
119
570
|
cancelAll(): Promise<void>;
|
|
120
571
|
}
|
|
121
|
-
/** Persist
|
|
572
|
+
/** Persist per-plugin state across restarts (quota: a few MB). Requires `storage`. */
|
|
122
573
|
export interface OpenPetsStorageApi {
|
|
123
574
|
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
124
575
|
set(key: string, value: unknown): Promise<void>;
|
|
125
576
|
delete(key: string): Promise<void>;
|
|
577
|
+
keys(): Promise<string[]>;
|
|
578
|
+
/** Reactive subscription to a key. Returns an unsubscribe function. */
|
|
579
|
+
subscribe(key: string, handler: (value: unknown) => void): () => void;
|
|
126
580
|
}
|
|
127
581
|
/** Read user configuration and react to changes. Always available. */
|
|
128
582
|
export interface OpenPetsConfigApi {
|
|
@@ -130,22 +584,200 @@ export interface OpenPetsConfigApi {
|
|
|
130
584
|
/** Subscribe to config changes. Returns an unsubscribe function. */
|
|
131
585
|
onChange<T = Record<string, unknown>>(handler: (config: T) => void | Promise<void>): () => void;
|
|
132
586
|
}
|
|
133
|
-
/**
|
|
134
|
-
export
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
587
|
+
/** Inter-plugin pub/sub. Topics should be namespaced `pluginId/topic`. Requires `bus`. */
|
|
588
|
+
export interface OpenPetsBusApi {
|
|
589
|
+
/** Publish a clone-safe payload. Rate- and size-capped by the host. */
|
|
590
|
+
publish(topic: string, payload: unknown): Promise<void>;
|
|
591
|
+
subscribe(topic: string, handler: (payload: unknown) => void): () => void;
|
|
592
|
+
}
|
|
593
|
+
/** Options for {@link OpenPetsNetApi.fetch}. Non-GET methods require `network:write`. */
|
|
594
|
+
export interface OpenPetsNetFetchOptions {
|
|
595
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
596
|
+
headers?: Record<string, string>;
|
|
597
|
+
body?: string;
|
|
598
|
+
timeoutMs?: number;
|
|
599
|
+
}
|
|
600
|
+
/** Response returned by {@link OpenPetsNetApi.fetch}. */
|
|
601
|
+
export interface OpenPetsHttpResponse {
|
|
602
|
+
status: number;
|
|
603
|
+
ok: boolean;
|
|
604
|
+
headers: Record<string, string>;
|
|
605
|
+
text: string;
|
|
606
|
+
json?: unknown;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* HTTPS fetch to manifest-declared, user-approved hosts. Requires `network`.
|
|
610
|
+
* HTTPS-only with redirect, response-size, and private-IP/SSRF guards.
|
|
611
|
+
*/
|
|
612
|
+
export interface OpenPetsNetApi {
|
|
613
|
+
fetch(url: string, options?: OpenPetsNetFetchOptions): Promise<OpenPetsHttpResponse>;
|
|
614
|
+
/** Streaming fetch (SSE/chunked) for LLM-style responses. */
|
|
615
|
+
stream(url: string, options: OpenPetsNetFetchOptions, onChunk: (chunk: string) => void): Promise<{
|
|
616
|
+
status: number;
|
|
617
|
+
ok: boolean;
|
|
618
|
+
}>;
|
|
619
|
+
}
|
|
620
|
+
/** v2 GET-only fetch options, kept for back-compat (`ctx.http`). */
|
|
621
|
+
export interface OpenPetsHttpOptions {
|
|
622
|
+
method?: "GET";
|
|
623
|
+
headers?: Record<string, string>;
|
|
624
|
+
timeoutMs?: number;
|
|
625
|
+
}
|
|
626
|
+
/** v2 HTTP namespace, kept for back-compat. Requires `network`. */
|
|
627
|
+
export interface OpenPetsHttpApi {
|
|
628
|
+
fetch(url: string, options?: OpenPetsHttpOptions): Promise<OpenPetsHttpResponse>;
|
|
629
|
+
}
|
|
630
|
+
/** A tool the model may call (host AI gateway function calling). */
|
|
631
|
+
export interface OpenPetsAiTool {
|
|
632
|
+
name: string;
|
|
633
|
+
description?: string;
|
|
634
|
+
/** JSON Schema for the tool's input. */
|
|
635
|
+
inputSchema: Record<string, unknown>;
|
|
636
|
+
}
|
|
637
|
+
/** A tool call requested by the model. */
|
|
638
|
+
export interface OpenPetsAiToolCall {
|
|
639
|
+
name: string;
|
|
640
|
+
input: Record<string, unknown>;
|
|
641
|
+
}
|
|
642
|
+
/** Request for {@link OpenPetsAiApi.complete} / {@link OpenPetsAiApi.stream}. */
|
|
643
|
+
export interface OpenPetsAiRequest {
|
|
644
|
+
system?: string;
|
|
645
|
+
messages: Array<{
|
|
646
|
+
role: "user" | "assistant";
|
|
647
|
+
content: string;
|
|
648
|
+
}>;
|
|
649
|
+
maxTokens?: number;
|
|
650
|
+
temperature?: number;
|
|
651
|
+
tools?: OpenPetsAiTool[];
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Host AI gateway backed by the user's one configured provider/model.
|
|
655
|
+
* Keys live in host config, never in plugin code. Requires `ai`.
|
|
656
|
+
*/
|
|
657
|
+
export interface OpenPetsAiApi {
|
|
658
|
+
/** Whether a provider is configured. */
|
|
659
|
+
available(): Promise<boolean>;
|
|
660
|
+
complete(req: OpenPetsAiRequest): Promise<{
|
|
661
|
+
text: string;
|
|
662
|
+
toolCalls?: OpenPetsAiToolCall[];
|
|
663
|
+
}>;
|
|
664
|
+
stream(req: OpenPetsAiRequest, onToken: (chunk: string) => void): Promise<{
|
|
665
|
+
text: string;
|
|
666
|
+
}>;
|
|
667
|
+
}
|
|
668
|
+
/** Encrypted per-plugin credentials (OS keychain / safeStorage). Requires `secrets`. */
|
|
669
|
+
export interface OpenPetsSecretsApi {
|
|
670
|
+
set(key: string, value: string): Promise<void>;
|
|
671
|
+
/** Returned only to the owning plugin. */
|
|
672
|
+
get(key: string): Promise<string | undefined>;
|
|
673
|
+
delete(key: string): Promise<void>;
|
|
674
|
+
has(key: string): Promise<boolean>;
|
|
675
|
+
}
|
|
676
|
+
/** TTS out (`voice:speak`) and opt-in, push-to-talk STT in (`voice:listen`). */
|
|
677
|
+
export interface OpenPetsVoiceApi {
|
|
678
|
+
speak(text: string, opts?: {
|
|
679
|
+
voice?: string;
|
|
680
|
+
rate?: number;
|
|
681
|
+
}): Promise<void>;
|
|
682
|
+
/**
|
|
683
|
+
* One-shot speech-to-text. Off by default, never ambient, clearly
|
|
684
|
+
* indicated. Requires `voice:listen` (sensitive) and a configured
|
|
685
|
+
* transcription-capable AI provider.
|
|
686
|
+
*/
|
|
687
|
+
listen(opts?: {
|
|
688
|
+
timeoutMs?: number;
|
|
689
|
+
}): Promise<{
|
|
690
|
+
text: string;
|
|
691
|
+
}>;
|
|
692
|
+
}
|
|
693
|
+
/** Host-mediated OAuth configuration for the host-approved provider registry. */
|
|
694
|
+
export interface OpenPetsOauthConfig {
|
|
695
|
+
provider: "google" | "spotify";
|
|
696
|
+
clientId: string;
|
|
697
|
+
/** Optional installed-app credential secret required by the provider token endpoint. */
|
|
698
|
+
clientSecret?: string;
|
|
699
|
+
scopes: string[];
|
|
700
|
+
}
|
|
701
|
+
/** Tokens returned by the host after running the OAuth dance. */
|
|
702
|
+
export interface OpenPetsOauthTokens {
|
|
703
|
+
accessToken: string;
|
|
704
|
+
refreshToken?: string;
|
|
705
|
+
expiresAt?: number;
|
|
706
|
+
}
|
|
707
|
+
/** Stable OAuth error codes returned by host-managed providers. */
|
|
708
|
+
export type OpenPetsOauthErrorCode = "invalid_grant";
|
|
709
|
+
/** OAuth errors may expose this code for reconnect-required handling. */
|
|
710
|
+
export interface OpenPetsOauthError extends Error {
|
|
711
|
+
readonly code: OpenPetsOauthErrorCode;
|
|
712
|
+
}
|
|
713
|
+
/** Host-mediated OAuth: the host opens the system browser and runs PKCE. Requires `auth`. */
|
|
714
|
+
export interface OpenPetsAuthApi {
|
|
715
|
+
oauth(config: OpenPetsOauthConfig): Promise<OpenPetsOauthTokens>;
|
|
716
|
+
refresh(provider: string): Promise<{
|
|
717
|
+
accessToken: string;
|
|
718
|
+
expiresAt?: number;
|
|
719
|
+
}>;
|
|
720
|
+
signOut(provider: string): Promise<void>;
|
|
721
|
+
}
|
|
722
|
+
/** A user-picked file. Reads are size-capped; no plugin-chosen paths. */
|
|
723
|
+
export interface OpenPetsPickedFile {
|
|
724
|
+
name: string;
|
|
725
|
+
sizeBytes: number;
|
|
726
|
+
readText(): Promise<string>;
|
|
727
|
+
readBytes(): Promise<Uint8Array>;
|
|
728
|
+
}
|
|
729
|
+
/** User-initiated file access behind OS dialogs. Requires `files`. */
|
|
730
|
+
export interface OpenPetsFilesApi {
|
|
731
|
+
pick(opts?: {
|
|
732
|
+
accept?: string[];
|
|
733
|
+
multiple?: boolean;
|
|
734
|
+
}): Promise<OpenPetsPickedFile[]>;
|
|
735
|
+
save(opts: {
|
|
736
|
+
suggestedName: string;
|
|
737
|
+
data: string | Uint8Array;
|
|
738
|
+
}): Promise<void>;
|
|
739
|
+
}
|
|
740
|
+
/** Read-only environment info. Always non-sensitive. */
|
|
741
|
+
export interface OpenPetsSystemInfo {
|
|
742
|
+
platform: "mac" | "win" | "linux";
|
|
743
|
+
locale: string;
|
|
744
|
+
timezone: string;
|
|
745
|
+
theme: "light" | "dark";
|
|
746
|
+
appVersion: string;
|
|
747
|
+
online: boolean;
|
|
748
|
+
}
|
|
749
|
+
/** Aggregate machine metrics — never per-process or per-app data. */
|
|
750
|
+
export interface OpenPetsSystemMetrics {
|
|
751
|
+
/** 0–100, recent average. */
|
|
752
|
+
cpuPercent: number;
|
|
753
|
+
/** 0–100. */
|
|
754
|
+
memUsedPercent: number;
|
|
755
|
+
battery?: {
|
|
756
|
+
percent: number;
|
|
757
|
+
charging: boolean;
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
/** Read-only environment + open-external + gated clipboard. */
|
|
761
|
+
export interface OpenPetsSystemApi {
|
|
762
|
+
/** Always available. */
|
|
763
|
+
info(): Promise<OpenPetsSystemInfo>;
|
|
764
|
+
/** Requires `system:metrics`. */
|
|
765
|
+
metrics(): Promise<OpenPetsSystemMetrics>;
|
|
766
|
+
/** HTTPS-only; opens the user's real browser. Requires `system:openExternal`. */
|
|
767
|
+
openExternal(url: string): Promise<void>;
|
|
768
|
+
/**
|
|
769
|
+
* Allowed only from inside a user-invoked command handler, never ambient.
|
|
770
|
+
* Requires `clipboard` (sensitive).
|
|
771
|
+
*/
|
|
772
|
+
readClipboardText(): Promise<string>;
|
|
773
|
+
/** Requires `clipboard`. */
|
|
774
|
+
writeClipboardText(text: string): Promise<void>;
|
|
139
775
|
}
|
|
140
776
|
/** Show a short status line in the Plugins window. Requires `status`. */
|
|
141
777
|
export interface OpenPetsStatusApi {
|
|
142
778
|
set(status: OpenPetsStatus): Promise<void>;
|
|
143
779
|
clear(): Promise<void>;
|
|
144
780
|
}
|
|
145
|
-
/** Fetch approved HTTPS hosts through the OpenPets proxy. Requires `network`. */
|
|
146
|
-
export interface OpenPetsHttpApi {
|
|
147
|
-
fetch(url: string, options?: OpenPetsHttpOptions): Promise<OpenPetsHttpResponse>;
|
|
148
|
-
}
|
|
149
781
|
/** Write to the desktop app log under the `plugin` scope. Always available. */
|
|
150
782
|
export interface OpenPetsLogApi {
|
|
151
783
|
debug(...args: unknown[]): Promise<void>;
|
|
@@ -157,23 +789,67 @@ export interface OpenPetsLogApi {
|
|
|
157
789
|
* The capability object passed to {@link OpenPetsPluginDefinition.start}.
|
|
158
790
|
*
|
|
159
791
|
* Each namespace is only functional when the matching permission is approved
|
|
160
|
-
* in the manifest. `config` and `
|
|
792
|
+
* in the manifest. `config`, `log`, `assets`, and `system.info` are always
|
|
793
|
+
* available.
|
|
794
|
+
*
|
|
795
|
+
* `pet` is an alias for `pets.default` (back-compat + convenience); the v2
|
|
796
|
+
* surface (`ctx.pet.speak(text)`, `ctx.http.fetch`) keeps working.
|
|
161
797
|
*/
|
|
162
798
|
export interface OpenPetsContext {
|
|
163
|
-
|
|
799
|
+
pets: OpenPetsPetsApi;
|
|
800
|
+
pet: OpenPetsPetHandle;
|
|
801
|
+
ui: OpenPetsUiApi;
|
|
802
|
+
audio: OpenPetsAudioApi;
|
|
803
|
+
events: OpenPetsEventsApi;
|
|
804
|
+
assets: OpenPetsAssetsApi;
|
|
805
|
+
bus: OpenPetsBusApi;
|
|
164
806
|
schedule: OpenPetsScheduleApi;
|
|
165
807
|
storage: OpenPetsStorageApi;
|
|
166
808
|
config: OpenPetsConfigApi;
|
|
809
|
+
net: OpenPetsNetApi;
|
|
810
|
+
notify: OpenPetsNotifyApi;
|
|
811
|
+
ai: OpenPetsAiApi;
|
|
812
|
+
secrets: OpenPetsSecretsApi;
|
|
813
|
+
voice: OpenPetsVoiceApi;
|
|
814
|
+
auth: OpenPetsAuthApi;
|
|
815
|
+
files: OpenPetsFilesApi;
|
|
816
|
+
system: OpenPetsSystemApi;
|
|
167
817
|
commands: OpenPetsCommandsApi;
|
|
168
818
|
status: OpenPetsStatusApi;
|
|
819
|
+
/** v2 alias of `net` (GET-only). */
|
|
169
820
|
http: OpenPetsHttpApi;
|
|
170
821
|
log: OpenPetsLogApi;
|
|
822
|
+
/**
|
|
823
|
+
* Translate a key against the plugin's own `locales/<locale>.json` catalogs
|
|
824
|
+
* for the active host locale, falling back to the plugin's `en` catalog and
|
|
825
|
+
* then to the raw key. `{var}` placeholders are interpolated from `vars`.
|
|
826
|
+
*
|
|
827
|
+
* Use this for strings the plugin *composes at runtime* (bubble/notify/status
|
|
828
|
+
* bodies). Static manifest strings (`name`, `description`, `configSchema`
|
|
829
|
+
* labels, command titles) should instead use the `$t:key` reference form,
|
|
830
|
+
* which the host resolves at display time.
|
|
831
|
+
*
|
|
832
|
+
* ```ts
|
|
833
|
+
* await ctx.ui.bubble({ text: ctx.t("reminder.fire", { message: "Stretch" }) })
|
|
834
|
+
* // locales/ja.json: { "reminder.fire": "リマインダー: {message}" } -> "リマインダー: Stretch"
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
t: (key: string, vars?: Record<string, string | number>) => string;
|
|
838
|
+
/**
|
|
839
|
+
* The active host locale string (e.g. `"en"`, `"ja"`, `"pt-BR"`, `"zh-Hans"`).
|
|
840
|
+
* Read it to branch on language at runtime; `ctx.t` already follows it.
|
|
841
|
+
*
|
|
842
|
+
* ```ts
|
|
843
|
+
* if (ctx.locale.startsWith("ja")) { /* ... *\/ }
|
|
844
|
+
* ```
|
|
845
|
+
*/
|
|
846
|
+
readonly locale: string;
|
|
171
847
|
}
|
|
172
848
|
/** The object you pass to {@link OpenPetsPluginApi.register}. */
|
|
173
849
|
export interface OpenPetsPluginDefinition {
|
|
174
850
|
/** Runs when the plugin is enabled or the app launches. */
|
|
175
851
|
start(ctx: OpenPetsContext): void | Promise<void>;
|
|
176
|
-
/** Optional cleanup. Schedules and
|
|
852
|
+
/** Optional cleanup. Schedules, commands, bubbles, and subscriptions are torn down for you. */
|
|
177
853
|
stop?(ctx?: OpenPetsContext): void | Promise<void>;
|
|
178
854
|
}
|
|
179
855
|
/** The injected global used to register a plugin. */
|
|
@@ -192,7 +868,11 @@ export interface OpenPetsPluginApi {
|
|
|
192
868
|
*/
|
|
193
869
|
export type OpenPetsPluginEntry = (api: OpenPetsPluginApi) => void | Promise<void>;
|
|
194
870
|
/** Field types supported by `configSchema` in the manifest. */
|
|
195
|
-
export type OpenPetsConfigFieldType = "text" | "textarea" | "number" | "boolean" | "select" | "time" | "list" | "multiselect"
|
|
871
|
+
export type OpenPetsConfigFieldType = "text" | "textarea" | "number" | "boolean" | "select" | "time" | "date" | "list" | "multiselect" | "sound"
|
|
872
|
+
/** Masked input, encrypted at rest, never logged or echoed (v3). */
|
|
873
|
+
| "secret";
|
|
874
|
+
/** v2 alias: the old flat pet namespace shape. */
|
|
875
|
+
export type OpenPetsPetApi = Pick<OpenPetsPetHandle, "speak" | "react" | "moveBy" | "wander" | "moveToHome">;
|
|
196
876
|
declare global {
|
|
197
877
|
/**
|
|
198
878
|
* Injected by the OpenPets runtime. Call once at the top level of your
|