Kokoro-82M TTS + README/diagram update + dead-code/Ollama cleanup
Browse files- .env.example +0 -3
- README.md +12 -3
- package-lock.json +998 -10
- package.json +1 -0
- server/agent-core.mjs +1 -1
- server/index.mjs +4 -12
- server/model-chat.mjs +1 -13
- server/ollama-client.mjs +0 -146
- server/research-tools.mjs +0 -28
- src/App.tsx +90 -117
- src/data/neighborhoods.ts +0 -50
- src/lib/tts.ts +41 -0
- src/styles.css +8 -0
.env.example
CHANGED
|
@@ -59,7 +59,4 @@ AGENT_FANOUT=1
|
|
| 59 |
# the decisions; this small assistant summarises each agent's evidence. The 0.5B is tiny, so it
|
| 60 |
# often falls back to the main model — use openbmb/MiniCPM4-8B-GGUF for genuine summaries.
|
| 61 |
AGENT_SUMMARIZER_PROVIDER=llamacpp
|
| 62 |
-
OLLAMA_MODEL=
|
| 63 |
-
OLLAMA_HOST=http://127.0.0.1:11434
|
| 64 |
-
OLLAMA_TIMEOUT_MS=60000
|
| 65 |
AGENT_PORT=8787
|
|
|
|
| 59 |
# the decisions; this small assistant summarises each agent's evidence. The 0.5B is tiny, so it
|
| 60 |
# often falls back to the main model — use openbmb/MiniCPM4-8B-GGUF for genuine summaries.
|
| 61 |
AGENT_SUMMARIZER_PROVIDER=llamacpp
|
|
|
|
|
|
|
|
|
|
| 62 |
AGENT_PORT=8787
|
README.md
CHANGED
|
@@ -23,8 +23,10 @@ tags:
|
|
| 23 |
- achievement:sharing
|
| 24 |
- achievement:fieldnotes
|
| 25 |
models:
|
| 26 |
-
- Qwen/Qwen3-Coder-30B-A3B-Instruct
|
| 27 |
- nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16
|
|
|
|
|
|
|
|
|
|
| 28 |
---
|
| 29 |
|
| 30 |
# 6ixPulse
|
|
@@ -56,7 +58,8 @@ The app then ranks Toronto neighborhoods, animates the map to the areas it is re
|
|
| 56 |
- **Fans out a researcher per City Agent.** Affordability, Commute, Safety, Lifestyle and Growth agents each reason over only their own evidence; a **Recommendation agent runs last** with every agent's finding *and* all of their sources.
|
| 57 |
- **Fails closed.** The UI withholds a rent, commute, safety, growth claim, or score unless the backend can tie it to source evidence — sources are named, never "S1".
|
| 58 |
- **Shows a real Mapbox GL JS 3D map** with a research tour that zooms into each area while it is being researched, then flies out-and-in to the next.
|
| 59 |
-
- **
|
|
|
|
| 60 |
|
| 61 |
## Architecture
|
| 62 |
|
|
@@ -106,14 +109,16 @@ flowchart TB
|
|
| 106 |
Score --- Transit
|
| 107 |
Score --- CMHC
|
| 108 |
|
| 109 |
-
subgraph Models["
|
| 110 |
Main["Main: NVIDIA Nemotron Nano Omni Reasoning<br/>temp 0.6 · enable_thinking · reasoning_budget<br/>↳ fallback: HF Qwen3-Coder"]
|
| 111 |
Assist["Assistant: OpenBMB MiniCPM via llama.cpp<br/>summarises each agent's evidence"]
|
|
|
|
| 112 |
end
|
| 113 |
Discover --- Main
|
| 114 |
Fanout --- Assist
|
| 115 |
Fanout --- Main
|
| 116 |
Recommend --- Main
|
|
|
|
| 117 |
```
|
| 118 |
|
| 119 |
## Tech Stack
|
|
@@ -128,6 +133,7 @@ flowchart TB
|
|
| 128 |
- Models (all < 32B):
|
| 129 |
- Main agentic brain: `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning` (build.nvidia.com)
|
| 130 |
- Summarisation assistant: OpenBMB MiniCPM via llama.cpp (`openbmb/MiniCPM4-*-GGUF`)
|
|
|
|
| 131 |
- Fallback: `Qwen/Qwen3-Coder-30B-A3B-Instruct` on the HF Router
|
| 132 |
|
| 133 |
## Build Small Hackathon Readiness
|
|
@@ -214,6 +220,8 @@ HF_MODEL=Qwen/Qwen3-Coder-30B-A3B-Instruct
|
|
| 214 |
|
| 215 |
The reasoning model uses the Nemotron recipe (matching `ChatNVIDIA`): `temperature=0.6`, `top_p=0.95`, `chat_template_kwargs={"enable_thinking": true}`, and a `reasoning_budget`; its `<think>` reasoning is captured separately from the JSON answer. Thinking is enabled only for the decisions (discovery, recommendation, synthesis), and the per-agent fan-out runs in parallel on hosted APIs, so a full run stays within the response budget.
|
| 216 |
|
|
|
|
|
|
|
| 217 |
## Gradio Space
|
| 218 |
|
| 219 |
This repo is prepared for a Docker-backed Gradio Space using `gradio.Server`, which is designed for custom frontends like React while still giving the project Gradio's API engine, queuing, MCP support, and Hugging Face Spaces hosting.
|
|
@@ -320,6 +328,7 @@ Dockerfile Docker Space image with Node + Python
|
|
| 320 |
src/App.tsx app shell, agent panels, scores, listings
|
| 321 |
src/components/MapCanvas.tsx Mapbox/deck.gl map + research tour
|
| 322 |
src/lib/agentApi.ts frontend API client types
|
|
|
|
| 323 |
server/index.mjs agent API server; orchestrates the pipeline
|
| 324 |
server/discover.mjs model-driven neighbourhood discovery (+ coordinates)
|
| 325 |
server/score-tools.mjs 8-dimension scoring from named no-key sources
|
|
|
|
| 23 |
- achievement:sharing
|
| 24 |
- achievement:fieldnotes
|
| 25 |
models:
|
|
|
|
| 26 |
- nvidia/Nemotron-3-Nano-Omni-30B-A3B-Reasoning-BF16
|
| 27 |
+
- Qwen/Qwen3-Coder-30B-A3B-Instruct
|
| 28 |
+
- openbmb/MiniCPM4-0.5B
|
| 29 |
+
- hexgrad/Kokoro-82M
|
| 30 |
---
|
| 31 |
|
| 32 |
# 6ixPulse
|
|
|
|
| 58 |
- **Fans out a researcher per City Agent.** Affordability, Commute, Safety, Lifestyle and Growth agents each reason over only their own evidence; a **Recommendation agent runs last** with every agent's finding *and* all of their sources.
|
| 59 |
- **Fails closed.** The UI withholds a rent, commute, safety, growth claim, or score unless the backend can tie it to source evidence — sources are named, never "S1".
|
| 60 |
- **Shows a real Mapbox GL JS 3D map** with a research tour that zooms into each area while it is being researched, then flies out-and-in to the next.
|
| 61 |
+
- **Reads the findings aloud.** A Play button narrates a short spoken summary using **Kokoro-82M** neural TTS running entirely in the browser — no key, no backend.
|
| 62 |
+
- **Models, all < 32B.** NVIDIA Nemotron Nano Omni Reasoning is the main brain (with `enable_thinking`); the small OpenBMB model on llama.cpp assists with summarisation; Kokoro-82M handles speech. Falls back to HF when a provider is unavailable.
|
| 63 |
|
| 64 |
## Architecture
|
| 65 |
|
|
|
|
| 109 |
Score --- Transit
|
| 110 |
Score --- CMHC
|
| 111 |
|
| 112 |
+
subgraph Models["Models · all under 32B"]
|
| 113 |
Main["Main: NVIDIA Nemotron Nano Omni Reasoning<br/>temp 0.6 · enable_thinking · reasoning_budget<br/>↳ fallback: HF Qwen3-Coder"]
|
| 114 |
Assist["Assistant: OpenBMB MiniCPM via llama.cpp<br/>summarises each agent's evidence"]
|
| 115 |
+
Speech["Voice: Kokoro-82M neural TTS<br/>in-browser, narrates the summary"]
|
| 116 |
end
|
| 117 |
Discover --- Main
|
| 118 |
Fanout --- Assist
|
| 119 |
Fanout --- Main
|
| 120 |
Recommend --- Main
|
| 121 |
+
Panels -. Play .-> Speech
|
| 122 |
```
|
| 123 |
|
| 124 |
## Tech Stack
|
|
|
|
| 133 |
- Models (all < 32B):
|
| 134 |
- Main agentic brain: `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning` (build.nvidia.com)
|
| 135 |
- Summarisation assistant: OpenBMB MiniCPM via llama.cpp (`openbmb/MiniCPM4-*-GGUF`)
|
| 136 |
+
- Speech: `hexgrad/Kokoro-82M` neural TTS in the browser (transformers.js)
|
| 137 |
- Fallback: `Qwen/Qwen3-Coder-30B-A3B-Instruct` on the HF Router
|
| 138 |
|
| 139 |
## Build Small Hackathon Readiness
|
|
|
|
| 220 |
|
| 221 |
The reasoning model uses the Nemotron recipe (matching `ChatNVIDIA`): `temperature=0.6`, `top_p=0.95`, `chat_template_kwargs={"enable_thinking": true}`, and a `reasoning_budget`; its `<think>` reasoning is captured separately from the JSON answer. Thinking is enabled only for the decisions (discovery, recommendation, synthesis), and the per-agent fan-out runs in parallel on hosted APIs, so a full run stays within the response budget.
|
| 222 |
|
| 223 |
+
For speech, the Play button uses **`hexgrad/Kokoro-82M`** neural TTS via `transformers.js`, running fully in the browser (ONNX/WASM). It is lazy-loaded — the ~80 MB model only downloads on the first Play, then is cached — and falls back to the browser's built-in speech while it loads or where it can't run. No key, no backend, 82M parameters.
|
| 224 |
+
|
| 225 |
## Gradio Space
|
| 226 |
|
| 227 |
This repo is prepared for a Docker-backed Gradio Space using `gradio.Server`, which is designed for custom frontends like React while still giving the project Gradio's API engine, queuing, MCP support, and Hugging Face Spaces hosting.
|
|
|
|
| 328 |
src/App.tsx app shell, agent panels, scores, listings
|
| 329 |
src/components/MapCanvas.tsx Mapbox/deck.gl map + research tour
|
| 330 |
src/lib/agentApi.ts frontend API client types
|
| 331 |
+
src/lib/tts.ts Kokoro-82M in-browser narration
|
| 332 |
server/index.mjs agent API server; orchestrates the pipeline
|
| 333 |
server/discover.mjs model-driven neighbourhood discovery (+ coordinates)
|
| 334 |
server/score-tools.mjs 8-dimension scoring from named no-key sources
|
package-lock.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
| 11 |
"@deck.gl/core": "^9.0.0",
|
| 12 |
"@deck.gl/layers": "^9.0.0",
|
| 13 |
"@deck.gl/mapbox": "^9.0.0",
|
|
|
|
| 14 |
"lucide-react": "^0.468.0",
|
| 15 |
"mapbox-gl": "^3.11.1",
|
| 16 |
"react": "^19.0.0",
|
|
@@ -100,22 +101,519 @@
|
|
| 100 |
"version": "1.10.0",
|
| 101 |
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
| 102 |
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
"dev": true,
|
| 104 |
"license": "MIT",
|
| 105 |
"optional": true,
|
| 106 |
-
"dependencies": {
|
| 107 |
-
"tslib": "^2.4.0"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
}
|
| 109 |
},
|
| 110 |
-
"node_modules/@
|
| 111 |
-
"version": "
|
| 112 |
-
"resolved": "https://registry.npmjs.org/@
|
| 113 |
-
"integrity": "sha512-
|
| 114 |
-
"
|
| 115 |
-
|
|
|
|
|
|
|
| 116 |
"optional": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
"dependencies": {
|
| 118 |
-
"
|
|
|
|
|
|
|
|
|
|
| 119 |
}
|
| 120 |
},
|
| 121 |
"node_modules/@loaders.gl/core": {
|
|
@@ -367,6 +865,63 @@
|
|
| 367 |
"integrity": "sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==",
|
| 368 |
"license": "MIT"
|
| 369 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
"node_modules/@rolldown/binding-android-arm64": {
|
| 371 |
"version": "1.0.3",
|
| 372 |
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
|
|
@@ -798,6 +1353,13 @@
|
|
| 798 |
"node": ">=12.17"
|
| 799 |
}
|
| 800 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 801 |
"node_modules/chalk": {
|
| 802 |
"version": "4.1.2",
|
| 803 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
@@ -835,6 +1397,15 @@
|
|
| 835 |
"integrity": "sha512-pmcgaGHAxfYtKr4BtSaM/+/3vvQJJLkvQibEdO2eb5eiHrRgEAd43M2tpBGi4eIX32kXyvPLQVT23qNnuFaa8w==",
|
| 836 |
"license": "ISC"
|
| 837 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 838 |
"node_modules/color-convert": {
|
| 839 |
"version": "2.0.1",
|
| 840 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
@@ -904,22 +1475,97 @@
|
|
| 904 |
"dev": true,
|
| 905 |
"license": "MIT"
|
| 906 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 907 |
"node_modules/detect-libc": {
|
| 908 |
"version": "2.1.2",
|
| 909 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
| 910 |
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
| 911 |
-
"dev": true,
|
| 912 |
"license": "Apache-2.0",
|
| 913 |
"engines": {
|
| 914 |
"node": ">=8"
|
| 915 |
}
|
| 916 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 917 |
"node_modules/earcut": {
|
| 918 |
"version": "2.2.4",
|
| 919 |
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
|
| 920 |
"integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
|
| 921 |
"license": "ISC"
|
| 922 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 923 |
"node_modules/fdir": {
|
| 924 |
"version": "6.5.0",
|
| 925 |
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
|
@@ -988,6 +1634,57 @@
|
|
| 988 |
"integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==",
|
| 989 |
"license": "MIT"
|
| 990 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 991 |
"node_modules/has-flag": {
|
| 992 |
"version": "4.0.0",
|
| 993 |
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
|
@@ -997,6 +1694,18 @@
|
|
| 997 |
"node": ">=8"
|
| 998 |
}
|
| 999 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1000 |
"node_modules/json-bignum": {
|
| 1001 |
"version": "0.0.3",
|
| 1002 |
"resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz",
|
|
@@ -1005,12 +1714,28 @@
|
|
| 1005 |
"node": ">=0.8"
|
| 1006 |
}
|
| 1007 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1008 |
"node_modules/kdbush": {
|
| 1009 |
"version": "4.1.0",
|
| 1010 |
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz",
|
| 1011 |
"integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==",
|
| 1012 |
"license": "ISC"
|
| 1013 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1014 |
"node_modules/lightningcss": {
|
| 1015 |
"version": "1.32.0",
|
| 1016 |
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
|
@@ -1278,6 +2003,12 @@
|
|
| 1278 |
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
| 1279 |
"license": "MIT"
|
| 1280 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1281 |
"node_modules/lucide-react": {
|
| 1282 |
"version": "0.468.0",
|
| 1283 |
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
|
|
@@ -1341,6 +2072,39 @@
|
|
| 1341 |
"tinyqueue": "3.0.0"
|
| 1342 |
}
|
| 1343 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1344 |
"node_modules/mjolnir.js": {
|
| 1345 |
"version": "3.0.0",
|
| 1346 |
"resolved": "https://registry.npmjs.org/mjolnir.js/-/mjolnir.js-3.0.0.tgz",
|
|
@@ -1372,6 +2136,58 @@
|
|
| 1372 |
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
| 1373 |
}
|
| 1374 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1375 |
"node_modules/pbf": {
|
| 1376 |
"version": "4.0.2",
|
| 1377 |
"resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.2.tgz",
|
|
@@ -1384,6 +2200,12 @@
|
|
| 1384 |
"pbf": "bin/pbf"
|
| 1385 |
}
|
| 1386 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1387 |
"node_modules/picocolors": {
|
| 1388 |
"version": "1.1.1",
|
| 1389 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
@@ -1404,6 +2226,12 @@
|
|
| 1404 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 1405 |
}
|
| 1406 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1407 |
"node_modules/postcss": {
|
| 1408 |
"version": "8.5.15",
|
| 1409 |
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
|
@@ -1439,6 +2267,29 @@
|
|
| 1439 |
"integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==",
|
| 1440 |
"license": "ISC"
|
| 1441 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1442 |
"node_modules/protocol-buffers-schema": {
|
| 1443 |
"version": "3.6.1",
|
| 1444 |
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz",
|
|
@@ -1481,6 +2332,23 @@
|
|
| 1481 |
"protocol-buffers-schema": "^3.3.1"
|
| 1482 |
}
|
| 1483 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1484 |
"node_modules/robust-predicates": {
|
| 1485 |
"version": "2.0.4",
|
| 1486 |
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz",
|
|
@@ -1527,6 +2395,83 @@
|
|
| 1527 |
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
| 1528 |
"license": "MIT"
|
| 1529 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1530 |
"node_modules/source-map-js": {
|
| 1531 |
"version": "1.2.1",
|
| 1532 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
@@ -1543,6 +2488,12 @@
|
|
| 1543 |
"integrity": "sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==",
|
| 1544 |
"license": "MIT"
|
| 1545 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1546 |
"node_modules/supercluster": {
|
| 1547 |
"version": "8.0.1",
|
| 1548 |
"resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
|
|
@@ -1577,6 +2528,22 @@
|
|
| 1577 |
"node": ">=12.17"
|
| 1578 |
}
|
| 1579 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1580 |
"node_modules/tinyglobby": {
|
| 1581 |
"version": "0.2.17",
|
| 1582 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
|
@@ -1606,6 +2573,18 @@
|
|
| 1606 |
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
| 1607 |
"license": "0BSD"
|
| 1608 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1609 |
"node_modules/typescript": {
|
| 1610 |
"version": "5.9.3",
|
| 1611 |
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
@@ -1721,6 +2700,15 @@
|
|
| 1721 |
"engines": {
|
| 1722 |
"node": ">=12.17"
|
| 1723 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1724 |
}
|
| 1725 |
}
|
| 1726 |
}
|
|
|
|
| 11 |
"@deck.gl/core": "^9.0.0",
|
| 12 |
"@deck.gl/layers": "^9.0.0",
|
| 13 |
"@deck.gl/mapbox": "^9.0.0",
|
| 14 |
+
"kokoro-js": "^1.2.1",
|
| 15 |
"lucide-react": "^0.468.0",
|
| 16 |
"mapbox-gl": "^3.11.1",
|
| 17 |
"react": "^19.0.0",
|
|
|
|
| 101 |
"version": "1.10.0",
|
| 102 |
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
| 103 |
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
| 104 |
+
"license": "MIT",
|
| 105 |
+
"optional": true,
|
| 106 |
+
"dependencies": {
|
| 107 |
+
"tslib": "^2.4.0"
|
| 108 |
+
}
|
| 109 |
+
},
|
| 110 |
+
"node_modules/@emnapi/wasi-threads": {
|
| 111 |
+
"version": "1.2.1",
|
| 112 |
+
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
| 113 |
+
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
|
| 114 |
"dev": true,
|
| 115 |
"license": "MIT",
|
| 116 |
"optional": true,
|
| 117 |
+
"dependencies": {
|
| 118 |
+
"tslib": "^2.4.0"
|
| 119 |
+
}
|
| 120 |
+
},
|
| 121 |
+
"node_modules/@huggingface/jinja": {
|
| 122 |
+
"version": "0.5.9",
|
| 123 |
+
"resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.9.tgz",
|
| 124 |
+
"integrity": "sha512-uWTG+l3VJRsl7EXxYizuL3P+cCPoc3cRqbWWRcQN0FhejRfbdq0RNhCmbY/YDtnTcz9icdLYuLDjsnz4d8JMuw==",
|
| 125 |
+
"license": "MIT",
|
| 126 |
+
"engines": {
|
| 127 |
+
"node": ">=18"
|
| 128 |
+
}
|
| 129 |
+
},
|
| 130 |
+
"node_modules/@huggingface/transformers": {
|
| 131 |
+
"version": "3.8.1",
|
| 132 |
+
"resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.8.1.tgz",
|
| 133 |
+
"integrity": "sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==",
|
| 134 |
+
"license": "Apache-2.0",
|
| 135 |
+
"dependencies": {
|
| 136 |
+
"@huggingface/jinja": "^0.5.3",
|
| 137 |
+
"onnxruntime-node": "1.21.0",
|
| 138 |
+
"onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4",
|
| 139 |
+
"sharp": "^0.34.1"
|
| 140 |
+
}
|
| 141 |
+
},
|
| 142 |
+
"node_modules/@img/colour": {
|
| 143 |
+
"version": "1.1.0",
|
| 144 |
+
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
|
| 145 |
+
"integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
|
| 146 |
+
"license": "MIT",
|
| 147 |
+
"engines": {
|
| 148 |
+
"node": ">=18"
|
| 149 |
+
}
|
| 150 |
+
},
|
| 151 |
+
"node_modules/@img/sharp-darwin-arm64": {
|
| 152 |
+
"version": "0.34.5",
|
| 153 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
| 154 |
+
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
| 155 |
+
"cpu": [
|
| 156 |
+
"arm64"
|
| 157 |
+
],
|
| 158 |
+
"license": "Apache-2.0",
|
| 159 |
+
"optional": true,
|
| 160 |
+
"os": [
|
| 161 |
+
"darwin"
|
| 162 |
+
],
|
| 163 |
+
"engines": {
|
| 164 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 165 |
+
},
|
| 166 |
+
"funding": {
|
| 167 |
+
"url": "https://opencollective.com/libvips"
|
| 168 |
+
},
|
| 169 |
+
"optionalDependencies": {
|
| 170 |
+
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
| 171 |
+
}
|
| 172 |
+
},
|
| 173 |
+
"node_modules/@img/sharp-darwin-x64": {
|
| 174 |
+
"version": "0.34.5",
|
| 175 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
| 176 |
+
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
| 177 |
+
"cpu": [
|
| 178 |
+
"x64"
|
| 179 |
+
],
|
| 180 |
+
"license": "Apache-2.0",
|
| 181 |
+
"optional": true,
|
| 182 |
+
"os": [
|
| 183 |
+
"darwin"
|
| 184 |
+
],
|
| 185 |
+
"engines": {
|
| 186 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 187 |
+
},
|
| 188 |
+
"funding": {
|
| 189 |
+
"url": "https://opencollective.com/libvips"
|
| 190 |
+
},
|
| 191 |
+
"optionalDependencies": {
|
| 192 |
+
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
| 193 |
+
}
|
| 194 |
+
},
|
| 195 |
+
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
| 196 |
+
"version": "1.2.4",
|
| 197 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
| 198 |
+
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
| 199 |
+
"cpu": [
|
| 200 |
+
"arm64"
|
| 201 |
+
],
|
| 202 |
+
"license": "LGPL-3.0-or-later",
|
| 203 |
+
"optional": true,
|
| 204 |
+
"os": [
|
| 205 |
+
"darwin"
|
| 206 |
+
],
|
| 207 |
+
"funding": {
|
| 208 |
+
"url": "https://opencollective.com/libvips"
|
| 209 |
+
}
|
| 210 |
+
},
|
| 211 |
+
"node_modules/@img/sharp-libvips-darwin-x64": {
|
| 212 |
+
"version": "1.2.4",
|
| 213 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
| 214 |
+
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
| 215 |
+
"cpu": [
|
| 216 |
+
"x64"
|
| 217 |
+
],
|
| 218 |
+
"license": "LGPL-3.0-or-later",
|
| 219 |
+
"optional": true,
|
| 220 |
+
"os": [
|
| 221 |
+
"darwin"
|
| 222 |
+
],
|
| 223 |
+
"funding": {
|
| 224 |
+
"url": "https://opencollective.com/libvips"
|
| 225 |
+
}
|
| 226 |
+
},
|
| 227 |
+
"node_modules/@img/sharp-libvips-linux-arm": {
|
| 228 |
+
"version": "1.2.4",
|
| 229 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
| 230 |
+
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
| 231 |
+
"cpu": [
|
| 232 |
+
"arm"
|
| 233 |
+
],
|
| 234 |
+
"license": "LGPL-3.0-or-later",
|
| 235 |
+
"optional": true,
|
| 236 |
+
"os": [
|
| 237 |
+
"linux"
|
| 238 |
+
],
|
| 239 |
+
"funding": {
|
| 240 |
+
"url": "https://opencollective.com/libvips"
|
| 241 |
+
}
|
| 242 |
+
},
|
| 243 |
+
"node_modules/@img/sharp-libvips-linux-arm64": {
|
| 244 |
+
"version": "1.2.4",
|
| 245 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
| 246 |
+
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
| 247 |
+
"cpu": [
|
| 248 |
+
"arm64"
|
| 249 |
+
],
|
| 250 |
+
"license": "LGPL-3.0-or-later",
|
| 251 |
+
"optional": true,
|
| 252 |
+
"os": [
|
| 253 |
+
"linux"
|
| 254 |
+
],
|
| 255 |
+
"funding": {
|
| 256 |
+
"url": "https://opencollective.com/libvips"
|
| 257 |
+
}
|
| 258 |
+
},
|
| 259 |
+
"node_modules/@img/sharp-libvips-linux-ppc64": {
|
| 260 |
+
"version": "1.2.4",
|
| 261 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
|
| 262 |
+
"integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
|
| 263 |
+
"cpu": [
|
| 264 |
+
"ppc64"
|
| 265 |
+
],
|
| 266 |
+
"license": "LGPL-3.0-or-later",
|
| 267 |
+
"optional": true,
|
| 268 |
+
"os": [
|
| 269 |
+
"linux"
|
| 270 |
+
],
|
| 271 |
+
"funding": {
|
| 272 |
+
"url": "https://opencollective.com/libvips"
|
| 273 |
+
}
|
| 274 |
+
},
|
| 275 |
+
"node_modules/@img/sharp-libvips-linux-riscv64": {
|
| 276 |
+
"version": "1.2.4",
|
| 277 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
|
| 278 |
+
"integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
|
| 279 |
+
"cpu": [
|
| 280 |
+
"riscv64"
|
| 281 |
+
],
|
| 282 |
+
"license": "LGPL-3.0-or-later",
|
| 283 |
+
"optional": true,
|
| 284 |
+
"os": [
|
| 285 |
+
"linux"
|
| 286 |
+
],
|
| 287 |
+
"funding": {
|
| 288 |
+
"url": "https://opencollective.com/libvips"
|
| 289 |
+
}
|
| 290 |
+
},
|
| 291 |
+
"node_modules/@img/sharp-libvips-linux-s390x": {
|
| 292 |
+
"version": "1.2.4",
|
| 293 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
| 294 |
+
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
| 295 |
+
"cpu": [
|
| 296 |
+
"s390x"
|
| 297 |
+
],
|
| 298 |
+
"license": "LGPL-3.0-or-later",
|
| 299 |
+
"optional": true,
|
| 300 |
+
"os": [
|
| 301 |
+
"linux"
|
| 302 |
+
],
|
| 303 |
+
"funding": {
|
| 304 |
+
"url": "https://opencollective.com/libvips"
|
| 305 |
+
}
|
| 306 |
+
},
|
| 307 |
+
"node_modules/@img/sharp-libvips-linux-x64": {
|
| 308 |
+
"version": "1.2.4",
|
| 309 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
| 310 |
+
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
| 311 |
+
"cpu": [
|
| 312 |
+
"x64"
|
| 313 |
+
],
|
| 314 |
+
"license": "LGPL-3.0-or-later",
|
| 315 |
+
"optional": true,
|
| 316 |
+
"os": [
|
| 317 |
+
"linux"
|
| 318 |
+
],
|
| 319 |
+
"funding": {
|
| 320 |
+
"url": "https://opencollective.com/libvips"
|
| 321 |
+
}
|
| 322 |
+
},
|
| 323 |
+
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
| 324 |
+
"version": "1.2.4",
|
| 325 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
| 326 |
+
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
| 327 |
+
"cpu": [
|
| 328 |
+
"arm64"
|
| 329 |
+
],
|
| 330 |
+
"license": "LGPL-3.0-or-later",
|
| 331 |
+
"optional": true,
|
| 332 |
+
"os": [
|
| 333 |
+
"linux"
|
| 334 |
+
],
|
| 335 |
+
"funding": {
|
| 336 |
+
"url": "https://opencollective.com/libvips"
|
| 337 |
+
}
|
| 338 |
+
},
|
| 339 |
+
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
| 340 |
+
"version": "1.2.4",
|
| 341 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
| 342 |
+
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
| 343 |
+
"cpu": [
|
| 344 |
+
"x64"
|
| 345 |
+
],
|
| 346 |
+
"license": "LGPL-3.0-or-later",
|
| 347 |
+
"optional": true,
|
| 348 |
+
"os": [
|
| 349 |
+
"linux"
|
| 350 |
+
],
|
| 351 |
+
"funding": {
|
| 352 |
+
"url": "https://opencollective.com/libvips"
|
| 353 |
+
}
|
| 354 |
+
},
|
| 355 |
+
"node_modules/@img/sharp-linux-arm": {
|
| 356 |
+
"version": "0.34.5",
|
| 357 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
| 358 |
+
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
| 359 |
+
"cpu": [
|
| 360 |
+
"arm"
|
| 361 |
+
],
|
| 362 |
+
"license": "Apache-2.0",
|
| 363 |
+
"optional": true,
|
| 364 |
+
"os": [
|
| 365 |
+
"linux"
|
| 366 |
+
],
|
| 367 |
+
"engines": {
|
| 368 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 369 |
+
},
|
| 370 |
+
"funding": {
|
| 371 |
+
"url": "https://opencollective.com/libvips"
|
| 372 |
+
},
|
| 373 |
+
"optionalDependencies": {
|
| 374 |
+
"@img/sharp-libvips-linux-arm": "1.2.4"
|
| 375 |
+
}
|
| 376 |
+
},
|
| 377 |
+
"node_modules/@img/sharp-linux-arm64": {
|
| 378 |
+
"version": "0.34.5",
|
| 379 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
| 380 |
+
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
| 381 |
+
"cpu": [
|
| 382 |
+
"arm64"
|
| 383 |
+
],
|
| 384 |
+
"license": "Apache-2.0",
|
| 385 |
+
"optional": true,
|
| 386 |
+
"os": [
|
| 387 |
+
"linux"
|
| 388 |
+
],
|
| 389 |
+
"engines": {
|
| 390 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 391 |
+
},
|
| 392 |
+
"funding": {
|
| 393 |
+
"url": "https://opencollective.com/libvips"
|
| 394 |
+
},
|
| 395 |
+
"optionalDependencies": {
|
| 396 |
+
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
| 397 |
+
}
|
| 398 |
+
},
|
| 399 |
+
"node_modules/@img/sharp-linux-ppc64": {
|
| 400 |
+
"version": "0.34.5",
|
| 401 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
|
| 402 |
+
"integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
|
| 403 |
+
"cpu": [
|
| 404 |
+
"ppc64"
|
| 405 |
+
],
|
| 406 |
+
"license": "Apache-2.0",
|
| 407 |
+
"optional": true,
|
| 408 |
+
"os": [
|
| 409 |
+
"linux"
|
| 410 |
+
],
|
| 411 |
+
"engines": {
|
| 412 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 413 |
+
},
|
| 414 |
+
"funding": {
|
| 415 |
+
"url": "https://opencollective.com/libvips"
|
| 416 |
+
},
|
| 417 |
+
"optionalDependencies": {
|
| 418 |
+
"@img/sharp-libvips-linux-ppc64": "1.2.4"
|
| 419 |
+
}
|
| 420 |
+
},
|
| 421 |
+
"node_modules/@img/sharp-linux-riscv64": {
|
| 422 |
+
"version": "0.34.5",
|
| 423 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
|
| 424 |
+
"integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
|
| 425 |
+
"cpu": [
|
| 426 |
+
"riscv64"
|
| 427 |
+
],
|
| 428 |
+
"license": "Apache-2.0",
|
| 429 |
+
"optional": true,
|
| 430 |
+
"os": [
|
| 431 |
+
"linux"
|
| 432 |
+
],
|
| 433 |
+
"engines": {
|
| 434 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 435 |
+
},
|
| 436 |
+
"funding": {
|
| 437 |
+
"url": "https://opencollective.com/libvips"
|
| 438 |
+
},
|
| 439 |
+
"optionalDependencies": {
|
| 440 |
+
"@img/sharp-libvips-linux-riscv64": "1.2.4"
|
| 441 |
+
}
|
| 442 |
+
},
|
| 443 |
+
"node_modules/@img/sharp-linux-s390x": {
|
| 444 |
+
"version": "0.34.5",
|
| 445 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
| 446 |
+
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
| 447 |
+
"cpu": [
|
| 448 |
+
"s390x"
|
| 449 |
+
],
|
| 450 |
+
"license": "Apache-2.0",
|
| 451 |
+
"optional": true,
|
| 452 |
+
"os": [
|
| 453 |
+
"linux"
|
| 454 |
+
],
|
| 455 |
+
"engines": {
|
| 456 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 457 |
+
},
|
| 458 |
+
"funding": {
|
| 459 |
+
"url": "https://opencollective.com/libvips"
|
| 460 |
+
},
|
| 461 |
+
"optionalDependencies": {
|
| 462 |
+
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
| 463 |
+
}
|
| 464 |
+
},
|
| 465 |
+
"node_modules/@img/sharp-linux-x64": {
|
| 466 |
+
"version": "0.34.5",
|
| 467 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
| 468 |
+
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
| 469 |
+
"cpu": [
|
| 470 |
+
"x64"
|
| 471 |
+
],
|
| 472 |
+
"license": "Apache-2.0",
|
| 473 |
+
"optional": true,
|
| 474 |
+
"os": [
|
| 475 |
+
"linux"
|
| 476 |
+
],
|
| 477 |
+
"engines": {
|
| 478 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 479 |
+
},
|
| 480 |
+
"funding": {
|
| 481 |
+
"url": "https://opencollective.com/libvips"
|
| 482 |
+
},
|
| 483 |
+
"optionalDependencies": {
|
| 484 |
+
"@img/sharp-libvips-linux-x64": "1.2.4"
|
| 485 |
+
}
|
| 486 |
+
},
|
| 487 |
+
"node_modules/@img/sharp-linuxmusl-arm64": {
|
| 488 |
+
"version": "0.34.5",
|
| 489 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
| 490 |
+
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
| 491 |
+
"cpu": [
|
| 492 |
+
"arm64"
|
| 493 |
+
],
|
| 494 |
+
"license": "Apache-2.0",
|
| 495 |
+
"optional": true,
|
| 496 |
+
"os": [
|
| 497 |
+
"linux"
|
| 498 |
+
],
|
| 499 |
+
"engines": {
|
| 500 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 501 |
+
},
|
| 502 |
+
"funding": {
|
| 503 |
+
"url": "https://opencollective.com/libvips"
|
| 504 |
+
},
|
| 505 |
+
"optionalDependencies": {
|
| 506 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
| 507 |
+
}
|
| 508 |
+
},
|
| 509 |
+
"node_modules/@img/sharp-linuxmusl-x64": {
|
| 510 |
+
"version": "0.34.5",
|
| 511 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
| 512 |
+
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
| 513 |
+
"cpu": [
|
| 514 |
+
"x64"
|
| 515 |
+
],
|
| 516 |
+
"license": "Apache-2.0",
|
| 517 |
+
"optional": true,
|
| 518 |
+
"os": [
|
| 519 |
+
"linux"
|
| 520 |
+
],
|
| 521 |
+
"engines": {
|
| 522 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 523 |
+
},
|
| 524 |
+
"funding": {
|
| 525 |
+
"url": "https://opencollective.com/libvips"
|
| 526 |
+
},
|
| 527 |
+
"optionalDependencies": {
|
| 528 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
| 529 |
+
}
|
| 530 |
+
},
|
| 531 |
+
"node_modules/@img/sharp-wasm32": {
|
| 532 |
+
"version": "0.34.5",
|
| 533 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
| 534 |
+
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
| 535 |
+
"cpu": [
|
| 536 |
+
"wasm32"
|
| 537 |
+
],
|
| 538 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
| 539 |
+
"optional": true,
|
| 540 |
+
"dependencies": {
|
| 541 |
+
"@emnapi/runtime": "^1.7.0"
|
| 542 |
+
},
|
| 543 |
+
"engines": {
|
| 544 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 545 |
+
},
|
| 546 |
+
"funding": {
|
| 547 |
+
"url": "https://opencollective.com/libvips"
|
| 548 |
+
}
|
| 549 |
+
},
|
| 550 |
+
"node_modules/@img/sharp-win32-arm64": {
|
| 551 |
+
"version": "0.34.5",
|
| 552 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
|
| 553 |
+
"integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
|
| 554 |
+
"cpu": [
|
| 555 |
+
"arm64"
|
| 556 |
+
],
|
| 557 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 558 |
+
"optional": true,
|
| 559 |
+
"os": [
|
| 560 |
+
"win32"
|
| 561 |
+
],
|
| 562 |
+
"engines": {
|
| 563 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 564 |
+
},
|
| 565 |
+
"funding": {
|
| 566 |
+
"url": "https://opencollective.com/libvips"
|
| 567 |
}
|
| 568 |
},
|
| 569 |
+
"node_modules/@img/sharp-win32-ia32": {
|
| 570 |
+
"version": "0.34.5",
|
| 571 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
| 572 |
+
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
| 573 |
+
"cpu": [
|
| 574 |
+
"ia32"
|
| 575 |
+
],
|
| 576 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 577 |
"optional": true,
|
| 578 |
+
"os": [
|
| 579 |
+
"win32"
|
| 580 |
+
],
|
| 581 |
+
"engines": {
|
| 582 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 583 |
+
},
|
| 584 |
+
"funding": {
|
| 585 |
+
"url": "https://opencollective.com/libvips"
|
| 586 |
+
}
|
| 587 |
+
},
|
| 588 |
+
"node_modules/@img/sharp-win32-x64": {
|
| 589 |
+
"version": "0.34.5",
|
| 590 |
+
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
| 591 |
+
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
| 592 |
+
"cpu": [
|
| 593 |
+
"x64"
|
| 594 |
+
],
|
| 595 |
+
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
| 596 |
+
"optional": true,
|
| 597 |
+
"os": [
|
| 598 |
+
"win32"
|
| 599 |
+
],
|
| 600 |
+
"engines": {
|
| 601 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 602 |
+
},
|
| 603 |
+
"funding": {
|
| 604 |
+
"url": "https://opencollective.com/libvips"
|
| 605 |
+
}
|
| 606 |
+
},
|
| 607 |
+
"node_modules/@isaacs/fs-minipass": {
|
| 608 |
+
"version": "4.0.1",
|
| 609 |
+
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
| 610 |
+
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
| 611 |
+
"license": "ISC",
|
| 612 |
"dependencies": {
|
| 613 |
+
"minipass": "^7.0.4"
|
| 614 |
+
},
|
| 615 |
+
"engines": {
|
| 616 |
+
"node": ">=18.0.0"
|
| 617 |
}
|
| 618 |
},
|
| 619 |
"node_modules/@loaders.gl/core": {
|
|
|
|
| 865 |
"integrity": "sha512-4VpAyMHOqydSvPlEyHwXaE+AkIdR03nX+Qhlxsk2D/IW4OVmDZgIsvJB1cDzyEEtcfKcnaEbfXeiPgejBceT6g==",
|
| 866 |
"license": "MIT"
|
| 867 |
},
|
| 868 |
+
"node_modules/@protobufjs/aspromise": {
|
| 869 |
+
"version": "1.1.2",
|
| 870 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
| 871 |
+
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
|
| 872 |
+
"license": "BSD-3-Clause"
|
| 873 |
+
},
|
| 874 |
+
"node_modules/@protobufjs/base64": {
|
| 875 |
+
"version": "1.1.2",
|
| 876 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
|
| 877 |
+
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
|
| 878 |
+
"license": "BSD-3-Clause"
|
| 879 |
+
},
|
| 880 |
+
"node_modules/@protobufjs/codegen": {
|
| 881 |
+
"version": "2.0.5",
|
| 882 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
|
| 883 |
+
"integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
|
| 884 |
+
"license": "BSD-3-Clause"
|
| 885 |
+
},
|
| 886 |
+
"node_modules/@protobufjs/eventemitter": {
|
| 887 |
+
"version": "1.1.1",
|
| 888 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
|
| 889 |
+
"integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
|
| 890 |
+
"license": "BSD-3-Clause"
|
| 891 |
+
},
|
| 892 |
+
"node_modules/@protobufjs/fetch": {
|
| 893 |
+
"version": "1.1.1",
|
| 894 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
|
| 895 |
+
"integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
|
| 896 |
+
"license": "BSD-3-Clause",
|
| 897 |
+
"dependencies": {
|
| 898 |
+
"@protobufjs/aspromise": "^1.1.1"
|
| 899 |
+
}
|
| 900 |
+
},
|
| 901 |
+
"node_modules/@protobufjs/float": {
|
| 902 |
+
"version": "1.0.2",
|
| 903 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
|
| 904 |
+
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
|
| 905 |
+
"license": "BSD-3-Clause"
|
| 906 |
+
},
|
| 907 |
+
"node_modules/@protobufjs/path": {
|
| 908 |
+
"version": "1.1.2",
|
| 909 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
|
| 910 |
+
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
|
| 911 |
+
"license": "BSD-3-Clause"
|
| 912 |
+
},
|
| 913 |
+
"node_modules/@protobufjs/pool": {
|
| 914 |
+
"version": "1.1.0",
|
| 915 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
|
| 916 |
+
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
|
| 917 |
+
"license": "BSD-3-Clause"
|
| 918 |
+
},
|
| 919 |
+
"node_modules/@protobufjs/utf8": {
|
| 920 |
+
"version": "1.1.1",
|
| 921 |
+
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz",
|
| 922 |
+
"integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==",
|
| 923 |
+
"license": "BSD-3-Clause"
|
| 924 |
+
},
|
| 925 |
"node_modules/@rolldown/binding-android-arm64": {
|
| 926 |
"version": "1.0.3",
|
| 927 |
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
|
|
|
|
| 1353 |
"node": ">=12.17"
|
| 1354 |
}
|
| 1355 |
},
|
| 1356 |
+
"node_modules/boolean": {
|
| 1357 |
+
"version": "3.2.0",
|
| 1358 |
+
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
| 1359 |
+
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
|
| 1360 |
+
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
| 1361 |
+
"license": "MIT"
|
| 1362 |
+
},
|
| 1363 |
"node_modules/chalk": {
|
| 1364 |
"version": "4.1.2",
|
| 1365 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
|
|
| 1397 |
"integrity": "sha512-pmcgaGHAxfYtKr4BtSaM/+/3vvQJJLkvQibEdO2eb5eiHrRgEAd43M2tpBGi4eIX32kXyvPLQVT23qNnuFaa8w==",
|
| 1398 |
"license": "ISC"
|
| 1399 |
},
|
| 1400 |
+
"node_modules/chownr": {
|
| 1401 |
+
"version": "3.0.0",
|
| 1402 |
+
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
| 1403 |
+
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
| 1404 |
+
"license": "BlueOak-1.0.0",
|
| 1405 |
+
"engines": {
|
| 1406 |
+
"node": ">=18"
|
| 1407 |
+
}
|
| 1408 |
+
},
|
| 1409 |
"node_modules/color-convert": {
|
| 1410 |
"version": "2.0.1",
|
| 1411 |
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
|
|
| 1475 |
"dev": true,
|
| 1476 |
"license": "MIT"
|
| 1477 |
},
|
| 1478 |
+
"node_modules/define-data-property": {
|
| 1479 |
+
"version": "1.1.4",
|
| 1480 |
+
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
| 1481 |
+
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
| 1482 |
+
"license": "MIT",
|
| 1483 |
+
"dependencies": {
|
| 1484 |
+
"es-define-property": "^1.0.0",
|
| 1485 |
+
"es-errors": "^1.3.0",
|
| 1486 |
+
"gopd": "^1.0.1"
|
| 1487 |
+
},
|
| 1488 |
+
"engines": {
|
| 1489 |
+
"node": ">= 0.4"
|
| 1490 |
+
},
|
| 1491 |
+
"funding": {
|
| 1492 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 1493 |
+
}
|
| 1494 |
+
},
|
| 1495 |
+
"node_modules/define-properties": {
|
| 1496 |
+
"version": "1.2.1",
|
| 1497 |
+
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
| 1498 |
+
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
| 1499 |
+
"license": "MIT",
|
| 1500 |
+
"dependencies": {
|
| 1501 |
+
"define-data-property": "^1.0.1",
|
| 1502 |
+
"has-property-descriptors": "^1.0.0",
|
| 1503 |
+
"object-keys": "^1.1.1"
|
| 1504 |
+
},
|
| 1505 |
+
"engines": {
|
| 1506 |
+
"node": ">= 0.4"
|
| 1507 |
+
},
|
| 1508 |
+
"funding": {
|
| 1509 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 1510 |
+
}
|
| 1511 |
+
},
|
| 1512 |
"node_modules/detect-libc": {
|
| 1513 |
"version": "2.1.2",
|
| 1514 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
| 1515 |
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
|
|
|
| 1516 |
"license": "Apache-2.0",
|
| 1517 |
"engines": {
|
| 1518 |
"node": ">=8"
|
| 1519 |
}
|
| 1520 |
},
|
| 1521 |
+
"node_modules/detect-node": {
|
| 1522 |
+
"version": "2.1.0",
|
| 1523 |
+
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
|
| 1524 |
+
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
|
| 1525 |
+
"license": "MIT"
|
| 1526 |
+
},
|
| 1527 |
"node_modules/earcut": {
|
| 1528 |
"version": "2.2.4",
|
| 1529 |
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
|
| 1530 |
"integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
|
| 1531 |
"license": "ISC"
|
| 1532 |
},
|
| 1533 |
+
"node_modules/es-define-property": {
|
| 1534 |
+
"version": "1.0.1",
|
| 1535 |
+
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
| 1536 |
+
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
| 1537 |
+
"license": "MIT",
|
| 1538 |
+
"engines": {
|
| 1539 |
+
"node": ">= 0.4"
|
| 1540 |
+
}
|
| 1541 |
+
},
|
| 1542 |
+
"node_modules/es-errors": {
|
| 1543 |
+
"version": "1.3.0",
|
| 1544 |
+
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
| 1545 |
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
| 1546 |
+
"license": "MIT",
|
| 1547 |
+
"engines": {
|
| 1548 |
+
"node": ">= 0.4"
|
| 1549 |
+
}
|
| 1550 |
+
},
|
| 1551 |
+
"node_modules/es6-error": {
|
| 1552 |
+
"version": "4.1.1",
|
| 1553 |
+
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
|
| 1554 |
+
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
| 1555 |
+
"license": "MIT"
|
| 1556 |
+
},
|
| 1557 |
+
"node_modules/escape-string-regexp": {
|
| 1558 |
+
"version": "4.0.0",
|
| 1559 |
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
| 1560 |
+
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
| 1561 |
+
"license": "MIT",
|
| 1562 |
+
"engines": {
|
| 1563 |
+
"node": ">=10"
|
| 1564 |
+
},
|
| 1565 |
+
"funding": {
|
| 1566 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 1567 |
+
}
|
| 1568 |
+
},
|
| 1569 |
"node_modules/fdir": {
|
| 1570 |
"version": "6.5.0",
|
| 1571 |
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
|
|
|
| 1634 |
"integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==",
|
| 1635 |
"license": "MIT"
|
| 1636 |
},
|
| 1637 |
+
"node_modules/global-agent": {
|
| 1638 |
+
"version": "3.0.0",
|
| 1639 |
+
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
|
| 1640 |
+
"integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
|
| 1641 |
+
"license": "BSD-3-Clause",
|
| 1642 |
+
"dependencies": {
|
| 1643 |
+
"boolean": "^3.0.1",
|
| 1644 |
+
"es6-error": "^4.1.1",
|
| 1645 |
+
"matcher": "^3.0.0",
|
| 1646 |
+
"roarr": "^2.15.3",
|
| 1647 |
+
"semver": "^7.3.2",
|
| 1648 |
+
"serialize-error": "^7.0.1"
|
| 1649 |
+
},
|
| 1650 |
+
"engines": {
|
| 1651 |
+
"node": ">=10.0"
|
| 1652 |
+
}
|
| 1653 |
+
},
|
| 1654 |
+
"node_modules/globalthis": {
|
| 1655 |
+
"version": "1.0.4",
|
| 1656 |
+
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
|
| 1657 |
+
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
|
| 1658 |
+
"license": "MIT",
|
| 1659 |
+
"dependencies": {
|
| 1660 |
+
"define-properties": "^1.2.1",
|
| 1661 |
+
"gopd": "^1.0.1"
|
| 1662 |
+
},
|
| 1663 |
+
"engines": {
|
| 1664 |
+
"node": ">= 0.4"
|
| 1665 |
+
},
|
| 1666 |
+
"funding": {
|
| 1667 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 1668 |
+
}
|
| 1669 |
+
},
|
| 1670 |
+
"node_modules/gopd": {
|
| 1671 |
+
"version": "1.2.0",
|
| 1672 |
+
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
| 1673 |
+
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
| 1674 |
+
"license": "MIT",
|
| 1675 |
+
"engines": {
|
| 1676 |
+
"node": ">= 0.4"
|
| 1677 |
+
},
|
| 1678 |
+
"funding": {
|
| 1679 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 1680 |
+
}
|
| 1681 |
+
},
|
| 1682 |
+
"node_modules/guid-typescript": {
|
| 1683 |
+
"version": "1.0.9",
|
| 1684 |
+
"resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz",
|
| 1685 |
+
"integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==",
|
| 1686 |
+
"license": "ISC"
|
| 1687 |
+
},
|
| 1688 |
"node_modules/has-flag": {
|
| 1689 |
"version": "4.0.0",
|
| 1690 |
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
|
|
|
| 1694 |
"node": ">=8"
|
| 1695 |
}
|
| 1696 |
},
|
| 1697 |
+
"node_modules/has-property-descriptors": {
|
| 1698 |
+
"version": "1.0.2",
|
| 1699 |
+
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
| 1700 |
+
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
| 1701 |
+
"license": "MIT",
|
| 1702 |
+
"dependencies": {
|
| 1703 |
+
"es-define-property": "^1.0.0"
|
| 1704 |
+
},
|
| 1705 |
+
"funding": {
|
| 1706 |
+
"url": "https://github.com/sponsors/ljharb"
|
| 1707 |
+
}
|
| 1708 |
+
},
|
| 1709 |
"node_modules/json-bignum": {
|
| 1710 |
"version": "0.0.3",
|
| 1711 |
"resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz",
|
|
|
|
| 1714 |
"node": ">=0.8"
|
| 1715 |
}
|
| 1716 |
},
|
| 1717 |
+
"node_modules/json-stringify-safe": {
|
| 1718 |
+
"version": "5.0.1",
|
| 1719 |
+
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
| 1720 |
+
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
| 1721 |
+
"license": "ISC"
|
| 1722 |
+
},
|
| 1723 |
"node_modules/kdbush": {
|
| 1724 |
"version": "4.1.0",
|
| 1725 |
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz",
|
| 1726 |
"integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==",
|
| 1727 |
"license": "ISC"
|
| 1728 |
},
|
| 1729 |
+
"node_modules/kokoro-js": {
|
| 1730 |
+
"version": "1.2.1",
|
| 1731 |
+
"resolved": "https://registry.npmjs.org/kokoro-js/-/kokoro-js-1.2.1.tgz",
|
| 1732 |
+
"integrity": "sha512-oq0HZJWis3t8lERkMJh84WLU86dpYD0EuBPtqYnLlQzyFP1OkyBRDcweAqCfhNOpltyN9j/azp1H6uuC47gShw==",
|
| 1733 |
+
"license": "Apache-2.0",
|
| 1734 |
+
"dependencies": {
|
| 1735 |
+
"@huggingface/transformers": "^3.5.1",
|
| 1736 |
+
"phonemizer": "^1.2.1"
|
| 1737 |
+
}
|
| 1738 |
+
},
|
| 1739 |
"node_modules/lightningcss": {
|
| 1740 |
"version": "1.32.0",
|
| 1741 |
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
|
|
|
| 2003 |
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
| 2004 |
"license": "MIT"
|
| 2005 |
},
|
| 2006 |
+
"node_modules/long": {
|
| 2007 |
+
"version": "5.3.2",
|
| 2008 |
+
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
| 2009 |
+
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
|
| 2010 |
+
"license": "Apache-2.0"
|
| 2011 |
+
},
|
| 2012 |
"node_modules/lucide-react": {
|
| 2013 |
"version": "0.468.0",
|
| 2014 |
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
|
|
|
|
| 2072 |
"tinyqueue": "3.0.0"
|
| 2073 |
}
|
| 2074 |
},
|
| 2075 |
+
"node_modules/matcher": {
|
| 2076 |
+
"version": "3.0.0",
|
| 2077 |
+
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
|
| 2078 |
+
"integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
|
| 2079 |
+
"license": "MIT",
|
| 2080 |
+
"dependencies": {
|
| 2081 |
+
"escape-string-regexp": "^4.0.0"
|
| 2082 |
+
},
|
| 2083 |
+
"engines": {
|
| 2084 |
+
"node": ">=10"
|
| 2085 |
+
}
|
| 2086 |
+
},
|
| 2087 |
+
"node_modules/minipass": {
|
| 2088 |
+
"version": "7.1.3",
|
| 2089 |
+
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
|
| 2090 |
+
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
|
| 2091 |
+
"license": "BlueOak-1.0.0",
|
| 2092 |
+
"engines": {
|
| 2093 |
+
"node": ">=16 || 14 >=14.17"
|
| 2094 |
+
}
|
| 2095 |
+
},
|
| 2096 |
+
"node_modules/minizlib": {
|
| 2097 |
+
"version": "3.1.0",
|
| 2098 |
+
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
|
| 2099 |
+
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
|
| 2100 |
+
"license": "MIT",
|
| 2101 |
+
"dependencies": {
|
| 2102 |
+
"minipass": "^7.1.2"
|
| 2103 |
+
},
|
| 2104 |
+
"engines": {
|
| 2105 |
+
"node": ">= 18"
|
| 2106 |
+
}
|
| 2107 |
+
},
|
| 2108 |
"node_modules/mjolnir.js": {
|
| 2109 |
"version": "3.0.0",
|
| 2110 |
"resolved": "https://registry.npmjs.org/mjolnir.js/-/mjolnir.js-3.0.0.tgz",
|
|
|
|
| 2136 |
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
| 2137 |
}
|
| 2138 |
},
|
| 2139 |
+
"node_modules/object-keys": {
|
| 2140 |
+
"version": "1.1.1",
|
| 2141 |
+
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
| 2142 |
+
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
| 2143 |
+
"license": "MIT",
|
| 2144 |
+
"engines": {
|
| 2145 |
+
"node": ">= 0.4"
|
| 2146 |
+
}
|
| 2147 |
+
},
|
| 2148 |
+
"node_modules/onnxruntime-common": {
|
| 2149 |
+
"version": "1.21.0",
|
| 2150 |
+
"resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz",
|
| 2151 |
+
"integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==",
|
| 2152 |
+
"license": "MIT"
|
| 2153 |
+
},
|
| 2154 |
+
"node_modules/onnxruntime-node": {
|
| 2155 |
+
"version": "1.21.0",
|
| 2156 |
+
"resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz",
|
| 2157 |
+
"integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==",
|
| 2158 |
+
"hasInstallScript": true,
|
| 2159 |
+
"license": "MIT",
|
| 2160 |
+
"os": [
|
| 2161 |
+
"win32",
|
| 2162 |
+
"darwin",
|
| 2163 |
+
"linux"
|
| 2164 |
+
],
|
| 2165 |
+
"dependencies": {
|
| 2166 |
+
"global-agent": "^3.0.0",
|
| 2167 |
+
"onnxruntime-common": "1.21.0",
|
| 2168 |
+
"tar": "^7.0.1"
|
| 2169 |
+
}
|
| 2170 |
+
},
|
| 2171 |
+
"node_modules/onnxruntime-web": {
|
| 2172 |
+
"version": "1.22.0-dev.20250409-89f8206ba4",
|
| 2173 |
+
"resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz",
|
| 2174 |
+
"integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==",
|
| 2175 |
+
"license": "MIT",
|
| 2176 |
+
"dependencies": {
|
| 2177 |
+
"flatbuffers": "^25.1.24",
|
| 2178 |
+
"guid-typescript": "^1.0.9",
|
| 2179 |
+
"long": "^5.2.3",
|
| 2180 |
+
"onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4",
|
| 2181 |
+
"platform": "^1.3.6",
|
| 2182 |
+
"protobufjs": "^7.2.4"
|
| 2183 |
+
}
|
| 2184 |
+
},
|
| 2185 |
+
"node_modules/onnxruntime-web/node_modules/onnxruntime-common": {
|
| 2186 |
+
"version": "1.22.0-dev.20250409-89f8206ba4",
|
| 2187 |
+
"resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz",
|
| 2188 |
+
"integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==",
|
| 2189 |
+
"license": "MIT"
|
| 2190 |
+
},
|
| 2191 |
"node_modules/pbf": {
|
| 2192 |
"version": "4.0.2",
|
| 2193 |
"resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.2.tgz",
|
|
|
|
| 2200 |
"pbf": "bin/pbf"
|
| 2201 |
}
|
| 2202 |
},
|
| 2203 |
+
"node_modules/phonemizer": {
|
| 2204 |
+
"version": "1.2.1",
|
| 2205 |
+
"resolved": "https://registry.npmjs.org/phonemizer/-/phonemizer-1.2.1.tgz",
|
| 2206 |
+
"integrity": "sha512-v0KJ4mi2T4Q7eJQ0W15Xd4G9k4kICSXE8bpDeJ8jisL4RyJhNWsweKTOi88QXFc4r4LZlz5jVL5lCHhkpdT71A==",
|
| 2207 |
+
"license": "Apache-2.0"
|
| 2208 |
+
},
|
| 2209 |
"node_modules/picocolors": {
|
| 2210 |
"version": "1.1.1",
|
| 2211 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
|
|
| 2226 |
"url": "https://github.com/sponsors/jonschlinkert"
|
| 2227 |
}
|
| 2228 |
},
|
| 2229 |
+
"node_modules/platform": {
|
| 2230 |
+
"version": "1.3.6",
|
| 2231 |
+
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz",
|
| 2232 |
+
"integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==",
|
| 2233 |
+
"license": "MIT"
|
| 2234 |
+
},
|
| 2235 |
"node_modules/postcss": {
|
| 2236 |
"version": "8.5.15",
|
| 2237 |
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
|
|
|
| 2267 |
"integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==",
|
| 2268 |
"license": "ISC"
|
| 2269 |
},
|
| 2270 |
+
"node_modules/protobufjs": {
|
| 2271 |
+
"version": "7.6.4",
|
| 2272 |
+
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz",
|
| 2273 |
+
"integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==",
|
| 2274 |
+
"hasInstallScript": true,
|
| 2275 |
+
"license": "BSD-3-Clause",
|
| 2276 |
+
"dependencies": {
|
| 2277 |
+
"@protobufjs/aspromise": "^1.1.2",
|
| 2278 |
+
"@protobufjs/base64": "^1.1.2",
|
| 2279 |
+
"@protobufjs/codegen": "^2.0.5",
|
| 2280 |
+
"@protobufjs/eventemitter": "^1.1.1",
|
| 2281 |
+
"@protobufjs/fetch": "^1.1.1",
|
| 2282 |
+
"@protobufjs/float": "^1.0.2",
|
| 2283 |
+
"@protobufjs/path": "^1.1.2",
|
| 2284 |
+
"@protobufjs/pool": "^1.1.0",
|
| 2285 |
+
"@protobufjs/utf8": "^1.1.1",
|
| 2286 |
+
"@types/node": ">=13.7.0",
|
| 2287 |
+
"long": "^5.3.2"
|
| 2288 |
+
},
|
| 2289 |
+
"engines": {
|
| 2290 |
+
"node": ">=12.0.0"
|
| 2291 |
+
}
|
| 2292 |
+
},
|
| 2293 |
"node_modules/protocol-buffers-schema": {
|
| 2294 |
"version": "3.6.1",
|
| 2295 |
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz",
|
|
|
|
| 2332 |
"protocol-buffers-schema": "^3.3.1"
|
| 2333 |
}
|
| 2334 |
},
|
| 2335 |
+
"node_modules/roarr": {
|
| 2336 |
+
"version": "2.15.4",
|
| 2337 |
+
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
|
| 2338 |
+
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
|
| 2339 |
+
"license": "BSD-3-Clause",
|
| 2340 |
+
"dependencies": {
|
| 2341 |
+
"boolean": "^3.0.1",
|
| 2342 |
+
"detect-node": "^2.0.4",
|
| 2343 |
+
"globalthis": "^1.0.1",
|
| 2344 |
+
"json-stringify-safe": "^5.0.1",
|
| 2345 |
+
"semver-compare": "^1.0.0",
|
| 2346 |
+
"sprintf-js": "^1.1.2"
|
| 2347 |
+
},
|
| 2348 |
+
"engines": {
|
| 2349 |
+
"node": ">=8.0"
|
| 2350 |
+
}
|
| 2351 |
+
},
|
| 2352 |
"node_modules/robust-predicates": {
|
| 2353 |
"version": "2.0.4",
|
| 2354 |
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz",
|
|
|
|
| 2395 |
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
| 2396 |
"license": "MIT"
|
| 2397 |
},
|
| 2398 |
+
"node_modules/semver": {
|
| 2399 |
+
"version": "7.8.4",
|
| 2400 |
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
|
| 2401 |
+
"integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
|
| 2402 |
+
"license": "ISC",
|
| 2403 |
+
"bin": {
|
| 2404 |
+
"semver": "bin/semver.js"
|
| 2405 |
+
},
|
| 2406 |
+
"engines": {
|
| 2407 |
+
"node": ">=10"
|
| 2408 |
+
}
|
| 2409 |
+
},
|
| 2410 |
+
"node_modules/semver-compare": {
|
| 2411 |
+
"version": "1.0.0",
|
| 2412 |
+
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
|
| 2413 |
+
"integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
|
| 2414 |
+
"license": "MIT"
|
| 2415 |
+
},
|
| 2416 |
+
"node_modules/serialize-error": {
|
| 2417 |
+
"version": "7.0.1",
|
| 2418 |
+
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
|
| 2419 |
+
"integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
|
| 2420 |
+
"license": "MIT",
|
| 2421 |
+
"dependencies": {
|
| 2422 |
+
"type-fest": "^0.13.1"
|
| 2423 |
+
},
|
| 2424 |
+
"engines": {
|
| 2425 |
+
"node": ">=10"
|
| 2426 |
+
},
|
| 2427 |
+
"funding": {
|
| 2428 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 2429 |
+
}
|
| 2430 |
+
},
|
| 2431 |
+
"node_modules/sharp": {
|
| 2432 |
+
"version": "0.34.5",
|
| 2433 |
+
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
| 2434 |
+
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
| 2435 |
+
"hasInstallScript": true,
|
| 2436 |
+
"license": "Apache-2.0",
|
| 2437 |
+
"dependencies": {
|
| 2438 |
+
"@img/colour": "^1.0.0",
|
| 2439 |
+
"detect-libc": "^2.1.2",
|
| 2440 |
+
"semver": "^7.7.3"
|
| 2441 |
+
},
|
| 2442 |
+
"engines": {
|
| 2443 |
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
| 2444 |
+
},
|
| 2445 |
+
"funding": {
|
| 2446 |
+
"url": "https://opencollective.com/libvips"
|
| 2447 |
+
},
|
| 2448 |
+
"optionalDependencies": {
|
| 2449 |
+
"@img/sharp-darwin-arm64": "0.34.5",
|
| 2450 |
+
"@img/sharp-darwin-x64": "0.34.5",
|
| 2451 |
+
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
| 2452 |
+
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
| 2453 |
+
"@img/sharp-libvips-linux-arm": "1.2.4",
|
| 2454 |
+
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
| 2455 |
+
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
| 2456 |
+
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
| 2457 |
+
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
| 2458 |
+
"@img/sharp-libvips-linux-x64": "1.2.4",
|
| 2459 |
+
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
| 2460 |
+
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
| 2461 |
+
"@img/sharp-linux-arm": "0.34.5",
|
| 2462 |
+
"@img/sharp-linux-arm64": "0.34.5",
|
| 2463 |
+
"@img/sharp-linux-ppc64": "0.34.5",
|
| 2464 |
+
"@img/sharp-linux-riscv64": "0.34.5",
|
| 2465 |
+
"@img/sharp-linux-s390x": "0.34.5",
|
| 2466 |
+
"@img/sharp-linux-x64": "0.34.5",
|
| 2467 |
+
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
| 2468 |
+
"@img/sharp-linuxmusl-x64": "0.34.5",
|
| 2469 |
+
"@img/sharp-wasm32": "0.34.5",
|
| 2470 |
+
"@img/sharp-win32-arm64": "0.34.5",
|
| 2471 |
+
"@img/sharp-win32-ia32": "0.34.5",
|
| 2472 |
+
"@img/sharp-win32-x64": "0.34.5"
|
| 2473 |
+
}
|
| 2474 |
+
},
|
| 2475 |
"node_modules/source-map-js": {
|
| 2476 |
"version": "1.2.1",
|
| 2477 |
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
|
|
|
| 2488 |
"integrity": "sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==",
|
| 2489 |
"license": "MIT"
|
| 2490 |
},
|
| 2491 |
+
"node_modules/sprintf-js": {
|
| 2492 |
+
"version": "1.1.3",
|
| 2493 |
+
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
| 2494 |
+
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
| 2495 |
+
"license": "BSD-3-Clause"
|
| 2496 |
+
},
|
| 2497 |
"node_modules/supercluster": {
|
| 2498 |
"version": "8.0.1",
|
| 2499 |
"resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
|
|
|
|
| 2528 |
"node": ">=12.17"
|
| 2529 |
}
|
| 2530 |
},
|
| 2531 |
+
"node_modules/tar": {
|
| 2532 |
+
"version": "7.5.16",
|
| 2533 |
+
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
|
| 2534 |
+
"integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==",
|
| 2535 |
+
"license": "BlueOak-1.0.0",
|
| 2536 |
+
"dependencies": {
|
| 2537 |
+
"@isaacs/fs-minipass": "^4.0.0",
|
| 2538 |
+
"chownr": "^3.0.0",
|
| 2539 |
+
"minipass": "^7.1.2",
|
| 2540 |
+
"minizlib": "^3.1.0",
|
| 2541 |
+
"yallist": "^5.0.0"
|
| 2542 |
+
},
|
| 2543 |
+
"engines": {
|
| 2544 |
+
"node": ">=18"
|
| 2545 |
+
}
|
| 2546 |
+
},
|
| 2547 |
"node_modules/tinyglobby": {
|
| 2548 |
"version": "0.2.17",
|
| 2549 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
|
|
|
| 2573 |
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
| 2574 |
"license": "0BSD"
|
| 2575 |
},
|
| 2576 |
+
"node_modules/type-fest": {
|
| 2577 |
+
"version": "0.13.1",
|
| 2578 |
+
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
|
| 2579 |
+
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
|
| 2580 |
+
"license": "(MIT OR CC0-1.0)",
|
| 2581 |
+
"engines": {
|
| 2582 |
+
"node": ">=10"
|
| 2583 |
+
},
|
| 2584 |
+
"funding": {
|
| 2585 |
+
"url": "https://github.com/sponsors/sindresorhus"
|
| 2586 |
+
}
|
| 2587 |
+
},
|
| 2588 |
"node_modules/typescript": {
|
| 2589 |
"version": "5.9.3",
|
| 2590 |
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
|
|
|
| 2700 |
"engines": {
|
| 2701 |
"node": ">=12.17"
|
| 2702 |
}
|
| 2703 |
+
},
|
| 2704 |
+
"node_modules/yallist": {
|
| 2705 |
+
"version": "5.0.0",
|
| 2706 |
+
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
| 2707 |
+
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
| 2708 |
+
"license": "BlueOak-1.0.0",
|
| 2709 |
+
"engines": {
|
| 2710 |
+
"node": ">=18"
|
| 2711 |
+
}
|
| 2712 |
}
|
| 2713 |
}
|
| 2714 |
}
|
package.json
CHANGED
|
@@ -17,6 +17,7 @@
|
|
| 17 |
"@deck.gl/core": "^9.0.0",
|
| 18 |
"@deck.gl/layers": "^9.0.0",
|
| 19 |
"@deck.gl/mapbox": "^9.0.0",
|
|
|
|
| 20 |
"lucide-react": "^0.468.0",
|
| 21 |
"mapbox-gl": "^3.11.1",
|
| 22 |
"react": "^19.0.0",
|
|
|
|
| 17 |
"@deck.gl/core": "^9.0.0",
|
| 18 |
"@deck.gl/layers": "^9.0.0",
|
| 19 |
"@deck.gl/mapbox": "^9.0.0",
|
| 20 |
+
"kokoro-js": "^1.2.1",
|
| 21 |
"lucide-react": "^0.468.0",
|
| 22 |
"mapbox-gl": "^3.11.1",
|
| 23 |
"react": "^19.0.0",
|
server/agent-core.mjs
CHANGED
|
@@ -416,7 +416,7 @@ function buildEvidenceRecommendation(run, selected, webResearch, evidenceNotes)
|
|
| 416 |
}
|
| 417 |
|
| 418 |
function sanitizeTrace(trace = []) {
|
| 419 |
-
const visibleTools = new Set(["discover_neighborhoods", "plan_research", "parse_renter_intent", "housing_web_research", "score_neighborhoods", "hf_reasoning", "nvidia_reasoning", "
|
| 420 |
return trace
|
| 421 |
.filter((step) => visibleTools.has(step.tool) || step.tool.startsWith("agent_"))
|
| 422 |
.map((step) => {
|
|
|
|
| 416 |
}
|
| 417 |
|
| 418 |
function sanitizeTrace(trace = []) {
|
| 419 |
+
const visibleTools = new Set(["discover_neighborhoods", "plan_research", "parse_renter_intent", "housing_web_research", "score_neighborhoods", "hf_reasoning", "nvidia_reasoning", "llamacpp_reasoning"]);
|
| 420 |
return trace
|
| 421 |
.filter((step) => visibleTools.has(step.tool) || step.tool.startsWith("agent_"))
|
| 422 |
.map((step) => {
|
server/index.mjs
CHANGED
|
@@ -4,7 +4,6 @@ import { resolve } from "node:path";
|
|
| 4 |
import { applyEvidencePolicy, buildLocalAgentRun, mergeModelRecommendation } from "./agent-core.mjs";
|
| 5 |
import { configuredModel, runHfAgent } from "./hf-client.mjs";
|
| 6 |
import { configuredNvidiaModel, runNvidiaAgent } from "./nvidia-client.mjs";
|
| 7 |
-
import { configuredOllamaModel, runOllamaAgent } from "./ollama-client.mjs";
|
| 8 |
import { configuredLlamaCppModel, llamaCppEnabled, runLlamaCppAgent } from "./llamacpp-client.mjs";
|
| 9 |
import { runAgentFanOut } from "./agent-fanout.mjs";
|
| 10 |
import { discoverNeighborhoods, buildDiscoveredRows } from "./discover.mjs";
|
|
@@ -45,7 +44,6 @@ const server = createServer(async (request, response) => {
|
|
| 45 |
),
|
| 46 |
nvidiaConfigured: Boolean(process.env.NVIDIA_API_KEY || process.env.NGC_API_KEY),
|
| 47 |
llamacppConfigured: llamaCppEnabled(),
|
| 48 |
-
ollamaConfigured: Boolean(configuredOllamaModel()),
|
| 49 |
searchProvider: configuredSearchProvider(),
|
| 50 |
search: searchProviderStatus(),
|
| 51 |
researchEnabled: process.env.RESEARCH_ENABLED !== "0",
|
|
@@ -302,9 +300,6 @@ async function runConfiguredModel(localRun) {
|
|
| 302 |
if (provider === "llamacpp") {
|
| 303 |
return { provider, ...(await runLlamaCppAgent(localRun)) };
|
| 304 |
}
|
| 305 |
-
if (provider === "ollama") {
|
| 306 |
-
return { provider, ...(await runOllamaAgent(localRun)) };
|
| 307 |
-
}
|
| 308 |
if (provider === "nvidia") {
|
| 309 |
return { provider, ...(await runNvidiaAgent(localRun)) };
|
| 310 |
}
|
|
@@ -313,20 +308,18 @@ async function runConfiguredModel(localRun) {
|
|
| 313 |
}
|
| 314 |
|
| 315 |
// auto: Nemotron (NVIDIA) first when keyed, then a local llama.cpp/OpenBMB GGUF,
|
| 316 |
-
// then
|
| 317 |
const nvidia = await runNvidiaAgent(localRun);
|
| 318 |
if (nvidia.status === "done") return { provider: "nvidia", ...nvidia };
|
| 319 |
const llamacpp = await runLlamaCppAgent(localRun);
|
| 320 |
if (llamacpp.status === "done") return { provider: "llamacpp", ...llamacpp };
|
| 321 |
-
const ollama = await runOllamaAgent(localRun);
|
| 322 |
-
if (ollama.status === "done") return { provider: "ollama", ...ollama };
|
| 323 |
const hf = await runHfAgent(localRun);
|
| 324 |
if (hf.status === "done") return { provider: "hf", ...hf };
|
| 325 |
|
| 326 |
return {
|
| 327 |
provider: "auto",
|
| 328 |
status: "error",
|
| 329 |
-
reason: `NVIDIA: ${nvidia.reason}; llama.cpp: ${llamacpp.reason};
|
| 330 |
model: configuredAgentModel(),
|
| 331 |
result: null,
|
| 332 |
};
|
|
@@ -334,7 +327,7 @@ async function runConfiguredModel(localRun) {
|
|
| 334 |
|
| 335 |
function configuredProvider() {
|
| 336 |
const raw = (process.env.AGENT_MODEL_PROVIDER || process.env.AGENT_PROVIDER || "hf").toLowerCase();
|
| 337 |
-
if (["nvidia", "llamacpp", "
|
| 338 |
return "hf";
|
| 339 |
}
|
| 340 |
|
|
@@ -342,9 +335,8 @@ function configuredAgentModel() {
|
|
| 342 |
const provider = configuredProvider();
|
| 343 |
if (provider === "nvidia") return configuredNvidiaModel();
|
| 344 |
if (provider === "llamacpp") return configuredLlamaCppModel();
|
| 345 |
-
if (provider === "ollama") return configuredOllamaModel();
|
| 346 |
if (provider === "auto") {
|
| 347 |
-
return configuredNvidiaModel() || configuredLlamaCppModel() ||
|
| 348 |
}
|
| 349 |
return configuredModel();
|
| 350 |
}
|
|
|
|
| 4 |
import { applyEvidencePolicy, buildLocalAgentRun, mergeModelRecommendation } from "./agent-core.mjs";
|
| 5 |
import { configuredModel, runHfAgent } from "./hf-client.mjs";
|
| 6 |
import { configuredNvidiaModel, runNvidiaAgent } from "./nvidia-client.mjs";
|
|
|
|
| 7 |
import { configuredLlamaCppModel, llamaCppEnabled, runLlamaCppAgent } from "./llamacpp-client.mjs";
|
| 8 |
import { runAgentFanOut } from "./agent-fanout.mjs";
|
| 9 |
import { discoverNeighborhoods, buildDiscoveredRows } from "./discover.mjs";
|
|
|
|
| 44 |
),
|
| 45 |
nvidiaConfigured: Boolean(process.env.NVIDIA_API_KEY || process.env.NGC_API_KEY),
|
| 46 |
llamacppConfigured: llamaCppEnabled(),
|
|
|
|
| 47 |
searchProvider: configuredSearchProvider(),
|
| 48 |
search: searchProviderStatus(),
|
| 49 |
researchEnabled: process.env.RESEARCH_ENABLED !== "0",
|
|
|
|
| 300 |
if (provider === "llamacpp") {
|
| 301 |
return { provider, ...(await runLlamaCppAgent(localRun)) };
|
| 302 |
}
|
|
|
|
|
|
|
|
|
|
| 303 |
if (provider === "nvidia") {
|
| 304 |
return { provider, ...(await runNvidiaAgent(localRun)) };
|
| 305 |
}
|
|
|
|
| 308 |
}
|
| 309 |
|
| 310 |
// auto: Nemotron (NVIDIA) first when keyed, then a local llama.cpp/OpenBMB GGUF,
|
| 311 |
+
// then the HF model — so the agent always lands on a working brain.
|
| 312 |
const nvidia = await runNvidiaAgent(localRun);
|
| 313 |
if (nvidia.status === "done") return { provider: "nvidia", ...nvidia };
|
| 314 |
const llamacpp = await runLlamaCppAgent(localRun);
|
| 315 |
if (llamacpp.status === "done") return { provider: "llamacpp", ...llamacpp };
|
|
|
|
|
|
|
| 316 |
const hf = await runHfAgent(localRun);
|
| 317 |
if (hf.status === "done") return { provider: "hf", ...hf };
|
| 318 |
|
| 319 |
return {
|
| 320 |
provider: "auto",
|
| 321 |
status: "error",
|
| 322 |
+
reason: `NVIDIA: ${nvidia.reason}; llama.cpp: ${llamacpp.reason}; Hugging Face: ${hf.reason}`,
|
| 323 |
model: configuredAgentModel(),
|
| 324 |
result: null,
|
| 325 |
};
|
|
|
|
| 327 |
|
| 328 |
function configuredProvider() {
|
| 329 |
const raw = (process.env.AGENT_MODEL_PROVIDER || process.env.AGENT_PROVIDER || "hf").toLowerCase();
|
| 330 |
+
if (["nvidia", "llamacpp", "hf", "auto"].includes(raw)) return raw;
|
| 331 |
return "hf";
|
| 332 |
}
|
| 333 |
|
|
|
|
| 335 |
const provider = configuredProvider();
|
| 336 |
if (provider === "nvidia") return configuredNvidiaModel();
|
| 337 |
if (provider === "llamacpp") return configuredLlamaCppModel();
|
|
|
|
| 338 |
if (provider === "auto") {
|
| 339 |
+
return configuredNvidiaModel() || configuredLlamaCppModel() || configuredModel();
|
| 340 |
}
|
| 341 |
return configuredModel();
|
| 342 |
}
|
server/model-chat.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
// Shared "talk to the configured agentic model" helper. Resolves whichever brain is
|
| 2 |
-
// active (Nemotron / llama.cpp+OpenBMB /
|
| 3 |
// request, so the per-agent fan-out reasons with the SAME agentic model as the synthesiser.
|
| 4 |
import { stripReasoning } from "./model-prompt.mjs";
|
| 5 |
|
|
@@ -18,7 +18,6 @@ export function resolveActiveProvider(env = process.env) {
|
|
| 18 |
const has = {
|
| 19 |
nvidia: Boolean(env.NVIDIA_API_KEY || env.NGC_API_KEY),
|
| 20 |
llamacpp: env.LLAMACPP_ENABLED === "1",
|
| 21 |
-
ollama: Boolean(env.OLLAMA_MODEL || env.AGENT_OLLAMA_MODEL),
|
| 22 |
hf: Boolean(env.HF_TOKEN || env.HUGGINGFACEHUB_API_TOKEN || env.HUGGING_FACE_HUB_TOKEN),
|
| 23 |
};
|
| 24 |
if (raw !== "auto" && raw !== "") return has[raw] ? raw : firstAvailable(has);
|
|
@@ -28,7 +27,6 @@ export function resolveActiveProvider(env = process.env) {
|
|
| 28 |
function firstAvailable(has) {
|
| 29 |
if (has.nvidia) return "nvidia";
|
| 30 |
if (has.llamacpp) return "llamacpp";
|
| 31 |
-
if (has.ollama) return "ollama";
|
| 32 |
if (has.hf) return "hf";
|
| 33 |
return null;
|
| 34 |
}
|
|
@@ -37,7 +35,6 @@ function availability(env) {
|
|
| 37 |
return {
|
| 38 |
nvidia: Boolean(env.NVIDIA_API_KEY || env.NGC_API_KEY),
|
| 39 |
llamacpp: env.LLAMACPP_ENABLED === "1",
|
| 40 |
-
ollama: Boolean(env.OLLAMA_MODEL || env.AGENT_OLLAMA_MODEL),
|
| 41 |
hf: Boolean(env.HF_TOKEN || env.HUGGINGFACEHUB_API_TOKEN || env.HUGGING_FACE_HUB_TOKEN),
|
| 42 |
};
|
| 43 |
}
|
|
@@ -51,7 +48,6 @@ export function resolveMainProvider(env = process.env) {
|
|
| 51 |
if (raw !== "auto" && raw !== "" && has[raw]) return raw;
|
| 52 |
if (has.nvidia) return "nvidia";
|
| 53 |
if (has.hf) return "hf";
|
| 54 |
-
if (has.ollama) return "ollama";
|
| 55 |
if (has.llamacpp) return "llamacpp";
|
| 56 |
return null;
|
| 57 |
}
|
|
@@ -85,14 +81,6 @@ function endpointFor(provider, env) {
|
|
| 85 |
grammar: true,
|
| 86 |
};
|
| 87 |
}
|
| 88 |
-
if (provider === "ollama") {
|
| 89 |
-
const host = env.OLLAMA_HOST || "http://127.0.0.1:11434";
|
| 90 |
-
return {
|
| 91 |
-
url: env.OLLAMA_CHAT_COMPLETIONS_URL || `${host.replace(/\/$/, "")}/v1/chat/completions`,
|
| 92 |
-
model: env.OLLAMA_MODEL || env.AGENT_OLLAMA_MODEL,
|
| 93 |
-
auth: "ollama",
|
| 94 |
-
};
|
| 95 |
-
}
|
| 96 |
return {
|
| 97 |
url: env.HF_CHAT_COMPLETIONS_URL || "https://router.huggingface.co/v1/chat/completions",
|
| 98 |
model: env.HF_MODEL || "Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
|
|
|
| 1 |
// Shared "talk to the configured agentic model" helper. Resolves whichever brain is
|
| 2 |
+
// active (Nemotron / llama.cpp+OpenBMB / HF) and sends an OpenAI-compatible chat
|
| 3 |
// request, so the per-agent fan-out reasons with the SAME agentic model as the synthesiser.
|
| 4 |
import { stripReasoning } from "./model-prompt.mjs";
|
| 5 |
|
|
|
|
| 18 |
const has = {
|
| 19 |
nvidia: Boolean(env.NVIDIA_API_KEY || env.NGC_API_KEY),
|
| 20 |
llamacpp: env.LLAMACPP_ENABLED === "1",
|
|
|
|
| 21 |
hf: Boolean(env.HF_TOKEN || env.HUGGINGFACEHUB_API_TOKEN || env.HUGGING_FACE_HUB_TOKEN),
|
| 22 |
};
|
| 23 |
if (raw !== "auto" && raw !== "") return has[raw] ? raw : firstAvailable(has);
|
|
|
|
| 27 |
function firstAvailable(has) {
|
| 28 |
if (has.nvidia) return "nvidia";
|
| 29 |
if (has.llamacpp) return "llamacpp";
|
|
|
|
| 30 |
if (has.hf) return "hf";
|
| 31 |
return null;
|
| 32 |
}
|
|
|
|
| 35 |
return {
|
| 36 |
nvidia: Boolean(env.NVIDIA_API_KEY || env.NGC_API_KEY),
|
| 37 |
llamacpp: env.LLAMACPP_ENABLED === "1",
|
|
|
|
| 38 |
hf: Boolean(env.HF_TOKEN || env.HUGGINGFACEHUB_API_TOKEN || env.HUGGING_FACE_HUB_TOKEN),
|
| 39 |
};
|
| 40 |
}
|
|
|
|
| 48 |
if (raw !== "auto" && raw !== "" && has[raw]) return raw;
|
| 49 |
if (has.nvidia) return "nvidia";
|
| 50 |
if (has.hf) return "hf";
|
|
|
|
| 51 |
if (has.llamacpp) return "llamacpp";
|
| 52 |
return null;
|
| 53 |
}
|
|
|
|
| 81 |
grammar: true,
|
| 82 |
};
|
| 83 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
return {
|
| 85 |
url: env.HF_CHAT_COMPLETIONS_URL || "https://router.huggingface.co/v1/chat/completions",
|
| 86 |
model: env.HF_MODEL || "Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
server/ollama-client.mjs
DELETED
|
@@ -1,146 +0,0 @@
|
|
| 1 |
-
import { buildModelContext } from "./agent-core.mjs";
|
| 2 |
-
import { SYSTEM_PROMPT, parseModelJson } from "./model-prompt.mjs";
|
| 3 |
-
|
| 4 |
-
const DEFAULT_OLLAMA_URL = "http://127.0.0.1:11434/v1/chat/completions";
|
| 5 |
-
|
| 6 |
-
export async function runOllamaAgent(localRun, env = process.env) {
|
| 7 |
-
if (env.AGENT_OFFLINE === "1") {
|
| 8 |
-
return {
|
| 9 |
-
status: "skipped",
|
| 10 |
-
reason: "AGENT_OFFLINE is enabled",
|
| 11 |
-
model: configuredOllamaModel(env),
|
| 12 |
-
result: null,
|
| 13 |
-
};
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
const model = configuredOllamaModel(env);
|
| 17 |
-
if (!model) {
|
| 18 |
-
return {
|
| 19 |
-
status: "skipped",
|
| 20 |
-
reason: "OLLAMA_MODEL is not configured",
|
| 21 |
-
model: null,
|
| 22 |
-
result: null,
|
| 23 |
-
};
|
| 24 |
-
}
|
| 25 |
-
|
| 26 |
-
const context = buildModelContext(localRun);
|
| 27 |
-
const basePayload = {
|
| 28 |
-
model,
|
| 29 |
-
messages: [
|
| 30 |
-
{ role: "system", content: SYSTEM_PROMPT },
|
| 31 |
-
{ role: "user", content: JSON.stringify(context) },
|
| 32 |
-
],
|
| 33 |
-
temperature: Number(env.OLLAMA_TEMPERATURE ?? 0.2),
|
| 34 |
-
max_tokens: Number(env.OLLAMA_MAX_TOKENS ?? 900),
|
| 35 |
-
stream: false,
|
| 36 |
-
};
|
| 37 |
-
|
| 38 |
-
const richPayload = {
|
| 39 |
-
...basePayload,
|
| 40 |
-
response_format: { type: "json_object" },
|
| 41 |
-
reasoning_effort: env.OLLAMA_REASONING_EFFORT || "medium",
|
| 42 |
-
};
|
| 43 |
-
|
| 44 |
-
try {
|
| 45 |
-
const body = await postChat(richPayload, env);
|
| 46 |
-
return {
|
| 47 |
-
status: "done",
|
| 48 |
-
reason: null,
|
| 49 |
-
model,
|
| 50 |
-
result: parseModelJson(body, "Ollama"),
|
| 51 |
-
};
|
| 52 |
-
} catch (error) {
|
| 53 |
-
if (isRetryableProviderError(error)) {
|
| 54 |
-
try {
|
| 55 |
-
const body = await postChat(basePayload, env);
|
| 56 |
-
return {
|
| 57 |
-
status: "done",
|
| 58 |
-
reason: "Retried without JSON/reasoning parameters",
|
| 59 |
-
model,
|
| 60 |
-
result: parseModelJson(body, "Ollama"),
|
| 61 |
-
};
|
| 62 |
-
} catch (retryError) {
|
| 63 |
-
return errorResult(retryError, model);
|
| 64 |
-
}
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
return errorResult(error, model);
|
| 68 |
-
}
|
| 69 |
-
}
|
| 70 |
-
|
| 71 |
-
export function configuredOllamaModel(env = process.env) {
|
| 72 |
-
return env.OLLAMA_MODEL || env.AGENT_OLLAMA_MODEL || "";
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
export function ollamaChatCompletionsUrl(env = process.env) {
|
| 76 |
-
if (env.OLLAMA_CHAT_COMPLETIONS_URL) return env.OLLAMA_CHAT_COMPLETIONS_URL;
|
| 77 |
-
const host = env.OLLAMA_HOST || "http://127.0.0.1:11434";
|
| 78 |
-
return `${host.replace(/\/$/, "")}/v1/chat/completions`;
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
async function postChat(payload, env) {
|
| 82 |
-
const timeoutMs = Number(env.OLLAMA_TIMEOUT_MS ?? 60000);
|
| 83 |
-
const controller = new AbortController();
|
| 84 |
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
| 85 |
-
|
| 86 |
-
try {
|
| 87 |
-
const response = await fetch(ollamaChatCompletionsUrl(env), {
|
| 88 |
-
method: "POST",
|
| 89 |
-
headers: {
|
| 90 |
-
Authorization: "Bearer ollama",
|
| 91 |
-
"Content-Type": "application/json",
|
| 92 |
-
},
|
| 93 |
-
body: JSON.stringify(payload),
|
| 94 |
-
signal: controller.signal,
|
| 95 |
-
});
|
| 96 |
-
|
| 97 |
-
const text = await response.text();
|
| 98 |
-
if (!response.ok) {
|
| 99 |
-
throw new OllamaRequestError(response.status, conciseError(text));
|
| 100 |
-
}
|
| 101 |
-
|
| 102 |
-
try {
|
| 103 |
-
return JSON.parse(text);
|
| 104 |
-
} catch {
|
| 105 |
-
throw new Error("Ollama returned a non-JSON chat response");
|
| 106 |
-
}
|
| 107 |
-
} catch (error) {
|
| 108 |
-
if (error?.name === "AbortError") {
|
| 109 |
-
throw new Error(`Ollama request timed out after ${timeoutMs}ms`);
|
| 110 |
-
}
|
| 111 |
-
throw error;
|
| 112 |
-
} finally {
|
| 113 |
-
clearTimeout(timeout);
|
| 114 |
-
}
|
| 115 |
-
}
|
| 116 |
-
|
| 117 |
-
function isRetryableProviderError(error) {
|
| 118 |
-
return error instanceof OllamaRequestError && (error.status === 400 || error.status === 422);
|
| 119 |
-
}
|
| 120 |
-
|
| 121 |
-
function errorResult(error, model) {
|
| 122 |
-
return {
|
| 123 |
-
status: "error",
|
| 124 |
-
reason: error instanceof Error ? error.message : "Unknown Ollama error",
|
| 125 |
-
model,
|
| 126 |
-
result: null,
|
| 127 |
-
};
|
| 128 |
-
}
|
| 129 |
-
|
| 130 |
-
function conciseError(text) {
|
| 131 |
-
if (!text) return "empty error body";
|
| 132 |
-
try {
|
| 133 |
-
const parsed = JSON.parse(text);
|
| 134 |
-
return parsed.error?.message || parsed.error || parsed.message || JSON.stringify(parsed).slice(0, 500);
|
| 135 |
-
} catch {
|
| 136 |
-
return text.slice(0, 500);
|
| 137 |
-
}
|
| 138 |
-
}
|
| 139 |
-
|
| 140 |
-
class OllamaRequestError extends Error {
|
| 141 |
-
constructor(status, message) {
|
| 142 |
-
super(`Ollama request failed with HTTP ${status}: ${message}`);
|
| 143 |
-
this.name = "OllamaRequestError";
|
| 144 |
-
this.status = status;
|
| 145 |
-
}
|
| 146 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
server/research-tools.mjs
CHANGED
|
@@ -114,34 +114,6 @@ const TORONTO_DATASETS = {
|
|
| 114 |
},
|
| 115 |
};
|
| 116 |
|
| 117 |
-
const SOURCE_CATEGORIES = [
|
| 118 |
-
{
|
| 119 |
-
category: "listings",
|
| 120 |
-
sourceType: "market_listing",
|
| 121 |
-
domains: ["realtor.ca", "zillow.com", "rentals.ca", "condos.ca", "zumper.com", "padmapper.com"],
|
| 122 |
-
},
|
| 123 |
-
{
|
| 124 |
-
category: "community",
|
| 125 |
-
sourceType: "resident_discussion",
|
| 126 |
-
domains: ["reddit.com/r/askTO", "reddit.com/r/TorontoRenting", "reddit.com/r/toronto"],
|
| 127 |
-
},
|
| 128 |
-
{
|
| 129 |
-
category: "reviews",
|
| 130 |
-
sourceType: "local_reviews",
|
| 131 |
-
domains: ["google.com/maps", "yelp.ca", "tripadvisor.ca"],
|
| 132 |
-
},
|
| 133 |
-
{
|
| 134 |
-
category: "official",
|
| 135 |
-
sourceType: "official_context",
|
| 136 |
-
domains: ["toronto.ca", "ttc.ca", "torontopolice.on.ca", "metrolinx.com"],
|
| 137 |
-
},
|
| 138 |
-
{
|
| 139 |
-
category: "market",
|
| 140 |
-
sourceType: "market_context",
|
| 141 |
-
domains: ["zolo.ca", "housesigma.com", "strata.ca", "rentals.ca/blog", "wowa.ca"],
|
| 142 |
-
},
|
| 143 |
-
];
|
| 144 |
-
|
| 145 |
const officialDataCache = new Map();
|
| 146 |
|
| 147 |
export async function runHousingResearch(localRun, env = process.env) {
|
|
|
|
| 114 |
},
|
| 115 |
};
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
const officialDataCache = new Map();
|
| 118 |
|
| 119 |
export async function runHousingResearch(localRun, env = process.env) {
|
src/App.tsx
CHANGED
|
@@ -26,13 +26,13 @@ import {
|
|
| 26 |
import MapCanvas from "./components/MapCanvas";
|
| 27 |
import { DIMENSIONS, type DimensionKey, type LayerKey } from "./data/neighborhoods";
|
| 28 |
import { runAgentBackend, type AgentBackendRun } from "./lib/agentApi";
|
|
|
|
| 29 |
import {
|
| 30 |
agentDimension,
|
| 31 |
cityAgents,
|
| 32 |
colorForScore,
|
| 33 |
consensus,
|
| 34 |
defaultPrompt,
|
| 35 |
-
formatRentRange,
|
| 36 |
getAgentFinding,
|
| 37 |
getAgentThinking,
|
| 38 |
initialAgentStates,
|
|
@@ -684,31 +684,57 @@ function DetailPanel({
|
|
| 684 |
recommendation: AgentBackendRun["recommendation"] | null;
|
| 685 |
}) {
|
| 686 |
const fit = consensus(selected.overall);
|
| 687 |
-
const [
|
|
|
|
|
|
|
| 688 |
|
| 689 |
const stopSpeech = useCallback(() => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 690 |
if (typeof window !== "undefined" && window.speechSynthesis) window.speechSynthesis.cancel();
|
| 691 |
-
|
| 692 |
}, []);
|
| 693 |
|
| 694 |
// Stop narration when the neighbourhood changes or the panel unmounts.
|
| 695 |
useEffect(() => stopSpeech, [selected.id, stopSpeech]);
|
| 696 |
|
| 697 |
-
const togglePlay = () => {
|
| 698 |
-
if (
|
| 699 |
-
if (playing) {
|
| 700 |
stopSpeech();
|
| 701 |
return;
|
| 702 |
}
|
| 703 |
-
const
|
| 704 |
-
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
| 708 |
-
|
| 709 |
-
|
| 710 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
};
|
|
|
|
|
|
|
| 712 |
const safetyFact = findNeighborhoodFact(webResearch, selected.name, "safety");
|
| 713 |
const rentFact = findNeighborhoodFact(webResearch, selected.name, "rent");
|
| 714 |
const commuteFact = findNeighborhoodFact(webResearch, selected.name, "commute");
|
|
@@ -831,8 +857,14 @@ function DetailPanel({
|
|
| 831 |
onClick={togglePlay}
|
| 832 |
aria-label={playing ? "Stop summary audio" : "Play summary audio"}
|
| 833 |
>
|
| 834 |
-
{
|
| 835 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 836 |
</button>
|
| 837 |
</div>
|
| 838 |
</section>
|
|
@@ -1079,13 +1111,6 @@ function CompareModal({
|
|
| 1079 |
);
|
| 1080 |
}
|
| 1081 |
|
| 1082 |
-
function ScoreBadge({ score }: { score: number }) {
|
| 1083 |
-
return (
|
| 1084 |
-
<span className="score-badge" style={{ background: colorForScore(score || 1) }}>
|
| 1085 |
-
{score}
|
| 1086 |
-
</span>
|
| 1087 |
-
);
|
| 1088 |
-
}
|
| 1089 |
|
| 1090 |
function TrustBadge({ sourced }: { sourced: boolean }) {
|
| 1091 |
return <span className={`trust-badge ${sourced ? "sourced" : "pending"}`}>{sourced ? "Sourced" : "Needs source"}</span>;
|
|
@@ -1162,7 +1187,48 @@ function buildSpokenSummary(
|
|
| 1162 |
}
|
| 1163 |
const text = parts.join(" ").replace(/\s+/g, " ").trim();
|
| 1164 |
const words = text.split(" ");
|
| 1165 |
-
return words.length >
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1166 |
}
|
| 1167 |
|
| 1168 |
function TowerLogo() {
|
|
@@ -1186,80 +1252,6 @@ function TowerLogo() {
|
|
| 1186 |
);
|
| 1187 |
}
|
| 1188 |
|
| 1189 |
-
function Sparkline({ selected }: { selected: RankedNeighborhood }) {
|
| 1190 |
-
const { path, area } = useMemo(() => {
|
| 1191 |
-
const count = 26;
|
| 1192 |
-
const width = 240;
|
| 1193 |
-
const height = 56;
|
| 1194 |
-
const pad = 5;
|
| 1195 |
-
const values = Array.from({ length: count }, (_, index) => {
|
| 1196 |
-
return (
|
| 1197 |
-
10 +
|
| 1198 |
-
(selected.trend / 12) * index * 1.15 +
|
| 1199 |
-
Math.sin(index * 1.3 + selected.name.length) * 3 +
|
| 1200 |
-
Math.cos(index * 0.7 + selected.seed) * 2
|
| 1201 |
-
);
|
| 1202 |
-
});
|
| 1203 |
-
const min = Math.min(...values);
|
| 1204 |
-
const max = Math.max(...values);
|
| 1205 |
-
const x = (index: number) => (index / (count - 1)) * (width - pad * 2) + pad;
|
| 1206 |
-
const y = (value: number) =>
|
| 1207 |
-
height - pad - ((value - min) / ((max - min) || 1)) * (height - pad * 2);
|
| 1208 |
-
const line = values
|
| 1209 |
-
.map((value, index) => `${index ? "L" : "M"}${x(index).toFixed(1)} ${y(value).toFixed(1)}`)
|
| 1210 |
-
.join(" ");
|
| 1211 |
-
return {
|
| 1212 |
-
path: line,
|
| 1213 |
-
area: `${line} L ${x(count - 1).toFixed(1)} ${height} L ${x(0).toFixed(1)} ${height} Z`,
|
| 1214 |
-
};
|
| 1215 |
-
}, [selected]);
|
| 1216 |
-
|
| 1217 |
-
return (
|
| 1218 |
-
<svg viewBox="0 0 240 56" preserveAspectRatio="none" aria-hidden="true">
|
| 1219 |
-
<path d={area} fill="rgba(95, 127, 170, 0.16)" />
|
| 1220 |
-
<path d={path} fill="none" stroke="#46648d" strokeWidth="2" strokeLinecap="round" />
|
| 1221 |
-
</svg>
|
| 1222 |
-
);
|
| 1223 |
-
}
|
| 1224 |
-
|
| 1225 |
-
function buildWhy(neighborhood: RankedNeighborhood) {
|
| 1226 |
-
const rows: Array<{ tone: "good" | "warn"; text: string }> = [];
|
| 1227 |
-
const candidates: Array<[DimensionKey, string]> = [
|
| 1228 |
-
["commute", `${neighborhood.comLo}-${neighborhood.comHi} min to Union via ${neighborhood.comMode}`],
|
| 1229 |
-
["affordability", "Lower rent pressure than the downtown core"],
|
| 1230 |
-
["amenities", "Strong grocery, cafe and service access"],
|
| 1231 |
-
["lifestyle", neighborhood.lifeHi],
|
| 1232 |
-
["transit", "Strong transit access"],
|
| 1233 |
-
["safety", "Relatively strong safety signals"],
|
| 1234 |
-
["growth", neighborhood.growthNote],
|
| 1235 |
-
];
|
| 1236 |
-
|
| 1237 |
-
candidates.forEach(([dimension, text]) => {
|
| 1238 |
-
if (rows.length < 4 && neighborhood.dims[dimension] >= 75) rows.push({ tone: "good", text });
|
| 1239 |
-
});
|
| 1240 |
-
|
| 1241 |
-
if (rows.length < 3) {
|
| 1242 |
-
candidates.forEach(([, text]) => {
|
| 1243 |
-
if (rows.length < 4 && !rows.some((row) => row.text === text)) rows.push({ tone: "good", text });
|
| 1244 |
-
});
|
| 1245 |
-
}
|
| 1246 |
-
|
| 1247 |
-
const weakest = candidates.reduce((low, current) =>
|
| 1248 |
-
neighborhood.dims[current[0]] < neighborhood.dims[low[0]] ? current : low,
|
| 1249 |
-
);
|
| 1250 |
-
const warnings: Record<DimensionKey, string> = {
|
| 1251 |
-
affordability: "Pricey at the very top end",
|
| 1252 |
-
safety: "Mixed safety signals, verify locally",
|
| 1253 |
-
commute: "Longer commute on some routes",
|
| 1254 |
-
transit: "Transit can need a transfer",
|
| 1255 |
-
amenities: "Fewer late-night options",
|
| 1256 |
-
lifestyle: "Quieter after dark",
|
| 1257 |
-
growth: "Slower projected upside",
|
| 1258 |
-
};
|
| 1259 |
-
rows.push({ tone: "warn", text: warnings[weakest[0]] });
|
| 1260 |
-
return rows;
|
| 1261 |
-
}
|
| 1262 |
-
|
| 1263 |
function priorityChips(parsed: ParsedPrompt) {
|
| 1264 |
const meta: Record<DimensionKey, [string, string]> = {
|
| 1265 |
affordability: ["Affordability", "#5f7faa"],
|
|
@@ -1336,25 +1328,6 @@ function alpha(hex: string, value: number) {
|
|
| 1336 |
return `rgba(${red},${green},${blue},${value})`;
|
| 1337 |
}
|
| 1338 |
|
| 1339 |
-
function hasNeighborhoodSource(
|
| 1340 |
-
webResearch: AgentBackendRun["webResearch"] | null,
|
| 1341 |
-
neighborhood: string,
|
| 1342 |
-
sourceTypes: string[],
|
| 1343 |
-
) {
|
| 1344 |
-
if (!webResearch?.enabled) return false;
|
| 1345 |
-
const target = normalizeEvidenceName(neighborhood);
|
| 1346 |
-
return webResearch.sources.some((source) => {
|
| 1347 |
-
const sourceNeighborhood = normalizeEvidenceName(source.neighborhood);
|
| 1348 |
-
const sourceTypeMatch = sourceTypes.includes(source.sourceType);
|
| 1349 |
-
const neighborhoodMatch =
|
| 1350 |
-
!sourceNeighborhood ||
|
| 1351 |
-
sourceNeighborhood.includes(target) ||
|
| 1352 |
-
target.includes(sourceNeighborhood) ||
|
| 1353 |
-
source.neighborhood.includes(", ");
|
| 1354 |
-
return sourceTypeMatch && neighborhoodMatch;
|
| 1355 |
-
});
|
| 1356 |
-
}
|
| 1357 |
-
|
| 1358 |
function findNeighborhoodFact(
|
| 1359 |
webResearch: AgentBackendRun["webResearch"] | null,
|
| 1360 |
neighborhood: string,
|
|
|
|
| 26 |
import MapCanvas from "./components/MapCanvas";
|
| 27 |
import { DIMENSIONS, type DimensionKey, type LayerKey } from "./data/neighborhoods";
|
| 28 |
import { runAgentBackend, type AgentBackendRun } from "./lib/agentApi";
|
| 29 |
+
import { synthesizeKokoro } from "./lib/tts";
|
| 30 |
import {
|
| 31 |
agentDimension,
|
| 32 |
cityAgents,
|
| 33 |
colorForScore,
|
| 34 |
consensus,
|
| 35 |
defaultPrompt,
|
|
|
|
| 36 |
getAgentFinding,
|
| 37 |
getAgentThinking,
|
| 38 |
initialAgentStates,
|
|
|
|
| 684 |
recommendation: AgentBackendRun["recommendation"] | null;
|
| 685 |
}) {
|
| 686 |
const fit = consensus(selected.overall);
|
| 687 |
+
const [audioState, setAudioState] = useState<"idle" | "loading" | "playing">("idle");
|
| 688 |
+
const audioRef = useRef<HTMLAudioElement | null>(null);
|
| 689 |
+
const reqRef = useRef(0);
|
| 690 |
|
| 691 |
const stopSpeech = useCallback(() => {
|
| 692 |
+
reqRef.current += 1; // invalidate any in-flight synthesis
|
| 693 |
+
if (audioRef.current) {
|
| 694 |
+
audioRef.current.pause();
|
| 695 |
+
if (audioRef.current.src) URL.revokeObjectURL(audioRef.current.src);
|
| 696 |
+
audioRef.current = null;
|
| 697 |
+
}
|
| 698 |
if (typeof window !== "undefined" && window.speechSynthesis) window.speechSynthesis.cancel();
|
| 699 |
+
setAudioState("idle");
|
| 700 |
}, []);
|
| 701 |
|
| 702 |
// Stop narration when the neighbourhood changes or the panel unmounts.
|
| 703 |
useEffect(() => stopSpeech, [selected.id, stopSpeech]);
|
| 704 |
|
| 705 |
+
const togglePlay = async () => {
|
| 706 |
+
if (audioState !== "idle") {
|
|
|
|
| 707 |
stopSpeech();
|
| 708 |
return;
|
| 709 |
}
|
| 710 |
+
const text = buildSpokenSummary(selected, recommendation, webResearch);
|
| 711 |
+
const req = (reqRef.current += 1);
|
| 712 |
+
setAudioState("loading");
|
| 713 |
+
try {
|
| 714 |
+
const url = await synthesizeKokoro(text);
|
| 715 |
+
if (reqRef.current !== req) {
|
| 716 |
+
URL.revokeObjectURL(url);
|
| 717 |
+
return;
|
| 718 |
+
}
|
| 719 |
+
const element = new Audio(url);
|
| 720 |
+
audioRef.current = element;
|
| 721 |
+
element.onended = () => {
|
| 722 |
+
URL.revokeObjectURL(url);
|
| 723 |
+
if (reqRef.current === req) setAudioState("idle");
|
| 724 |
+
};
|
| 725 |
+
await element.play();
|
| 726 |
+
if (reqRef.current === req) setAudioState("playing");
|
| 727 |
+
} catch {
|
| 728 |
+
// Kokoro unavailable (still downloading / unsupported) — fall back to the browser voice.
|
| 729 |
+
if (reqRef.current !== req) return;
|
| 730 |
+
speakWithBrowser(text, () => {
|
| 731 |
+
if (reqRef.current === req) setAudioState("idle");
|
| 732 |
+
});
|
| 733 |
+
setAudioState("playing");
|
| 734 |
+
}
|
| 735 |
};
|
| 736 |
+
|
| 737 |
+
const playing = audioState !== "idle";
|
| 738 |
const safetyFact = findNeighborhoodFact(webResearch, selected.name, "safety");
|
| 739 |
const rentFact = findNeighborhoodFact(webResearch, selected.name, "rent");
|
| 740 |
const commuteFact = findNeighborhoodFact(webResearch, selected.name, "commute");
|
|
|
|
| 857 |
onClick={togglePlay}
|
| 858 |
aria-label={playing ? "Stop summary audio" : "Play summary audio"}
|
| 859 |
>
|
| 860 |
+
{audioState === "loading" ? (
|
| 861 |
+
<LoaderCircle size={14} className="spin" />
|
| 862 |
+
) : audioState === "playing" ? (
|
| 863 |
+
<Square size={14} fill="currentColor" />
|
| 864 |
+
) : (
|
| 865 |
+
<Volume2 size={15} />
|
| 866 |
+
)}
|
| 867 |
+
{audioState === "loading" ? "Voice…" : audioState === "playing" ? "Stop" : "Play"}
|
| 868 |
</button>
|
| 869 |
</div>
|
| 870 |
</section>
|
|
|
|
| 1111 |
);
|
| 1112 |
}
|
| 1113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1114 |
|
| 1115 |
function TrustBadge({ sourced }: { sourced: boolean }) {
|
| 1116 |
return <span className={`trust-badge ${sourced ? "sourced" : "pending"}`}>{sourced ? "Sourced" : "Needs source"}</span>;
|
|
|
|
| 1187 |
}
|
| 1188 |
const text = parts.join(" ").replace(/\s+/g, " ").trim();
|
| 1189 |
const words = text.split(" ");
|
| 1190 |
+
return words.length > 55 ? `${words.slice(0, 55).join(" ").replace(/[,;:]+$/, "")}.` : text;
|
| 1191 |
+
}
|
| 1192 |
+
|
| 1193 |
+
// Choose the most natural-sounding English voice the browser offers. Cloud/"Natural" voices
|
| 1194 |
+
// (non-localService) sound far smoother than the default robotic system voice.
|
| 1195 |
+
function pickVoice(voices: SpeechSynthesisVoice[]) {
|
| 1196 |
+
if (!voices.length) return null;
|
| 1197 |
+
const english = voices.filter((voice) => /^en[-_]?/i.test(voice.lang));
|
| 1198 |
+
const pool = english.length ? english : voices;
|
| 1199 |
+
const score = (voice: SpeechSynthesisVoice) => {
|
| 1200 |
+
let value = 0;
|
| 1201 |
+
if (/natural|neural|premium|enhanced/i.test(voice.name)) value += 100;
|
| 1202 |
+
if (/google/i.test(voice.name)) value += 60;
|
| 1203 |
+
if (/(samantha|ava|allison|serena|zoe|jenny|aria|libby|sonia|nora|emma)/i.test(voice.name)) value += 50;
|
| 1204 |
+
if (!voice.localService) value += 30;
|
| 1205 |
+
if (/en[-_]US/i.test(voice.lang)) value += 12;
|
| 1206 |
+
if (/en[-_](CA|GB|AU)/i.test(voice.lang)) value += 8;
|
| 1207 |
+
if (/zira|david|mark|microsoft/i.test(voice.name)) value -= 15;
|
| 1208 |
+
return value;
|
| 1209 |
+
};
|
| 1210 |
+
return [...pool].sort((a, b) => score(b) - score(a))[0] ?? null;
|
| 1211 |
+
}
|
| 1212 |
+
|
| 1213 |
+
// Fallback narration using the browser's built-in speech, for the brief window while Kokoro
|
| 1214 |
+
// downloads or on browsers where it can't run.
|
| 1215 |
+
function speakWithBrowser(text: string, onEnd: () => void) {
|
| 1216 |
+
if (typeof window === "undefined" || !window.speechSynthesis) {
|
| 1217 |
+
onEnd();
|
| 1218 |
+
return;
|
| 1219 |
+
}
|
| 1220 |
+
const utterance = new SpeechSynthesisUtterance(text);
|
| 1221 |
+
const voice = pickVoice(window.speechSynthesis.getVoices());
|
| 1222 |
+
if (voice) {
|
| 1223 |
+
utterance.voice = voice;
|
| 1224 |
+
utterance.lang = voice.lang;
|
| 1225 |
+
}
|
| 1226 |
+
utterance.rate = 0.96;
|
| 1227 |
+
utterance.pitch = 1.02;
|
| 1228 |
+
utterance.onend = onEnd;
|
| 1229 |
+
utterance.onerror = onEnd;
|
| 1230 |
+
window.speechSynthesis.cancel();
|
| 1231 |
+
window.speechSynthesis.speak(utterance);
|
| 1232 |
}
|
| 1233 |
|
| 1234 |
function TowerLogo() {
|
|
|
|
| 1252 |
);
|
| 1253 |
}
|
| 1254 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1255 |
function priorityChips(parsed: ParsedPrompt) {
|
| 1256 |
const meta: Record<DimensionKey, [string, string]> = {
|
| 1257 |
affordability: ["Affordability", "#5f7faa"],
|
|
|
|
| 1328 |
return `rgba(${red},${green},${blue},${value})`;
|
| 1329 |
}
|
| 1330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1331 |
function findNeighborhoodFact(
|
| 1332 |
webResearch: AgentBackendRun["webResearch"] | null,
|
| 1333 |
neighborhood: string,
|
src/data/neighborhoods.ts
CHANGED
|
@@ -47,11 +47,6 @@ export interface Neighborhood {
|
|
| 47 |
tradeoff: string;
|
| 48 |
}
|
| 49 |
|
| 50 |
-
export interface NeighborhoodFeatureProperties {
|
| 51 |
-
id: string;
|
| 52 |
-
name: string;
|
| 53 |
-
}
|
| 54 |
-
|
| 55 |
export const DIMENSIONS: DimensionKey[] = [
|
| 56 |
"affordability",
|
| 57 |
"safety",
|
|
@@ -442,48 +437,3 @@ export const neighborhoods: Neighborhood[] = [
|
|
| 442 |
tradeoff: "Well over the rent cap; you pay for the convenience.",
|
| 443 |
},
|
| 444 |
];
|
| 445 |
-
|
| 446 |
-
export const unionStation: LngLat = [-79.3806, 43.6452];
|
| 447 |
-
|
| 448 |
-
function mockBoundary(
|
| 449 |
-
[lng, lat]: LngLat,
|
| 450 |
-
radiusLng: number,
|
| 451 |
-
radiusLat: number,
|
| 452 |
-
seed: number,
|
| 453 |
-
): LngLat[] {
|
| 454 |
-
const points: LngLat[] = [];
|
| 455 |
-
for (let i = 0; i < 18; i += 1) {
|
| 456 |
-
const angle = (Math.PI * 2 * i) / 18;
|
| 457 |
-
const wobble = 1 + Math.sin(seed * 1.7 + i * 0.9) * 0.14;
|
| 458 |
-
points.push([
|
| 459 |
-
Number((lng + Math.cos(angle) * radiusLng * wobble).toFixed(6)),
|
| 460 |
-
Number((lat + Math.sin(angle) * radiusLat * wobble).toFixed(6)),
|
| 461 |
-
]);
|
| 462 |
-
}
|
| 463 |
-
points.push(points[0]);
|
| 464 |
-
return points;
|
| 465 |
-
}
|
| 466 |
-
|
| 467 |
-
export function buildNeighborhoodGeoJson(rows = neighborhoods) {
|
| 468 |
-
return {
|
| 469 |
-
type: "FeatureCollection",
|
| 470 |
-
features: rows.map((neighborhood) => ({
|
| 471 |
-
type: "Feature",
|
| 472 |
-
properties: {
|
| 473 |
-
id: neighborhood.id,
|
| 474 |
-
name: neighborhood.name,
|
| 475 |
-
} satisfies NeighborhoodFeatureProperties,
|
| 476 |
-
geometry: {
|
| 477 |
-
type: "Polygon",
|
| 478 |
-
coordinates: [
|
| 479 |
-
mockBoundary(
|
| 480 |
-
neighborhood.center,
|
| 481 |
-
neighborhood.radiusLng,
|
| 482 |
-
neighborhood.radiusLat,
|
| 483 |
-
neighborhood.seed,
|
| 484 |
-
),
|
| 485 |
-
],
|
| 486 |
-
},
|
| 487 |
-
})),
|
| 488 |
-
};
|
| 489 |
-
}
|
|
|
|
| 47 |
tradeoff: string;
|
| 48 |
}
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
export const DIMENSIONS: DimensionKey[] = [
|
| 51 |
"affordability",
|
| 52 |
"safety",
|
|
|
|
| 437 |
tradeoff: "Well over the rent cap; you pay for the convenience.",
|
| 438 |
},
|
| 439 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/tts.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Kokoro-82M neural text-to-speech, run entirely in the browser via transformers.js (ONNX).
|
| 2 |
+
// 82M params — well under the hackathon's 32B limit — with no API key and no backend. The
|
| 3 |
+
// model (~80MB, quantised) downloads from the Hugging Face CDN on first use, then is cached.
|
| 4 |
+
|
| 5 |
+
const MODEL_ID = "onnx-community/Kokoro-82M-v1.0-ONNX";
|
| 6 |
+
const DEFAULT_VOICE = "af_heart"; // warm, natural American female
|
| 7 |
+
|
| 8 |
+
// kokoro-js has no bundled types; keep the surface we use minimal.
|
| 9 |
+
type KokoroModel = {
|
| 10 |
+
generate: (text: string, options: { voice: string }) => Promise<{ toBlob: () => Blob }>;
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
let modelPromise: Promise<KokoroModel> | null = null;
|
| 14 |
+
|
| 15 |
+
async function loadModel(): Promise<KokoroModel> {
|
| 16 |
+
if (!modelPromise) {
|
| 17 |
+
modelPromise = (async () => {
|
| 18 |
+
const { KokoroTTS } = await import("kokoro-js");
|
| 19 |
+
return (await KokoroTTS.from_pretrained(MODEL_ID, {
|
| 20 |
+
dtype: "q8",
|
| 21 |
+
device: "wasm",
|
| 22 |
+
})) as unknown as KokoroModel;
|
| 23 |
+
})().catch((error) => {
|
| 24 |
+
modelPromise = null; // allow a retry on next click
|
| 25 |
+
throw error;
|
| 26 |
+
});
|
| 27 |
+
}
|
| 28 |
+
return modelPromise;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
// Warm the model in the background so the first Play click is fast.
|
| 32 |
+
export function preloadKokoro(): void {
|
| 33 |
+
void loadModel().catch(() => {});
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
// Synthesize text and return an object-URL for an audio blob. Caller plays + revokes it.
|
| 37 |
+
export async function synthesizeKokoro(text: string, voice: string = DEFAULT_VOICE): Promise<string> {
|
| 38 |
+
const model = await loadModel();
|
| 39 |
+
const audio = await model.generate(text, { voice });
|
| 40 |
+
return URL.createObjectURL(audio.toBlob());
|
| 41 |
+
}
|
src/styles.css
CHANGED
|
@@ -260,6 +260,14 @@ textarea:focus-visible {
|
|
| 260 |
50% { box-shadow: 0 0 0 5px rgba(48, 75, 120, 0); }
|
| 261 |
}
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
.map-scan-fx {
|
| 264 |
position: absolute;
|
| 265 |
inset: 0;
|
|
|
|
| 260 |
50% { box-shadow: 0 0 0 5px rgba(48, 75, 120, 0); }
|
| 261 |
}
|
| 262 |
|
| 263 |
+
.secondary-action .spin {
|
| 264 |
+
animation: tts-spin 0.9s linear infinite;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
@keyframes tts-spin {
|
| 268 |
+
to { transform: rotate(360deg); }
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
.map-scan-fx {
|
| 272 |
position: absolute;
|
| 273 |
inset: 0;
|