signalk-openwakeword 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -87
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -1
- package/dist/index.js.map +1 -1
- package/package.json +14 -5
- package/public/172.mjs +1 -0
- package/public/540.mjs +2 -0
- package/public/540.mjs.LICENSE.txt +9 -0
- package/public/main.mjs +1 -0
- package/public/remoteEntry.js +1 -0
package/README.md
CHANGED
|
@@ -1,89 +1,143 @@
|
|
|
1
1
|
# signalk-openwakeword
|
|
2
2
|
|
|
3
|
-
> **Status: ALPHA
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
> **Status: ALPHA.** This SignalK Wyoming system is 100% vibecoded slop. I
|
|
4
|
+
> don't have the right hardware yet to test it, so I'm putting it out there
|
|
5
|
+
> for people to test in the meantime. It _should_ work. File issues for
|
|
6
|
+
> anything that doesn't.
|
|
7
|
+
|
|
8
|
+
## What is this?
|
|
9
|
+
|
|
10
|
+
Wake word detection for [Signal K](https://signalk.org) — the part of a
|
|
11
|
+
voice assistant that listens for "okay nabu" (or "hey jarvis", "alexa", …)
|
|
12
|
+
so the rest of the stack knows when to start paying attention. The plugin
|
|
13
|
+
runs [openWakeWord](https://github.com/rhasspy/wyoming-openwakeword) as a
|
|
14
|
+
background service and takes care of everything around it: starting it in a
|
|
15
|
+
container (via the
|
|
16
|
+
[signalk-container](https://www.npmjs.com/package/signalk-container)
|
|
17
|
+
plugin), checking that it stays healthy, and telling the rest of the voice
|
|
18
|
+
stack where to find it. You never have to touch docker or podman yourself.
|
|
19
|
+
|
|
20
|
+
It is the wake-word building block of the
|
|
21
|
+
[signalk-wyoming voice-assistant family](https://github.com/hoeken/signalk-wyoming)
|
|
22
|
+
— install it together with the `signalk-wyoming` orchestrator,
|
|
23
|
+
`signalk-whisper` (speech to text), and `signalk-piper` (text to speech) to
|
|
24
|
+
get voice commands on your boat. Because it speaks the standard
|
|
25
|
+
[Wyoming protocol](https://github.com/rhasspy/wyoming), it also works as a
|
|
26
|
+
standalone wake word server for other software such as Home Assistant.
|
|
15
27
|
|
|
16
28
|
**Fully offline:** all wake word models ship inside the container image.
|
|
17
|
-
First start pulls the ~90 MB image and nothing else — no model downloads,
|
|
18
|
-
surprises at sea.
|
|
29
|
+
First start pulls the ~90 MB image and nothing else — no model downloads,
|
|
30
|
+
no surprises at sea.
|
|
19
31
|
|
|
20
32
|
## Requirements
|
|
21
33
|
|
|
22
|
-
- Signal K server ≥ 2.x on Node
|
|
23
|
-
- The
|
|
24
|
-
plugin with a working podman or docker runtime
|
|
34
|
+
- Signal K server ≥ 2.x on **Node 24+**
|
|
35
|
+
- The **signalk-container** plugin with a working podman or docker runtime
|
|
25
36
|
- ~384 MB RAM headroom for the container (the default memory cap)
|
|
26
37
|
- amd64 or arm64 (no armv7 — upstream stopped publishing it)
|
|
27
38
|
|
|
28
39
|
## Install
|
|
29
40
|
|
|
30
|
-
Install **signalk-openwakeword** from the Signal K App Store (
|
|
31
|
-
signalk-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`
|
|
35
|
-
container.
|
|
41
|
+
Install **signalk-openwakeword** from the Signal K App Store (or
|
|
42
|
+
`npm install signalk-openwakeword` in your server directory), enable it in
|
|
43
|
+
Plugin Config, and enable the signalk-container plugin if you have not
|
|
44
|
+
already. The plugin pulls and starts a pinned, tested release of the
|
|
45
|
+
service and reports `ready` once the detector actually answers — not just
|
|
46
|
+
once the container is up.
|
|
36
47
|
|
|
37
48
|
## Configuration
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
50
|
+
The plugin ships a graphical configuration panel (Server → Plugin Config →
|
|
51
|
+
openWakeWord) with a live container status card, a one-click image update
|
|
52
|
+
check/apply, a version dropdown fed by Docker Hub, wake word checkboxes
|
|
53
|
+
driven by the models the running service actually advertises, and all the
|
|
54
|
+
settings below — with inline warnings when a selected wake word is missing
|
|
55
|
+
or the service is open to the network. On servers without custom-panel
|
|
56
|
+
support you get a plain settings form with the same options.
|
|
57
|
+
|
|
58
|
+
| Setting | Default | Notes |
|
|
59
|
+
| ---------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `wakeWords` | `["okay_nabu"]` | Wake words your satellites use. See [Wake words & sensitivity](#wake-words--sensitivity). |
|
|
61
|
+
| `threshold` | `0.5` | Wake probability threshold (0–1). Lower = more sensitive, more false wakes. |
|
|
62
|
+
| `triggerLevel` | `1` | Activations above the threshold before a detection fires. Raise it in noisy cabins. |
|
|
63
|
+
| `port` | `10400` | Host TCP port the Wyoming service is published on. |
|
|
64
|
+
| `bind` | `0.0.0.0` | Host interface for the published port. See [Security](#security). |
|
|
65
|
+
| `imageTag` | `auto` | `auto` runs the pinned, tested upstream release (**2.1.0**) and follows plugin updates. Set an explicit Docker tag to pin something else. |
|
|
66
|
+
| `memoryLimit` | `384m` | Container memory cap (swap disabled). |
|
|
67
|
+
| `restartPolicy` | `unless-stopped` | Container restart policy. |
|
|
68
|
+
| `advanced.refractorySeconds` | _(unset)_ | Minimum seconds between re-detections (upstream default 2.0). |
|
|
69
|
+
| `advanced.customModels` | `false` | Load your own model files. See [Custom wake words](#custom-wake-words). |
|
|
70
|
+
| `advanced.advertiseHost` | _(unset)_ | Overrides the host part of the advertised `tcp://` URI (containerized Signal K, multi-NIC hosts). |
|
|
71
|
+
|
|
72
|
+
### Wake words & sensitivity
|
|
73
|
+
|
|
74
|
+
The built-in wake words are `okay_nabu` (default), `hey_jarvis`,
|
|
75
|
+
`hey_mycroft`, `alexa`, and `hey_rhasspy`. The `wakeWords` list is what
|
|
76
|
+
your satellites will listen for — it is validated against the running
|
|
77
|
+
service and shared with the `signalk-wyoming` orchestrator, and the config
|
|
78
|
+
panel warns you if a selected word is not available (note: upstream 2.0.0
|
|
79
|
+
renamed `ok_nabu` to `okay_nabu`; the old name silently matches nothing).
|
|
80
|
+
|
|
81
|
+
Tuning for your boat:
|
|
82
|
+
|
|
83
|
+
- **Missing wakes** (it doesn't hear you): lower `threshold` a little, e.g.
|
|
84
|
+
`0.4`.
|
|
85
|
+
- **False wakes** (it triggers on engine noise or conversation): raise
|
|
86
|
+
`threshold`, or raise `triggerLevel` to `2`–`3` so a single borderline
|
|
87
|
+
hit isn't enough.
|
|
88
|
+
- **Double triggers** from one utterance: set
|
|
89
|
+
`advanced.refractorySeconds` (upstream default is 2 seconds between
|
|
90
|
+
re-detections).
|
|
91
|
+
|
|
92
|
+
## Custom wake words
|
|
93
|
+
|
|
94
|
+
Want your boat to answer to its own name? Enable
|
|
95
|
+
`advanced.customModels`, then drop openWakeWord `.tflite` model files into
|
|
96
|
+
the `custom/` folder inside the **signalk-container** plugin's data
|
|
97
|
+
directory (`<signalk>/plugin-config-data/signalk-container/custom/` —
|
|
98
|
+
create `custom/` if it doesn't exist; note this is signalk-container's
|
|
99
|
+
directory, shared by all plugins that use it, not this plugin's own) and
|
|
100
|
+
restart the plugin. If Signal K itself runs in a container with a
|
|
101
|
+
volume-backed data directory, put the files in the corresponding location
|
|
102
|
+
inside that volume. A `_v1.0`-style filename suffix is stripped for the
|
|
103
|
+
model id. A webapp upload UI is planned for v1.x; the manual drop works
|
|
104
|
+
today.
|
|
52
105
|
|
|
53
106
|
## Using it from other software
|
|
54
107
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
`wyoming-service` PropertyValues convention:
|
|
108
|
+
Once ready, the service is a plain Wyoming wake word server at
|
|
109
|
+
`tcp://<boat-server>:10400`:
|
|
58
110
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
111
|
+
- **signalk-wyoming** discovers it automatically — nothing to configure.
|
|
112
|
+
- **Remote satellites** (cockpit Pis running `wyoming-satellite`) point at
|
|
113
|
+
it with `--wake-uri tcp://<boat-server>:10400 --wake-word-name okay_nabu`.
|
|
114
|
+
- **Home Assistant** (or any other Wyoming client) can use it via the
|
|
115
|
+
Wyoming integration at the same URI — no Signal K required on the client
|
|
116
|
+
side.
|
|
62
117
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
118
|
+
## HTTP API
|
|
119
|
+
|
|
120
|
+
| Endpoint | Access | Purpose |
|
|
121
|
+
| ----------------------------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------- |
|
|
122
|
+
| `GET /plugins/signalk-openwakeword/api/status` | any authenticated user | Current state: `{ status, uri, tag, containerState, lastHealth, info }` |
|
|
123
|
+
| `GET /plugins/signalk-openwakeword/api/versions` | any authenticated user | Available image versions from Docker Hub (feeds the config panel; works while plugin disabled) |
|
|
124
|
+
| `GET /plugins/signalk-openwakeword/api/update/check` | admin | Check whether a newer image is available |
|
|
125
|
+
| `POST /plugins/signalk-openwakeword/api/update/apply` | admin | Pull and switch to the newer image |
|
|
67
126
|
|
|
68
127
|
## Health & notifications
|
|
69
128
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
for the service, running).
|
|
79
|
-
- `GET /plugins/signalk-openwakeword/api/status` returns
|
|
80
|
-
`{ status, uri, tag, containerState, lastHealth, info }` (readonly access).
|
|
81
|
-
`GET /api/update/check` / `POST /api/update/apply` (admin) manage container
|
|
82
|
-
image updates.
|
|
129
|
+
The plugin checks the service every 30 seconds. If it stops answering,
|
|
130
|
+
after three consecutive failures (about 90 seconds) it raises the Signal K
|
|
131
|
+
notification **`notifications.voice.openwakeword`** with `state: "alarm"`
|
|
132
|
+
and shows an error in Plugin Config. When the service answers again
|
|
133
|
+
everything clears back to normal automatically — no action needed.
|
|
134
|
+
|
|
135
|
+
The alarm is visual-only by design: plugins that read notifications aloud
|
|
136
|
+
won't try to _speak_ the voice stack's own failure.
|
|
83
137
|
|
|
84
138
|
## Security
|
|
85
139
|
|
|
86
|
-
|
|
140
|
+
Wyoming has **no authentication.** Unlike whisper/piper (loopback-only by
|
|
87
141
|
default), the wake word service must be reachable from your LAN so remote
|
|
88
142
|
satellites can stream audio to it — that is why `bind` defaults to
|
|
89
143
|
`0.0.0.0`. The exposure is modest (openWakeWord only ever sees audio a
|
|
@@ -93,35 +147,10 @@ satellite port like a baby monitor. On marina wifi, put the boat network
|
|
|
93
147
|
behind a firewall or VLAN, or use WireGuard between boat segments. If every
|
|
94
148
|
satellite runs on the server itself, set `bind` to `127.0.0.1`.
|
|
95
149
|
|
|
96
|
-
## Custom wake words
|
|
97
|
-
|
|
98
|
-
Enable `advanced.customModels`, then drop openWakeWord `.tflite` model files
|
|
99
|
-
into the `custom/` folder inside the **signalk-container** plugin's data
|
|
100
|
-
directory (`<signalk>/plugin-config-data/signalk-container/custom/` — create
|
|
101
|
-
`custom/` if it doesn't exist) and restart the plugin. The mount is provided
|
|
102
|
-
by signalk-container's `signalkDataMount`, which always maps `/data` to
|
|
103
|
-
signalk-container's _own_ data directory (shared by every plugin that uses
|
|
104
|
-
it), **not** to this plugin's `plugin-config-data/signalk-openwakeword/`
|
|
105
|
-
directory. If Signal K itself runs in a container with a volume-backed data
|
|
106
|
-
directory, put the files in the corresponding location inside that volume.
|
|
107
|
-
The container loads them via `--custom-model-dir /data/custom`; a `_v1.0`
|
|
108
|
-
style filename suffix is stripped for the model id. A webapp upload UI is
|
|
109
|
-
planned for v1.x; the manual drop works today.
|
|
110
|
-
|
|
111
150
|
## Development
|
|
112
151
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
npm run build # tsc → dist/
|
|
116
|
-
npm test # typecheck + vitest (mock Wyoming server, fake container manager)
|
|
117
|
-
npm run ci-lint # eslint + prettier --check
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Tests never touch docker: the container manager is faked and the Wyoming
|
|
121
|
-
endpoint is the scriptable `signalk-wyoming/mock` server (a devDependency
|
|
122
|
-
on the [signalk-wyoming](https://github.com/hoeken/signalk-wyoming)
|
|
123
|
-
package). Production code has no runtime dependency on it — the plugin
|
|
124
|
-
embeds its own ~150-line `describe` client.
|
|
152
|
+
See [DEVELOPERS.md](DEVELOPERS.md) for the code layout, build/test
|
|
153
|
+
commands, architecture notes, and the service-discovery contract.
|
|
125
154
|
|
|
126
155
|
## License
|
|
127
156
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,0BAA0B,CAAC;AAalC,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,iBAAiB,CACf,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAC/B,IAAI,CAAC;IACR,iBAAiB,CAAC,IAAI;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC;CAC/E;AAOD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,4DAA4D;IAC5D,MAAM,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;CACtD;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,kBAAkB,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;CACpD;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,GAAG,EAAE,SAAS,EACd,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM,GACjC,kBAAkB,CAgJpB"}
|
package/dist/index.js
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* advertises the service on the shared `wyoming-service` PropertyValues
|
|
7
7
|
* convention, and keeps a protocol-native health loop running.
|
|
8
8
|
*/
|
|
9
|
-
import { ManagedContainer, startSafely, errMsg, } from "signalk-container-helper";
|
|
9
|
+
import { ManagedContainer, startSafely, errMsg, fetchWithTimeout, } from "signalk-container-helper";
|
|
10
10
|
import { buildContainerConfig, CONFIG_SCHEMA, CONTAINER_NAME, IMAGE, isSemverTag, PLUGIN_ID, PLUGIN_NAME, resolveTag, withDefaults, } from "./config.js";
|
|
11
11
|
import { ServiceRunner, } from "./service.js";
|
|
12
|
+
/** Docker Hub tag listing backing the config panel's version dropdown. */
|
|
13
|
+
const TAGS_URL = `https://hub.docker.com/v2/repositories/${IMAGE}/tags/?page_size=25`;
|
|
12
14
|
/**
|
|
13
15
|
* Plugin factory. The optional `timing` parameter is a test seam — the
|
|
14
16
|
* Signal K loader only ever passes `app`.
|
|
@@ -115,7 +117,44 @@ export default function createPlugin(app, timing = {}) {
|
|
|
115
117
|
res.status(500).json({ error: errMsg(err) });
|
|
116
118
|
}
|
|
117
119
|
}));
|
|
120
|
+
// Version-dropdown feed for the config panel. Deliberately not
|
|
121
|
+
// guarded by the running flag: the operator picks a tag while the
|
|
122
|
+
// plugin is still disabled, and the route only reaches out on demand.
|
|
123
|
+
readonlyRouter.get("/api/versions", async (_req, res) => {
|
|
124
|
+
try {
|
|
125
|
+
const response = await fetchWithTimeout(TAGS_URL, {
|
|
126
|
+
timeoutMs: 10_000,
|
|
127
|
+
});
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
res
|
|
130
|
+
.status(502)
|
|
131
|
+
.json({ error: `Docker Hub answered HTTP ${response.status}` });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const body = (await response.json());
|
|
135
|
+
const versions = (Array.isArray(body.results) ? body.results : [])
|
|
136
|
+
.map((r) => (typeof r?.name === "string" ? r.name : ""))
|
|
137
|
+
.filter(isSemverTag)
|
|
138
|
+
.sort(compareSemverDesc)
|
|
139
|
+
.map((tag) => ({ tag }));
|
|
140
|
+
res.json({ versions });
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
res.status(502).json({ error: errMsg(err) });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
118
146
|
},
|
|
119
147
|
};
|
|
120
148
|
}
|
|
149
|
+
/** Numeric-descending compare for the plain x.y.z tags isSemverTag admits. */
|
|
150
|
+
function compareSemverDesc(a, b) {
|
|
151
|
+
const pa = a.split(".").map(Number);
|
|
152
|
+
const pb = b.split(".").map(Number);
|
|
153
|
+
for (let i = 0; i < 3; i += 1) {
|
|
154
|
+
const d = (pb[i] ?? 0) - (pa[i] ?? 0);
|
|
155
|
+
if (d !== 0)
|
|
156
|
+
return d;
|
|
157
|
+
}
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
121
160
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalk-openwakeword",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Wyoming openWakeWord wake word detection service for Signal K — runs rhasspy/wyoming-openwakeword in a managed container.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
|
+
"public",
|
|
10
11
|
"README.md",
|
|
11
12
|
"LICENSE"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
|
-
"build": "tsc",
|
|
15
|
+
"build": "tsc && webpack",
|
|
15
16
|
"test": "npm run typecheck:test && vitest run",
|
|
16
17
|
"test:watch": "vitest",
|
|
17
18
|
"typecheck": "tsc --noEmit",
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"prepublishOnly": "npm run build && npm test"
|
|
26
27
|
},
|
|
27
28
|
"lint-staged": {
|
|
28
|
-
"*.ts": [
|
|
29
|
+
"*.{ts,jsx}": [
|
|
29
30
|
"eslint --fix",
|
|
30
31
|
"prettier --write"
|
|
31
32
|
],
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
},
|
|
34
35
|
"keywords": [
|
|
35
36
|
"signalk-node-server-plugin",
|
|
37
|
+
"signalk-plugin-configurator",
|
|
36
38
|
"signalk-category-utility",
|
|
37
39
|
"wyoming",
|
|
38
40
|
"openwakeword",
|
|
@@ -56,21 +58,28 @@
|
|
|
56
58
|
"node": ">=24"
|
|
57
59
|
},
|
|
58
60
|
"dependencies": {
|
|
59
|
-
"signalk-container-helper": "^0.1
|
|
61
|
+
"signalk-container-helper": "^0.2.1"
|
|
60
62
|
},
|
|
61
63
|
"devDependencies": {
|
|
64
|
+
"@babel/core": "^7.29.0",
|
|
65
|
+
"@babel/preset-react": "^7.28.5",
|
|
62
66
|
"@eslint/js": "^10.0.1",
|
|
63
67
|
"@signalk/server-api": "^2.30.0",
|
|
64
68
|
"@types/node": "^24.0.0",
|
|
69
|
+
"babel-loader": "^10.1.1",
|
|
65
70
|
"eslint": "^10.2.0",
|
|
66
71
|
"eslint-config-prettier": "^10.1.8",
|
|
67
72
|
"globals": "^17.4.0",
|
|
68
73
|
"husky": "^9.1.7",
|
|
69
74
|
"lint-staged": "^16.4.0",
|
|
70
75
|
"prettier": "^3.8.1",
|
|
76
|
+
"react": "^19.2.4",
|
|
77
|
+
"react-dom": "^19.2.4",
|
|
71
78
|
"signalk-wyoming": "^0.1.0",
|
|
72
79
|
"typescript": "^5.5.0",
|
|
73
80
|
"typescript-eslint": "^8.58.0",
|
|
74
|
-
"vitest": "^4.1.10"
|
|
81
|
+
"vitest": "^4.1.10",
|
|
82
|
+
"webpack": "^5.105.4",
|
|
83
|
+
"webpack-cli": "^7.0.2"
|
|
75
84
|
}
|
|
76
85
|
}
|
package/public/172.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const __webpack_esm_id__=172;export const __webpack_esm_ids__=[172];export const __webpack_esm_modules__={172(e,t,r){r.d(t,{default:()=>S}),r.r(t);var n=r(231);function a(e,t={}){const{stableCount:r=5,preCount:n=3}=t,a=e.filter(e=>"number"==typeof e.pr),o=e.filter(e=>"number"!=typeof e.pr);return{prVersions:a,stableVersions:o.filter(e=>!e.prerelease).slice(0,r),preVersions:o.filter(e=>e.prerelease).slice(0,n)}}const o={root:{fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',color:"#333",padding:"16px 0"},sectionTitle:{fontSize:13,fontWeight:600,color:"#888",textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:10,marginTop:24},btn:{display:"inline-flex",alignItems:"center",gap:8,padding:"8px 16px",border:"none",borderRadius:6,fontSize:13,fontWeight:600,cursor:"pointer"},btnPrimary:{background:"#3b82f6",color:"#fff"},btnSecondary:{background:"#f1f5f9",color:"#475569",border:"1px solid #e2e8f0"},btnWarn:{background:"#f59e0b",color:"#fff"},btnDanger:{background:"#ef4444",color:"#fff"},btnDisabled:{opacity:.5,cursor:"not-allowed"},btnSmall:{padding:"4px 12px",fontSize:12},status:{marginTop:8,fontSize:12,minHeight:18},card:{display:"flex",alignItems:"center",gap:14,padding:"14px 18px",background:"#f8f9fa",border:"1px solid #e0e0e0",borderRadius:10,marginBottom:12},cardIcon:{width:44,height:44,borderRadius:10,display:"flex",alignItems:"center",justifyContent:"center",fontSize:20,fontWeight:700,flexShrink:0},cardInfo:{flex:1},cardTitle:{fontSize:15,fontWeight:600,color:"#333"},cardMeta:{fontSize:12,color:"#888"},stateIndicator:{width:10,height:10,borderRadius:"50%",flexShrink:0},fieldRow:{display:"flex",alignItems:"center",gap:12,marginBottom:10},label:{fontSize:13,fontWeight:500,color:"#555",width:180,flexShrink:0},select:{padding:"6px 10px",borderRadius:6,border:"1px solid #ccc",fontSize:13,background:"#fff",color:"#333",minWidth:200},input:{padding:"6px 10px",borderRadius:6,border:"1px solid #ccc",fontSize:13,background:"#fff",color:"#333",width:200},inputSmall:{padding:"6px 10px",borderRadius:6,border:"1px solid #ccc",fontSize:13,background:"#fff",color:"#333",width:80},checkbox:{width:16,height:16,accentColor:"#3b82f6"},hint:{fontSize:11,color:"#aaa",marginLeft:8},link:{color:"#3b82f6",textDecoration:"none",fontSize:13,fontWeight:600},textarea:{padding:"6px 10px",borderRadius:6,border:"1px solid #ccc",fontSize:13,fontFamily:"monospace",background:"#fff",color:"#333",width:"100%",minHeight:70,boxSizing:"border-box",resize:"vertical"},empty:{textAlign:"center",padding:"30px 16px",color:"#999",fontSize:13},tag:{display:"inline-block",padding:"2px 8px",borderRadius:4,fontSize:10,fontWeight:600,marginLeft:8},tagPre:{background:"#fef3c7",color:"#92400e"},tagLatest:{background:"#dcfce7",color:"#166534"},warnBanner:{padding:"12px 16px",background:"#fef2f2",border:"1px solid #fecaca",borderRadius:10,marginBottom:12,fontSize:13,color:"#991b1b",lineHeight:1.5},warnBannerTitle:{fontWeight:700,marginBottom:4},infoBanner:{padding:"12px 16px",background:"#fffbeb",border:"1px solid #fde68a",borderRadius:10,marginBottom:12,fontSize:13,color:"#92400e",lineHeight:1.5},bannerCode:{display:"block",marginTop:8,padding:"8px 10px",background:"#fff",border:"1px solid #fecaca",borderRadius:6,fontFamily:"monospace",fontSize:12,color:"#7f1d1d",whiteSpace:"pre-wrap",wordBreak:"break-word"},statsGrid:{display:"grid",gridTemplateColumns:"repeat(auto-fit, minmax(140px, 1fr))",gap:10,marginBottom:12},statCard:{padding:"12px 16px",background:"#f8f9fa",border:"1px solid #e0e0e0",borderRadius:10,textAlign:"center"},statValue:{fontSize:22,fontWeight:700,color:"#333"},statLabel:{fontSize:11,color:"#888",marginTop:2}},l={ok:"#10b981",warn:"#f59e0b",error:"#ef4444"};function i(e){const{runningTag:t,tagKind:r,currentVersion:n,latestVersion:a,updateAvailable:o,reason:l,fromCache:i,lastSuccessfulCheckAt:s}=e??{};return"offline"===l?i&&s?`Offline — last checked ${function(e){try{const t=new Date(e).getTime(),r=Math.max(0,Math.floor((Date.now()-t)/1e3));if(r<5)return"just now";if(r<60)return`${r}s ago`;const n=Math.floor(r/60);if(n<60)return`${n}m ago`;const a=Math.floor(n/60);return a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`}catch{return e}}(s)}: ${o?"update available":"up to date"}`:"Offline — never checked yet":"newer-version"===l?`Update available: ${n} → ${a}`:"digest-drift"===l?`Image rebuild available for :${t}${a?` (latest stable: ${a})`:""}`:"up-to-date"===l?"floating"===r&&a?`Up to date with :${t} (latest stable: ${a})`:`Up to date (${n||t})`:"older-than-pinned"===l?`Pinned to ${n}; latest stable is ${a}`:"error"===l?`Check error: ${e?.error||"unknown"}`:`State: ${l||"unknown"}`}function s({children:e}){return n.createElement("div",{style:o.sectionTitle},e)}function c({children:e,color:t}){return n.createElement("span",{style:{...o.hint,...t?{color:t}:{}}},e)}function d({label:e,hint:t,hintColor:r,children:a}){return n.createElement("div",{style:o.fieldRow},n.createElement("span",{style:o.label},e),a,null!=t&&""!==t&&n.createElement(c,{color:r},t))}function u({state:e="ok",color:t,title:r,style:a}){return n.createElement("div",{style:{...o.stateIndicator,background:t??l[e],...a},title:r})}function p({icon:e,iconBackground:t,iconColor:r,title:a,meta:i,state:s="ok",stateTitle:c,link:d,children:p}){const m="error"===s&&!t;return n.createElement("div",{style:o.card},n.createElement("div",{style:{...o.cardIcon,background:m?"#fef2f2":t??"#3b82f6",color:m?l.error:r??"#fff"}},e),n.createElement("div",{style:o.cardInfo},n.createElement("div",{style:o.cardTitle},a),null!=i&&n.createElement("div",{style:o.cardMeta},i)),p,d&&n.createElement("a",{href:d.href,target:"_blank",rel:"noopener noreferrer",style:o.link},d.label),n.createElement(u,{state:s,title:c}))}function m({title:e,defaultOpen:t=!1,children:r}){const[a,l]=(0,n.useState)(t);return n.createElement("div",null,n.createElement("button",{type:"button","aria-expanded":a,style:{...o.sectionTitle,cursor:"pointer",userSelect:"none",display:"flex",alignItems:"center",gap:6,width:"100%",textAlign:"left",background:"none",border:"none",padding:0},onClick:()=>l(!a)},n.createElement("span",{style:{fontSize:10,transition:"transform 0.15s",transform:a?"rotate(90deg)":"rotate(0deg)"}},"▶"),e),a&&n.createElement("div",{style:{marginBottom:16}},r))}const g={primary:o.btnPrimary,secondary:o.btnSecondary,warn:o.btnWarn,danger:o.btnDanger};function f({variant:e="primary",small:t=!1,busy:r=!1,busyLabel:a,disabled:l=!1,onClick:i,title:s,style:c,children:d}){const u=l||r;return n.createElement("button",{type:"button",style:{...o.btn,...g[e],...t?o.btnSmall:{},...u?o.btnDisabled:{},...c},onClick:i,disabled:u,title:s},r?a??d:d)}function b({message:e,error:t=!1,style:r}){return e?n.createElement("div",{style:{...o.status,color:t?l.error:l.ok,marginTop:16,...r}},e):null}const h=[{tag:"latest",label:"latest (recommended)"}];function y({value:e,onChange:t,versions:r,floatingOptions:i=h,stableCount:s,preCount:d,loading:u=!1,error:p,onRefresh:m,disabled:g=!1,style:b}){const y={stableCount:s,preCount:d},{prVersions:k,stableVersions:v,preVersions:w}=a(r,y),E=function(e,t,r=["latest"],n={}){return e?function(e,t=["latest"],r={}){const{prVersions:n,stableVersions:o,preVersions:l}=a(e,r);return new Set([...t,...l.map(e=>e.tag),...o.map(e=>e.tag),...n.map(e=>e.tag)])}(t,r,n).has(e)?null:e:null}(e,r,i.map(e=>e.tag),y);return n.createElement(n.Fragment,null,n.createElement("select",{style:{...o.select,...b},value:e,onChange:e=>t(e.target.value),disabled:g},i.map(e=>n.createElement("option",{key:e.tag,value:e.tag},e.label??e.tag)),w.map(e=>n.createElement("option",{key:e.tag,value:e.tag},e.tag," (pre-release)")),v.map((e,t)=>n.createElement("option",{key:e.tag,value:e.tag},e.tag,0===t?" (current stable)":"")),k.length>0&&n.createElement("optgroup",{label:"PR test images"},k.map(e=>n.createElement("option",{key:e.tag,value:e.tag},e.tag,e.title?` — ${e.title}`:""))),E&&n.createElement("option",{value:E},E," (running)")),u&&n.createElement(c,null,"loading releases..."),m&&n.createElement(f,{small:!0,style:{padding:"4px 10px",fontSize:11},onClick:m,title:"Refresh available versions"},"↻"),p&&n.createElement(c,{color:l.error},p))}function k({checkUrl:e,applyUrl:t,tag:r,onApplied:a,updateLabel:o="Update",disabled:s=!1,style:c}){const d=function(e){const{checkUrl:t,applyUrl:r}=e,[a,o]=(0,n.useState)(!1),[l,i]=(0,n.useState)(!1),[s,c]=(0,n.useState)(null),[d,u]=(0,n.useState)("");return{checking:a,applying:l,result:s,error:d,check:(0,n.useCallback)(async()=>{o(!0),u("");try{const e=await fetch(t),r=await e.json().catch(()=>null);if(e.ok&&r&&"object"==typeof r)c(r);else{const t=r?.error??`HTTP ${e.status}`;u(`Check failed: ${t}`)}}catch(e){u(`Check failed: ${e instanceof Error?e.message:String(e)}`)}o(!1)},[t]),apply:(0,n.useCallback)(async e=>{let t;i(!0),u("");try{const n=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e?{tag:e}:{})}),a=await n.json().catch(()=>null);n.ok?(t={ok:!0,tag:a?.tag},c(null)):(t={ok:!1,error:a?.error??`HTTP ${n.status}`},u(`Update failed: ${t.error}`))}catch(e){t={ok:!1,error:e instanceof Error?e.message:String(e)},u(`Update failed: ${t.error}`)}return i(!1),t},[r])}}({checkUrl:e,applyUrl:t}),[u,p]=(0,n.useState)("");return n.createElement("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:12,...c}},d.result?.updateAvailable?n.createElement(n.Fragment,null,n.createElement("span",{style:{fontSize:13}},i(d.result)),n.createElement(f,{small:!0,variant:"warn",busy:d.applying,busyLabel:"Updating...",disabled:s||d.checking,onClick:()=>{(async()=>{p("");const e=await d.apply(r);e.ok&&(p(e.tag?`Updated to ${e.tag}.`:"Updated."),a?.(e.tag))})()},title:"Pull the image and recreate the container"},o)):d.result?n.createElement("span",{style:{fontSize:12,color:"#888"}},i(d.result)):n.createElement(f,{small:!0,variant:"secondary",busy:d.checking,busyLabel:"Checking...",disabled:s||d.applying,onClick:()=>{d.check()}},"Check for updates"),u&&n.createElement("span",{style:{fontSize:12,color:l.ok}},u),d.error&&n.createElement("span",{style:{fontSize:12,color:l.error}},d.error))}const v="/plugins/signalk-openwakeword",w={imageTag:"auto",bind:"0.0.0.0",wakeWords:["okay_nabu"],threshold:.5,triggerLevel:1,memoryLimit:"384m",restartPolicy:"unless-stopped"},E=["okay_nabu","hey_jarvis","hey_mycroft","alexa","hey_rhasspy"];function S({configuration:e,save:t}){const r=e||{},a=r.advanced||{},[i,c]=(0,n.useState)(()=>{const e=Array.isArray(r.wakeWords)?r.wakeWords.filter(e=>"string"==typeof e&&""!==e):[];return e.length>0?e:[...w.wakeWords]}),[u,g]=(0,n.useState)(""),[h,S]=(0,n.useState)(String("number"==typeof r.threshold?r.threshold:w.threshold)),[x,C]=(0,n.useState)(String("number"==typeof r.triggerLevel?r.triggerLevel:w.triggerLevel)),[$,z]=(0,n.useState)(String(r.port??10400)),[T,_]=(0,n.useState)("127.0.0.1"===r.bind?"127.0.0.1":w.bind),[A,R]=(0,n.useState)(r.imageTag||w.imageTag),[W,I]=(0,n.useState)(r.memoryLimit||w.memoryLimit),[L,U]=(0,n.useState)(r.restartPolicy||w.restartPolicy),[B,H]=(0,n.useState)("number"==typeof a.refractorySeconds?String(a.refractorySeconds):""),[N,P]=(0,n.useState)(!0===a.customModels),[j,V]=(0,n.useState)("string"==typeof a.advertiseHost?a.advertiseHost:""),[M,D]=(0,n.useState)(""),{status:F,loading:O,refresh:G}=function(e,t={}){const{intervalMs:r=5e3}=t,[a,o]=(0,n.useState)(null),[l,i]=(0,n.useState)(!0),s=(0,n.useRef)(0),c=(0,n.useRef)(t.fallback??null),d=(0,n.useCallback)(async t=>{const r=++s.current;let n=c.current;try{const r=await fetch(e,{signal:t}),a=await r.json().catch(()=>null);a&&"object"==typeof a&&(n=a)}catch{}r===s.current&&(o(n),i(!1))},[e]);return(0,n.useEffect)(()=>{let e=!1,t=null;const n=new AbortController,a=async()=>{await d(n.signal),!e&&r>0&&(t=setTimeout(a,r))};return a(),()=>{e=!0,n.abort(),t&&clearTimeout(t)}},[d,r]),{status:a,loading:l,refresh:()=>d()}}(`${v}/api/status`,{fallback:{status:"not_running"}}),K=function(e){const[t,r]=(0,n.useState)([]),[a,o]=(0,n.useState)(""),[l,i]=(0,n.useState)(!1),s=(0,n.useRef)(0),c=(0,n.useCallback)(async()=>{const t=++s.current;i(!0);try{const n=await fetch(e),a=await n.json().catch(()=>null),l=function(e,t){if(!e)return{versions:null,versionsError:"⚠ Could not reach GitHub — showing last known versions, retry"};const r=t&&"object"==typeof t?t:{},n=Array.isArray(r)?r:Array.isArray(r.versions)?r.versions:[],a=!Array.isArray(r)&&r.sources&&"object"==typeof r.sources?r.sources:{};let o="";return"rate-limited"===a.prImages?o="⚠ GitHub rate-limited — PR test images temporarily unavailable, retry shortly":"rate-limited"===a.releases?o="⚠ GitHub rate-limited — some versions temporarily unavailable, retry shortly":"error"!==a.prImages&&"error"!==a.releases||(o="⚠ Could not fetch some versions from GitHub, retry"),{versions:n,versionsError:o}}(n.ok,a);if(t!==s.current)return;null!==l.versions&&r(l.versions),o(l.versionsError)}catch{if(t!==s.current)return;o("⚠ Offline — showing last known versions")}i(!1)},[e]);return(0,n.useEffect)(()=>{c()},[c]),{versions:t,versionsError:a,loading:l,refresh:c}}(`${v}/api/versions`),q=F&&"string"==typeof F.status?F.status:"not_running",J="ready"===q?"ok":"starting"===q?"warn":"error",Q=function(e){const t=[];if(!e||!Array.isArray(e.wake))return t;for(const r of e.wake)if(r&&Array.isArray(r.models))for(const e of r.models)e&&"string"==typeof e.name&&""!==e.name&&t.push(e.name);return t}(F&&F.info),X=O?"Checking...":"ready"===q?`rhasspy/wyoming-openwakeword:${F.tag} at ${F.uri}`+(Q.length>0?` — ${Q.length} wake word model${1===Q.length?"":"s"}`:""):"starting"===q?"Starting — wake word models ship in the image, nothing to download":"error"===q?"Not answering"+(F&&F.uri?` at ${F.uri}`:""):"Not running",Y=Q.length>0?Q:E,Z=[...Y,...i.filter(e=>!Y.includes(e))],ee="ready"===q&&Q.length>0?i.filter(e=>!Q.includes(e)):[],te=()=>{const e=u.trim();g(""),""===e||i.includes(e)||c(t=>[...t,e])};return n.createElement("div",{style:o.root},n.createElement(s,null,"openWakeWord status"),n.createElement(p,{icon:"O",iconBackground:"ready"===q?"#7c3aed":void 0,title:"openWakeWord (Wyoming)",meta:X,state:J,stateTitle:q}),"not_running"!==q&&"stopped"!==q&&n.createElement(k,{checkUrl:`${v}/api/update/check`,applyUrl:`${v}/api/update/apply`,tag:A,onApplied:()=>{G()}}),n.createElement(s,null,"Settings"),n.createElement(d,{label:"Wake words",hint:ee.length>0?`not available on the running service: ${ee.join(", ")} (2.0.0 renamed ok_nabu to okay_nabu)`:"what satellites can listen for; clients select models per connection",hintColor:ee.length>0?l.warn:void 0},n.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:"6px 16px"}},Z.map(e=>n.createElement("label",{key:e,style:{display:"inline-flex",alignItems:"center",gap:6,fontSize:13}},n.createElement("input",{style:o.checkbox,type:"checkbox",checked:i.includes(e),onChange:()=>(e=>{c(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])})(e)}),e)))),n.createElement(d,{label:"Add wake word",hint:"a model name not listed above (e.g. a custom model, before its first start)"},n.createElement("input",{style:{...o.input,width:180},value:u,onChange:e=>g(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),te())},placeholder:"model_name"}),n.createElement(f,{variant:"secondary",onClick:te},"Add")),n.createElement(d,{label:"Detection threshold",hint:"0–1; lower = more sensitive but more false wakes"},n.createElement("input",{style:{...o.input,width:90},type:"number",min:"0",max:"1",step:"0.05",value:h,onChange:e=>S(e.target.value)})),n.createElement(d,{label:"Trigger level",hint:"activations above the threshold before a detection fires; raise in noisy cabins"},n.createElement("input",{style:{...o.input,width:90},type:"number",min:"1",step:"1",value:x,onChange:e=>C(e.target.value)})),n.createElement(d,{label:"Image version"},n.createElement(y,{value:A,onChange:R,versions:K.versions,floatingOptions:[{tag:"auto",label:"auto (pinned release, recommended)"}],loading:K.loading,error:K.versionsError,onRefresh:K.refresh})),n.createElement(d,{label:"Host port",hint:"satellites connect to tcp://<boat-server>:<this port>"},n.createElement("input",{style:{...o.input,width:90},type:"number",value:$,onChange:e=>z(e.target.value)})),n.createElement(d,{label:"Bind address",hint:"0.0.0.0"===T?"LAN-reachable — required for remote satellites; Wyoming has no authentication, firewall/VLAN on marina wifi":"only satellites on this machine can reach the service",hintColor:"0.0.0.0"===T?l.warn:void 0},n.createElement("select",{style:o.select,value:T,onChange:e=>_(e.target.value)},n.createElement("option",{value:"0.0.0.0"},"0.0.0.0 (all interfaces)"),n.createElement("option",{value:"127.0.0.1"},"127.0.0.1 (this machine only)"))),n.createElement(m,{title:"Advanced"},n.createElement(d,{label:"Refractory seconds",hint:"optional minimum seconds between re-detections; upstream default 2.0"},n.createElement("input",{style:{...o.input,width:90},type:"number",step:"0.5",value:B,onChange:e=>H(e.target.value)})),n.createElement(d,{label:"Custom wake word models",hint:"load .tflite files from plugin-config-data/signalk-container/custom/ (--custom-model-dir)"},n.createElement("input",{style:o.checkbox,type:"checkbox",checked:N,onChange:e=>P(e.target.checked)})),n.createElement(d,{label:"Advertise host",hint:"optional host override for the advertised tcp:// URI (containerized Signal K, multi-NIC)"},n.createElement("input",{style:{...o.input,width:180},value:j,onChange:e=>V(e.target.value),placeholder:"automatic"})),n.createElement(d,{label:"Memory limit",hint:'hard cap, e.g. "384m" or "1g"'},n.createElement("input",{style:{...o.input,width:90},value:W,onChange:e=>I(e.target.value)})),n.createElement(d,{label:"Restart policy"},n.createElement("select",{style:o.select,value:L,onChange:e=>U(e.target.value)},n.createElement("option",{value:"unless-stopped"},"unless-stopped"),n.createElement("option",{value:"always"},"always"),n.createElement("option",{value:"no"},"no")))),n.createElement("div",{style:{marginTop:24}},n.createElement(f,{onClick:()=>{const e={customModels:N},n=Number(B);""!==B&&Number.isFinite(n)&&(e.refractorySeconds=n),""!==j.trim()&&(e.advertiseHost=j.trim());const a=Number(h),o=Number(x),l=Number($);t({...r,wakeWords:i.length>0?i:[...w.wakeWords],threshold:""!==h&&Number.isFinite(a)?a:w.threshold,triggerLevel:""!==x&&Number.isFinite(o)?o:w.triggerLevel,port:""!==$&&Number.isFinite(l)?l:10400,bind:T,imageTag:A,memoryLimit:W,restartPolicy:L,advanced:e}),D("Saved. Signal K restarts the plugin with the new configuration.")}},"Save Configuration")),n.createElement(b,{message:M}))}}};
|
package/public/540.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 540.mjs.LICENSE.txt */
|
|
2
|
+
export const __webpack_esm_id__=540;export const __webpack_esm_ids__=[540];export const __webpack_esm_modules__={869(e,t){var n=Symbol.for("react.transitional.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),u=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),i=Symbol.for("react.context"),a=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),l=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),d=Symbol.iterator,_={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,m={};function b(e,t,n){this.props=e,this.context=t,this.refs=m,this.updater=n||_}function v(){}function S(e,t,n){this.props=e,this.context=t,this.refs=m,this.updater=n||_}b.prototype.isReactComponent={},b.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},b.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},v.prototype=b.prototype;var E=S.prototype=new v;E.constructor=S,h(E,b.prototype),E.isPureReactComponent=!0;var w=Array.isArray;function g(){}var k={H:null,A:null,T:null,S:null},H=Object.prototype.hasOwnProperty;function j(e,t,r){var o=r.ref;return{$$typeof:n,type:e,key:t,ref:void 0!==o?o:null,props:r}}function R(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}var C=/\/+/g;function $(e,t){return"object"==typeof e&&null!==e&&null!=e.key?(n=""+e.key,r={"=":"=0",":":"=2"},"$"+n.replace(/[=:]/g,function(e){return r[e]})):t.toString(36);var n,r}function x(e,t,o,u,c){var s=typeof e;"undefined"!==s&&"boolean"!==s||(e=null);var i,a,f=!1;if(null===e)f=!0;else switch(s){case"bigint":case"string":case"number":f=!0;break;case"object":switch(e.$$typeof){case n:case r:f=!0;break;case p:return x((f=e._init)(e._payload),t,o,u,c)}}if(f)return c=c(e),f=""===u?"."+$(e,0):u,w(c)?(o="",null!=f&&(o=f.replace(C,"$&/")+"/"),x(c,t,o,"",function(e){return e})):null!=c&&(R(c)&&(i=c,a=o+(null==c.key||e&&e.key===c.key?"":(""+c.key).replace(C,"$&/")+"/")+f,c=j(i.type,a,i.props)),t.push(c)),1;f=0;var l,y=""===u?".":u+":";if(w(e))for(var _=0;_<e.length;_++)f+=x(u=e[_],t,o,s=y+$(u,_),c);else if("function"==typeof(_=null===(l=e)||"object"!=typeof l?null:"function"==typeof(l=d&&l[d]||l["@@iterator"])?l:null))for(e=_.call(e),_=0;!(u=e.next()).done;)f+=x(u=u.value,t,o,s=y+$(u,_++),c);else if("object"===s){if("function"==typeof e.then)return x(function(e){switch(e.status){case"fulfilled":return e.value;case"rejected":throw e.reason;default:switch("string"==typeof e.status?e.then(g,g):(e.status="pending",e.then(function(t){"pending"===e.status&&(e.status="fulfilled",e.value=t)},function(t){"pending"===e.status&&(e.status="rejected",e.reason=t)})),e.status){case"fulfilled":return e.value;case"rejected":throw e.reason}}throw e}(e),t,o,u,c);throw t=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.")}return f}function T(e,t,n){if(null==e)return e;var r=[],o=0;return x(e,r,"","",function(e){return t.call(n,e,o++)}),r}function A(e){if(-1===e._status){var t=e._result;(t=t()).then(function(t){0!==e._status&&-1!==e._status||(e._status=1,e._result=t)},function(t){0!==e._status&&-1!==e._status||(e._status=2,e._result=t)}),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var O="function"==typeof reportError?reportError:function(e){if("object"==typeof window&&"function"==typeof window.ErrorEvent){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:"object"==typeof e&&null!==e&&"string"==typeof e.message?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if("object"==typeof process&&"function"==typeof process.emit)return void process.emit("uncaughtException",e);console.error(e)},I={map:T,forEach:function(e,t,n){T(e,function(){t.apply(this,arguments)},n)},count:function(e){var t=0;return T(e,function(){t++}),t},toArray:function(e){return T(e,function(e){return e})||[]},only:function(e){if(!R(e))throw Error("React.Children.only expected to receive a single React element child.");return e}};t.Activity=y,t.Children=I,t.Component=b,t.Fragment=o,t.Profiler=c,t.PureComponent=S,t.StrictMode=u,t.Suspense=f,t.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=k,t.__COMPILER_RUNTIME={__proto__:null,c:function(e){return k.H.useMemoCache(e)}},t.cache=function(e){return function(){return e.apply(null,arguments)}},t.cacheSignal=function(){return null},t.cloneElement=function(e,t,n){if(null==e)throw Error("The argument must be a React element, but you passed "+e+".");var r=h({},e.props),o=e.key;if(null!=t)for(u in void 0!==t.key&&(o=""+t.key),t)!H.call(t,u)||"key"===u||"__self"===u||"__source"===u||"ref"===u&&void 0===t.ref||(r[u]=t[u]);var u=arguments.length-2;if(1===u)r.children=n;else if(1<u){for(var c=Array(u),s=0;s<u;s++)c[s]=arguments[s+2];r.children=c}return j(e.type,o,r)},t.createContext=function(e){return(e={$$typeof:i,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider=e,e.Consumer={$$typeof:s,_context:e},e},t.createElement=function(e,t,n){var r,o={},u=null;if(null!=t)for(r in void 0!==t.key&&(u=""+t.key),t)H.call(t,r)&&"key"!==r&&"__self"!==r&&"__source"!==r&&(o[r]=t[r]);var c=arguments.length-2;if(1===c)o.children=n;else if(1<c){for(var s=Array(c),i=0;i<c;i++)s[i]=arguments[i+2];o.children=s}if(e&&e.defaultProps)for(r in c=e.defaultProps)void 0===o[r]&&(o[r]=c[r]);return j(e,u,o)},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:a,render:e}},t.isValidElement=R,t.lazy=function(e){return{$$typeof:p,_payload:{_status:-1,_result:e},_init:A}},t.memo=function(e,t){return{$$typeof:l,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=k.T,n={};k.T=n;try{var r=e(),o=k.S;null!==o&&o(n,r),"object"==typeof r&&null!==r&&"function"==typeof r.then&&r.then(g,O)}catch(e){O(e)}finally{null!==t&&null!==n.types&&(t.types=n.types),k.T=t}},t.unstable_useCacheRefresh=function(){return k.H.useCacheRefresh()},t.use=function(e){return k.H.use(e)},t.useActionState=function(e,t,n){return k.H.useActionState(e,t,n)},t.useCallback=function(e,t){return k.H.useCallback(e,t)},t.useContext=function(e){return k.H.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e,t){return k.H.useDeferredValue(e,t)},t.useEffect=function(e,t){return k.H.useEffect(e,t)},t.useEffectEvent=function(e){return k.H.useEffectEvent(e)},t.useId=function(){return k.H.useId()},t.useImperativeHandle=function(e,t,n){return k.H.useImperativeHandle(e,t,n)},t.useInsertionEffect=function(e,t){return k.H.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return k.H.useLayoutEffect(e,t)},t.useMemo=function(e,t){return k.H.useMemo(e,t)},t.useOptimistic=function(e,t){return k.H.useOptimistic(e,t)},t.useReducer=function(e,t,n){return k.H.useReducer(e,t,n)},t.useRef=function(e){return k.H.useRef(e)},t.useState=function(e){return k.H.useState(e)},t.useSyncExternalStore=function(e,t,n){return k.H.useSyncExternalStore(e,t,n)},t.useTransition=function(){return k.H.useTransition()},t.version="19.2.8"},540(e,t,n){e.exports=n(869)}};
|
package/public/main.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={980(){}};const o={};function t(r){const s=o[r];if(void 0!==s)return s.exports;const n=o[r]={exports:{}};return e[r](n,n.exports,t),n.exports}t.m=e,t.c=o,t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce((o,r)=>(t.f[r](e,o),o),[])),t.u=e=>e+".mjs",t.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{t.S={};const e={},o={};t.I=(r,s)=>{s||(s=[]);let n=o[r];if(n||(n=o[r]={}),s.indexOf(n)>=0)return;if(s.push(n),e[r])return e[r];t.o(t.S,r)||(t.S[r]={});const i=t.S[r],c="signalk-openwakeword",_=[];return"default"===r&&((e,o,r,s)=>{const n=i[e]=i[e]||{},_=n[o];(!_||!_.loaded&&(1!=!_.eager?s:c>_.from))&&(n[o]={get:()=>t.e(540).then(()=>()=>t(540)),from:c,eager:!1})})("react","19.2.8"),e[r]=_.length?Promise.all(_).then(()=>e[r]=1):1}})(),(()=>{const e={792:0},o=o=>{let{__webpack_esm_ids__:r,__webpack_esm_modules__:s,__webpack_esm_runtime__:n}=o;var i,c,_=0;for(i in s)t.o(s,i)&&(t.m[i]=s[i]);for(n&&n(t);_<r.length;_++)c=r[_],t.o(e,c)&&e[c]&&e[c][0](),e[r[_]]=0};t.f.j=(r,s)=>{let n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)s.push(n[1]);else{let i=import("./"+t.u(r)).then(o,o=>{throw 0!==e[r]&&(e[r]=void 0),o});i=Promise.race([i,new Promise(o=>n=e[r]=[o])]),s.push(n[1]=i)}}})(),t(980);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={623(e,r,t){const n={"./PluginConfigurationPanel":()=>t.e(172).then(()=>()=>t(172))},o=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),i=(e,r)=>{if(!t.S)return;const n="default",o=t.S[n];if(o&&o!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)};t.d(r,{get:()=>o,init:()=>i})}};const r={};function t(n){const o=r[n];if(void 0!==o)return o.exports;const i=r[n]={exports:{}};return e[n](i,i.exports,t),i.exports}t.m=e,t.c=r,t.d=(e,r)=>{if(Array.isArray(r))for(var n=0;n<r.length;){var o=r[n++],i=r[n++];t.o(e,o)?0===i&&n++:0===i?Object.defineProperty(e,o,{enumerable:!0,value:r[n++]}):Object.defineProperty(e,o,{enumerable:!0,get:i})}else for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce((r,n)=>(t.f[n](e,r),r),[])),t.u=e=>e+".mjs",t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t.r=e=>{Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{t.S={};const e={},r={};t.I=(n,o)=>{o||(o=[]);let i=r[n];if(i||(i=r[n]={}),o.indexOf(i)>=0)return;if(o.push(i),e[n])return e[n];t.o(t.S,n)||(t.S[n]={});const s=t.S[n],a="signalk-openwakeword",u=[];return"default"===n&&((e,r,n,o)=>{const i=s[e]=s[e]||{},u=i[r];(!u||!u.loaded&&(1!=!u.eager?o:a>u.from))&&(i[r]={get:()=>t.e(540).then(()=>()=>t(540)),from:a,eager:!1})})("react","19.2.8"),e[n]=u.length?Promise.all(u).then(()=>e[n]=1):1}})(),(()=>{var e=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),n=t[1]?r(t[1]):[];return t[2]&&(n.length++,n.push.apply(n,r(t[2]))),t[3]&&(n.push([]),n.push.apply(n,r(t[3]))),n},r=e=>{var t=e[0],n="";if(1===e.length)return"*";if(t+.5){n+=0==t?">=":-1==t?"<":1==t?"^":2==t?"~":t>0?"=":"!=";for(var o=1,i=1;i<e.length;i++)o--,n+="u"==(typeof(a=e[i]))[0]?"-":(o>0?".":"")+(o=2,a);return n}var s=[];for(i=1;i<e.length;i++){var a=e[i];s.push(0===a?"not("+u()+")":1===a?"("+u()+" || "+u()+")":2===a?s.pop()+" "+s.pop():r(a))}return u();function u(){return s.pop().replace(/^\((.+)\)$/,"$1")}},n=(r,t)=>{if(0 in r){t=e(t);var o=r[0],i=o<0;i&&(o=-o-1);for(var s=0,a=1,u=!0;;a++,s++){var f,l,c=a<r.length?(typeof r[a])[0]:"";if(s>=t.length||"o"==(l=(typeof(f=t[s]))[0]))return!u||("u"==c?a>o&&!i:""==c!=i);if("u"==l){if(!u||"u"!=c)return!1}else if(u)if(c==l)if(a<=o){if(f!=r[a])return!1}else{if(i?f>r[a]:f<r[a])return!1;f!=r[a]&&(u=!1)}else if("s"!=c&&"n"!=c){if(i||a<=o)return!1;u=!1,a--}else{if(a<=o||l<c!=i)return!1;u=!1}else"s"!=c&&"n"!=c&&(u=!1,a--)}}var p=[],d=p.pop.bind(p);for(s=1;s<r.length;s++){var h=r[s];p.push(1==h?d()|d():2==h?d()&d():h?n(h,t):!d())}return!!d()};const o=(r,t,n)=>{const o=n?(e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}))(r[t]):r[t];return Object.keys(o).reduce((r,t)=>!r||!o[r].loaded&&((r,t)=>{r=e(r),t=e(t);for(var n=0;;){if(n>=r.length)return n<t.length&&"u"!=(typeof t[n])[0];var o=r[n],i=(typeof o)[0];if(n>=t.length)return"u"==i;var s=t[n],a=(typeof s)[0];if(i!=a)return"o"==i&&"n"==a||"s"==a||"u"==i;if("o"!=i&&"u"!=i&&o!=s)return o<s;n++}})(r,t)?t:r,0)},i=(e,r,t)=>t?t():((e,r)=>(e=>{throw new Error(e)})("Shared module "+r+" doesn't exist in shared scope "+e))(e,r),s=(e=>function(r,n,o,i,s){const a=t.I(r);return a?.then&&!o?a.then(e.bind(e,r,t.S[r],n,!1,i,s)):e(r,t.S[r],n,o,i,s)})((e,s,a,u,f,l)=>{if(!((e,r)=>e&&t.o(e,r))(s,a))return i(e,a,l);const c=o(s,a,u);return n(f,c)||(d=((e,t,n,o)=>"Unsatisfied version "+n+" from "+(n&&e[t][n].from)+" of shared singleton module "+t+" (required "+r(o)+")")(s,a,c,f),"undefined"!=typeof console&&console.warn&&console.warn(d)),(p=s[a][c]).loaded=1,p.get();var p,d}),a={},u={231:()=>s("default","react",!1,[1,19],()=>t.e(540).then(()=>()=>t(540)))},f={172:[231]},l={};t.f.consumes=(e,r)=>{t.o(f,e)&&f[e].forEach(e=>{if(t.o(a,e))return r.push(a[e]);if(!l[e]){const n=r=>{a[e]=0,t.m[e]=n=>{delete t.c[e],n.exports=r()}};l[e]=!0;const o=r=>{delete a[e],t.m[e]=n=>{throw delete t.c[e],r}};try{const t=u[e]();t.then?r.push(a[e]=t.then(n).catch(o)):n(t)}catch(e){o(e)}}})}})(),(()=>{const e={393:0},r=r=>{let{__webpack_esm_ids__:n,__webpack_esm_modules__:o,__webpack_esm_runtime__:i}=r;var s,a,u=0;for(s in o)t.o(o,s)&&(t.m[s]=o[s]);for(i&&i(t);u<n.length;u++)a=n[u],t.o(e,a)&&e[a]&&e[a][0](),e[n[u]]=0};t.f.j=(n,o)=>{let i=t.o(e,n)?e[n]:void 0;if(0!==i)if(i)o.push(i[1]);else{let s=import("./"+t.u(n)).then(r,r=>{throw 0!==e[n]&&(e[n]=void 0),r});s=Promise.race([s,new Promise(r=>i=e[n]=[r])]),o.push(i[1]=s)}}})();let n=t(623);const o=n.get,i=n.init;export{o as get,i as init};
|