agent-robot-avatar 0.5.2 → 0.7.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/CHANGELOG.md +56 -7
- package/README.md +93 -16
- package/agent-robot-avatar-lite.js +44 -0
- package/agent-robot-avatar.js +2 -2
- package/index.d.ts +94 -17
- package/lite.d.ts +5 -0
- package/package.json +12 -5
- package/src/agent-robot-avatar-actions.js +17 -14
- package/src/agent-robot-avatar-core.js +5 -2
- package/src/agent-robot-avatar-gestures.js +9 -0
- package/src/agent-robot-avatar-runtime.js +58 -12
- package/src/agent-robot-avatar-skin-patterns.js +234 -0
- package/src/agent-robot-avatar-skins.js +256 -0
- package/src/agent-robot-avatar-version.js +1 -1
- package/src/agent-robot-avatar-waiting.js +30 -6
- package/src/skins/catalog.js +218 -0
- package/src/skins/collection-materials.js +118 -0
- package/src/skins/eyelids.js +32 -0
- package/src/skins/glaze-variants.js +29 -0
- package/src/skins/layered-texture.js +162 -0
- package/src/skins/material-data.js +111 -0
- package/src/skins/material-library.js +302 -0
- package/src/skins/metal-tint.js +11 -0
- package/src/skins/more-materials.js +69 -0
- package/src/skins/native.js +754 -0
- package/src/skins/paints.js +3 -0
- package/src/skins/revised-materials.js +44 -0
- package/src/skins/second-pass-materials.js +71 -0
- package/src/skins/soft-materials.js +111 -0
- package/src/skins/sports-materials.js +38 -0
- package/src/skins/wood-materials.js +68 -0
- package/assets/support/alipay.png +0 -0
- package/assets/support/wechat-pay.png +0 -0
- package/docs/README.de.md +0 -186
- package/docs/README.es.md +0 -186
- package/docs/README.fr.md +0 -186
- package/docs/README.ja.md +0 -186
- package/docs/README.ko.md +0 -186
- package/docs/README.pt.md +0 -186
- package/docs/README.ru.md +0 -186
- package/docs/README.zh-CN.md +0 -190
- package/docs/README.zh-TW.md +0 -186
- package/src/agent-robot-avatar-antenna-flash.js +0 -127
package/CHANGELOG.md
CHANGED
|
@@ -4,27 +4,72 @@ All notable user-facing changes to Agent Robot Avatar are documented here.
|
|
|
4
4
|
|
|
5
5
|
The project follows Semantic Versioning for public releases. Internal development build numbers are not part of the public version history.
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [0.7.0] - 2026-10-29
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### Added
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- 188 skins in 17 series. Pick one by number with `skin="301"` or `setSkin(301)`; `setSkin(null)` goes back to the flat color.
|
|
12
|
+
- Skin numbers are permanent: the series number plus two digits, so 305 is the fifth skin of series 3. New skins take the next free number, and numbers are never reused.
|
|
13
|
+
- Every skin works with every expression and gesture, and its light follows the pointer.
|
|
14
|
+
- `SKINS`, `SKIN_SERIES` and `SKIN_NAMES` list the skins, for building a skin picker.
|
|
15
|
+
- Skin code loads only when a page uses a skin. `loadSkins()` loads it in advance.
|
|
16
|
+
- `agent-robot-avatar/lite`: the same avatar without any skin code.
|
|
17
|
+
- The demo has a Skin Gallery and a page with every skin.
|
|
18
|
+
|
|
19
|
+
## [0.6.0] - 2026-10-23
|
|
20
|
+
|
|
21
|
+
### Upgrading from 0.5.x
|
|
22
|
+
|
|
23
|
+
Several actions are renamed after what the avatar does on screen, instead of the situation they were first written for. The old names keep working in 0.6 and print a one-time notice in the browser console; they stop working in 1.0. To upgrade, replace the old names in `play()` calls and in `action-state` or `face-state` listeners:
|
|
24
|
+
|
|
25
|
+
| Old name | New name | What it looks like |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `send` | `affirm` | A nod |
|
|
28
|
+
| `warning` | `wary` | Head turned, one eye close, a guarded up-and-down look |
|
|
29
|
+
| `error`, `system-error`, `connection-error` | `refuse` | A head shake |
|
|
30
|
+
| `blocked`, `policy-blocked` | `angry` | Lowered, glaring eyes |
|
|
31
|
+
| `wait` | `waiting-spin` (or `waiting`) | The default waiting spin |
|
|
32
|
+
| `failed`, `fail` | `failure` | |
|
|
33
|
+
| `verify`, `review` | `inspect` | |
|
|
34
|
+
| `slot` | `random` | |
|
|
35
|
+
|
|
36
|
+
`action-state` now reports `affirm`, `wary`, `angry` and `refuse`, and `face-state` reports `wary` and `refuse`. A shake reads as "no", so use `refuse` when the Agent cannot or will not do something, and `failure` when a task or connection fails. Antenna blinking is removed: `setAntennaFlash()` now does nothing and prints a one-time notice, and it is deleted in 1.0. Packages that depend on `^0.5.x` do not pick up 0.6 automatically.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Added the `waiting-wave` action: both eyes bob in staggered waves. `startWaiting({ variant: 'wave' })` loops it continuously.
|
|
41
|
+
- Added `waiting-spin` as the explicit name of the default waiting motion, and `startWaiting({ variant: 'spin' })`.
|
|
42
|
+
- Added brand-inspired color palettes to the demo. Colors apply to a stage card around the avatar; hovering a swatch previews it, a dice button picks a random palette, a swap button exchanges the background and head colors, and a reset button appears on the stage while the colors differ from the default. The page opens by rolling the stage through the palettes in step with the eyes' reel spin, ending with a faint rainbow ripple.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Renamed actions as listed above.
|
|
47
|
+
- Demo labels now describe the expression: Waiting · Spin, Waiting · Scroll, Affirm, Wary, Angry and Refuse. The toolbar row is one card as wide as the actions, with Head shape and a random-colors button.
|
|
48
|
+
- Refined the wary expression with independently tilted eyes, adjusted eye proportions and eyelids.
|
|
49
|
+
|
|
50
|
+
### Also in this release
|
|
12
51
|
|
|
13
|
-
-
|
|
52
|
+
- The embedded eyes engine for robot and dev-board screens is still in development. It will get its own version number and release; progress is tracked in [embedded/CHANGELOG.md](embedded/CHANGELOG.md).
|
|
14
53
|
|
|
15
|
-
|
|
54
|
+
### Removed
|
|
55
|
+
|
|
56
|
+
- Removed antenna blinking (`setAntennaFlash()`), which added little and is no longer shown in the demo.
|
|
16
57
|
|
|
17
58
|
### Fixed
|
|
18
59
|
|
|
19
|
-
-
|
|
60
|
+
- The demo no longer shows intermediate layouts while loading, keeps its action rows even and stable on phones and under browser page translators, and keeps an open panel on screen.
|
|
20
61
|
|
|
21
|
-
## [0.5.
|
|
62
|
+
## [0.5.2] - 2026-10-06
|
|
22
63
|
|
|
23
64
|
### Added
|
|
24
65
|
|
|
25
66
|
- Added the `love` action: the eyes lean together into a heart, beat three times, then return.
|
|
26
67
|
- Added the `random` action (alias `slot`): the eyes roll like slot-machine reels, then settle with a bounce.
|
|
27
68
|
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- `love` now shows the full heart under reduced motion, and `love` and `random` follow motion preference changes while they play.
|
|
72
|
+
|
|
28
73
|
## [0.4.3] - 2026-09-22
|
|
29
74
|
|
|
30
75
|
### Fixed
|
|
@@ -160,6 +205,8 @@ First public release.
|
|
|
160
205
|
- npm-compatible package metadata for later package publication
|
|
161
206
|
- Contribution guide, issue templates, pull request template, MIT License, and Ko-fi funding metadata
|
|
162
207
|
|
|
208
|
+
[0.6.0]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.6.0
|
|
209
|
+
[0.5.2]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.5.2
|
|
163
210
|
[0.4.3]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.4.3
|
|
164
211
|
[0.4.2]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.4.2
|
|
165
212
|
[0.3.2]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.3.2
|
|
@@ -168,3 +215,5 @@ First public release.
|
|
|
168
215
|
[0.2.1]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.2.1
|
|
169
216
|
[0.2.0]: https://github.com/CX-ARTLab/agent-robot-avatar/releases/tag/v0.2.0
|
|
170
217
|
[0.1.0]: https://github.com/CX-ARTLab/agent-robot-avatar/releases/tag/v0.1.0
|
|
218
|
+
|
|
219
|
+
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
[English](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/README.md) | [简体中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-CN.md) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.md) | [Русский](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.ru.md) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md) | [Português](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.pt.md) | [Deutsch](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.de.md) | [日本語](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.ja.md) | [한국어](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.ko.md) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.md)
|
|
8
8
|
|
|
9
|
-
 [](./LICENSE) [](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [](https://ko-fi.com/P0E625WIOI)
|
|
10
10
|
|
|
11
11
|
   
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@ Built with SVG and vanilla JavaScript, it works as a native custom element with
|
|
|
26
26
|
|
|
27
27
|
## Live Demo
|
|
28
28
|
|
|
29
|
-
[Open the interactive demo](https://cx-artlab.github.io/agent-robot-avatar/)
|
|
29
|
+
[Open the interactive demo](https://cx-artlab.github.io/agent-robot-avatar/) · [Visit the Skin Gallery](https://cx-artlab.github.io/agent-robot-avatar/skins.html)
|
|
30
30
|
|
|
31
31
|
## Highlights
|
|
32
32
|
|
|
@@ -38,11 +38,12 @@ Built with SVG and vanilla JavaScript, it works as a native custom element with
|
|
|
38
38
|
- Jelly-style drag deformation with elastic recovery
|
|
39
39
|
- Press-and-hold squeeze and draggable spring antenna interactions
|
|
40
40
|
- Programmatically controlled Agent states and expressions
|
|
41
|
-
-
|
|
41
|
+
- Expressions for waiting, success, failure, affirm, wary, inspect, angry, refuse, love and more
|
|
42
42
|
- Reduced-motion support
|
|
43
43
|
- Configurable sleep behavior
|
|
44
44
|
- Adjustable head roundness
|
|
45
|
-
-
|
|
45
|
+
- 188 numbered skins in 17 series, with light that follows the pointer
|
|
46
|
+
- A lite build without skins for the smallest pages
|
|
46
47
|
- TypeScript declarations included
|
|
47
48
|
|
|
48
49
|
## Install
|
|
@@ -69,27 +70,54 @@ Then add the component:
|
|
|
69
70
|
|
|
70
71
|
No initialization code is required. The avatar enters its default idle behavior automatically.
|
|
71
72
|
|
|
73
|
+
### Lite build
|
|
74
|
+
|
|
75
|
+
For pages that never use skins, `agent-robot-avatar/lite` is the same avatar without any skin code:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import 'agent-robot-avatar/lite';
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
In the lite build the `skin` attribute is ignored, and the console notes that skins need the full build.
|
|
82
|
+
|
|
72
83
|
## Basic usage
|
|
73
84
|
|
|
74
85
|
```js
|
|
75
86
|
const avatar = document.querySelector('#avatar');
|
|
76
87
|
|
|
77
88
|
avatar.play('success');
|
|
78
|
-
avatar.play('
|
|
79
|
-
avatar.play('
|
|
89
|
+
avatar.play('wary');
|
|
90
|
+
avatar.play('refuse');
|
|
80
91
|
|
|
81
92
|
avatar.reset();
|
|
82
93
|
```
|
|
83
94
|
|
|
84
95
|
Available actions:
|
|
85
96
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`
|
|
89
|
-
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
`
|
|
97
|
+
| Action | Looks like | Use when |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| `idle` | Blinks and glances around | Default state |
|
|
100
|
+
| `bored` | Glances slowly from side to side | Nothing has happened for a while |
|
|
101
|
+
| `waiting-spin` | Eyes circle from side to side | Waiting for a reply (default) |
|
|
102
|
+
| `waiting-wrap` | Eyes slide out one side and back in the other | Waiting for a reply |
|
|
103
|
+
| `waiting-wave` | Eyes bob up and down in turn | Waiting for a reply |
|
|
104
|
+
| `input` | Eyes become blinking text cursors | The user is typing |
|
|
105
|
+
| `affirm` | Nods | Got it, confirmed |
|
|
106
|
+
| `success` | Happy, smiling eyes | Task completed |
|
|
107
|
+
| `failure` | Head and eyes droop | Task or connection failed |
|
|
108
|
+
| `wary` | Turns its head and gives a guarded up-and-down look | An action needs confirmation |
|
|
109
|
+
| `inspect` | Narrows its eyes and scans up and down | Checking or reviewing something |
|
|
110
|
+
| `angry` | Lowered, glaring eyes | Content blocked |
|
|
111
|
+
| `refuse` | Shakes its head | Cannot or will not do the request |
|
|
112
|
+
| `surprise` | Wide-open eyes | Something unexpected |
|
|
113
|
+
| `love` | Eyes merge into a beating heart | Thanks, affection |
|
|
114
|
+
| `random` | Eyes spin like slot-machine reels | Random pick, playful moment |
|
|
115
|
+
| `sleep` | Closes its eyes and sleeps | No activity for a long time |
|
|
116
|
+
| `wake` | Opens its eyes and wakes up | Activity resumes |
|
|
117
|
+
|
|
118
|
+
Waiting actions play one round with `play()`. `startWaiting({ variant: 'spin' | 'wrap' | 'wave' })` loops until another action starts or `stopWaiting()` is called.
|
|
119
|
+
|
|
120
|
+
Names from 0.5 (`send`, `warning`, `error`, `blocked`, `slot` and others) still work with a console notice until 1.0; see the [upgrade table](CHANGELOG.md#upgrading-from-05x).
|
|
93
121
|
|
|
94
122
|
For a real Agent request lifecycle:
|
|
95
123
|
|
|
@@ -99,11 +127,14 @@ avatar.startWaiting();
|
|
|
99
127
|
// Alternative waiting motion: eyes turn out through one side and return through the other.
|
|
100
128
|
avatar.startWaiting({ variant: 'wrap' });
|
|
101
129
|
|
|
130
|
+
// Alternative waiting motion: staggered vertical eye waves.
|
|
131
|
+
avatar.startWaiting({ variant: 'wave' });
|
|
132
|
+
|
|
102
133
|
try {
|
|
103
134
|
const result = await runAgentRequest();
|
|
104
135
|
await avatar.play(result.ok ? 'success' : 'failure');
|
|
105
136
|
} catch (error) {
|
|
106
|
-
await avatar.play('
|
|
137
|
+
await avatar.play('failure');
|
|
107
138
|
}
|
|
108
139
|
```
|
|
109
140
|
|
|
@@ -128,19 +159,60 @@ try {
|
|
|
128
159
|
| `motion` | Motion policy: `auto`, `reduce`, or `full` |
|
|
129
160
|
| `press-squeeze` | Center press-and-hold squeeze; set to `false` to disable |
|
|
130
161
|
| `antenna-drag` | Antenna drag, spring return, and angry reaction; set to `false` to disable |
|
|
162
|
+
| `skin` | Skin number, such as `301`; leave it out for the flat color |
|
|
131
163
|
|
|
132
164
|
Common runtime controls:
|
|
133
165
|
|
|
134
166
|
```js
|
|
135
167
|
avatar.setPointerFollow(false);
|
|
136
168
|
avatar.setHeadRoundness(75);
|
|
137
|
-
avatar.setAntennaFlash(true);
|
|
138
169
|
avatar.setPressSqueeze(true);
|
|
139
170
|
avatar.setAntennaDrag(true);
|
|
140
171
|
```
|
|
141
172
|
|
|
142
173
|
The avatar center begins the squeeze interaction. Moving more than 4 CSS pixels transfers the same pointer gesture to the existing head drag. Dragging the antenna uses the same pull limit as head dragging and ends with the existing angry reaction.
|
|
143
174
|
|
|
175
|
+
## Skins · New in 0.7
|
|
176
|
+
|
|
177
|
+
188 skins in 17 series, with light that follows the pointer. Every skin has a permanent number: the series number followed by two digits, so 305 is the fifth skin of series 3. Titles may be reworded later; numbers never change and are never reused.
|
|
178
|
+
|
|
179
|
+
<img src="./assets/readme/skin-gallery.jpg" alt="Skin Gallery: featured skins, filters and search" width="100%">
|
|
180
|
+
|
|
181
|
+
```html
|
|
182
|
+
<agent-robot-avatar skin="301"></agent-robot-avatar>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
avatar.setSkin(102); // or '102'
|
|
187
|
+
avatar.setSkin(null); // back to the flat color
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
See every skin with its number on the [all skins page](https://cx-artlab.github.io/agent-robot-avatar/materials/).
|
|
191
|
+
|
|
192
|
+
| Series | Numbers |
|
|
193
|
+
| --- | --- |
|
|
194
|
+
| Glaze | 101–106 |
|
|
195
|
+
| Ice glass | 201–206 |
|
|
196
|
+
| Gummy | 301–312 |
|
|
197
|
+
| Candy glass | 401–406 |
|
|
198
|
+
| Acrylic | 501–512 |
|
|
199
|
+
| Jelly | 601–612 |
|
|
200
|
+
| Gradient | 701–712 |
|
|
201
|
+
| Frosted glass | 801–806 |
|
|
202
|
+
| Metal | 901–930 |
|
|
203
|
+
| Gems and ceramics | 1001–1012 |
|
|
204
|
+
| Wood | 1101–1106 |
|
|
205
|
+
| Balls | 1201–1210 |
|
|
206
|
+
| Clear and shimmer | 1301–1305 |
|
|
207
|
+
| Fabric and leather | 1401–1412 |
|
|
208
|
+
| Sweets and fruit | 1501–1512 |
|
|
209
|
+
| Nature | 1601–1612 |
|
|
210
|
+
| Patterns and tech | 1701–1717 |
|
|
211
|
+
|
|
212
|
+
Skin painters download the first time a skin is used, so a page without skins never loads them. `await loadSkins()` loads them in advance. `SKINS` holds each skin’s Chinese and English titles and colors, `SKIN_SERIES` the series, and `SKIN_NAMES` every number.
|
|
213
|
+
|
|
214
|
+
Every expression and gesture works with a skin. When the skin is removed, the `color` attribute applies again.
|
|
215
|
+
|
|
144
216
|
## Events and integration
|
|
145
217
|
|
|
146
218
|
The component emits `face-state` for visual state changes and `action-state` for semantic action lifecycle changes.
|
|
@@ -155,13 +227,17 @@ Designed for modern browsers with support for ES Modules, Custom Elements, SVG,
|
|
|
155
227
|
|
|
156
228
|
Automated browser tests cover Chromium, Firefox, and WebKit.
|
|
157
229
|
|
|
230
|
+
## Hardware version (in development)
|
|
231
|
+
|
|
232
|
+
A C++ version that shows the avatar's expressions on robot and dev-board screens (it draws only the eyes) is in development and not released yet. See the [hardware guide](https://github.com/CX-ArtLab/agent-robot-avatar/tree/main/embedded).
|
|
233
|
+
|
|
158
234
|
## Contributing
|
|
159
235
|
|
|
160
236
|
Issues and pull requests are welcome. See [`CONTRIBUTING.md`](./CONTRIBUTING.md) before submitting changes.
|
|
161
237
|
|
|
162
238
|
## Project status
|
|
163
239
|
|
|
164
|
-
**Current public version: v0.
|
|
240
|
+
**Current public version: v0.6.0**
|
|
165
241
|
|
|
166
242
|
The public API is intentionally kept compact while the project evolves toward a future `1.0.0` stability commitment.
|
|
167
243
|
|
|
@@ -184,3 +260,4 @@ MIT License. See [`LICENSE`](./LICENSE).
|
|
|
184
260
|
If this project is useful to you, you can buy me a coffee.
|
|
185
261
|
|
|
186
262
|
<a href='https://ko-fi.com/P0E625WIOI' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
263
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// The smallest build: every expression and gesture, without skins. The skin
|
|
2
|
+
// attribute and setSkin() only explain where skins live, so a page written for
|
|
3
|
+
// the full build keeps working with the plain avatar.
|
|
4
|
+
import AgentRobotAvatar from './src/agent-robot-avatar-extension-host.js';
|
|
5
|
+
import './src/agent-robot-avatar-actions.js';
|
|
6
|
+
import './src/agent-robot-avatar-antenna.js';
|
|
7
|
+
import './src/agent-robot-avatar-waiting.js';
|
|
8
|
+
import './src/agent-robot-avatar-inspect.js';
|
|
9
|
+
import './src/agent-robot-avatar-failure.js';
|
|
10
|
+
import './src/agent-robot-avatar-love.js';
|
|
11
|
+
import './src/agent-robot-avatar-random.js';
|
|
12
|
+
import './src/agent-robot-avatar-head-roundness.js';
|
|
13
|
+
import './src/agent-robot-avatar-gestures.js';
|
|
14
|
+
import './src/agent-robot-avatar-runtime.js';
|
|
15
|
+
import { VERSION } from './src/agent-robot-avatar-version.js';
|
|
16
|
+
|
|
17
|
+
const proto = AgentRobotAvatar.prototype;
|
|
18
|
+
let warned = false;
|
|
19
|
+
function explain() {
|
|
20
|
+
if (warned) return;
|
|
21
|
+
warned = true;
|
|
22
|
+
console.warn('agent-robot-avatar: skins are not part of the lite build; import "agent-robot-avatar" instead of "agent-robot-avatar/lite" to use them.');
|
|
23
|
+
}
|
|
24
|
+
if (!proto.setSkin) {
|
|
25
|
+
proto._applySkinAttribute = function() { if (this.getAttribute('skin')) explain(); };
|
|
26
|
+
proto.setSkin = function(value = null) {
|
|
27
|
+
if (value !== null && value !== 'none') explain();
|
|
28
|
+
return this;
|
|
29
|
+
};
|
|
30
|
+
proto.getSkin = () => null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Elements already present in markup can upgrade while the core module is
|
|
34
|
+
// loading, before runtime extensions finish installing their prototype hooks.
|
|
35
|
+
if (typeof document !== 'undefined') {
|
|
36
|
+
document.querySelectorAll('agent-robot-avatar').forEach(avatar => avatar._resumeFrames?.());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof window !== 'undefined') {
|
|
40
|
+
window.AgentRobotAvatarVersion = VERSION;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { AgentRobotAvatar, VERSION };
|
|
44
|
+
export default AgentRobotAvatar;
|
package/agent-robot-avatar.js
CHANGED
|
@@ -2,13 +2,13 @@ import AgentRobotAvatar from './src/agent-robot-avatar-extension-host.js';
|
|
|
2
2
|
import './src/agent-robot-avatar-actions.js';
|
|
3
3
|
import './src/agent-robot-avatar-antenna.js';
|
|
4
4
|
import './src/agent-robot-avatar-waiting.js';
|
|
5
|
-
import './src/agent-robot-avatar-antenna-flash.js';
|
|
6
5
|
import './src/agent-robot-avatar-inspect.js';
|
|
7
6
|
import './src/agent-robot-avatar-failure.js';
|
|
8
7
|
import './src/agent-robot-avatar-love.js';
|
|
9
8
|
import './src/agent-robot-avatar-random.js';
|
|
10
9
|
import './src/agent-robot-avatar-head-roundness.js';
|
|
11
10
|
import './src/agent-robot-avatar-gestures.js';
|
|
11
|
+
import { SKIN_NAMES, SKINS, SKIN_SERIES, loadSkins } from './src/agent-robot-avatar-skins.js';
|
|
12
12
|
import './src/agent-robot-avatar-runtime.js';
|
|
13
13
|
import { VERSION } from './src/agent-robot-avatar-version.js';
|
|
14
14
|
|
|
@@ -24,5 +24,5 @@ if (typeof window !== 'undefined') {
|
|
|
24
24
|
window.AgentRobotAvatarVersion = VERSION;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export { AgentRobotAvatar, VERSION };
|
|
27
|
+
export { AgentRobotAvatar, SKIN_NAMES, SKINS, SKIN_SERIES, VERSION, loadSkins };
|
|
28
28
|
export default AgentRobotAvatar;
|
package/index.d.ts
CHANGED
|
@@ -2,30 +2,99 @@ export type AgentRobotAvatarAction =
|
|
|
2
2
|
| 'idle'
|
|
3
3
|
| 'bored'
|
|
4
4
|
| 'waiting'
|
|
5
|
-
| '
|
|
5
|
+
| 'waiting-spin'
|
|
6
6
|
| 'waiting-wrap'
|
|
7
|
+
| 'waiting-wave'
|
|
7
8
|
| 'input'
|
|
8
|
-
| '
|
|
9
|
+
| 'affirm'
|
|
9
10
|
| 'success'
|
|
10
11
|
| 'failure'
|
|
12
|
+
| 'wary'
|
|
13
|
+
| 'inspect'
|
|
14
|
+
| 'angry'
|
|
15
|
+
| 'refuse'
|
|
16
|
+
| 'surprise'
|
|
17
|
+
| 'love'
|
|
18
|
+
| 'random'
|
|
19
|
+
| 'sleep'
|
|
20
|
+
| 'wake'
|
|
21
|
+
| AgentRobotAvatarDeprecatedAction;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Older names that still play the same action but log a one-time deprecation
|
|
25
|
+
* notice. They are removed in 1.0.
|
|
26
|
+
*/
|
|
27
|
+
export type AgentRobotAvatarDeprecatedAction =
|
|
28
|
+
| 'wait'
|
|
29
|
+
| 'send'
|
|
11
30
|
| 'failed'
|
|
12
31
|
| 'fail'
|
|
13
32
|
| 'warning'
|
|
14
|
-
| 'inspect'
|
|
15
33
|
| 'verify'
|
|
16
34
|
| 'review'
|
|
17
|
-
| 'angry'
|
|
18
35
|
| 'blocked'
|
|
19
36
|
| 'policy-blocked'
|
|
20
37
|
| 'error'
|
|
21
38
|
| 'system-error'
|
|
22
39
|
| 'connection-error'
|
|
23
|
-
| '
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
| 'slot';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Skin numbers for the `skin` attribute and `setSkin()`: the series number
|
|
44
|
+
* followed by two digits, so `305` is the fifth skin of series 3. A number is
|
|
45
|
+
* permanent; titles may be reworded, numbers never change and are never reused.
|
|
46
|
+
*/
|
|
47
|
+
export type AgentRobotAvatarSkin =
|
|
48
|
+
| '101' | '102' | '103' | '104' | '105' | '106' | '201' | '202' | '203' | '204' | '205' | '206'
|
|
49
|
+
| '301' | '302' | '303' | '304' | '305' | '306' | '307' | '308' | '309' | '310' | '311' | '312'
|
|
50
|
+
| '401' | '402' | '403' | '404' | '405' | '406' | '501' | '502' | '503' | '504' | '505' | '506'
|
|
51
|
+
| '507' | '508' | '509' | '510' | '511' | '512' | '601' | '602' | '603' | '604' | '605' | '606'
|
|
52
|
+
| '607' | '608' | '609' | '610' | '611' | '612' | '701' | '702' | '703' | '704' | '705' | '706'
|
|
53
|
+
| '707' | '708' | '709' | '710' | '711' | '712' | '801' | '802' | '803' | '804' | '805' | '806'
|
|
54
|
+
| '901' | '902' | '903' | '904' | '905' | '906' | '907' | '908' | '909' | '910' | '911' | '912'
|
|
55
|
+
| '913' | '914' | '915' | '916' | '917' | '918' | '919' | '920' | '921' | '922' | '923' | '924'
|
|
56
|
+
| '925' | '926' | '927' | '928' | '929' | '930' | '1001' | '1002' | '1003' | '1004' | '1005' | '1006'
|
|
57
|
+
| '1007' | '1008' | '1009' | '1010' | '1011' | '1012' | '1101' | '1102' | '1103' | '1104' | '1105' | '1106'
|
|
58
|
+
| '1201' | '1202' | '1203' | '1204' | '1205' | '1206' | '1207' | '1208' | '1209' | '1210' | '1301' | '1302'
|
|
59
|
+
| '1303' | '1304' | '1305' | '1401' | '1402' | '1403' | '1404' | '1405' | '1406' | '1407' | '1408' | '1409'
|
|
60
|
+
| '1410' | '1411' | '1412' | '1501' | '1502' | '1503' | '1504' | '1505' | '1506' | '1507' | '1508' | '1509'
|
|
61
|
+
| '1510' | '1511' | '1512' | '1601' | '1602' | '1603' | '1604' | '1605' | '1606' | '1607' | '1608' | '1609'
|
|
62
|
+
| '1610' | '1611' | '1612' | '1701' | '1702' | '1703' | '1704' | '1705' | '1706' | '1707' | '1708' | '1709'
|
|
63
|
+
| '1710' | '1711' | '1712' | '1713' | '1714' | '1715' | '1716' | '1717';
|
|
64
|
+
|
|
65
|
+
/** Display information for one skin. */
|
|
66
|
+
export interface AgentRobotAvatarSkinInfo {
|
|
67
|
+
/** The series id, such as `'glaze'` or `'metal'`. */
|
|
68
|
+
readonly series: string;
|
|
69
|
+
/** Chinese title. */
|
|
70
|
+
readonly title: string;
|
|
71
|
+
/** English title. */
|
|
72
|
+
readonly titleEn: string;
|
|
73
|
+
/** Representative colors, light to dark. */
|
|
74
|
+
readonly base: readonly string[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** A group of related skins, in gallery order. */
|
|
78
|
+
export interface AgentRobotAvatarSkinSeries {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
/** The first digits of every skin number in the series. */
|
|
81
|
+
readonly number: number;
|
|
82
|
+
readonly title: string;
|
|
83
|
+
readonly titleEn: string;
|
|
84
|
+
readonly skins: readonly AgentRobotAvatarSkin[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Every skin number, in gallery order. */
|
|
88
|
+
export declare const SKIN_NAMES: readonly AgentRobotAvatarSkin[];
|
|
89
|
+
/** Titles and colors for every skin, by number. */
|
|
90
|
+
export declare const SKINS: Readonly<Record<AgentRobotAvatarSkin, AgentRobotAvatarSkinInfo>>;
|
|
91
|
+
/** The skin series, in gallery order. */
|
|
92
|
+
export declare const SKIN_SERIES: readonly AgentRobotAvatarSkinSeries[];
|
|
93
|
+
/**
|
|
94
|
+
* Skin painters download the first time a skin is used, so the first skin shows
|
|
95
|
+
* a moment after it is set. Await this to load them in advance.
|
|
96
|
+
*/
|
|
97
|
+
export declare function loadSkins(): Promise<void>;
|
|
29
98
|
|
|
30
99
|
export type AgentRobotAvatarState =
|
|
31
100
|
| 'idle'
|
|
@@ -39,8 +108,8 @@ export type AgentRobotAvatarState =
|
|
|
39
108
|
| 'love'
|
|
40
109
|
| 'random'
|
|
41
110
|
| 'waiting'
|
|
42
|
-
| '
|
|
43
|
-
| '
|
|
111
|
+
| 'wary'
|
|
112
|
+
| 'refuse'
|
|
44
113
|
| 'inspect'
|
|
45
114
|
| 'failure'
|
|
46
115
|
| 'squeeze'
|
|
@@ -51,14 +120,13 @@ export type AgentRobotAvatarCanonicalAction =
|
|
|
51
120
|
| 'bored'
|
|
52
121
|
| 'waiting'
|
|
53
122
|
| 'input'
|
|
54
|
-
| '
|
|
123
|
+
| 'affirm'
|
|
55
124
|
| 'success'
|
|
56
125
|
| 'failure'
|
|
57
|
-
| '
|
|
126
|
+
| 'wary'
|
|
58
127
|
| 'inspect'
|
|
59
128
|
| 'angry'
|
|
60
|
-
| '
|
|
61
|
-
| 'error'
|
|
129
|
+
| 'refuse'
|
|
62
130
|
| 'surprise'
|
|
63
131
|
| 'love'
|
|
64
132
|
| 'random'
|
|
@@ -73,7 +141,7 @@ export type AgentRobotAvatarActionSource = 'api' | 'interaction' | 'automatic';
|
|
|
73
141
|
export type AgentRobotAvatarWakeOn = 'activity' | 'interaction' | 'manual';
|
|
74
142
|
export type AgentRobotAvatarMotion = 'auto' | 'reduce' | 'full';
|
|
75
143
|
export interface AgentRobotAvatarWaitingOptions {
|
|
76
|
-
variant?: 'default' | 'wrap';
|
|
144
|
+
variant?: 'default' | 'spin' | 'wrap' | 'wave';
|
|
77
145
|
}
|
|
78
146
|
|
|
79
147
|
export interface AgentRobotAvatarActionStateDetail {
|
|
@@ -97,11 +165,19 @@ export declare class AgentRobotAvatar extends HTMLElement {
|
|
|
97
165
|
startWaiting(options?: AgentRobotAvatarWaitingOptions): Promise<this>;
|
|
98
166
|
stopWaiting(): this;
|
|
99
167
|
setPointerFollow(enabled?: boolean): this;
|
|
168
|
+
/** @deprecated Removed in 0.6; does nothing and logs a one-time notice. Deleted in 1.0. */
|
|
100
169
|
setAntennaFlash(enabled?: boolean): this;
|
|
101
170
|
setPressSqueeze(enabled?: boolean): this;
|
|
102
171
|
setAntennaDrag(enabled?: boolean): this;
|
|
103
172
|
setHeadRoundness(value?: number): this;
|
|
104
173
|
getHeadRoundness(): number;
|
|
174
|
+
/**
|
|
175
|
+
* Dresses the head in a numbered skin with light that follows the pointer.
|
|
176
|
+
* Same as the `skin` attribute; `null` or `'none'` returns to the flat color.
|
|
177
|
+
* Throws for an unknown number.
|
|
178
|
+
*/
|
|
179
|
+
setSkin(skin?: AgentRobotAvatarSkin | number | 'none' | null): this;
|
|
180
|
+
getSkin(): AgentRobotAvatarSkin | null;
|
|
105
181
|
noteActivity(wake?: boolean): void;
|
|
106
182
|
|
|
107
183
|
addEventListener<K extends keyof AgentRobotAvatarEventMap>(
|
|
@@ -126,3 +202,4 @@ declare global {
|
|
|
126
202
|
'agent-robot-avatar': AgentRobotAvatar;
|
|
127
203
|
}
|
|
128
204
|
}
|
|
205
|
+
|
package/lite.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The lite build: the same avatar without skins. setSkin() keeps its type so a
|
|
2
|
+
// page can switch builds, but it only logs that skins need the full build.
|
|
3
|
+
export { AgentRobotAvatar, VERSION } from './index.js';
|
|
4
|
+
export { default } from './index.js';
|
|
5
|
+
export type * from './index.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-robot-avatar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A lightweight expressive robot avatar Web Component for AI agents and interactive applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./agent-robot-avatar.js",
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"types": "./index.d.ts",
|
|
15
15
|
"import": "./agent-robot-avatar.js",
|
|
16
16
|
"default": "./agent-robot-avatar.js"
|
|
17
|
+
},
|
|
18
|
+
"./lite": {
|
|
19
|
+
"types": "./lite.d.ts",
|
|
20
|
+
"import": "./agent-robot-avatar-lite.js",
|
|
21
|
+
"default": "./agent-robot-avatar-lite.js"
|
|
17
22
|
}
|
|
18
23
|
},
|
|
19
24
|
"sideEffects": true,
|
|
@@ -21,20 +26,22 @@
|
|
|
21
26
|
"dev": "node scripts/serve.mjs",
|
|
22
27
|
"build:pages": "node scripts/build-pages.mjs",
|
|
23
28
|
"check": "node scripts/check-source.mjs",
|
|
24
|
-
"test": "npm run check && npm run test:types && npm run test:release && npm run test:package && npm run test:browser && npm run
|
|
29
|
+
"test": "npm run check && npm run test:types && npm run test:release && npm run test:package && npm run test:waiting && npm run test:browser && npm run test:pages",
|
|
25
30
|
"release:check": "npm test && npm publish --dry-run --ignore-scripts --tag latest",
|
|
26
31
|
"prepublishOnly": "npm test && node scripts/check-publish-tag.mjs",
|
|
27
32
|
"test:types": "tsc -p tsconfig.types.json",
|
|
28
33
|
"test:release": "node --test tests/release.test.mjs",
|
|
29
34
|
"test:package": "node --test tests/package.test.mjs",
|
|
30
|
-
"test:
|
|
35
|
+
"test:waiting": "node --test tests/waiting-wave.test.mjs",
|
|
36
|
+
"test:browser": "playwright test",
|
|
37
|
+
"test:pages": "node --test tests/pages-public.test.mjs"
|
|
31
38
|
},
|
|
32
39
|
"files": [
|
|
33
40
|
"agent-robot-avatar.js",
|
|
41
|
+
"agent-robot-avatar-lite.js",
|
|
34
42
|
"index.d.ts",
|
|
43
|
+
"lite.d.ts",
|
|
35
44
|
"src/",
|
|
36
|
-
"assets/support/",
|
|
37
|
-
"docs/",
|
|
38
45
|
"README.md",
|
|
39
46
|
"CHANGELOG.md",
|
|
40
47
|
"LICENSE"
|
|
@@ -23,7 +23,7 @@ const WARNING_TIMING = Object.freeze({
|
|
|
23
23
|
W5: 200,
|
|
24
24
|
W5P: 300,
|
|
25
25
|
W6: 200,
|
|
26
|
-
W6P:
|
|
26
|
+
W6P: 500,
|
|
27
27
|
W7: 100,
|
|
28
28
|
W8: 800,
|
|
29
29
|
W9: 227,
|
|
@@ -200,7 +200,7 @@ proto.error = async function() {
|
|
|
200
200
|
const eyeDuration = 980;
|
|
201
201
|
const headDuration = 1380;
|
|
202
202
|
this._systemErrorShake = { start: performance.now(), duration: eyeDuration };
|
|
203
|
-
dispatchActionState(this, '
|
|
203
|
+
dispatchActionState(this, 'refuse');
|
|
204
204
|
|
|
205
205
|
centerHeadTransform(this);
|
|
206
206
|
if (this._headMotion?.animate) {
|
|
@@ -234,7 +234,7 @@ proto.warning = async function() {
|
|
|
234
234
|
const token = this._transitionToken;
|
|
235
235
|
const duration = WARNING_PHASES.duration;
|
|
236
236
|
this._warningFx = { start: performance.now(), duration };
|
|
237
|
-
dispatchActionState(this, '
|
|
237
|
+
dispatchActionState(this, 'wary');
|
|
238
238
|
|
|
239
239
|
centerHeadTransform(this);
|
|
240
240
|
if (this._headMotion?.animate) {
|
|
@@ -345,29 +345,32 @@ function drawWarning(now) {
|
|
|
345
345
|
farDeepLidDrop = segment(elapsed, WARNING_PHASES.w6Start, WARNING_PHASES.w6End, 3.5, 0);
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
const nearSX = lerp(1, 1.
|
|
348
|
+
const nearSX = lerp(1, 1.37, proximity);
|
|
349
349
|
const nearSY = lerp(1, 1.40, proximity);
|
|
350
|
-
const farSX = lerp(1, 0.
|
|
351
|
-
const farSY = lerp(1, 0.
|
|
350
|
+
const farSX = lerp(1, 0.68, proximity);
|
|
351
|
+
const farSY = lerp(1, 0.99, proximity);
|
|
352
|
+
|
|
353
|
+
const nearTilt = lerp(0, -6.5, proximity);
|
|
354
|
+
const farTilt = lerp(0, 7.5, proximity);
|
|
352
355
|
|
|
353
356
|
const nearX = lerp(86, 102.0, proximity);
|
|
354
|
-
const farX = lerp(154,
|
|
357
|
+
const farX = lerp(154, 174.5, proximity);
|
|
355
358
|
const nearY = lerp(126, 125.5, proximity);
|
|
356
|
-
const farY = lerp(126,
|
|
359
|
+
const farY = lerp(126, 133.5, proximity) + farLowOffset;
|
|
357
360
|
|
|
358
361
|
this._leftEye.setAttribute(
|
|
359
362
|
'transform',
|
|
360
|
-
`translate(${nearX.toFixed(2)} ${nearY.toFixed(2)}) scale(${nearSX.toFixed(3)} ${nearSY.toFixed(3)})`
|
|
363
|
+
`translate(${nearX.toFixed(2)} ${nearY.toFixed(2)}) rotate(${nearTilt.toFixed(2)}) scale(${nearSX.toFixed(3)} ${nearSY.toFixed(3)})`
|
|
361
364
|
);
|
|
362
365
|
this._rightEye.setAttribute(
|
|
363
366
|
'transform',
|
|
364
|
-
`translate(${farX.toFixed(2)} ${farY.toFixed(2)}) scale(${farSX.toFixed(3)} ${farSY.toFixed(3)})`
|
|
367
|
+
`translate(${farX.toFixed(2)} ${farY.toFixed(2)}) rotate(${farTilt.toFixed(2)}) scale(${farSX.toFixed(3)} ${farSY.toFixed(3)})`
|
|
365
368
|
);
|
|
366
369
|
|
|
367
|
-
const nearTopY = lerp(-36, -
|
|
368
|
-
const farTopY = lerp(-36, -
|
|
369
|
-
const nearTopRot = lerp(0,
|
|
370
|
-
const farTopRot = lerp(0, -
|
|
370
|
+
const nearTopY = lerp(-36, -8.0, lids) + lidShift;
|
|
371
|
+
const farTopY = lerp(-36, -10.0, lids) + lidShift * 0.95 + farDeepLidDrop;
|
|
372
|
+
const nearTopRot = lerp(0, 25.0, lids);
|
|
373
|
+
const farTopRot = lerp(0, -17.0, lids);
|
|
371
374
|
|
|
372
375
|
this._leftTop.setAttribute('y', (nearTopY - 90).toFixed(2));
|
|
373
376
|
this._leftTop.setAttribute('height', '90');
|