@lovelace_lol/polymer 0.0.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/README.md +226 -0
- package/dist/index.d.ts +2603 -0
- package/dist/index.js +1031 -0
- package/dist/test.cjs +1519 -0
- package/dist/worker/agency-worker.js +972 -0
- package/dist/worker/manifest.edn +1 -0
- package/package.json +57 -0
- package/shadow-cljs.edn +173 -0
- package/src/polymer/animation/agency.cljs +84 -0
- package/src/polymer/animation/domain.cljs +110 -0
- package/src/polymer/animation/planner.cljs +88 -0
- package/src/polymer/animation/runtime.cljs +137 -0
- package/src/polymer/animation/scheduler.cljs +178 -0
- package/src/polymer/animation/service.cljs +981 -0
- package/src/polymer/animation/state.cljs +112 -0
- package/src/polymer/blink/agency.cljs +131 -0
- package/src/polymer/blink/planner.cljs +115 -0
- package/src/polymer/blink/scheduler.cljs +90 -0
- package/src/polymer/blink/snippet.cljs +50 -0
- package/src/polymer/blink/state.cljs +102 -0
- package/src/polymer/camera_context/agency.cljs +132 -0
- package/src/polymer/camera_context/domain.cljs +186 -0
- package/src/polymer/camera_context/planner.cljs +50 -0
- package/src/polymer/camera_context/scheduler.cljs +113 -0
- package/src/polymer/camera_context/state.cljs +121 -0
- package/src/polymer/character.cljs +471 -0
- package/src/polymer/conversation/agency.cljs +83 -0
- package/src/polymer/conversation/domain.cljs +35 -0
- package/src/polymer/conversation/effector.cljs +130 -0
- package/src/polymer/conversation/planner.cljs +178 -0
- package/src/polymer/conversation/scheduler.cljs +202 -0
- package/src/polymer/conversation/service.cljs +329 -0
- package/src/polymer/conversation/state.cljs +186 -0
- package/src/polymer/core.cljs +172 -0
- package/src/polymer/eye_head/agency.cljs +75 -0
- package/src/polymer/eye_head/domain.cljs +133 -0
- package/src/polymer/eye_head/goap.cljs +106 -0
- package/src/polymer/eye_head/scheduler.cljs +176 -0
- package/src/polymer/eye_head/service.cljs +259 -0
- package/src/polymer/eye_head/snippet.cljs +92 -0
- package/src/polymer/eye_head/state.cljs +167 -0
- package/src/polymer/gaze/agency.cljs +85 -0
- package/src/polymer/gaze/domain.cljs +211 -0
- package/src/polymer/gaze/goap.cljs +208 -0
- package/src/polymer/gaze/scheduler.cljs +184 -0
- package/src/polymer/gaze/state.cljs +202 -0
- package/src/polymer/gesture/agency.cljs +185 -0
- package/src/polymer/gesture/goap.cljs +461 -0
- package/src/polymer/gesture/scheduler.cljs +122 -0
- package/src/polymer/gesture/snippet.cljs +198 -0
- package/src/polymer/gesture/state.cljs +273 -0
- package/src/polymer/lipsync/agency.cljs +593 -0
- package/src/polymer/lipsync/articulation/jaw.cljs +258 -0
- package/src/polymer/lipsync/articulation/snippet.cljs +605 -0
- package/src/polymer/lipsync/articulation/tongue.cljs +418 -0
- package/src/polymer/lipsync/articulation/visemes.cljs +429 -0
- package/src/polymer/lipsync/goap.cljs +132 -0
- package/src/polymer/lipsync/pronunciation/effector.cljs +51 -0
- package/src/polymer/lipsync/scheduler.cljs +302 -0
- package/src/polymer/lipsync/state.cljs +202 -0
- package/src/polymer/nlp/phonemes.cljs +164 -0
- package/src/polymer/prosodic/agency.cljs +196 -0
- package/src/polymer/prosodic/goap.cljs +122 -0
- package/src/polymer/prosodic/scheduler.cljs +99 -0
- package/src/polymer/prosodic/snippet.cljs +106 -0
- package/src/polymer/prosodic/state.cljs +139 -0
- package/src/polymer/runtime/embody.cljs +117 -0
- package/src/polymer/runtime/embody_wasm.cljs +177 -0
- package/src/polymer/runtime/rust_embody_host.cljs +645 -0
- package/src/polymer/society.cljs +239 -0
- package/src/polymer/stream.cljs +130 -0
- package/src/polymer/transcription/agency.cljs +69 -0
- package/src/polymer/transcription/domain.cljs +68 -0
- package/src/polymer/transcription/effector.cljs +611 -0
- package/src/polymer/transcription/planner.cljs +203 -0
- package/src/polymer/transcription/scheduler.cljs +225 -0
- package/src/polymer/transcription/service.cljs +209 -0
- package/src/polymer/transcription/state.cljs +239 -0
- package/src/polymer/tts/agency.cljs +503 -0
- package/src/polymer/tts/azure.cljs +290 -0
- package/src/polymer/tts/planner.cljs +178 -0
- package/src/polymer/tts/runtime.cljs +624 -0
- package/src/polymer/tts/scheduler.cljs +162 -0
- package/src/polymer/tts/state.cljs +191 -0
- package/src/polymer/worker.cljs +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Polymer
|
|
2
|
+
|
|
3
|
+
Clean ClojureScript character agency package for Character Loom.
|
|
4
|
+
|
|
5
|
+
Production releases publish to npm as `@lovelace_lol/polymer` on every push to `main`. Hosts should depend on the npm package (`latest` or a semver range). PR staging may still use git SHA pins or `Depends-on` / pkg.pr.new preview URLs.
|
|
6
|
+
|
|
7
|
+
Polymer is intentionally separate from Latticework and Polyester. It is built as
|
|
8
|
+
a Society of Mind agency system: small CLJS agencies collaborate through streams,
|
|
9
|
+
plan locally, schedule their own work, and keep side effects inside the agencies
|
|
10
|
+
responsible for performing them.
|
|
11
|
+
|
|
12
|
+
See [docs/agency-architecture.md](docs/agency-architecture.md) for the agency
|
|
13
|
+
collaboration, scheduler, side-effect, stream, and runtime-target rules.
|
|
14
|
+
|
|
15
|
+
## Agency API
|
|
16
|
+
|
|
17
|
+
The package exposes an agency system:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
const agencies = createCharacterAgencies();
|
|
21
|
+
agencies.dispatch({ agency: "blink", command: { type: "enable" } });
|
|
22
|
+
|
|
23
|
+
agencies.events.subscribe((message) => {});
|
|
24
|
+
agencies.snapshot();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Agencies communicate through incoming and outgoing streams of plain data.
|
|
28
|
+
Messages may be facts, goals, requests, constraints, priorities, status, or
|
|
29
|
+
diagnostics. Requests that imply side effects are handled by the receiving
|
|
30
|
+
agency's local planner, scheduler, and effector path.
|
|
31
|
+
|
|
32
|
+
Host applications may dispatch external commands, observe outgoing streams, and
|
|
33
|
+
read snapshots for diagnostics or configuration. Host applications should not
|
|
34
|
+
serve as the normal message bus between Polymer agencies.
|
|
35
|
+
|
|
36
|
+
## Current Agencies
|
|
37
|
+
|
|
38
|
+
Polymer currently includes early Blink, Animation, Gaze, Eye/Head Tracking,
|
|
39
|
+
TTS, LipSync, Prosodic Expression, and Gesture agencies, plus first slices for
|
|
40
|
+
Conversation, Camera Context, and Transcription. These are implementation
|
|
41
|
+
milestones, not the limits of the architecture. Each agency should follow the
|
|
42
|
+
same local GOAP/planner, scheduler, stream, transform, and effector pattern as
|
|
43
|
+
the package grows.
|
|
44
|
+
|
|
45
|
+
The text-only LipSync pronunciation fallback and its accuracy limits are
|
|
46
|
+
documented in [`docs/lipsync-pronunciation-fallback.md`](docs/lipsync-pronunciation-fallback.md).
|
|
47
|
+
|
|
48
|
+
Runtime-specific work belongs at the edge. The current animation path can target
|
|
49
|
+
the existing web runtime, but Polymer core should remain able to support other
|
|
50
|
+
runtime targets such as Babylon, Unity, Godot, robotics, or future animation
|
|
51
|
+
libraries through separate runtime-specific boundaries.
|
|
52
|
+
|
|
53
|
+
Hair appearance and physics are model/runtime capabilities rather than
|
|
54
|
+
character-behavior agencies. Polymer therefore does not expose a Hair agency,
|
|
55
|
+
Hair planner, or Hair scheduler. It continues to re-export Embody's hair color,
|
|
56
|
+
material-normalization, and Wasm physics APIs so hosts can configure the
|
|
57
|
+
character runtime without importing Embody directly.
|
|
58
|
+
|
|
59
|
+
## Gesture Agency
|
|
60
|
+
|
|
61
|
+
Gesture is the arm/hand gesticulation agency. It accepts LoomLarge-authored
|
|
62
|
+
gesture snapshots as plain data and turns them into typed bone-channel animation
|
|
63
|
+
snippets. It does not call scene bones, host UI state, storage, or the animation
|
|
64
|
+
runtime.
|
|
65
|
+
Gesture snapshots are compatible with the Gestures tab profile shape: id/name,
|
|
66
|
+
optional description or text representation, emoji trigger, left/right/both/custom
|
|
67
|
+
scope, captured source metadata, duration, priority, affected bones, static bone
|
|
68
|
+
targets, and optional time-based keyframes.
|
|
69
|
+
|
|
70
|
+
Gesture commands can still name an exact gesture or emoji, but the planner also
|
|
71
|
+
accepts gesture goals. A goal asks Gesture to choose from the authored library by
|
|
72
|
+
intent, tags, scope, required or avoided effectors, cooldown, active conflicts,
|
|
73
|
+
and capacity before it emits Animation requests.
|
|
74
|
+
|
|
75
|
+
### Gesture GOAP Planning
|
|
76
|
+
|
|
77
|
+
Gesture GOAP plans for one local world-state transition: a suitable authored
|
|
78
|
+
arm/hand gesture is selected and safely scheduled through Animation, or the
|
|
79
|
+
agency records why that goal cannot be satisfied. It is not a second public
|
|
80
|
+
playback API.
|
|
81
|
+
|
|
82
|
+
The planner uses the incoming command, the gesture library, active snippets, and
|
|
83
|
+
Gesture config to decide:
|
|
84
|
+
|
|
85
|
+
- which gesture best satisfies an explicit gesture id, emoji mapping, intent,
|
|
86
|
+
tags, text hints, scope, and bone constraints
|
|
87
|
+
- whether the selected gesture is valid motion and is out of cooldown
|
|
88
|
+
- whether active snippets conflict on affected bones
|
|
89
|
+
- whether capacity is available under `maxActive`
|
|
90
|
+
- whether to ignore, remove only conflicting snippets, remove the oldest snippets
|
|
91
|
+
needed for capacity, build a snippet, schedule Animation, and record the result
|
|
92
|
+
|
|
93
|
+
Host integrations should prefer the character agency network so Gesture's
|
|
94
|
+
animation requests are routed to Animation inside Polymer:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
const agencies = createCharacterAgencies({
|
|
98
|
+
animation: { engine },
|
|
99
|
+
gesture: {
|
|
100
|
+
gestures: profile.characterGestures,
|
|
101
|
+
emojiMappings: profile.gestureEmojiMappings,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
agencies.dispatch({ agency: "gesture", command: { type: "playEmoji", emoji: "👋" } });
|
|
106
|
+
agencies.dispatch({
|
|
107
|
+
agency: "gesture",
|
|
108
|
+
command: {
|
|
109
|
+
type: "gesture.goal",
|
|
110
|
+
goal: {
|
|
111
|
+
intent: "greeting",
|
|
112
|
+
tags: ["wave"],
|
|
113
|
+
scope: "right",
|
|
114
|
+
avoidBones: ["HAND_L"],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The host supplies the gesture library and may observe streams for diagnostics,
|
|
121
|
+
but Gesture's own scheduler is responsible for replacement, cancellation, and
|
|
122
|
+
completion cleanup before Animation owns the runtime side effect.
|
|
123
|
+
|
|
124
|
+
## Character host (Embody scene + model loading)
|
|
125
|
+
|
|
126
|
+
Polymer re-exports Embody's character host so LoomLarge and other hosts can set
|
|
127
|
+
up a character without depending on Embody directly.
|
|
128
|
+
|
|
129
|
+
Default path — pass a container element and a character URL:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
import {
|
|
133
|
+
createCharacterHost,
|
|
134
|
+
createCharacterAgencies,
|
|
135
|
+
} from '@lovelace_lol/polymer';
|
|
136
|
+
|
|
137
|
+
const host = await createCharacterHost({
|
|
138
|
+
container: document.getElementById('viewport'),
|
|
139
|
+
character: {
|
|
140
|
+
modelUrl: '/characters/jonathan.glb',
|
|
141
|
+
presetType: 'cc4',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const agencies = createCharacterAgencies({
|
|
146
|
+
animation: { engine: host.engine },
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Named scene types (`studio`, `showcase`, `inspection`, `void`) bundle
|
|
151
|
+
background, lighting preset, and shadow-plane defaults; enumerate them via
|
|
152
|
+
`CHARACTER_SCENE_TYPES` / `CHARACTER_SCENE_TYPE_IDS`:
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
const host = await createCharacterHost({
|
|
156
|
+
container,
|
|
157
|
+
character: { modelUrl: '/characters/jonathan.glb' },
|
|
158
|
+
scene: { type: 'showcase' },
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Advanced path — inject an existing Three.js scene:
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
const host = await createCharacterHost({
|
|
166
|
+
container: mountEl,
|
|
167
|
+
character: { modelUrl: '/characters/jonathan.glb', presetType: 'cc4' },
|
|
168
|
+
external: { scene, renderer, camera },
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Polymer stays agency-oriented: it does not own the render loop. Use
|
|
173
|
+
`createCharacterHost` / `loadCharacterModel` for scene+model setup, then inject
|
|
174
|
+
`host.engine` into `createCharacterAgencies`.
|
|
175
|
+
|
|
176
|
+
For an already-managed Three.js scene, Polymer also exposes a CLJS-owned host
|
|
177
|
+
that talks directly to Embody's Rust/Wasm `RuntimeCore`:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
import {
|
|
181
|
+
createRustEmbodyHostUnbound,
|
|
182
|
+
initEmbodyCore,
|
|
183
|
+
supportsRustEmbodyPreset,
|
|
184
|
+
} from '@lovelace_lol/polymer';
|
|
185
|
+
|
|
186
|
+
await initEmbodyCore();
|
|
187
|
+
if (supportsRustEmbodyPreset('cc4')) {
|
|
188
|
+
const engine = createRustEmbodyHostUnbound({
|
|
189
|
+
presetType: 'cc4',
|
|
190
|
+
profile: characterProfileOverrides,
|
|
191
|
+
});
|
|
192
|
+
engine.onReady({ model, meshes });
|
|
193
|
+
engine.start();
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The CLJS host owns the JavaScript API and render-loop bridge. Rust owns preset
|
|
198
|
+
lookup, profile merge and intake, compiled bindings, transitions, and packed
|
|
199
|
+
frame evaluation. Unsupported presets must stay on the compatibility host until
|
|
200
|
+
they are explicitly embedded; they are never treated as CC4 aliases.
|
|
201
|
+
|
|
202
|
+
## Git Install Contract
|
|
203
|
+
|
|
204
|
+
Polymer Git-SHA consumers should import checked-in JavaScript artifacts from
|
|
205
|
+
`dist`. They should not need Java, Shadow CLJS, or a local Polymer build during
|
|
206
|
+
application install.
|
|
207
|
+
|
|
208
|
+
The package intentionally has no `prepare`, `install`, or `postinstall` build
|
|
209
|
+
lifecycle. Polymer CI runs the CLJS build, verifies that `dist` exposes the
|
|
210
|
+
browser ESM API that Git-SHA consumers import, and `prepublishOnly` repeats the
|
|
211
|
+
build/test/API check before an npm publish.
|
|
212
|
+
|
|
213
|
+
## Worker Protocol Artifact
|
|
214
|
+
|
|
215
|
+
The package also ships `@lovelace_lol/polymer/worker/agency-worker.js` as an
|
|
216
|
+
opt-in transport around the complete character agency API. It accepts
|
|
217
|
+
`createCharacterAgencies`, `dispatch`, `snapshot`, and `dispose` messages and
|
|
218
|
+
returns character events, snapshots, and lifecycle messages as plain data. The
|
|
219
|
+
Worker does not add another planner or route between agencies; Polymer's
|
|
220
|
+
character network keeps that responsibility.
|
|
221
|
+
|
|
222
|
+
CI executes the compiled artifact in a real Node worker thread. LoomLarge does
|
|
223
|
+
not use this artifact yet, and this PR does not decide which agencies should be
|
|
224
|
+
placed in workers. Selective placement, profiling, transferables, and worker
|
|
225
|
+
pool decisions remain tracked in
|
|
226
|
+
[issue #62](https://github.com/meekmachine/Polymer/issues/62).
|