agent-robot-avatar 0.2.0 → 0.2.1

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 CHANGED
@@ -6,6 +6,16 @@ The project follows Semantic Versioning for public releases. Internal developmen
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.1] - 2026-09-05
10
+
11
+ ### Fixed
12
+
13
+ - Fixed dynamic custom-element creation failing because the constructor added a host style attribute; preserved default and explicit sizing.
14
+ - Prevented interrupted expression continuations and animation callbacks from overriding resets or newer actions.
15
+ - Fixed automatic sleep repeatedly restarting its own preparation instead of reaching sleep.
16
+ - Synchronized dynamic head colors with the eye masks and antenna, including while sleep rendering is paused.
17
+ - Cancelled pending timers, animations, waiting, and drag feedback on disconnect; reattached avatars start idle with their settings preserved.
18
+
9
19
  ## [0.2.0] - 2026-09-04
10
20
 
11
21
  First stable release of the backward-compatible 0.2 series.
@@ -56,5 +66,6 @@ First public release.
56
66
  - npm-compatible package metadata for later package publication
57
67
  - Contribution guide, issue templates, pull request template, MIT License, and Ko-fi funding metadata
58
68
 
69
+ [0.2.1]: https://github.com/CX-ArtLab/agent-robot-avatar/releases/tag/v0.2.1
59
70
  [0.2.0]: https://github.com/CX-ARTLab/agent-robot-avatar/releases/tag/v0.2.0
60
71
  [0.1.0]: https://github.com/CX-ARTLab/agent-robot-avatar/releases/tag/v0.1.0
package/README.md CHANGED
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Version](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](./LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](./LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  A lightweight, expressive robot avatar Web Component for AI agents and other interactive applications.
14
14
 
15
+ Suitable for AI assistant and agent interfaces, including products and experiences similar to ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI, and OpenCode.
16
+
17
+ It can also be used for desktop pets, virtual pets, desktop companions, digital mascots, chatbot avatars, and other interactive character experiences.
18
+
19
+ Agent Robot Avatar can also be used as a visual feedback layer for AG-UI-style agent interfaces.
20
+
15
21
  Agent Robot Avatar is built with SVG and vanilla JavaScript. It has no third-party animation framework dependency, works as a native custom element, and exposes a compact API for expressions, interaction states, pointer behavior, waiting feedback, and head-shape customization.
16
22
 
17
- **Current public version: v0.2.0**
23
+ **Current public version: v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="./assets/demo/agent-robot-avatar-demo.gif" alt="Agent Robot Avatar interactive animation demo" width="560">
21
27
  </p>
22
28
 
29
+ ## Live Demo
30
+
31
+ Try the interactive demo: [Open Agent Robot Avatar](https://cx-artlab.github.io/agent-robot-avatar/?lang=en)
32
+
23
33
  ## Highlights
24
34
 
25
35
  - Pure SVG + vanilla JavaScript
@@ -75,7 +85,7 @@ avatar.play('success');
75
85
  avatar.play('failure');
76
86
  avatar.play('warning');
77
87
  avatar.play('inspect');
78
- avatar.play('angry');
88
+ avatar.play('blocked');
79
89
  avatar.play('error');
80
90
  ```
81
91
 
@@ -85,6 +95,8 @@ Return to the default idle state:
85
95
  avatar.reset();
86
96
  ```
87
97
 
98
+ `reset()` cancels pending animations and returns to idle. Removing the element also cancels timers, animations, waiting, and drag feedback, without emitting a `face-state` event for cleanup. Reattaching starts from idle and preserves appearance and behavior settings. Cancelled animation promises resolve normally.
99
+
88
100
  ## Actions and states
89
101
 
90
102
  | State | API name | Intended use |
@@ -98,7 +110,7 @@ avatar.reset();
98
110
  | Failure | `failure` | A task completed unsuccessfully |
99
111
  | Warning | `warning` | A risky or destructive action needs confirmation |
100
112
  | Inspect | `inspect` | Reviewing, checking, or verifying a result |
101
- | Blocked | `angry` | A request is blocked, disallowed, or cannot proceed |
113
+ | Blocked | `blocked` | A request is blocked, disallowed, or cannot proceed |
102
114
  | System error | `error` | Connection, service, or system failure |
103
115
  | Surprise | `surprise` | An unexpected event or result |
104
116
  | Sleep | `sleep` | Enter the sleep state |
@@ -113,8 +125,8 @@ avatar.play('failed'); // same as failure
113
125
  avatar.play('fail'); // same as failure
114
126
  avatar.play('verify'); // same as inspect
115
127
  avatar.play('review'); // same as inspect
116
- avatar.play('blocked'); // same as angry
117
- avatar.play('policy-blocked'); // same as angry
128
+ avatar.play('angry'); // same visual expression as blocked
129
+ avatar.play('policy-blocked'); // same as blocked
118
130
  avatar.play('system-error'); // same as error
119
131
  avatar.play('connection-error'); // same as error
120
132
  ```
@@ -269,7 +281,7 @@ Issues and pull requests are welcome. See [`CONTRIBUTING.md`](./CONTRIBUTING.md)
269
281
 
270
282
  ## Project status
271
283
 
272
- v0.1.0 is the first public release line. The public API is intentionally small so it can evolve carefully before a future `1.0.0` stability commitment.
284
+ v0.2.1 is the current public release. v0.1.0 remains available as the first public version. The public API is intentionally small so it can evolve carefully before a future `1.0.0` stability commitment.
273
285
 
274
286
  Agent Robot Avatar is independently developed and is not affiliated with, endorsed by, or representative of any AI platform or brand.
275
287
 
package/docs/README.de.md CHANGED
@@ -6,18 +6,28 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Entwicklungsversion](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  Eine leichte, ausdrucksstarke Roboter-Avatar-Web-Component für KI-Agenten und andere interaktive Anwendungen.
12
12
 
13
+ Geeignet für KI-Assistenten- und Agent-Oberflächen, einschließlich Produkten und Erlebnissen ähnlich wie ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI und OpenCode.
14
+
15
+ Sie kann außerdem für Desktop Pets, virtuelle Haustiere, Desktop-Begleiter, digitale Maskottchen, Chatbot-Avatare und andere interaktive Charaktererlebnisse verwendet werden.
16
+
17
+ Agent Robot Avatar kann außerdem als visuelle Feedback-Ebene für Agent-Oberflächen im AG-UI-Stil eingesetzt werden.
18
+
13
19
  Agent Robot Avatar basiert auf SVG und Vanilla JavaScript und benötigt kein externes Animationsframework. Die Komponente funktioniert als natives Custom Element und stellt eine kompakte API für Ausdrücke, Interaktionszustände, Pointer-Following, Wartefeedback und Kopfform bereit.
14
20
 
15
- **Aktuelle öffentliche Version: v0.2.0**
21
+ **Aktuelle öffentliche Version: v0.2.1**
16
22
 
17
23
  <p align="center">
18
24
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Interaktive animierte Demo von Agent Robot Avatar" width="560">
19
25
  </p>
20
26
 
27
+ ## Live-Demo
28
+
29
+ Interaktive Demo ausprobieren: [Agent Robot Avatar öffnen](https://cx-artlab.github.io/agent-robot-avatar/?lang=de)
30
+
21
31
  ## Highlights
22
32
 
23
33
  - SVG + Vanilla JavaScript
@@ -49,7 +59,7 @@ avatar.play('success');
49
59
  avatar.play('failure');
50
60
  avatar.play('warning');
51
61
  avatar.play('inspect');
52
- avatar.play('angry');
62
+ avatar.play('blocked');
53
63
  avatar.play('error');
54
64
  avatar.reset();
55
65
  ```
@@ -67,7 +77,7 @@ avatar.reset();
67
77
  | Failure | `failure` | Aufgabe wurde erfolglos abgeschlossen |
68
78
  | Warning | `warning` | Eine wichtige Aktion benötigt Bestätigung |
69
79
  | Inspect | `inspect` | Ergebnis prüfen oder verifizieren |
70
- | Blocked | `angry` | Anfrage blockiert oder kann nicht fortgesetzt werden |
80
+ | Blocked | `blocked` | Anfrage blockiert oder kann nicht fortgesetzt werden |
71
81
  | System error | `error` | Verbindungs-, Dienst- oder Systemfehler |
72
82
  | Surprise | `surprise` | Unerwartetes Ereignis oder Ergebnis |
73
83
  | Sleep | `sleep` | Schlafzustand aktivieren |
@@ -75,6 +85,8 @@ avatar.reset();
75
85
 
76
86
  `failure` beschreibt einen Fehlschlag der Aufgabe selbst; `error` ist für Verbindungs-, Dienst- oder Systemprobleme reserviert. `waiting` bezeichnet eine laufende Anfrage, `bored` dagegen Inaktivität.
77
87
 
88
+ `angry` bleibt als kompatibler Name für denselben visuellen Ausdruck wie `blocked` verfügbar.
89
+
78
90
  ```js
79
91
  avatar.startWaiting();
80
92
  avatar.stopWaiting();
@@ -137,7 +149,7 @@ Issues und Pull Requests sind willkommen. Bitte vor Änderungen [`CONTRIBUTING.m
137
149
 
138
150
  ## Projektstatus
139
151
 
140
- v0.1.0 ist die erste öffentliche Release-Linie. Die öffentliche API bleibt bewusst klein, damit sie vor einer späteren Stabilitätszusage mit `1.0.0` sorgfältig weiterentwickelt werden kann.
152
+ v0.2.1 ist die aktuelle öffentliche Version. v0.1.0 bleibt als erste öffentliche Version verfügbar. Die öffentliche API bleibt bewusst klein, damit sie vor einer späteren Stabilitätszusage mit `1.0.0` sorgfältig weiterentwickelt werden kann.
141
153
 
142
154
  Agent Robot Avatar ist ein unabhängig entwickeltes Open-Source-Projekt und steht in keiner offiziellen Verbindung zu einer KI-Plattform oder Marke.
143
155
 
package/docs/README.es.md CHANGED
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Versión de desarrollo](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Versión](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  Un Web Component ligero y expresivo de avatar robótico para agentes de IA y otras aplicaciones interactivas.
14
14
 
15
+ Es adecuado para interfaces de asistentes y agentes de IA, incluidos productos y experiencias similares a ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI y OpenCode.
16
+
17
+ También puede utilizarse para desktop pets, mascotas virtuales, compañeros de escritorio, mascotas digitales, avatares de chatbots y otras experiencias con personajes interactivos.
18
+
19
+ Agent Robot Avatar también puede funcionar como una capa de feedback visual para interfaces de agentes de estilo AG-UI.
20
+
15
21
  Agent Robot Avatar está construido con SVG y JavaScript nativo, sin depender de frameworks de animación de terceros. Funciona como un Custom Element nativo y ofrece una API compacta para expresiones, estados de interacción, seguimiento del puntero, espera y forma de la cabeza.
16
22
 
17
- **Versión pública actual: v0.2.0**
23
+ **Versión pública actual: v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Demostración animada interactiva de Agent Robot Avatar" width="560">
21
27
  </p>
22
28
 
29
+ ## Demo en vivo
30
+
31
+ Prueba la demo interactiva: [Abrir Agent Robot Avatar](https://cx-artlab.github.io/agent-robot-avatar/?lang=es)
32
+
23
33
  ## Características principales
24
34
 
25
35
  - SVG + JavaScript nativo
@@ -57,7 +67,7 @@ avatar.play('success');
57
67
  avatar.play('failure');
58
68
  avatar.play('warning');
59
69
  avatar.play('inspect');
60
- avatar.play('angry');
70
+ avatar.play('blocked');
61
71
  avatar.play('error');
62
72
 
63
73
  avatar.reset();
@@ -76,7 +86,7 @@ avatar.reset();
76
86
  | Failure | `failure` | La tarea terminó sin éxito |
77
87
  | Warning | `warning` | Acción arriesgada o destructiva que requiere confirmación |
78
88
  | Inspect | `inspect` | Revisar, comprobar o verificar un resultado |
79
- | Blocked | `angry` | Solicitud bloqueada o que no puede continuar |
89
+ | Blocked | `blocked` | Solicitud bloqueada o que no puede continuar |
80
90
  | System error | `error` | Error de conexión, servicio o sistema |
81
91
  | Surprise | `surprise` | Resultado o evento inesperado |
82
92
  | Sleep | `sleep` | Entrar en reposo |
@@ -91,7 +101,7 @@ avatar.play('failed');
91
101
  avatar.play('fail');
92
102
  avatar.play('verify');
93
103
  avatar.play('review');
94
- avatar.play('blocked');
104
+ avatar.play('angry'); // misma expresión visual que blocked
95
105
  avatar.play('policy-blocked');
96
106
  avatar.play('system-error');
97
107
  avatar.play('connection-error');
@@ -200,7 +210,7 @@ Se aceptan Issues y Pull Requests. Consulta [`CONTRIBUTING.md`](../CONTRIBUTING.
200
210
 
201
211
  ## Estado del proyecto
202
212
 
203
- v0.1.0 es la primera línea de versión pública. La API pública se mantiene deliberadamente pequeña para poder evolucionar con cuidado antes de un futuro compromiso de estabilidad `1.0.0`.
213
+ v0.2.1 es la versión pública actual. v0.1.0 continúa disponible como la primera versión pública. La API pública se mantiene deliberadamente pequeña para poder evolucionar con cuidado antes de un futuro compromiso de estabilidad `1.0.0`.
204
214
 
205
215
  Agent Robot Avatar es un proyecto independiente de código abierto y no está afiliado, respaldado ni representa a ninguna plataforma o marca de IA.
206
216
 
package/docs/README.fr.md CHANGED
@@ -6,18 +6,28 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Version](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  Un Web Component léger et expressif d’avatar robot pour les agents IA et d’autres applications interactives.
12
12
 
13
+ Il convient aux interfaces d’assistants IA et d’Agents, notamment aux produits et expériences similaires à ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI et OpenCode.
14
+
15
+ Il peut également être utilisé pour les desktop pets, animaux virtuels, compagnons de bureau, mascottes numériques, avatars de chatbots et autres expériences de personnages interactifs.
16
+
17
+ Agent Robot Avatar peut également servir de couche de retour visuel pour les interfaces d’Agents de style AG-UI.
18
+
13
19
  Agent Robot Avatar est construit avec SVG et JavaScript natif, sans framework d’animation tiers. Il fonctionne comme un Custom Element natif et propose une API compacte pour les expressions, les états d’interaction, le suivi du pointeur, l’attente et la forme de la tête.
14
20
 
15
- **Version publique actuelle : v0.2.0**
21
+ **Version publique actuelle : v0.2.1**
16
22
 
17
23
  <p align="center">
18
24
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Démonstration animée interactive d’Agent Robot Avatar" width="560">
19
25
  </p>
20
26
 
27
+ ## Démo en ligne
28
+
29
+ Essayez la démo interactive : [Ouvrir Agent Robot Avatar](https://cx-artlab.github.io/agent-robot-avatar/?lang=fr)
30
+
21
31
  ## Points forts
22
32
 
23
33
  - SVG + JavaScript natif
@@ -55,7 +65,7 @@ avatar.play('success');
55
65
  avatar.play('failure');
56
66
  avatar.play('warning');
57
67
  avatar.play('inspect');
58
- avatar.play('angry');
68
+ avatar.play('blocked');
59
69
  avatar.play('error');
60
70
 
61
71
  avatar.reset();
@@ -74,7 +84,7 @@ avatar.reset();
74
84
  | Failure | `failure` | Tâche terminée sans succès |
75
85
  | Warning | `warning` | Action importante nécessitant confirmation |
76
86
  | Inspect | `inspect` | Examiner, contrôler ou vérifier un résultat |
77
- | Blocked | `angry` | Requête bloquée ou impossible à poursuivre |
87
+ | Blocked | `blocked` | Requête bloquée ou impossible à poursuivre |
78
88
  | System error | `error` | Erreur de connexion, de service ou système |
79
89
  | Surprise | `surprise` | Événement ou résultat inattendu |
80
90
  | Sleep | `sleep` | Entrer en veille |
@@ -89,7 +99,7 @@ avatar.play('failed');
89
99
  avatar.play('fail');
90
100
  avatar.play('verify');
91
101
  avatar.play('review');
92
- avatar.play('blocked');
102
+ avatar.play('angry'); // même expression visuelle que blocked
93
103
  avatar.play('policy-blocked');
94
104
  avatar.play('system-error');
95
105
  avatar.play('connection-error');
@@ -198,7 +208,7 @@ Issues et Pull Requests sont les bienvenus. Consultez [`CONTRIBUTING.md`](../CON
198
208
 
199
209
  ## État du projet
200
210
 
201
- v0.1.0 est la première ligne de version publique. L’API publique reste volontairement limitée afin d’évoluer avec prudence avant un futur engagement de stabilité `1.0.0`.
211
+ v0.2.1 est la version publique actuelle. v0.1.0 reste disponible comme première version publique. L’API publique reste volontairement limitée afin d’évoluer avec prudence avant un futur engagement de stabilité `1.0.0`.
202
212
 
203
213
  Agent Robot Avatar est un projet open source développé indépendamment ; il n’est affilié, approuvé ni représentatif d’aucune plateforme ou marque d’IA.
204
214
 
package/docs/README.ja.md CHANGED
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Version](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  AI エージェントやその他のインタラクティブなアプリケーションで使える、軽量で表情豊かなロボットアバター Web Component です。
14
14
 
15
+ AI アシスタントや Agent のインターフェースに適しており、ChatGPT、Claude、Codex、Cursor、Grok Bot、Gemini CLI、OpenCode に似た製品や体験で利用できます。
16
+
17
+ デスクトップペット、バーチャルペット、デスクトップコンパニオン、デジタルマスコット、チャットボットのアバターなど、さまざまなインタラクティブキャラクター体験にも利用できます。
18
+
19
+ Agent Robot Avatar は、AG-UI スタイルの Agent インターフェースにおける視覚的なフィードバックレイヤーとしても利用できます。
20
+
15
21
  Agent Robot Avatar は SVG と Vanilla JavaScript だけで構築され、サードパーティー製アニメーションフレームワークに依存しません。ネイティブ Custom Element として動作し、表情、状態、ポインター追従、待機フィードバック、頭部形状をシンプルな API で制御できます。
16
22
 
17
- **現在の公開バージョン:v0.2.0**
23
+ **現在の公開バージョン:v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Agent Robot Avatar インタラクティブアニメーションデモ" width="560">
21
27
  </p>
22
28
 
29
+ ## ライブデモ
30
+
31
+ インタラクティブデモを試す:[Agent Robot Avatar を開く](https://cx-artlab.github.io/agent-robot-avatar/?lang=ja)
32
+
23
33
  ## 特長
24
34
 
25
35
  - SVG + Vanilla JavaScript
@@ -57,7 +67,7 @@ avatar.play('success');
57
67
  avatar.play('failure');
58
68
  avatar.play('warning');
59
69
  avatar.play('inspect');
60
- avatar.play('angry');
70
+ avatar.play('blocked');
61
71
  avatar.play('error');
62
72
 
63
73
  avatar.reset();
@@ -76,7 +86,7 @@ avatar.reset();
76
86
  | Failure | `failure` | タスク自体が失敗 |
77
87
  | Warning | `warning` | 危険・破壊的な操作の確認 |
78
88
  | Inspect | `inspect` | 結果の確認・検証 |
79
- | Blocked | `angry` | リクエストが拒否・停止された状態 |
89
+ | Blocked | `blocked` | リクエストが拒否・停止された状態 |
80
90
  | System error | `error` | 接続・サービス・システム障害 |
81
91
  | Surprise | `surprise` | 予期しない結果 |
82
92
  | Sleep | `sleep` | スリープへ移行 |
@@ -91,7 +101,7 @@ avatar.play('failed');
91
101
  avatar.play('fail');
92
102
  avatar.play('verify');
93
103
  avatar.play('review');
94
- avatar.play('blocked');
104
+ avatar.play('angry'); // blocked と同じ表情
95
105
  avatar.play('policy-blocked');
96
106
  avatar.play('system-error');
97
107
  avatar.play('connection-error');
@@ -200,7 +210,7 @@ Issue と Pull Request を歓迎します。提出前に [`CONTRIBUTING.md`](../
200
210
 
201
211
  ## プロジェクトの状態
202
212
 
203
- v0.1.0 は最初の公開リリースラインです。将来の `1.0.0` に向けて慎重に進化できるよう、公開 API は意図的に小さく保っています。
213
+ v0.2.1 は現在の公開バージョンです。v0.1.0 は最初の公開バージョンとして引き続き利用できます。将来の `1.0.0` に向けて慎重に進化できるよう、公開 API は意図的に小さく保っています。
204
214
 
205
215
  Agent Robot Avatar は独立して開発されたオープンソースプロジェクトであり、特定の AI プラットフォームやブランドとは提携・公式承認関係にありません。
206
216
 
package/docs/README.ko.md CHANGED
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![개발 버전](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![버전](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  AI 에이전트와 다양한 인터랙티브 애플리케이션에서 사용할 수 있는 가볍고 표현력 있는 로봇 아바타 Web Component입니다.
14
14
 
15
+ ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI, OpenCode와 유사한 제품과 경험을 포함해 AI 어시스턴트 및 Agent 인터페이스에 적합합니다.
16
+
17
+ 데스크톱 펫, 가상 펫, 데스크톱 컴패니언, 디지털 마스코트, 챗봇 아바타 및 기타 인터랙티브 캐릭터 경험에도 사용할 수 있습니다.
18
+
19
+ Agent Robot Avatar는 AG-UI 스타일 Agent 인터페이스의 시각적 피드백 레이어로도 사용할 수 있습니다.
20
+
15
21
  Agent Robot Avatar는 SVG와 Vanilla JavaScript로만 구성되어 있으며 타사 애니메이션 프레임워크에 의존하지 않습니다. 네이티브 Custom Element로 동작하고 표정, 상호작용 상태, 포인터 추적, 대기 피드백, 머리 형태를 제어하는 간결한 API를 제공합니다.
16
22
 
17
- **현재 공개 버전: v0.2.0**
23
+ **현재 공개 버전: v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Agent Robot Avatar 인터랙티브 애니메이션 데모" width="560">
21
27
  </p>
22
28
 
29
+ ## 라이브 데모
30
+
31
+ 인터랙티브 데모 체험: [Agent Robot Avatar 열기](https://cx-artlab.github.io/agent-robot-avatar/?lang=ko)
32
+
23
33
  ## 주요 특징
24
34
 
25
35
  - 순수 SVG + Vanilla JavaScript
@@ -57,7 +67,7 @@ avatar.play('success');
57
67
  avatar.play('failure');
58
68
  avatar.play('warning');
59
69
  avatar.play('inspect');
60
- avatar.play('angry');
70
+ avatar.play('blocked');
61
71
  avatar.play('error');
62
72
 
63
73
  avatar.reset();
@@ -76,7 +86,7 @@ avatar.reset();
76
86
  | Failure | `failure` | 작업 결과 실패 |
77
87
  | Warning | `warning` | 위험하거나 파괴적인 동작 확인 |
78
88
  | Inspect | `inspect` | 결과 검토 / 확인 / 검증 |
79
- | Blocked | `angry` | 요청이 차단되거나 진행 불가 |
89
+ | Blocked | `blocked` | 요청이 차단되거나 진행 불가 |
80
90
  | System error | `error` | 연결, 서비스 또는 시스템 오류 |
81
91
  | Surprise | `surprise` | 예상하지 못한 결과 |
82
92
  | Sleep | `sleep` | 수면 상태 진입 |
@@ -91,7 +101,7 @@ avatar.play('failed');
91
101
  avatar.play('fail');
92
102
  avatar.play('verify');
93
103
  avatar.play('review');
94
- avatar.play('blocked');
104
+ avatar.play('angry'); // blocked와 동일한 표정
95
105
  avatar.play('policy-blocked');
96
106
  avatar.play('system-error');
97
107
  avatar.play('connection-error');
@@ -200,7 +210,7 @@ Issue와 Pull Request를 환영합니다. 제출 전 [`CONTRIBUTING.md`](../CONT
200
210
 
201
211
  ## 프로젝트 상태
202
212
 
203
- v0.1.0은 첫 공개 릴리스 라인입니다. 향후 `1.0.0` 안정성 약속 이전에 신중하게 발전시킬 수 있도록 공개 API를 의도적으로 작게 유지하고 있습니다.
213
+ v0.2.1은 현재 공개 버전입니다. v0.1.0은 첫 공개 버전으로 계속 제공됩니다. 향후 `1.0.0` 안정성 약속 이전에 신중하게 발전시킬 수 있도록 공개 API를 의도적으로 작게 유지하고 있습니다.
204
214
 
205
215
  Agent Robot Avatar는 독립적으로 개발된 오픈 소스 프로젝트이며 특정 AI 플랫폼이나 브랜드와 제휴하거나 공식 승인을 받은 프로젝트가 아닙니다.
206
216
 
package/docs/README.pt.md CHANGED
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Versão de desenvolvimento](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Versão](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  Um Web Component leve e expressivo de avatar robótico para agentes de IA e outras aplicações interativas.
14
14
 
15
+ É adequado para interfaces de assistentes e agentes de IA, incluindo produtos e experiências semelhantes a ChatGPT, Claude, Codex, Cursor, Grok Bot, Gemini CLI e OpenCode.
16
+
17
+ Também pode ser usado em desktop pets, pets virtuais, companheiros de desktop, mascotes digitais, avatares de chatbot e outras experiências com personagens interativos.
18
+
19
+ Agent Robot Avatar também pode funcionar como uma camada de feedback visual para interfaces de agentes no estilo AG-UI.
20
+
15
21
  Agent Robot Avatar é construído com SVG e JavaScript puro, sem dependência de frameworks de animação de terceiros. Funciona como um Custom Element nativo e oferece uma API compacta para expressões, estados de interação, seguimento do ponteiro, feedback de espera e formato da cabeça.
16
22
 
17
- **Versão pública atual: v0.2.0**
23
+ **Versão pública atual: v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Demonstração animada interativa do Agent Robot Avatar" width="560">
21
27
  </p>
22
28
 
29
+ ## Demo ao vivo
30
+
31
+ Experimente a demo interativa: [Abrir Agent Robot Avatar](https://cx-artlab.github.io/agent-robot-avatar/?lang=pt)
32
+
23
33
  ## Principais recursos
24
34
 
25
35
  - SVG + JavaScript puro
@@ -57,7 +67,7 @@ avatar.play('success');
57
67
  avatar.play('failure');
58
68
  avatar.play('warning');
59
69
  avatar.play('inspect');
60
- avatar.play('angry');
70
+ avatar.play('blocked');
61
71
  avatar.play('error');
62
72
 
63
73
  avatar.reset();
@@ -76,7 +86,7 @@ avatar.reset();
76
86
  | Failure | `failure` | Tarefa concluída sem sucesso |
77
87
  | Warning | `warning` | Ação arriscada ou destrutiva exige confirmação |
78
88
  | Inspect | `inspect` | Revisar, conferir ou verificar um resultado |
79
- | Blocked | `angry` | Solicitação bloqueada ou impossibilitada de continuar |
89
+ | Blocked | `blocked` | Solicitação bloqueada ou impossibilitada de continuar |
80
90
  | System error | `error` | Falha de conexão, serviço ou sistema |
81
91
  | Surprise | `surprise` | Evento ou resultado inesperado |
82
92
  | Sleep | `sleep` | Entrar em repouso |
@@ -91,7 +101,7 @@ avatar.play('failed');
91
101
  avatar.play('fail');
92
102
  avatar.play('verify');
93
103
  avatar.play('review');
94
- avatar.play('blocked');
104
+ avatar.play('angry'); // mesma expressão visual de blocked
95
105
  avatar.play('policy-blocked');
96
106
  avatar.play('system-error');
97
107
  avatar.play('connection-error');
@@ -200,7 +210,7 @@ Issues e Pull Requests são bem-vindos. Leia [`CONTRIBUTING.md`](../CONTRIBUTING
200
210
 
201
211
  ## Status do projeto
202
212
 
203
- v0.1.0 é a primeira linha de lançamento público. A API pública é mantida deliberadamente pequena para evoluir com cuidado antes de um futuro compromisso de estabilidade `1.0.0`.
213
+ v0.2.1 é a versão pública atual. v0.1.0 continua disponível como a primeira versão pública. A API pública é mantida deliberadamente pequena para evoluir com cuidado antes de um futuro compromisso de estabilidade `1.0.0`.
204
214
 
205
215
  Agent Robot Avatar é um projeto independente de código aberto e não é afiliado, endossado nem representa nenhuma plataforma ou marca de IA.
206
216
 
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Version](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  一个轻量、富有表现力的机器人头像 Web Component,可用于 AI Agent,也可用于其他需要交互反馈的应用。
14
14
 
15
+ 适用于 AI 助手和 Agent 交互界面,包括与 ChatGPT、Claude、Codex、Cursor、Grok Bot、Gemini CLI 和 OpenCode 类似的产品与使用场景。
16
+
17
+ 它也可用于桌面宠物、虚拟宠物、桌面伙伴、数字吉祥物、聊天机器人头像以及其他互动角色体验。
18
+
19
+ Agent Robot Avatar 也可作为 AG-UI 类 Agent 界面的视觉反馈层。
20
+
15
21
  Agent Robot Avatar 基于 SVG 与原生 JavaScript 构建,不依赖第三方动画框架。它作为原生自定义元素工作,并提供一组尽量精简的 API,用于控制表情、交互状态、鼠标跟随、等待反馈和头部造型。
16
22
 
17
- **当前公开版本:v0.2.0**
23
+ **当前公开版本:v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Agent Robot Avatar 交互动画演示" width="560">
21
27
  </p>
22
28
 
29
+ ## 在线演示
30
+
31
+ 直接体验交互效果:[打开 Agent Robot Avatar 在线演示](https://cx-artlab.github.io/agent-robot-avatar/?lang=zh-CN)
32
+
23
33
  ## 主要特点
24
34
 
25
35
  - 纯 SVG + 原生 JavaScript
@@ -75,7 +85,7 @@ avatar.play('success');
75
85
  avatar.play('failure');
76
86
  avatar.play('warning');
77
87
  avatar.play('inspect');
78
- avatar.play('angry');
88
+ avatar.play('blocked');
79
89
  avatar.play('error');
80
90
  ```
81
91
 
@@ -85,6 +95,8 @@ avatar.play('error');
85
95
  avatar.reset();
86
96
  ```
87
97
 
98
+ `reset()` 会取消待完成的动画并恢复待机。移除元素也会取消计时器、动画、等待和拖拽反馈,清理过程不会触发 `face-state` 事件。重新挂载后从待机开始,并保留外观和行为设置。被取消的动画 Promise 会正常完成。
99
+
88
100
  ## 状态与表情
89
101
 
90
102
  | 状态 | API 名称 | 典型用途 |
@@ -98,7 +110,7 @@ avatar.reset();
98
110
  | 失败 | `failure` | 任务执行完成,但结果失败 |
99
111
  | 警告确认 | `warning` | 高风险、覆盖、删除等操作需要再次确认 |
100
112
  | 审视 | `inspect` | 检查、核对或验证结果 |
101
- | 内容阻止 | `angry` | 请求被阻止、不允许执行或无法继续 |
113
+ | 内容阻止 | `blocked` | 请求被阻止、不允许执行或无法继续 |
102
114
  | 系统错误 | `error` | 网络、服务或系统本身发生错误 |
103
115
  | 惊讶 | `surprise` | 出现意外事件或结果 |
104
116
  | 睡眠 | `sleep` | 进入睡眠状态 |
@@ -113,8 +125,8 @@ avatar.play('failed'); // 等同 failure
113
125
  avatar.play('fail'); // 等同 failure
114
126
  avatar.play('verify'); // 等同 inspect
115
127
  avatar.play('review'); // 等同 inspect
116
- avatar.play('blocked'); // 等同 angry
117
- avatar.play('policy-blocked'); // 等同 angry
128
+ avatar.play('angry'); // 与 blocked 使用相同表情
129
+ avatar.play('policy-blocked'); // 等同 blocked
118
130
  avatar.play('system-error'); // 等同 error
119
131
  avatar.play('connection-error'); // 等同 error
120
132
  ```
@@ -269,7 +281,7 @@ Agent Robot Avatar 面向支持 ES Modules、Custom Elements、SVG、Pointer Eve
269
281
 
270
282
  ## 项目状态
271
283
 
272
- v0.1.0 是首个公开版本线。当前刻意保持较小的公开 API,以便在未来 `1.0.0` 稳定性承诺之前继续谨慎演进。
284
+ v0.2.1 是当前公开版本。v0.1.0 作为首个公开版本继续保留。当前刻意保持较小的公开 API,以便在未来 `1.0.0` 稳定性承诺之前继续谨慎演进。
273
285
 
274
286
  Agent Robot Avatar 为独立开发的开源项目,不隶属于、代表或获得任何 AI 平台或品牌的官方背书。
275
287
 
@@ -6,20 +6,30 @@
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) | [繁體中文](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.zh-TW.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) | [Español](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.es.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) | [Français](https://github.com/CX-ArtLab/agent-robot-avatar/blob/main/docs/README.fr.md)
8
8
 
9
- ![Version](https://img.shields.io/badge/version-v0.2.0-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
9
+ ![Version](https://img.shields.io/badge/version-v0.2.1-111111?style=flat-square) [![License](https://img.shields.io/badge/license-MIT-0A7EA4?style=flat-square)](../LICENSE) [![CI](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml/badge.svg?branch=main)](https://github.com/CX-ArtLab/agent-robot-avatar/actions/workflows/validate.yml) [![Ko-fi](https://img.shields.io/badge/Ko--fi-Support-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white)](https://ko-fi.com/P0E625WIOI)
10
10
 
11
11
  ![Vanilla JavaScript](https://img.shields.io/badge/Vanilla-JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=000) ![Web Component](https://img.shields.io/badge/Web-Native%20Component-5A67D8?style=flat-square) ![SVG](https://img.shields.io/badge/Rendering-SVG-FFB13B?style=flat-square&logo=svg&logoColor=000) ![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-2EA44F?style=flat-square) ![14 Agent States](https://img.shields.io/badge/Agent%20states-14-8B5CF6?style=flat-square) ![Pointer Following](https://img.shields.io/badge/Pointer-following-00A67E?style=flat-square) ![Jelly Drag](https://img.shields.io/badge/Drag-jelly%20physics-FF69B4?style=flat-square)
12
12
 
13
13
  一個輕量、富有表現力的機器人頭像 Web Component,可用於 AI Agent,也可用於其他需要互動回饋的應用。
14
14
 
15
+ 適用於 AI 助理與 Agent 互動介面,包括與 ChatGPT、Claude、Codex、Cursor、Grok Bot、Gemini CLI 和 OpenCode 類似的產品與使用情境。
16
+
17
+ 也可用於桌面寵物、虛擬寵物、桌面夥伴、數位吉祥物、聊天機器人頭像,以及其他互動角色體驗。
18
+
19
+ Agent Robot Avatar 也可作為 AG-UI 類 Agent 介面的視覺回饋層。
20
+
15
21
  Agent Robot Avatar 以 SVG 與原生 JavaScript 建構,不依賴第三方動畫框架。它作為原生自訂元素運作,並提供精簡 API 來控制表情、互動狀態、指標跟隨、等待回饋與頭部造型。
16
22
 
17
- **目前公開版本:v0.2.0**
23
+ **目前公開版本:v0.2.1**
18
24
 
19
25
  <p align="center">
20
26
  <img src="../assets/demo/agent-robot-avatar-demo.gif" alt="Agent Robot Avatar 互動動畫展示" width="560">
21
27
  </p>
22
28
 
29
+ ## 線上展示
30
+
31
+ 直接體驗互動效果:[開啟 Agent Robot Avatar 線上展示](https://cx-artlab.github.io/agent-robot-avatar/?lang=zh-TW)
32
+
23
33
  ## 主要特色
24
34
 
25
35
  - 純 SVG + 原生 JavaScript
@@ -59,7 +69,7 @@ avatar.play('success');
59
69
  avatar.play('failure');
60
70
  avatar.play('warning');
61
71
  avatar.play('inspect');
62
- avatar.play('angry');
72
+ avatar.play('blocked');
63
73
  avatar.play('error');
64
74
 
65
75
  avatar.reset();
@@ -78,7 +88,7 @@ avatar.reset();
78
88
  | 失敗 | `failure` | 任務完成,但結果失敗 |
79
89
  | 警告確認 | `warning` | 高風險或破壞性操作需要確認 |
80
90
  | 審視 | `inspect` | 檢查、核對或驗證結果 |
81
- | 內容阻止 | `angry` | 請求被阻止、不允許或無法繼續 |
91
+ | 內容阻止 | `blocked` | 請求被阻止、不允許或無法繼續 |
82
92
  | 系統錯誤 | `error` | 連線、服務或系統錯誤 |
83
93
  | 驚訝 | `surprise` | 意外事件或結果 |
84
94
  | 睡眠 | `sleep` | 進入睡眠 |
@@ -93,7 +103,7 @@ avatar.play('failed');
93
103
  avatar.play('fail');
94
104
  avatar.play('verify');
95
105
  avatar.play('review');
96
- avatar.play('blocked');
106
+ avatar.play('angry'); // 與 blocked 使用相同表情
97
107
  avatar.play('policy-blocked');
98
108
  avatar.play('system-error');
99
109
  avatar.play('connection-error');
@@ -202,7 +212,7 @@ LICENSE MIT License
202
212
 
203
213
  ## 專案狀態
204
214
 
205
- v0.1.0 是第一個公開版本線。公開 API 目前刻意保持精簡,讓專案能在未來 `1.0.0` 穩定性承諾前持續謹慎演進。
215
+ v0.2.1 是目前的公開版本。v0.1.0 作為第一個公開版本繼續保留。公開 API 目前刻意保持精簡,讓專案能在未來 `1.0.0` 穩定性承諾前持續謹慎演進。
206
216
 
207
217
  Agent Robot Avatar 是獨立開發的開源專案,不隸屬、代表或獲得任何 AI 平台或品牌的官方背書。
208
218
 
@@ -216,4 +226,4 @@ MIT License。詳見 [`LICENSE`](../LICENSE)。
216
226
 
217
227
  | Ko-fi | 支付寶 | 微信支付 |
218
228
  | --- | --- | --- |
219
- | <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> | <img src="../assets/support/alipay.png" alt="支付寶收款碼" width="160"> | <img src="../assets/support/wechat-pay.png" alt="微信支付收款碼" width="160"> |
229
+ | <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> | <img src="../assets/support/alipay.png" alt="支付寶收款碼" width="160"> | <img src="../assets/support/wechat-pay.png" alt="WeChat Pay QR code" width="160"> |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-robot-avatar",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
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",
@@ -19,8 +19,9 @@
19
19
  "sideEffects": true,
20
20
  "scripts": {
21
21
  "dev": "node scripts/serve.mjs",
22
+ "build:pages": "node scripts/build-pages.mjs",
22
23
  "check": "node scripts/check-source.mjs",
23
- "test": "npm run check && npm run test:types && npm run test:release && npm run test:package && npm run test:browser",
24
+ "test": "npm run check && npm run test:types && npm run test:release && npm run test:package && npm run test:browser && npm run build:pages",
24
25
  "release:check": "npm test && npm publish --dry-run --ignore-scripts --tag latest",
25
26
  "prepublishOnly": "npm test && node scripts/check-publish-tag.mjs",
26
27
  "test:types": "tsc -p tsconfig.types.json",
@@ -204,13 +204,16 @@ proto.error = async function() {
204
204
 
205
205
  centerHeadTransform(this);
206
206
  if (this._headMotion?.animate) {
207
+ const animationToken = this._transitionToken;
207
208
  const anim = this._headMotion.animate([
208
209
  { transform: 'translateX(0px)', offset: 0, easing: 'cubic-bezier(.38,0,.28,1)' },
209
210
  { transform: 'translateX(-4px)', offset: 0.34, easing: 'cubic-bezier(.35,0,.22,1)' },
210
211
  { transform: 'translateX(4px)', offset: 0.72, easing: 'cubic-bezier(.35,0,.22,1)' },
211
212
  { transform: 'translateX(0px)', offset: 1 }
212
213
  ], { duration: headDuration, easing: 'linear', fill: 'forwards' });
213
- anim.onfinish = () => { this._headMotion.style.transform = 'translateX(0px)'; };
214
+ anim.onfinish = () => {
215
+ if (animationToken === this._transitionToken) this._headMotion.style.transform = 'translateX(0px)';
216
+ };
214
217
  }
215
218
 
216
219
  await this._wait(headDuration + 40);
@@ -235,6 +238,7 @@ proto.warning = async function() {
235
238
 
236
239
  centerHeadTransform(this);
237
240
  if (this._headMotion?.animate) {
241
+ const animationToken = this._transitionToken;
238
242
  const anim = this._headMotion.animate([
239
243
  { transform: 'translateY(0px)', offset: 0 },
240
244
  { transform: 'translateY(0px)', offset: WARNING_PHASES.w5Start / duration, easing: 'cubic-bezier(.38,0,.25,1)' },
@@ -245,7 +249,9 @@ proto.warning = async function() {
245
249
  { transform: 'translateY(0px)', offset: WARNING_PHASES.w7End / duration },
246
250
  { transform: 'translateY(0px)', offset: 1 }
247
251
  ], { duration, easing: 'linear', fill: 'forwards' });
248
- anim.onfinish = () => { this._headMotion.style.transform = 'translateY(0px)'; };
252
+ anim.onfinish = () => {
253
+ if (animationToken === this._transitionToken) this._headMotion.style.transform = 'translateY(0px)';
254
+ };
249
255
  }
250
256
 
251
257
  await this._wait(duration + 40);
@@ -142,6 +142,7 @@ const AgentRobotAvatar = (() => {
142
142
  this._inputWanted = false;
143
143
  this._sleeping = false;
144
144
  this._idleTimer = null;
145
+ this._pendingWaits = new Map();
145
146
  this._boredRoutine = null;
146
147
  this._boredLookSpeed = null;
147
148
  this._autoSleepMs = Number(this.getAttribute('auto-sleep')) || 0;
@@ -169,6 +170,7 @@ const AgentRobotAvatar = (() => {
169
170
  this.addEventListener('pointerdown', this._boundDragStart);
170
171
  this.addEventListener('click', this._boundClickCapture, true);
171
172
  this._running = !document.hidden;
173
+ this._lastActivity = performance.now();
172
174
  this._resumeFrames();
173
175
  }
174
176
 
@@ -176,6 +178,20 @@ const AgentRobotAvatar = (() => {
176
178
  unregisterConnectedFace(this);
177
179
  this.removeEventListener('pointerdown', this._boundDragStart);
178
180
  this.removeEventListener('click', this._boundClickCapture, true);
181
+ // Removal cancels work; reattachment starts idle with appearance settings intact.
182
+ this._resetToIdle(false);
183
+ this._blinkAnim = null;
184
+ this._blink = 1;
185
+ this._pointer.active = false;
186
+ this._pointer.influence = 0;
187
+ const drag = this._dragJelly;
188
+ if (drag.pointerId != null) {
189
+ try { this.releasePointerCapture(drag.pointerId); } catch (_) {}
190
+ }
191
+ drag.active = false;
192
+ drag.pointerId = null;
193
+ this._finishDragReturn(null);
194
+ this._suppressClick = false;
179
195
  this._running = false;
180
196
  cancelAnimationFrame(this._raf);
181
197
  this._raf = 0;
@@ -184,11 +200,18 @@ const AgentRobotAvatar = (() => {
184
200
  static get observedAttributes() { return ['color','size','auto-sleep']; }
185
201
  attributeChangedCallback(name, oldV, newV) {
186
202
  if (oldV === newV) return;
187
- if (name === 'color' && this._head) this._head.setAttribute('fill', newV || '#08090b');
203
+ if (name === 'color') this._applyColor(newV);
188
204
  if (name === 'size') this.style.setProperty('--face-size', `${Number(newV)||112}px`);
189
205
  if (name === 'auto-sleep') this._autoSleepMs = Number(newV) || 0;
190
206
  }
191
207
 
208
+ _applyColor(value) {
209
+ const color = value || '#08090b';
210
+ for (const part of [this._head, this._leftTop, this._rightTop, this._leftBottom, this._rightBottom, this._antennaDot]) {
211
+ if (part) part.setAttribute('fill', color);
212
+ }
213
+ }
214
+
192
215
  _renderShell() {
193
216
  this.shadowRoot.innerHTML = `
194
217
  <style>
@@ -246,10 +269,7 @@ const AgentRobotAvatar = (() => {
246
269
  this._rightTop = this.shadowRoot.getElementById('rightTop');
247
270
  this._leftBottom = this.shadowRoot.getElementById('leftBottom');
248
271
  this._rightBottom = this.shadowRoot.getElementById('rightBottom');
249
- const c = this.getAttribute('color') || '#08090b';
250
- this._head.setAttribute('fill', c);
251
- [this._leftTop,this._rightTop,this._leftBottom,this._rightBottom].forEach(el=>el.setAttribute('fill',c));
252
- this.style.setProperty('--face-size', `${Number(this.getAttribute('size'))||112}px`);
272
+ this._applyColor(this.getAttribute('color'));
253
273
  this._baseHeadPathD = this._headShape.getAttribute('d');
254
274
  this._baseHeadPoints = this._parseHeadPoints(this._baseHeadPathD);
255
275
  }
@@ -511,8 +531,14 @@ const AgentRobotAvatar = (() => {
511
531
  }
512
532
 
513
533
  reset() {
534
+ return this._resetToIdle();
535
+ }
536
+
537
+ _resetToIdle(notify = true) {
538
+ this._resetExtensionEffects?.();
514
539
  this._inputWanted = false;
515
540
  ++this._transitionToken;
541
+ this._cancelPendingWaits();
516
542
  this._boredRoutine = null;
517
543
  this._boredLookSpeed = null;
518
544
  this._sleeping = false;
@@ -520,7 +546,7 @@ const AgentRobotAvatar = (() => {
520
546
  this._eyeBob = null;
521
547
  this._angryEyeDrop = null;
522
548
  this._surpriseShake = null;
523
- this.setState('idle');
549
+ this.setState('idle', { notify, duration: notify ? 320 : 0 });
524
550
  return this;
525
551
  }
526
552
 
@@ -531,7 +557,7 @@ const AgentRobotAvatar = (() => {
531
557
  this._sleeping = name === 'sleep';
532
558
  if (name === 'idle' && !opts.keepGazeLock) this._releaseExpressionLock();
533
559
  this._startMorph(POSES[name], opts.duration ?? (name==='surprise'?170:320), opts.ease || EASE.outQuint);
534
- this.dispatchEvent(new CustomEvent('face-state', {detail:{state:name}}));
560
+ if (opts.notify !== false) this.dispatchEvent(new CustomEvent('face-state', {detail:{state:name}}));
535
561
  return this;
536
562
  }
537
563
 
@@ -559,6 +585,7 @@ const AgentRobotAvatar = (() => {
559
585
  } else {
560
586
  if (!(await this._prepareExpression({normalizePose:true, duration:180, pause:320}))) return;
561
587
  }
588
+ const token = this._transitionToken;
562
589
  this.setState('happy', {duration: fromDrag ? 180 : 220, keepGazeLock:true});
563
590
  this._eyeBob = {start: performance.now(), duration: 620, amp: 8};
564
591
  this._animateHead([
@@ -567,6 +594,7 @@ const AgentRobotAvatar = (() => {
567
594
  {transform:'translateY(0px)'}
568
595
  ], 760);
569
596
  await this._wait(980);
597
+ if (token !== this._transitionToken) return;
570
598
  this._eyeBob = null;
571
599
  if (this._state==='happy') await this._returnToIdle(520);
572
600
  }
@@ -575,6 +603,7 @@ const AgentRobotAvatar = (() => {
575
603
  this.noteActivity();
576
604
  this._inputWanted = false;
577
605
  if (!(await this._prepareExpression({normalizePose:true, duration:180, pause:320}))) return;
606
+ const token = this._transitionToken;
578
607
  this.setState('sad', {duration:320, keepGazeLock:true});
579
608
  this._eyeBob = {start: performance.now(), duration: 700, amp: 7};
580
609
  this._animateHead([
@@ -583,6 +612,7 @@ const AgentRobotAvatar = (() => {
583
612
  {transform:'translateY(0px)'}
584
613
  ], 820);
585
614
  await this._wait(1180);
615
+ if (token !== this._transitionToken) return;
586
616
  this._eyeBob = null;
587
617
  if (this._state==='sad') {
588
618
  await this._returnToIdle(560);
@@ -605,6 +635,7 @@ const AgentRobotAvatar = (() => {
605
635
  } else {
606
636
  if (!(await this._prepareExpression({normalizePose:true, duration:180, pause:320}))) return;
607
637
  }
638
+ const token = this._transitionToken;
608
639
  this.setState('angry', {duration: fromDrag ? 180 : 280, keepGazeLock:true});
609
640
  this._angryEyeDrop = {start: performance.now(), duration:680, amount:4.8};
610
641
  this._animateHead([
@@ -613,6 +644,7 @@ const AgentRobotAvatar = (() => {
613
644
  {transform:'translateY(0px)'}
614
645
  ], 820);
615
646
  await this._wait(980);
647
+ if (token !== this._transitionToken) return;
616
648
  this._angryEyeDrop = null;
617
649
  if (this._state==='angry') await this._returnToIdle(500);
618
650
  }
@@ -621,17 +653,19 @@ const AgentRobotAvatar = (() => {
621
653
  this.noteActivity();
622
654
  this._inputWanted = false;
623
655
  if (!(await this._prepareExpression({normalizePose:true, duration:180, pause:320}))) return;
656
+ const token = this._transitionToken;
624
657
  this._surpriseShake = null;
625
658
  const pre = {...POSES.idle, w:34, h:36, rx:18};
626
659
  this._startMorph(pre, 235, EASE.inOutCubic);
627
660
  await this._wait(235);
628
- if (this._state!=='idle') return;
661
+ if (token !== this._transitionToken || this._state!=='idle') return;
629
662
  this.setState('surprise', {duration:175, ease:EASE.outQuint, keepGazeLock:true});
630
663
  this._animateHead([{transform:'scale(1)'},{transform:'scale(1.035)'}], 175);
631
664
  await this._wait(175);
632
- if (this._state!=='surprise') return;
665
+ if (token !== this._transitionToken || this._state!=='surprise') return;
633
666
  this._surpriseShake = {start: performance.now(), duration:420};
634
667
  await this._wait(420);
668
+ if (token !== this._transitionToken) return;
635
669
  this._surpriseShake = null;
636
670
  if (this._state==='surprise') {
637
671
  this._animateHead([{transform:'scale(1.035)'},{transform:'scale(1)'}], 430);
@@ -643,6 +677,7 @@ const AgentRobotAvatar = (() => {
643
677
  this.noteActivity();
644
678
  this._inputWanted = false;
645
679
  if (!(await this._prepareExpression({normalizePose:true, duration:180, pause:320}))) return;
680
+ const token = this._transitionToken;
646
681
  this._eyeNod = {start: performance.now(), duration: 760};
647
682
  this._animateHead([
648
683
  {transform:'translateY(0px)'},
@@ -650,6 +685,7 @@ const AgentRobotAvatar = (() => {
650
685
  {transform:'translateY(0px)'}
651
686
  ], 920);
652
687
  await this._wait(860);
688
+ if (token !== this._transitionToken) return;
653
689
  this._eyeNod = null;
654
690
  this._releaseExpressionLock();
655
691
  }
@@ -657,21 +693,22 @@ const AgentRobotAvatar = (() => {
657
693
  async sleep() {
658
694
  if (this._sleeping) return;
659
695
  if (!(await this._prepareExpression({normalizePose:true, duration:160}))) return;
696
+ const token = this._transitionToken;
660
697
  this._blinkAnim = null;
661
698
  this._blink = 1;
662
699
  this._nextBlinkAt = performance.now() + 10000;
663
700
  this.setState('sleepy', {duration:940, ease:EASE.inOutCubic, keepGazeLock:true});
664
701
  await this._wait(980);
665
- if (this._state !== 'sleepy') return;
702
+ if (token !== this._transitionToken || this._state !== 'sleepy') return;
666
703
  const reopen = {...POSES.idle, topY:-22, bottomY:36};
667
704
  this._startMorph(reopen, 105, EASE.outQuint);
668
705
  await this._wait(120);
669
- if (this._state !== 'sleepy') return;
706
+ if (token !== this._transitionToken || this._state !== 'sleepy') return;
670
707
  this.setState('sleepy', {duration:820, ease:EASE.inOutCubic, keepGazeLock:true});
671
708
  await this._wait(870);
672
- if (this._state !== 'sleepy') return;
709
+ if (token !== this._transitionToken || this._state !== 'sleepy') return;
673
710
  await this._wait(120);
674
- if (this._state !== 'sleepy') return;
711
+ if (token !== this._transitionToken || this._state !== 'sleepy') return;
675
712
  this._animateHead([{transform:'translateY(0)'},{transform:'translateY(4px)'}],980);
676
713
  this._startMorph(POSES.sleep, 980, EASE.inOutCubic);
677
714
  this._state = 'sleep';
@@ -682,6 +719,7 @@ const AgentRobotAvatar = (() => {
682
719
 
683
720
  async wake() {
684
721
  if (!this._sleeping && this._state!=='sleep') return;
722
+ const token = ++this._transitionToken;
685
723
  this._expressionLock = true;
686
724
  this._sleeping = false;
687
725
  this._animateHead([
@@ -691,9 +729,12 @@ const AgentRobotAvatar = (() => {
691
729
  ], 500);
692
730
  this.setState('sleepy', {duration:240, keepGazeLock:true});
693
731
  await this._wait(260);
732
+ if (token !== this._transitionToken) return;
694
733
  this.setState('surprise', {duration:120, keepGazeLock:true});
695
734
  await this._wait(190);
735
+ if (token !== this._transitionToken) return;
696
736
  await this._returnToIdle(300);
737
+ if (token !== this._transitionToken) return;
697
738
  this._lastActivity = performance.now();
698
739
  }
699
740
 
@@ -715,18 +756,40 @@ const AgentRobotAvatar = (() => {
715
756
 
716
757
  _animateHead(frames, duration) {
717
758
  if (!this._headMotion.animate) return;
759
+ const token = this._transitionToken;
718
760
  const anim = this._headMotion.animate(frames, {duration, easing:'cubic-bezier(.16,1,.3,1)', fill:'forwards'});
719
- anim.onfinish = () => { this._headMotion.style.transform = frames[frames.length-1].transform || ''; };
761
+ anim.onfinish = () => {
762
+ if (token === this._transitionToken) {
763
+ this._headMotion.style.transform = frames[frames.length-1].transform || '';
764
+ }
765
+ };
720
766
  return anim;
721
767
  }
722
768
 
723
- _wait(ms) { return new Promise(r=>setTimeout(r,ms)); }
769
+ _wait(ms) {
770
+ return new Promise(resolve => {
771
+ const timer = setTimeout(() => {
772
+ this._pendingWaits.delete(timer);
773
+ resolve();
774
+ }, ms);
775
+ this._pendingWaits.set(timer, resolve);
776
+ });
777
+ }
778
+
779
+ _cancelPendingWaits() {
780
+ for (const [timer, resolve] of this._pendingWaits) {
781
+ clearTimeout(timer);
782
+ resolve();
783
+ }
784
+ this._pendingWaits.clear();
785
+ }
724
786
 
725
787
  async _returnToIdle(duration=320, ease=EASE.outQuint) {
788
+ const token = this._transitionToken;
726
789
  this.setState('idle', {duration, ease, keepGazeLock:true});
727
790
  this._headCenteringUntil = Math.max(this._headCenteringUntil || 0, performance.now() + duration);
728
791
  await this._wait(duration);
729
- if (this._state === 'idle') this._releaseExpressionLock();
792
+ if (token === this._transitionToken && this._state === 'idle') this._releaseExpressionLock();
730
793
  }
731
794
 
732
795
  async _prepareExpression({normalizePose=true, duration=180, pause=320}={}) {
@@ -848,7 +911,7 @@ const AgentRobotAvatar = (() => {
848
911
  }
849
912
 
850
913
  _autoSleep(now) {
851
- if (!this._autoSleepMs || this._sleeping || ['input','happy','sad','surprise'].includes(this._state)) return;
914
+ if (!this._autoSleepMs || this._sleeping || this._expressionLock || ['input','happy','sad','surprise'].includes(this._state)) return;
852
915
  if (now - this._lastActivity > this._autoSleepMs) this.sleep();
853
916
  }
854
917
 
@@ -58,9 +58,14 @@ proto.play = function(name) {
58
58
  return result;
59
59
  };
60
60
 
61
+ // Called dynamically by core reset and disconnect; custom-element lifecycle
62
+ // callbacks themselves were already registered before extensions loaded.
63
+ proto._resetExtensionEffects = function() {
64
+ for (const hook of resetHooks) hook.call(this);
65
+ };
66
+
61
67
  proto.reset = function() {
62
68
  this._resumeFrames?.();
63
- for (const hook of resetHooks) hook.call(this);
64
69
  return baseReset.call(this);
65
70
  };
66
71
 
@@ -13,6 +13,7 @@ function dispatchFailureState(instance, state) {
13
13
 
14
14
  function animateFailureHead(instance, frames, duration) {
15
15
  if (!instance._headMotion?.animate) return null;
16
+ const token = instance._transitionToken;
16
17
  instance._headMotion.style.transformBox = 'view-box';
17
18
  instance._headMotion.style.transformOrigin = '120px 120px';
18
19
  const anim = instance._headMotion.animate(frames, {
@@ -21,7 +22,9 @@ function animateFailureHead(instance, frames, duration) {
21
22
  fill: 'forwards',
22
23
  });
23
24
  anim.onfinish = () => {
24
- instance._headMotion.style.transform = frames[frames.length - 1].transform || '';
25
+ if (token === instance._transitionToken) {
26
+ instance._headMotion.style.transform = frames[frames.length - 1].transform || '';
27
+ }
25
28
  };
26
29
  return anim;
27
30
  }
@@ -95,6 +98,7 @@ proto.failure = async function() {
95
98
  { transform: 'translateY(0px)' },
96
99
  ], recover);
97
100
  if (this._state === 'sad') await this._returnToIdle(recover);
101
+ if (token !== this._transitionToken) return;
98
102
  this._failureFx = null;
99
103
  };
100
104
 
@@ -122,6 +122,7 @@ function verticalShift(elapsed, phases, offset) {
122
122
  // Keep the R60 head motion unchanged: down, up past center, then back to center.
123
123
  function animateInspectHead(instance, phases) {
124
124
  if (!instance._headMotion?.animate) return;
125
+ const token = instance._transitionToken;
125
126
  const start = phases.down1Start;
126
127
  const end = phases.center1End;
127
128
  const duration = Math.max(1, end - start);
@@ -142,7 +143,9 @@ function animateInspectHead(instance, phases) {
142
143
  easing: 'linear',
143
144
  fill: 'forwards',
144
145
  });
145
- anim.onfinish = () => { instance._headMotion.style.transform = 'translateY(0px)'; };
146
+ anim.onfinish = () => {
147
+ if (token === instance._transitionToken) instance._headMotion.style.transform = 'translateY(0px)';
148
+ };
146
149
  }
147
150
 
148
151
  proto.inspect = async function() {
@@ -1,3 +1,3 @@
1
- const VERSION = '0.2.0';
1
+ const VERSION = '0.2.1';
2
2
 
3
3
  export { VERSION };