@lovelace_lol/polymer 0.0.7 → 0.0.9

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.
Files changed (95) hide show
  1. package/README.md +434 -12
  2. package/dist/index.d.ts +1945 -244
  3. package/dist/index.js +1686 -1017
  4. package/dist/vision/face-worker.js +296 -0
  5. package/dist/vision/face_landmarker.task +0 -0
  6. package/dist/vision/manifest.edn +1 -0
  7. package/dist/vision/vision_bundle.js +2 -0
  8. package/dist/vision/wasm/vision_wasm_internal.js +8841 -0
  9. package/dist/vision/wasm/vision_wasm_internal.wasm +0 -0
  10. package/dist/vision/wasm/vision_wasm_module_internal.js +8837 -0
  11. package/dist/vision/wasm/vision_wasm_module_internal.wasm +0 -0
  12. package/dist/vision/wasm/vision_wasm_nosimd_internal.js +8832 -0
  13. package/dist/vision/wasm/vision_wasm_nosimd_internal.wasm +0 -0
  14. package/dist/worker/agency-worker.js +1276 -962
  15. package/dist/worker/manifest.edn +1 -1
  16. package/package.json +33 -20
  17. package/dist/test.cjs +0 -1519
  18. package/shadow-cljs.edn +0 -173
  19. package/src/polymer/animation/agency.cljs +0 -84
  20. package/src/polymer/animation/domain.cljs +0 -110
  21. package/src/polymer/animation/planner.cljs +0 -88
  22. package/src/polymer/animation/runtime.cljs +0 -137
  23. package/src/polymer/animation/scheduler.cljs +0 -178
  24. package/src/polymer/animation/service.cljs +0 -981
  25. package/src/polymer/animation/state.cljs +0 -112
  26. package/src/polymer/blink/agency.cljs +0 -131
  27. package/src/polymer/blink/planner.cljs +0 -115
  28. package/src/polymer/blink/scheduler.cljs +0 -90
  29. package/src/polymer/blink/snippet.cljs +0 -50
  30. package/src/polymer/blink/state.cljs +0 -102
  31. package/src/polymer/camera_context/agency.cljs +0 -132
  32. package/src/polymer/camera_context/domain.cljs +0 -186
  33. package/src/polymer/camera_context/planner.cljs +0 -50
  34. package/src/polymer/camera_context/scheduler.cljs +0 -113
  35. package/src/polymer/camera_context/state.cljs +0 -121
  36. package/src/polymer/character.cljs +0 -403
  37. package/src/polymer/conversation/agency.cljs +0 -83
  38. package/src/polymer/conversation/domain.cljs +0 -35
  39. package/src/polymer/conversation/effector.cljs +0 -130
  40. package/src/polymer/conversation/planner.cljs +0 -178
  41. package/src/polymer/conversation/scheduler.cljs +0 -202
  42. package/src/polymer/conversation/service.cljs +0 -329
  43. package/src/polymer/conversation/state.cljs +0 -186
  44. package/src/polymer/core.cljs +0 -172
  45. package/src/polymer/eye_head/agency.cljs +0 -75
  46. package/src/polymer/eye_head/domain.cljs +0 -133
  47. package/src/polymer/eye_head/goap.cljs +0 -106
  48. package/src/polymer/eye_head/scheduler.cljs +0 -176
  49. package/src/polymer/eye_head/service.cljs +0 -259
  50. package/src/polymer/eye_head/snippet.cljs +0 -92
  51. package/src/polymer/eye_head/state.cljs +0 -167
  52. package/src/polymer/gaze/agency.cljs +0 -85
  53. package/src/polymer/gaze/domain.cljs +0 -211
  54. package/src/polymer/gaze/goap.cljs +0 -208
  55. package/src/polymer/gaze/scheduler.cljs +0 -184
  56. package/src/polymer/gaze/state.cljs +0 -202
  57. package/src/polymer/gesture/agency.cljs +0 -185
  58. package/src/polymer/gesture/goap.cljs +0 -461
  59. package/src/polymer/gesture/scheduler.cljs +0 -122
  60. package/src/polymer/gesture/snippet.cljs +0 -198
  61. package/src/polymer/gesture/state.cljs +0 -273
  62. package/src/polymer/lipsync/agency.cljs +0 -593
  63. package/src/polymer/lipsync/articulation/jaw.cljs +0 -258
  64. package/src/polymer/lipsync/articulation/snippet.cljs +0 -605
  65. package/src/polymer/lipsync/articulation/tongue.cljs +0 -418
  66. package/src/polymer/lipsync/articulation/visemes.cljs +0 -429
  67. package/src/polymer/lipsync/goap.cljs +0 -132
  68. package/src/polymer/lipsync/pronunciation/effector.cljs +0 -51
  69. package/src/polymer/lipsync/scheduler.cljs +0 -302
  70. package/src/polymer/lipsync/state.cljs +0 -202
  71. package/src/polymer/nlp/phonemes.cljs +0 -164
  72. package/src/polymer/prosodic/agency.cljs +0 -196
  73. package/src/polymer/prosodic/goap.cljs +0 -122
  74. package/src/polymer/prosodic/scheduler.cljs +0 -99
  75. package/src/polymer/prosodic/snippet.cljs +0 -106
  76. package/src/polymer/prosodic/state.cljs +0 -139
  77. package/src/polymer/runtime/embody.cljs +0 -117
  78. package/src/polymer/runtime/embody_wasm.cljs +0 -177
  79. package/src/polymer/runtime/rust_embody_host.cljs +0 -647
  80. package/src/polymer/society.cljs +0 -253
  81. package/src/polymer/stream.cljs +0 -130
  82. package/src/polymer/transcription/agency.cljs +0 -69
  83. package/src/polymer/transcription/domain.cljs +0 -68
  84. package/src/polymer/transcription/effector.cljs +0 -611
  85. package/src/polymer/transcription/planner.cljs +0 -203
  86. package/src/polymer/transcription/scheduler.cljs +0 -225
  87. package/src/polymer/transcription/service.cljs +0 -209
  88. package/src/polymer/transcription/state.cljs +0 -239
  89. package/src/polymer/tts/agency.cljs +0 -503
  90. package/src/polymer/tts/azure.cljs +0 -290
  91. package/src/polymer/tts/planner.cljs +0 -178
  92. package/src/polymer/tts/runtime.cljs +0 -624
  93. package/src/polymer/tts/scheduler.cljs +0 -162
  94. package/src/polymer/tts/state.cljs +0 -191
  95. package/src/polymer/worker.cljs +0 -81
@@ -1,253 +0,0 @@
1
- (ns polymer.society)
2
-
3
- ;; Default agencySociety seed for hosts and character profiles.
4
- ;;
5
- ;; Mirrors today's hardcoded polymer.character routing. When character.cljs
6
- ;; gains or drops a route, update this seed in the same change.
7
- ;;
8
- ;; See docs/agency-architecture.md (Agency Society Config) and issues #63/#64.
9
-
10
- (def agency-names
11
- ["animation"
12
- "blink"
13
- "gaze"
14
- "eyeHeadTracking"
15
- "gesture"
16
- "cameraContext"
17
- "transcription"
18
- "conversation"
19
- "tts"
20
- "lipSync"
21
- "prosodic"])
22
-
23
- (def required-agency-names
24
- #{"animation" "transcription" "tts" "lipSync" "conversation"})
25
-
26
- (defn- agency-entry [name]
27
- {:required (contains? required-agency-names name)
28
- :enabled true
29
- :priors {}
30
- :configure {}})
31
-
32
- (defn- edge
33
- ([id from type to required]
34
- (edge id from type to required nil))
35
- ([id from type to required match]
36
- (cond-> {:id id
37
- :from from
38
- :type type
39
- :to to
40
- :required required
41
- :enabled true
42
- :credit 1.0}
43
- match (assoc :match match))))
44
-
45
- (def default-edges
46
- [;; Perception → gaze → motor
47
- (edge "cameraContext.camera.fact→gaze" "cameraContext" "camera.fact" "gaze" true)
48
- (edge "cameraContext.camera.stale→gaze" "cameraContext" "camera.stale" "gaze" true)
49
- (edge "gaze.eyeHeadTracking.requestGaze→eyeHeadTracking" "gaze" "eyeHeadTracking.requestGaze" "eyeHeadTracking" true)
50
- (edge "gaze.eyeHeadTracking.requestReset→eyeHeadTracking" "gaze" "eyeHeadTracking.requestReset" "eyeHeadTracking" true)
51
- (edge "gaze.eyeHeadTracking.requestCancel→eyeHeadTracking" "gaze" "eyeHeadTracking.requestCancel" "eyeHeadTracking" true)
52
-
53
- ;; Embodiment → animation apply gate
54
- (edge "blink.animation.requestScheduleSnippet→animation" "blink" "animation.requestScheduleSnippet" "animation" true)
55
- (edge "eyeHeadTracking.animation.requestScheduleSnippet→animation" "eyeHeadTracking" "animation.requestScheduleSnippet" "animation" true)
56
- (edge "eyeHeadTracking.animation.requestRemoveSnippet→animation" "eyeHeadTracking" "animation.requestRemoveSnippet" "animation" true)
57
- (edge "gesture.animation.requestScheduleSnippet→animation" "gesture" "animation.requestScheduleSnippet" "animation" true)
58
- (edge "gesture.animation.requestRemoveSnippet→animation" "gesture" "animation.requestRemoveSnippet" "animation" true)
59
- (edge "lipSync.animation.requestScheduleSnippet→animation" "lipSync" "animation.requestScheduleSnippet" "animation" true)
60
- (edge "lipSync.animation.requestRemoveSnippet→animation" "lipSync" "animation.requestRemoveSnippet" "animation" true)
61
- (edge "lipSync.animation.requestSeekSnippet→animation" "lipSync" "animation.requestSeekSnippet" "animation" true)
62
- (edge "prosodic.animation.requestScheduleSnippet→animation" "prosodic" "animation.requestScheduleSnippet" "animation" true)
63
- (edge "prosodic.animation.requestRemoveSnippet→animation" "prosodic" "animation.requestRemoveSnippet" "animation" true)
64
-
65
- ;; Blink ↔ prosodic coupling (seeded; not required — may be disabled per character)
66
- (edge "blink.signal.blink-fast→prosodic" "blink" "signal" "prosodic" false {:signal "blink-fast"})
67
-
68
- ;; Speech discourse (required cores)
69
- (edge "transcription.transcription.final→conversation" "transcription" "transcription.final" "conversation" true)
70
- (edge "transcription.transcription.interruption→conversation" "transcription" "transcription.interruption" "conversation" true)
71
- (edge "transcription.transcription.audioInterruption→conversation" "transcription" "transcription.audioInterruption" "conversation" true)
72
- (edge "conversation.conversation.userUtterance→prosodic" "conversation" "conversation.userUtterance" "prosodic" false)
73
- (edge "conversation.conversation.userUtterance→gaze" "conversation" "conversation.userUtterance" "gaze" false)
74
- (edge "conversation.conversation.agentUtterance→prosodic" "conversation" "conversation.agentUtterance" "prosodic" false)
75
- (edge "conversation.conversation.agentUtterance→gaze" "conversation" "conversation.agentUtterance" "gaze" false)
76
- (edge "conversation.conversation.requestResponse→prosodic" "conversation" "conversation.requestResponse" "prosodic" false)
77
- (edge "conversation.tts.requestSpeak→tts" "conversation" "tts.requestSpeak" "tts" true)
78
- (edge "conversation.conversation.cancelRequested→tts" "conversation" "conversation.cancelRequested" "tts" true)
79
- (edge "conversation.conversation.cancelRequested→prosodic" "conversation" "conversation.cancelRequested" "prosodic" false)
80
- (edge "conversation.conversation.cancelRequested→gaze" "conversation" "conversation.cancelRequested" "gaze" false)
81
- (edge "tts.lipSync.command→lipSync" "tts" "lipSync.command" "lipSync" true)
82
- (edge "tts.ttsStatusChanged→conversation" "tts" "ttsStatusChanged" "conversation" true)
83
- (edge "tts.ttsStatusChanged→transcription" "tts" "ttsStatusChanged" "transcription" true)
84
- (edge "tts.ttsSpeechStarted→prosodic" "tts" "ttsSpeechStarted" "prosodic" true)
85
- (edge "tts.ttsSpeechStarted→transcription" "tts" "ttsSpeechStarted" "transcription" true)
86
- (edge "tts.ttsSpeechStarted→conversation" "tts" "ttsSpeechStarted" "conversation" true)
87
- (edge "tts.ttsWordBoundary→prosodic" "tts" "ttsWordBoundary" "prosodic" true)
88
- (edge "tts.ttsSpeechStopped→prosodic" "tts" "ttsSpeechStopped" "prosodic" true)
89
- (edge "tts.ttsSpeechStopped→transcription" "tts" "ttsSpeechStopped" "transcription" true)
90
- (edge "tts.ttsSpeechStopped→conversation" "tts" "ttsSpeechStopped" "conversation" true)
91
- (edge "tts.ttsSpeechEnded→prosodic" "tts" "ttsSpeechEnded" "prosodic" true)
92
- (edge "tts.ttsSpeechEnded→transcription" "tts" "ttsSpeechEnded" "transcription" true)
93
- (edge "tts.ttsSpeechEnded→conversation" "tts" "ttsSpeechEnded" "conversation" true)])
94
-
95
- (def default-agency-society
96
- {:version 1
97
- :agencies (into {} (map (fn [name] [name (agency-entry name)]) agency-names))
98
- :edges default-edges
99
- :kLines []
100
- :cb5t {:E 0.5 :N 0.5 :C 0.5 :A 0.5 :O 0.5}
101
- :personaPackId nil
102
- :characterRollup {:type "weightedSum"}})
103
-
104
- (def DEFAULT_AGENCY_SOCIETY
105
- "JS-facing default agencySociety seed (plain JS object)."
106
- (clj->js default-agency-society))
107
-
108
- (defn default-edge-ids
109
- "Return the set of default edge ids for sync tests."
110
- []
111
- (set (map :id default-edges)))
112
-
113
- (defn value->clj [value]
114
- (cond
115
- (nil? value) nil
116
- (map? value) value
117
- :else (js->clj value :keywordize-keys true)))
118
-
119
- (defn finite-number? [value]
120
- (and (number? value) (js/isFinite value)))
121
-
122
- (defn clamp-credit [value]
123
- (if (finite-number? value)
124
- (max 0 (min 1 value))
125
- 1.0))
126
-
127
- (defn normalize-map [value]
128
- (let [resolved (value->clj value)]
129
- (if (map? resolved) resolved {})))
130
-
131
- (defn normalize-agency-entry [name provided]
132
- (let [base (agency-entry name)
133
- merged (merge base (normalize-map provided))
134
- required? (contains? required-agency-names name)]
135
- (assoc merged
136
- :required required?
137
- :enabled (if required? true (not (false? (:enabled merged))))
138
- :priors (normalize-map (:priors merged))
139
- :configure (normalize-map (:configure merged)))))
140
-
141
- (defn valid-edge? [edge]
142
- (and (string? (:id edge))
143
- (string? (:from edge))
144
- (string? (:type edge))
145
- (string? (:to edge))))
146
-
147
- (defn normalize-edge [base provided]
148
- (let [merged (merge base (normalize-map provided))
149
- required? (true? (:required base))
150
- requested-credit (clamp-credit (:credit merged))
151
- credit (if (and required? (not (pos? requested-credit)))
152
- (clamp-credit (:credit base))
153
- requested-credit)]
154
- (assoc merged
155
- :required required?
156
- :enabled (if required? true (not (false? (:enabled merged))))
157
- :credit credit
158
- :match (normalize-map (:match merged)))))
159
-
160
- (defn normalize-agency-society
161
- "Merge a profile society document over the canonical seed.
162
-
163
- Required agencies and edges cannot be disabled by profile data. Optional
164
- custom edges are retained when they have a complete data shape."
165
- [value]
166
- (let [provided (normalize-map value)
167
- provided-agencies (normalize-map (:agencies provided))
168
- provided-edges (->> (or (:edges provided) [])
169
- (map normalize-map)
170
- (filter #(string? (:id %))))
171
- provided-by-id (into {} (map (juxt :id identity) provided-edges))
172
- default-ids (default-edge-ids)
173
- normalized-defaults (mapv (fn [base]
174
- (normalize-edge base (get provided-by-id (:id base))))
175
- default-edges)
176
- custom-edges (->> provided-edges
177
- (remove #(contains? default-ids (:id %)))
178
- (filter valid-edge?)
179
- (mapv #(normalize-edge {} %)))]
180
- (-> default-agency-society
181
- (merge (select-keys provided [:kLines :cb5t :personaPackId :characterRollup]))
182
- (assoc :version 1
183
- :agencies (into {}
184
- (map (fn [name]
185
- [name (normalize-agency-entry
186
- name
187
- (or (get provided-agencies name)
188
- (get provided-agencies (keyword name))))])
189
- agency-names))
190
- :edges (into normalized-defaults custom-edges)))))
191
-
192
- (defn agency-entry-for [society name]
193
- (get-in society [:agencies name]))
194
-
195
- (defn agency-enabled? [society name]
196
- (true? (:enabled (agency-entry-for society name))))
197
-
198
- (defn agency-configure [society name]
199
- (:configure (agency-entry-for society name)))
200
-
201
- (defn agency-priors [society name]
202
- (:priors (agency-entry-for society name)))
203
-
204
- (defn match-event? [match event]
205
- (every? (fn [[key expected]] (= expected (get event key))) match))
206
-
207
- (defn accepted-edge-context
208
- [edge]
209
- {:edgeId (:id edge)
210
- :from (:from edge)
211
- :to (:to edge)
212
- :credit (:credit edge)})
213
-
214
- (defn route-contexts
215
- "Return all accepted edge metadata for one outgoing domain event.
216
-
217
- An empty result means the topology, agency enablement, match predicate, or edge
218
- credit rejected all candidate routes before they reached receiving agencies."
219
- [society from event]
220
- (if-not (agency-enabled? society from)
221
- []
222
- (into []
223
- (keep (fn [edge]
224
- (when (and (= from (:from edge))
225
- (= (:type event) (:type edge))
226
- (agency-enabled? society (:to edge))
227
- (:enabled edge)
228
- (pos? (:credit edge))
229
- (match-event? (:match edge) event))
230
- (accepted-edge-context edge))))
231
- (:edges society))))
232
-
233
- (defn route-context
234
- "Return one accepted edge metadata entry for an outgoing event and target.
235
-
236
- A nil result means the route was rejected before it reached the receiving
237
- agency."
238
- [society from event to]
239
- (some #(when (= to (:to %)) %)
240
- (route-contexts society from event)))
241
-
242
- (defn agency-config
243
- "Create one JS agency config without converting runtime/provider handles.
244
-
245
- Direct constructor options supply runtime objects. Profile `configure`
246
- values override operational knobs, and `priors` are attached as plain data
247
- for each agency's local planner."
248
- [root-config society name]
249
- (let [direct (when root-config (aget root-config name))
250
- output (js/Object.assign #js {} (or direct #js {})
251
- (clj->js (agency-configure society name)))]
252
- (aset output "priors" (clj->js (agency-priors society name)))
253
- output))
@@ -1,130 +0,0 @@
1
- (ns polymer.stream)
2
-
3
- ;; Polymer keeps its stream primitive deliberately small.
4
- ;;
5
- ;; The important architectural point is not this particular implementation.
6
- ;; The important point is the boundary shape: agencies exchange plain immutable
7
- ;; data. A specific agency, such as Animation, may own a runtime side effect,
8
- ;; but a host application should not become the cross-agency router.
9
-
10
- (defn- default-listener-error-reporter
11
- [{:keys [error]}]
12
- (.error js/console "[Polymer stream] listener failed" error))
13
-
14
- (defn- report-listener-error!
15
- [reporter listener payload error]
16
- (try
17
- (reporter {:type :stream/listener-error
18
- :listener listener
19
- :event payload
20
- :error error})
21
- (catch :default reporter-error
22
- ;; A broken diagnostic callback must not turn an isolated listener failure
23
- ;; back into a failed delivery pass.
24
- (.error js/console
25
- "[Polymer stream] listener error reporter failed"
26
- reporter-error
27
- error))))
28
-
29
- (defn create-stream
30
- "Create a synchronous in-process stream.
31
-
32
- Listeners receive JavaScript objects because this is the public package
33
- boundary. Inside Polymer we keep using Clojure maps so agency code stays
34
- simple and data-oriented.
35
-
36
- An optional :on-listener-error callback receives a Clojure map describing a
37
- failed listener. Errors are isolated from later listeners and are not emitted
38
- as a generic public stream."
39
- ([]
40
- (create-stream {}))
41
- ([{:keys [on-listener-error]}]
42
- (let [listeners (atom [])
43
- next-listener-id (atom 0)
44
- pending-events (atom cljs.core/PersistentQueue.EMPTY)
45
- draining? (atom false)
46
- reporter (or on-listener-error default-listener-error-reporter)]
47
- (letfn [(deliver! [event]
48
- (let [payload (clj->js event)
49
- ;; A listener added during this pass starts with the next
50
- ;; event. Each record still has a live flag so a listener
51
- ;; removed before its turn is skipped immediately.
52
- delivery-listeners @listeners]
53
- (doseq [{:keys [listener active?]} delivery-listeners]
54
- (when @active?
55
- (try
56
- (listener payload)
57
- (catch :default error
58
- (report-listener-error!
59
- reporter listener payload error)))))))
60
-
61
- (drain! []
62
- ;; Reentrant emits only append to the queue. The outer drain loop
63
- ;; completes the current event before processing nested events,
64
- ;; avoiding recursive delivery and preserving FIFO order.
65
- (when-not @draining?
66
- (reset! draining? true)
67
- (try
68
- (loop []
69
- (when (seq @pending-events)
70
- (let [event (peek @pending-events)]
71
- (swap! pending-events pop)
72
- (deliver! event)
73
- (recur))))
74
- (finally
75
- (reset! draining? false)))))]
76
- {:emit
77
- (fn [event]
78
- (swap! pending-events conj event)
79
- (drain!))
80
-
81
- :subscribe
82
- (fn [listener]
83
- ;; Subscription records preserve registration order and allow the same
84
- ;; callback to be subscribed independently more than once.
85
- (let [listener-id (swap! next-listener-id inc)
86
- active? (atom true)]
87
- (swap! listeners conj {:id listener-id
88
- :listener listener
89
- :active? active?})
90
- (fn []
91
- ;; compare-and-set! gives each subscription an idempotent cleanup
92
- ;; even when several owners race to tear down the same port.
93
- (when (compare-and-set! active? true false)
94
- (swap! listeners
95
- (fn [current]
96
- (into []
97
- (remove #(= listener-id (:id %)))
98
- current)))))))
99
-
100
- :dispose
101
- (fn []
102
- ;; Mark the current delivery snapshot inactive before clearing storage
103
- ;; so disposal during a callback skips later listeners and queued work.
104
- (doseq [{:keys [active?]} @listeners]
105
- (reset! active? false))
106
- (reset! listeners [])
107
- (reset! pending-events cljs.core/PersistentQueue.EMPTY))}))))
108
-
109
- (defn readable-port
110
- "Expose a JS-facing read-only stream port."
111
- [stream]
112
- #js {:subscribe (fn [listener] ((:subscribe stream) listener))})
113
-
114
- (defn writable-port
115
- "Expose a JS-facing writable stream port.
116
-
117
- The write function is supplied by the owning agency/system because writing to
118
- input usually means validating and routing a command, not blindly broadcasting
119
- data."
120
- [stream write!]
121
- #js {:write write!
122
- :subscribe (fn [listener] ((:subscribe stream) listener))})
123
-
124
- (defn subscribe-many
125
- "Subscribe one listener to several streams and return one unsubscriber."
126
- [streams listener]
127
- (let [unsubscribers (mapv #((:subscribe %) listener) streams)]
128
- (fn []
129
- (doseq [unsubscribe unsubscribers]
130
- (unsubscribe)))))
@@ -1,69 +0,0 @@
1
- (ns polymer.transcription.agency
2
- (:require [polymer.stream :as stream]
3
- [polymer.transcription.domain :as domain]
4
- [polymer.transcription.effector :as effector]
5
- [polymer.transcription.planner :as planner]
6
- [polymer.transcription.scheduler :as scheduler]
7
- [polymer.transcription.state :as state]))
8
-
9
- ;; Transcription turns provider recognition callbacks into stable speech facts.
10
- ;; Peer agencies only see data: partial/final transcripts, status, diagnostics,
11
- ;; and provider lifecycle requests. Browser work is private to the effector
12
- ;; reached through this agency's planner and scheduler.
13
-
14
- (defn now-ms
15
- []
16
- (.now js/Date))
17
-
18
- (defn create-transcription-agency
19
- ([config]
20
- (create-transcription-agency config nil))
21
- ([config runtime]
22
- (let [input-stream (stream/create-stream)
23
- event-stream (stream/create-stream)
24
- state-atom (atom (state/config->state config))
25
- disposed? (atom false)
26
- emit-input (:emit input-stream)
27
- emit-event (:emit event-stream)
28
- scheduler-atom (atom nil)]
29
- (letfn [(dispatch! [command]
30
- (when-not @disposed?
31
- (let [payload (domain/data-map command)
32
- plan (planner/plan-command payload @state-atom (now-ms))]
33
- (emit-input {:type "command"
34
- :agency "transcription"
35
- :command payload})
36
- (when-let [agency-scheduler @scheduler-atom]
37
- ((:schedule agency-scheduler) payload plan)))))
38
- (dispatch-type! [type]
39
- (dispatch! #js {:type type}))]
40
- (let [provider-effector (effector/create-effector
41
- {:dispatch dispatch!
42
- :get-state #(deref state-atom)
43
- :runtime runtime})
44
- agency-scheduler (scheduler/create-scheduler
45
- {:state-atom state-atom
46
- :emit-event emit-event
47
- :effector provider-effector})]
48
- (reset! scheduler-atom agency-scheduler)
49
- #js {:dispatch dispatch!
50
- :snapshot (fn [] (state/visible-state @state-atom))
51
- :input (stream/writable-port input-stream dispatch!)
52
- :events (stream/readable-port event-stream)
53
- :subscribeInput (fn [listener] ((:subscribe input-stream) listener))
54
- :subscribeEvents (fn [listener] ((:subscribe event-stream) listener))
55
- :subscribe (fn [listener] ((:subscribe event-stream) listener))
56
- :subscribeStatus (fn [listener] ((:subscribe event-stream) listener))
57
- :start (fn [] (dispatch-type! "start"))
58
- :stop (fn [] (dispatch-type! "stop"))
59
- :reset (fn [] (dispatch-type! "reset"))
60
- :setAgentAudioReferenceTrack
61
- (fn [track]
62
- ((:set-reference-track agency-scheduler) track))
63
- :queue (fn [] (clj->js ((:queue agency-scheduler))))
64
- :dispose (fn []
65
- (when-not @disposed?
66
- (reset! disposed? true)
67
- ((:dispose agency-scheduler))
68
- ((:dispose input-stream))
69
- ((:dispose event-stream))))})))))
@@ -1,68 +0,0 @@
1
- (ns polymer.transcription.domain
2
- (:require [clojure.string :as str]))
3
-
4
- ;; Pure Transcription transforms live here. Provider/browser work stays outside
5
- ;; this namespace; these helpers only normalize command data and transcript text.
6
-
7
- (defn data-map
8
- [value]
9
- (cond
10
- (map? value) value
11
- value (js->clj value :keywordize-keys true)
12
- :else {}))
13
-
14
- (defn clean-text
15
- [value]
16
- (let [text (str/trim (or value ""))]
17
- (when (pos? (count text))
18
- text)))
19
-
20
- (defn text-or
21
- [value fallback]
22
- (or (clean-text value) fallback))
23
-
24
- (defn transcript-text
25
- [command]
26
- (clean-text (or (:text command) (:transcript command))))
27
-
28
- (defn agent-source?
29
- [command]
30
- (contains? #{"agent" "tts" "speaker" "system"}
31
- (str/lower-case (or (:source command) (:speaker command) ""))))
32
-
33
- (defn word-tokens
34
- [text]
35
- (->> (str/split (str/lower-case (or text "")) #"\s+")
36
- (remove str/blank?)
37
- vec))
38
-
39
- (defn word-set
40
- [text]
41
- (set (word-tokens text)))
42
-
43
- (defn agent-echo?
44
- [command current-state]
45
- (let [text (or (transcript-text command) "")
46
- tokens (word-tokens text)
47
- words (set tokens)
48
- agent-words (:agentWords current-state)
49
- script (:agentScript current-state)
50
- overlap (count (filter agent-words words))]
51
- (and (get-in current-state [:config :agentFilteringEnabled])
52
- (:agentSpeaking current-state)
53
- (seq tokens)
54
- (or (every? agent-words tokens)
55
- (and (seq script) (str/starts-with? script (str/lower-case text)))
56
- (and (seq words)
57
- (pos? overlap)
58
- (>= (/ overlap (count words)) 0.65))))))
59
-
60
- (defn boundary-events
61
- [text now-ms]
62
- (->> (str/split (or text "") #"\s+")
63
- (remove str/blank?)
64
- (map-indexed (fn [index word]
65
- {:word word
66
- :index index
67
- :timestamp now-ms
68
- :speaker "user"}))))