@alisio/plugin-semantic 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.es.md +152 -0
  3. package/README.md +144 -2
  4. package/THIRD_PARTY_NOTICES.md +42 -0
  5. package/assets/architecture.svg +1 -0
  6. package/assets/ask-flow.svg +1 -0
  7. package/cover.svg +53 -0
  8. package/dist/apps.d.ts +26 -0
  9. package/dist/apps.d.ts.map +1 -0
  10. package/dist/apps.js +135 -0
  11. package/dist/apps.js.map +1 -0
  12. package/dist/embedded.html +2194 -0
  13. package/dist/engine/download.d.ts +77 -0
  14. package/dist/engine/download.d.ts.map +1 -0
  15. package/dist/engine/download.js +213 -0
  16. package/dist/engine/download.js.map +1 -0
  17. package/dist/engine/embedder.d.ts +55 -0
  18. package/dist/engine/embedder.d.ts.map +1 -0
  19. package/dist/engine/embedder.js +182 -0
  20. package/dist/engine/embedder.js.map +1 -0
  21. package/dist/engine/infer.d.ts +22 -0
  22. package/dist/engine/infer.d.ts.map +1 -0
  23. package/dist/engine/infer.js +53 -0
  24. package/dist/engine/infer.js.map +1 -0
  25. package/dist/engine/models.d.ts +45 -0
  26. package/dist/engine/models.d.ts.map +1 -0
  27. package/dist/engine/models.js +132 -0
  28. package/dist/engine/models.js.map +1 -0
  29. package/dist/engine/runtime.d.ts +46 -0
  30. package/dist/engine/runtime.d.ts.map +1 -0
  31. package/dist/engine/runtime.js +172 -0
  32. package/dist/engine/runtime.js.map +1 -0
  33. package/dist/engine/setup.d.ts +82 -0
  34. package/dist/engine/setup.d.ts.map +1 -0
  35. package/dist/engine/setup.js +183 -0
  36. package/dist/engine/setup.js.map +1 -0
  37. package/dist/engine/store.d.ts +46 -0
  38. package/dist/engine/store.d.ts.map +1 -0
  39. package/dist/engine/store.js +280 -0
  40. package/dist/engine/store.js.map +1 -0
  41. package/dist/engine/tar.d.ts +18 -0
  42. package/dist/engine/tar.d.ts.map +1 -0
  43. package/dist/engine/tar.js +198 -0
  44. package/dist/engine/tar.js.map +1 -0
  45. package/dist/engine/worker.d.ts +2 -0
  46. package/dist/engine/worker.d.ts.map +1 -0
  47. package/dist/engine/worker.js +64 -0
  48. package/dist/engine/worker.js.map +1 -0
  49. package/dist/errors.d.ts +15 -0
  50. package/dist/errors.d.ts.map +1 -0
  51. package/dist/errors.js +58 -0
  52. package/dist/errors.js.map +1 -0
  53. package/dist/index.d.ts +14 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +258 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/messages.d.ts +53 -0
  58. package/dist/messages.d.ts.map +1 -0
  59. package/dist/messages.js +118 -0
  60. package/dist/messages.js.map +1 -0
  61. package/dist/notebook/answer.d.ts +33 -0
  62. package/dist/notebook/answer.d.ts.map +1 -0
  63. package/dist/notebook/answer.js +77 -0
  64. package/dist/notebook/answer.js.map +1 -0
  65. package/dist/notebook/chunk.d.ts +23 -0
  66. package/dist/notebook/chunk.d.ts.map +1 -0
  67. package/dist/notebook/chunk.js +124 -0
  68. package/dist/notebook/chunk.js.map +1 -0
  69. package/dist/notebook/db.d.ts +98 -0
  70. package/dist/notebook/db.d.ts.map +1 -0
  71. package/dist/notebook/db.js +328 -0
  72. package/dist/notebook/db.js.map +1 -0
  73. package/dist/notebook/docx.d.ts +3 -0
  74. package/dist/notebook/docx.d.ts.map +1 -0
  75. package/dist/notebook/docx.js +16 -0
  76. package/dist/notebook/docx.js.map +1 -0
  77. package/dist/notebook/extract.d.ts +11 -0
  78. package/dist/notebook/extract.d.ts.map +1 -0
  79. package/dist/notebook/extract.js +99 -0
  80. package/dist/notebook/extract.js.map +1 -0
  81. package/dist/notebook/jobs.d.ts +31 -0
  82. package/dist/notebook/jobs.d.ts.map +1 -0
  83. package/dist/notebook/jobs.js +84 -0
  84. package/dist/notebook/jobs.js.map +1 -0
  85. package/dist/notebook/ooxml.d.ts +6 -0
  86. package/dist/notebook/ooxml.d.ts.map +1 -0
  87. package/dist/notebook/ooxml.js +131 -0
  88. package/dist/notebook/ooxml.js.map +1 -0
  89. package/dist/notebook/retrieve.d.ts +14 -0
  90. package/dist/notebook/retrieve.d.ts.map +1 -0
  91. package/dist/notebook/retrieve.js +37 -0
  92. package/dist/notebook/retrieve.js.map +1 -0
  93. package/dist/notebook/service.d.ts +72 -0
  94. package/dist/notebook/service.d.ts.map +1 -0
  95. package/dist/notebook/service.js +620 -0
  96. package/dist/notebook/service.js.map +1 -0
  97. package/dist/notebook/workspace.d.ts +17 -0
  98. package/dist/notebook/workspace.d.ts.map +1 -0
  99. package/dist/notebook/workspace.js +75 -0
  100. package/dist/notebook/workspace.js.map +1 -0
  101. package/dist/notebook/zip.d.ts +33 -0
  102. package/dist/notebook/zip.d.ts.map +1 -0
  103. package/dist/notebook/zip.js +154 -0
  104. package/dist/notebook/zip.js.map +1 -0
  105. package/dist/paths.d.ts +17 -0
  106. package/dist/paths.d.ts.map +1 -0
  107. package/dist/paths.js +28 -0
  108. package/dist/paths.js.map +1 -0
  109. package/dist/version.d.ts +2 -0
  110. package/dist/version.d.ts.map +1 -0
  111. package/dist/version.js +3 -0
  112. package/dist/version.js.map +1 -0
  113. package/icon.svg +16 -0
  114. package/package.json +62 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gustavo Gutiérrez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.es.md ADDED
@@ -0,0 +1,152 @@
1
+ # @alisio/plugin-semantic
2
+
3
+ ![Semantic](./cover.svg)
4
+
5
+ > English: [README.md](./README.md). Ambos README deben actualizarse en conjunto.
6
+
7
+ Búsqueda semántica local para Alisio y **Cuaderno**: una app donde reúnes tus propios archivos y
8
+ haces preguntas que se responden solo con ellos, con citas numeradas que abren el pasaje exacto.
9
+
10
+ - **Motor.** Un modelo de embeddings local (`multilingual-e5-small`, ONNX, CPU) y un almacén
11
+ vectorial LanceDB, registrados detrás de los puertos `api.semantic` de Alisio. Así cualquier
12
+ plugin puede usar búsqueda semántica.
13
+ - **App Cuaderno.** Cuadernos, fuentes desde tu equipo o el espacio de trabajo, un chat basado en
14
+ las fuentes que marques, una guía (resumen y preguntas sugeridas) y un visor de pasajes.
15
+ - **Herramienta del chat principal.** `notebook_search` permite que el chat de Alisio lea pasajes de
16
+ un cuaderno.
17
+
18
+ ## Requisitos
19
+
20
+ - Node `>=22.16`.
21
+ - **Alisio 0.11.7 o posterior.** Esa versión añade `api.semantic`; también incluye la API de apps de
22
+ plugins y su aviso de aprobación. En un host anterior el plugin se carga igualmente, no registra
23
+ proveedores y Cuaderno (si el host tiene apps) responde solo con búsqueda por palabras clave.
24
+ `/semantic:help` indica qué falta.
25
+
26
+ ## Instalación
27
+
28
+ ```bash
29
+ alisio install npm:@alisio/plugin-semantic
30
+ ```
31
+
32
+ Después abre **Notebook / Cuaderno** en el grupo **Aplicaciones**, encima de **Proyectos**.
33
+
34
+ ### Tamaño instalado
35
+
36
+ El paquete npm es pequeño (unos 0,7 MB) y **no instala binarios de ONNX**. La única dependencia
37
+ nativa que instala npm es LanceDB, y npm elige solo el paquete de tu plataforma:
38
+
39
+ | Parte | Tamaño en Linux x64 |
40
+ | --- | --- |
41
+ | Todo lo que añade `npm install` (medido) | **~168 MB** |
42
+ | de ello, LanceDB (`@lancedb/lancedb` + su paquete de plataforma) | ~148 MB |
43
+
44
+ ## Primer uso: una descarga única
45
+
46
+ Al instalar no se descarga nada. La primera vez, abre Cuaderno y elige **Descargar y preparar**, o
47
+ ejecuta:
48
+
49
+ ```text
50
+ /semantic:setup
51
+ ```
52
+
53
+ La búsqueda semántica necesita una **descarga única de unos 249 MB**; después funciona sin conexión
54
+ y no se vuelve a descargar nada:
55
+
56
+ - el motor de búsqueda local, ONNX Runtime 1.30.0 para CPU (el tarball npm fijado de
57
+ `onnxruntime-node`, ~114 MB; solo se conservan los archivos de tu plataforma, ~46 MB en Linux x64,
58
+ nunca las partes CUDA/GPU);
59
+ - el modelo `multilingual-e5-small` (cuantizado, ~135 MB, desde una revisión fijada de Hugging Face).
60
+
61
+ Cuaderno muestra el tamaño antes de empezar y luego una sola barra de progreso para ambos (total y
62
+ por archivo, en MB, con botón para cancelar); el comando imprime hitos de progreso. El tarball del
63
+ motor se comprueba contra la integridad sha512 del registro de npm y se extrae de forma segura (sin
64
+ rutas fuera de su carpeta, sin enlaces, con límites de tamaño); cada archivo del modelo se comprueba
65
+ contra su SHA-256 fijado. Una descarga cancelada, interrumpida o alterada no deja ningún archivo
66
+ parcial. Después Alisio te pide una vez activar estos proveedores (`semantic.e5`, `semantic.lance`);
67
+ nunca reemplaza otro proveedor que hayas configurado.
68
+
69
+ Sistemas compatibles con el motor: Linux x64/arm64, macOS con Apple silicon y Windows x64/arm64 (las
70
+ plataformas que incluye el motor fijado). En los demás, Cuaderno funciona con búsqueda por palabras
71
+ clave.
72
+
73
+ `/semantic:status` muestra el estado del motor, el modelo, el uso de disco y el número de cuadernos.
74
+
75
+ ## Cómo responde un cuaderno
76
+
77
+ ![Flujo de pregunta: búsqueda vectorial y por palabras clave, fusión, prompt, citas](./assets/ask-flow.svg)
78
+
79
+ 1. Tu pregunta se busca de dos formas: por significado (búsqueda vectorial) y por palabras exactas
80
+ (SQLite FTS5). Las dos clasificaciones se fusionan (Reciprocal Rank Fusion) y se conservan los 8
81
+ mejores pasajes. Sin el motor, la búsqueda por palabras clave sigue funcionando y la respuesta se
82
+ marca así.
83
+ 2. Si nada coincide, Cuaderno lo dice sin llamar al modelo.
84
+ 3. Si hay coincidencias, los pasajes van al modelo elegido en Alisio dentro de bloques numerados, con
85
+ la regla de que su contenido son datos, no instrucciones. El modelo no tiene herramientas.
86
+ 4. Las citas como `[2]` se comprueban: los números que no corresponden a ningún pasaje se eliminan y
87
+ una respuesta sin citas válidas muestra un aviso de "sin respaldo".
88
+
89
+ ![Arquitectura: marco, acciones, servicio del cuaderno, api.semantic y los proveedores](./assets/architecture.svg)
90
+
91
+ ## Privacidad
92
+
93
+ La lectura, la división en fragmentos y el indexado de tus archivos ocurren en este equipo. **Al
94
+ hacer una pregunta, los pasajes que coinciden y tu pregunta se envían al modelo elegido en Alisio**,
95
+ que puede ser un proveedor remoto. Cuaderno muestra este aviso una vez por cuaderno antes de la
96
+ primera pregunta. Con un proveedor de modelos local, todo se queda en tu equipo.
97
+
98
+ ## Archivos admitidos y límites
99
+
100
+ Texto (`.txt`, `.md`, `.csv`, `.json`), HTML, Word (`.docx`), PowerPoint (`.pptx`, diapositivas y
101
+ notas del orador; cada diapositiva se cita como "Diapositiva N"), Excel (`.xlsx`, cada hoja como
102
+ "Hoja: nombre" seguida de filas separadas por tabuladores; las fórmulas nunca se evalúan, se usan sus
103
+ valores guardados) y PDF con capa de texto (el texto se extrae en la app con PDF.js; los PDF
104
+ escaneados sin texto se indican, no incluye OCR). No se aceptan archivos con macros (`.pptm`,
105
+ `.xlsm`).
106
+
107
+ | Límite | Valor |
108
+ |---|---|
109
+ | Tamaño de archivo | 25 MB |
110
+ | Fuentes por cuaderno | 50 |
111
+ | Texto por fuente | 2.000.000 de caracteres |
112
+ | Pasajes por cuaderno | 20.000 |
113
+ | Pregunta | 4.000 caracteres |
114
+
115
+ ## Configuración
116
+
117
+ Define `pluginOverrides["semantic"].options` en la configuración de Alisio:
118
+
119
+ | Opción | Significado |
120
+ |---|---|
121
+ | `model` | `"e5-small"` (predeterminado, 384 dimensiones, modelo de ~135 MB), `"e5-base"` (768 dimensiones, ~296 MB) o `"minilm"` (384 dimensiones, ~135 MB). Solo estos valores; cualquier otro hace fallar la preparación con `unknown_model`. Cambiarlo requiere `/semantic:setup` de nuevo y **Reconstruir índice** en cada cuaderno. |
122
+ | `locale` | `"en"` o `"es"`: idioma de la salida de los comandos. La app sigue el idioma de Alisio. |
123
+
124
+ ## Comandos y herramienta
125
+
126
+ | Nombre | Qué hace |
127
+ |---|---|
128
+ | `/semantic:setup` | Descarga única del modelo y activación (`/semantic:setup cancel` la detiene) |
129
+ | `/semantic:status` | Estado del motor, modelo, uso de disco, cuadernos |
130
+ | `/semantic:help` | Cómo abrir Cuaderno; la versión mínima de Alisio |
131
+ | Herramienta `notebook_search` | Solo lectura: `{ notebook, query, topK ≤ 8 }` devuelve pasajes con nombre de fuente y página |
132
+
133
+ ## Seguridad
134
+
135
+ Los plugins son código de confianza: el backend se ejecuta dentro de Alisio, no en un entorno
136
+ aislado. Alisio aísla el marco de la app (sin red, sin formularios, scripts solo con nonce) y este
137
+ accede a los archivos solo mediante acciones; las rutas del espacio de trabajo se resuelven y deben
138
+ quedar dentro de él. El texto de una fuente puede contener instrucciones dirigidas al modelo
139
+ ("inyección de prompt"); el modelo no puede ejecutarlas porque no tiene herramientas, pero puede dar
140
+ una respuesta equivocada, que las citas permiten comprobar.
141
+
142
+ ## Desarrollo
143
+
144
+ ```bash
145
+ pnpm --filter @alisio/plugin-semantic test
146
+ pnpm --filter @alisio/plugin-semantic build
147
+ # Comprobación lenta y con red del motor y el modelo reales (descarga ~249 MB):
148
+ SEM_REAL_MODEL=1 pnpm --filter @alisio/plugin-semantic exec vitest run test/real-model.test.ts
149
+ ```
150
+
151
+ Consulta [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) para las licencias de las dependencias y
152
+ los modelos. Licencia MIT.
package/README.md CHANGED
@@ -1,3 +1,145 @@
1
- # Temporary Holding Version
1
+ # @alisio/plugin-semantic
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ![Semantic](./cover.svg)
4
+
5
+ > Español: [README.es.md](./README.es.md). Both READMEs must be updated together.
6
+
7
+ Local semantic search for Alisio, plus **Notebook**: an app where you collect your own files and ask
8
+ questions that are answered only from them, with numbered citations that open the exact passage.
9
+
10
+ - **Engine.** A local embedding model (`multilingual-e5-small`, ONNX, CPU) and a LanceDB vector
11
+ store, registered behind Alisio's `api.semantic` ports. Any plugin can then use semantic search.
12
+ - **Notebook app.** Notebooks, sources from your computer or the workspace, a chat grounded in the
13
+ sources you tick, a guide (summary and suggested questions) and a passage viewer.
14
+ - **Main chat tool.** `notebook_search` lets the Alisio chat read passages from a notebook.
15
+
16
+ ## Requirements
17
+
18
+ - Node `>=22.16`.
19
+ - **Alisio 0.11.7 or newer.** That release adds `api.semantic`; it also has the plugin apps API and
20
+ its approval prompt. On an older host the plugin still loads, registers no provider, and the
21
+ Notebook (when the host has apps) answers with keyword search only. `/semantic:help` says what is
22
+ missing.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ alisio install npm:@alisio/plugin-semantic
28
+ ```
29
+
30
+ Then open **Notebook / Cuaderno** in the **Apps** group above **Projects**.
31
+
32
+ ### Installed size
33
+
34
+ The npm package is small (about 0.7 MB) and installs **no ONNX binaries**. The only native
35
+ dependency installed by npm is LanceDB, and npm picks just your platform's package:
36
+
37
+ | Part | Size on Linux x64 |
38
+ | --- | --- |
39
+ | Everything `npm install` adds (measured) | **~168 MB** |
40
+ | of which LanceDB (`@lancedb/lancedb` + its platform package) | ~148 MB |
41
+
42
+ ## First use: a one-time download
43
+
44
+ Nothing is downloaded at install time. The first time, open Notebook and choose **Download and
45
+ prepare**, or run:
46
+
47
+ ```text
48
+ /semantic:setup
49
+ ```
50
+
51
+ Semantic search needs a **one-time download of about 249 MB**, after which it works offline and
52
+ nothing is downloaded again:
53
+
54
+ - the local search engine, ONNX Runtime 1.30.0 for CPU (the pinned `onnxruntime-node` npm tarball,
55
+ ~114 MB; only your platform's files, ~46 MB on Linux x64, are kept, never the CUDA/GPU parts);
56
+ - the model `multilingual-e5-small` (quantized, ~135 MB, from a pinned Hugging Face revision).
57
+
58
+ Notebook shows the size before starting, then one progress bar for both (overall and per file, in
59
+ MB, with a cancel button); the command prints progress milestones. The runtime tarball is checked
60
+ against the npm registry's sha512 integrity and extracted safely (no paths outside its folder, no
61
+ links, size caps); every model file is checked against its pinned SHA-256. A cancelled,
62
+ interrupted or tampered download leaves no partial file behind. Then Alisio asks you once to turn on
63
+ these providers (`semantic.e5`, `semantic.lance`); it never replaces another provider you
64
+ configured.
65
+
66
+ Supported systems for the engine: Linux x64/arm64, macOS on Apple silicon and Windows x64/arm64
67
+ (the platforms the pinned runtime ships). Elsewhere, Notebook works with keyword search.
68
+
69
+ `/semantic:status` shows engine health, the model, disk use and the number of notebooks.
70
+
71
+ ## How a Notebook answers
72
+
73
+ ![Ask flow: vector and keyword search, fusion, prompt, citations](./assets/ask-flow.svg)
74
+
75
+ 1. Your question is searched two ways: by meaning (vector search) and by exact words (SQLite FTS5).
76
+ The two rankings are fused (Reciprocal Rank Fusion) and the best 8 passages are kept. Without the
77
+ engine, keyword search still works and the answer is marked as such.
78
+ 2. If nothing matches, Notebook says so without calling the model.
79
+ 3. Otherwise the passages go to the model selected in Alisio inside numbered blocks, under a rule
80
+ that passage content is data, not instructions. The model has no tools.
81
+ 4. Citations like `[2]` are checked: numbers that match no passage are dropped, and an answer with
82
+ no valid citation shows a "not grounded" warning.
83
+
84
+ ![Architecture: frame, actions, notebook service, api.semantic and the providers](./assets/architecture.svg)
85
+
86
+ ## Privacy
87
+
88
+ Reading, chunking and indexing your files happens on this computer. **When you ask a question, the
89
+ matching passages and your question are sent to the model selected in Alisio**, which may be a
90
+ remote provider. Notebook shows this notice once per notebook before the first question. With a
91
+ local model provider, everything stays on your computer.
92
+
93
+ ## Supported files and limits
94
+
95
+ Text (`.txt`, `.md`, `.csv`, `.json`), HTML, Word (`.docx`), PowerPoint (`.pptx`, slides and
96
+ speaker notes; each slide is cited as "Slide N"), Excel (`.xlsx`, each sheet as "Sheet: name" followed
97
+ by tab-separated rows; formulas are never evaluated, their saved values are used) and PDF with a
98
+ text layer (text is extracted in the app with PDF.js; scanned PDFs without text are reported, OCR is
99
+ not included). Macro-enabled files (`.pptm`, `.xlsm`) are not accepted.
100
+
101
+ | Limit | Value |
102
+ |---|---|
103
+ | File size | 25 MB |
104
+ | Sources per notebook | 50 |
105
+ | Text per source | 2,000,000 characters |
106
+ | Passages per notebook | 20,000 |
107
+ | Question | 4,000 characters |
108
+
109
+ ## Configuration
110
+
111
+ Set `pluginOverrides["semantic"].options` in Alisio's configuration:
112
+
113
+ | Option | Meaning |
114
+ |---|---|
115
+ | `model` | `"e5-small"` (default, 384 dimensions, ~135 MB model), `"e5-base"` (768 dimensions, ~296 MB) or `"minilm"` (384 dimensions, ~135 MB). Only these values; anything else fails setup with `unknown_model`. Changing it requires `/semantic:setup` again and a **Rebuild index** in each notebook. |
116
+ | `locale` | `"en"` or `"es"`: language of the command output. The app follows Alisio's language. |
117
+
118
+ ## Commands and tool
119
+
120
+ | Name | What it does |
121
+ |---|---|
122
+ | `/semantic:setup` | One-time model download and activation (`/semantic:setup cancel` stops it) |
123
+ | `/semantic:status` | Engine health, model, disk use, notebooks |
124
+ | `/semantic:help` | How to open Notebook; the minimum Alisio version |
125
+ | `notebook_search` tool | Read-only: `{ notebook, query, topK ≤ 8 }` returns passages with source name and page |
126
+
127
+ ## Security
128
+
129
+ Plugins are trusted code: the backend runs inside Alisio, not in a sandbox. The app frame is
130
+ sandboxed by Alisio (no network, no forms, nonce-only scripts) and reaches files only through
131
+ actions; workspace paths are resolved and must stay inside the workspace. Source text may contain
132
+ instructions aimed at the model ("prompt injection"); the model cannot act on them because it has
133
+ no tools, but it may still give a wrong answer, which the citations let you check.
134
+
135
+ ## Development
136
+
137
+ ```bash
138
+ pnpm --filter @alisio/plugin-semantic test
139
+ pnpm --filter @alisio/plugin-semantic build
140
+ # Slow, networked check of the real runtime and model (downloads ~249 MB):
141
+ SEM_REAL_MODEL=1 pnpm --filter @alisio/plugin-semantic exec vitest run test/real-model.test.ts
142
+ ```
143
+
144
+ See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for the licenses of the dependencies and
145
+ models. MIT licensed.
@@ -0,0 +1,42 @@
1
+ # Third-party components
2
+
3
+ This package's own code is MIT licensed (see `LICENSE`). It depends on, bundles or downloads the
4
+ components below, which keep their own licenses.
5
+
6
+ ## Runtime dependencies (installed by npm, not bundled)
7
+
8
+ - **LanceDB** (`@lancedb/lancedb` 0.30.0 and its per-platform native package): Apache-2.0.
9
+ Source: https://github.com/lancedb/lancedb. Its peer dependency **Apache Arrow** (`apache-arrow`)
10
+ is Apache-2.0.
11
+ - **Tokenizers.js** (`@huggingface/tokenizers` 0.2.0): Apache-2.0, Hugging Face.
12
+ Source: https://github.com/huggingface/tokenizers.js. This is the tokenizer that transformers.js
13
+ uses; the embedding pipeline (tokenize, mean pooling, L2 normalization) is reimplemented in this
14
+ package on top of it and ONNX Runtime.
15
+
16
+ ## Downloaded on request by `/semantic:setup` (never installed by npm or shipped here)
17
+
18
+ - **ONNX Runtime** (`onnxruntime-node` 1.30.0 and `onnxruntime-common` 1.30.0): MIT, Microsoft
19
+ Corporation. Source: https://github.com/microsoft/onnxruntime. The pinned npm registry tarballs
20
+ are verified against their sha512 integrity; only the JavaScript loaders and the current
21
+ platform's CPU binaries (`onnxruntime_binding.node` and the ONNX Runtime shared library; on
22
+ Windows also the DirectML libraries the package ships) are extracted into Alisio's cache. Install
23
+ scripts are never run and the CUDA/TensorRT providers are never downloaded.
24
+
25
+ ## Bundled into `dist/embedded.html`
26
+
27
+ - **PDF.js** (`pdfjs-dist` 6.5.438, including its worker): Apache-2.0, Mozilla Foundation.
28
+ Source: https://github.com/mozilla/pdf.js. Used in the app frame to extract PDF text; no eval and
29
+ no WebAssembly.
30
+
31
+ ## Models (downloaded on request by `/semantic:setup`, never shipped in this package)
32
+
33
+ Files come from pinned revisions of Hugging Face repositories and are verified by SHA-256.
34
+
35
+ | Option | Downloaded from | Upstream model | License |
36
+ | --- | --- | --- | --- |
37
+ | `e5-small` (default) | `Xenova/multilingual-e5-small` | `intfloat/multilingual-e5-small` (Wang et al., "Multilingual E5 Text Embeddings", 2024) | MIT |
38
+ | `e5-base` | `Xenova/multilingual-e5-base` | `intfloat/multilingual-e5-base` | MIT |
39
+ | `minilm` | `Xenova/paraphrase-multilingual-MiniLM-L12-v2` | `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` | Apache-2.0 |
40
+
41
+ The `Xenova/*` repositories hold ONNX conversions (with 8-bit quantized weights) of the upstream
42
+ models, published for transformers.js; they carry the upstream model license.
@@ -0,0 +1 @@
1
+ <svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 1879.36px; background-color: #ffffff;" viewBox="-24 -24 1879.3594 708" role="graphics-document document" aria-roledescription="flowchart-v2"><rect x="-24" y="-24" width="1879.3594" height="708" fill="#ffffff"/><style>#my-svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#333333;stroke:#333333;}#my-svg .marker.cross{stroke:#333333;}#my-svg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#my-svg .cluster-label text{fill:#333;}#my-svg .cluster-label span{color:#333;}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:#333;color:#333;}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#my-svg .arrowheadPath{fill:#333333;}#my-svg .edgePaths .path{stroke:#333333;stroke-width:1px;}#my-svg .flowchart-link{stroke:#333333;fill:none;}#my-svg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#my-svg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#my-svg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#my-svg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#my-svg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#my-svg .cluster text{fill:#333;}#my-svg .cluster span{color:#333;}#my-svg .node .collapsed-indicator{fill:#aaaa33;stroke:none;opacity:0.6;}#my-svg .node .collapsed-separator{stroke:#aaaa33;stroke-width:0.75px;}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#my-svg .icon-shape .label rect,#my-svg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg .node .neo-node{stroke:#9370DB;}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:#9370DB;stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node .neo-line path{stroke:#9370DB;filter:none;}#my-svg [data-look="neo"].node circle{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].node circle .state-start{fill:#000000;}#my-svg [data-look="neo"].icon-shape .icon{fill:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:#9370DB;filter:drop-shadow(1px 2px 2px rgba(185, 185, 185, 1));}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="my-svg_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"><g class="cluster" id="my-svg-host" data-look="classic"><rect style="" x="1319.609375" y="8" width="248.75" height="252"/><g class="cluster-label" transform="translate(1407.5234375, 8)"><foreignObject width="72.921875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>Alisio host</p></span></div></foreignObject></g></g><g class="cluster" id="my-svg-plugin" data-look="classic"><rect style="" x="678.078125" y="280" width="1145.28125" height="372"/><g class="cluster-label" transform="translate(1156, 280)"><foreignObject width="189.4375" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>Semantic plugin (backend)</p></span></div></foreignObject></g></g><g class="cluster" id="my-svg-frame" data-look="classic"><rect style="" x="8" y="359.0144271850586" width="460" height="148"/><g class="cluster-label" transform="translate(109.9375, 359.0144271850586)"><foreignObject width="256.125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5;"><span class="nodeLabel"><p>Notebook frame (sandboxed iframe)</p></span></div></foreignObject></g></g></g><g class="edgePaths"><path d="M443,433.014L447.167,433.014C451.333,433.014,459.667,433.014,481.34,433.014C503.013,433.014,538.026,433.014,573.039,433.014C608.052,433.014,643.065,433.014,664.072,433.014C685.078,433.014,692.078,433.014,695.578,433.014L699.078,433.014" id="my-svg-L_ui_actions_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_ui_actions_0" data-points="W3sieCI6NDQzLCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn0seyJ4Ijo0NjgsInkiOjQzMy4wMTQ0MjcxODUwNTg2fSx7IngiOjU3My4wMzkwNjI1LCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn0seyJ4Ijo2NzguMDc4MTI1LCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn0seyJ4Ijo3MDMuMDc4MTI1LCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M213,433.014L217.167,433.014C221.333,433.014,229.667,433.014,237.333,433.014C245,433.014,252,433.014,255.5,433.014L259,433.014" id="my-svg-L_pdf_ui_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_pdf_ui_0" data-points="W3sieCI6MjEzLCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn0seyJ4IjoyMzgsInkiOjQzMy4wMTQ0MjcxODUwNTg2fSx7IngiOjI2MywieSI6NDMzLjAxNDQyNzE4NTA1ODZ9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M883.078,433.014L887.245,433.014C891.411,433.014,899.745,433.014,907.411,433.014C915.078,433.014,922.078,433.014,925.578,433.014L929.078,433.014" id="my-svg-L_actions_service_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_actions_service_0" data-points="W3sieCI6ODgzLjA3ODEyNSwieSI6NDMzLjAxNDQyNzE4NTA1ODZ9LHsieCI6OTA4LjA3ODEyNSwieSI6NDMzLjAxNDQyNzE4NTA1ODZ9LHsieCI6OTMzLjA3ODEyNSwieSI6NDMzLjAxNDQyNzE4NTA1ODZ9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1092.219,472.014L1112.907,483.683C1133.594,495.353,1174.969,518.691,1212.867,530.36C1250.766,542.029,1285.188,542.029,1311.211,542.029C1337.234,542.029,1354.859,542.029,1363.672,542.029L1372.484,542.029" id="my-svg-L_service_sqlite_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_service_sqlite_0" data-points="W3sieCI6MTA5Mi4yMTkwNTk1NDk5Mjc4LCJ5Ijo0NzIuMDE0NDI3MTg1MDU4Nn0seyJ4IjoxMjE2LjM0Mzc1LCJ5Ijo1NDIuMDI4ODU0MzcwMTE3Mn0seyJ4IjoxMzE5LjYwOTM3NSwieSI6NTQyLjAyODg1NDM3MDExNzJ9LHsieCI6MTM3Ni40ODQzNzUsInkiOjU0Mi4wMjg4NTQzNzAxMTcyfV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1085.363,394.014L1107.193,380.345C1129.023,366.676,1172.683,339.338,1211.725,325.669C1250.766,312,1285.188,312,1319.296,280.753C1353.404,249.506,1387.198,187.012,1404.095,155.765L1420.992,124.519" id="my-svg-L_service_port_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_service_port_0" data-points="W3sieCI6MTA4NS4zNjI5MjQ4NDAyMTc4LCJ5IjozOTQuMDE0NDI3MTg1MDU4Nn0seyJ4IjoxMjE2LjM0Mzc1LCJ5IjozMTJ9LHsieCI6MTMxOS42MDkzNzUsInkiOjMxMn0seyJ4IjoxNDIyLjg5NDcwMTA4Njk1NjUsInkiOjEyMX1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1113.078,433.014L1130.289,433.014C1147.5,433.014,1181.922,433.014,1216.344,433.014C1250.766,433.014,1285.188,433.014,1320.434,398.935C1355.681,364.855,1391.753,296.695,1409.789,262.615L1427.824,228.535" id="my-svg-L_service_model_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_service_model_0" data-points="W3sieCI6MTExMy4wNzgxMjUsInkiOjQzMy4wMTQ0MjcxODUwNTg2fSx7IngiOjEyMTYuMzQzNzUsInkiOjQzMy4wMTQ0MjcxODUwNTg2fSx7IngiOjEzMTkuNjA5Mzc1LCJ5Ijo0MzMuMDE0NDI3MTg1MDU4Nn0seyJ4IjoxNDI5LjY5NTM1ODYxODIyODMsInkiOjIyNX1d" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1533.984,69.698L1539.714,68.915C1545.443,68.132,1556.901,66.566,1566.797,119.95C1576.693,173.333,1585.026,281.667,1592.693,335.833C1600.359,390,1607.359,390,1610.859,390L1614.359,390" id="my-svg-L_port_embedder_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_port_embedder_0" data-points="W3sieCI6MTUzMy45ODQzNzUsInkiOjY5LjY5ODQ5MjQ2MjMxMTU2fSx7IngiOjE1NjguMzU5Mzc1LCJ5Ijo2NX0seyJ4IjoxNTkzLjM1OTM3NSwieSI6MzkwfSx7IngiOjE2MTguMzU5Mzc1LCJ5IjozOTB9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M1505.385,121L1515.88,127.667C1526.376,134.333,1547.368,147.667,1562.03,221.833C1576.693,296,1585.026,431,1592.693,498.5C1600.359,566,1607.359,566,1610.859,566L1614.359,566" id="my-svg-L_port_store_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_port_store_0" data-points="W3sieCI6MTUwNS4zODQ2OTE0NTU2OTYyLCJ5IjoxMjF9LHsieCI6MTU2OC4zNTkzNzUsInkiOjE2MX0seyJ4IjoxNTkzLjM1OTM3NSwieSI6NTY2fSx7IngiOjE2MTguMzU5Mzc1LCJ5Ijo1NjZ9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel" transform="translate(573.0390625, 433.0144271850586)"><g class="label" data-id="L_ui_actions_0" transform="translate(-80.0390625, -12)"><foreignObject width="160.078125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>MessagePort requests</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_pdf_ui_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_actions_service_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_service_sqlite_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1216.34375, 312)"><g class="label" data-id="L_service_port_0" transform="translate(-78.265625, -12)"><foreignObject width="156.53125" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>index, trySearch, drop</p></span></div></foreignObject></g></g><g class="edgeLabel" transform="translate(1216.34375, 433.0144271850586)"><g class="label" data-id="L_service_model_0" transform="translate(-73.609375, -12)"><foreignObject width="147.21875" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"><p>passages + question</p></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_port_embedder_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_port_store_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="my-svg-flowchart-ui-0" data-look="classic" transform="translate(353, 433.0144271850586)"><rect class="basic label-container" style="" x="-90" y="-39" width="180" height="78"/><g class="label" style="" transform="translate(-60, -24)"><rect/><foreignObject width="120" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>Sources, Chat, Guide</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-pdf-1" data-look="classic" transform="translate(123, 433.0144271850586)"><rect class="basic label-container" style="" x="-90" y="-39" width="180" height="78"/><g class="label" style="" transform="translate(-60, -24)"><rect/><foreignObject width="120" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>PDF.js text extraction</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-actions-2" data-look="classic" transform="translate(793.078125, 433.0144271850586)"><rect class="basic label-container" style="" x="-90" y="-39" width="180" height="78"/><g class="label" style="" transform="translate(-60, -24)"><rect/><foreignObject width="120" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>App actions (read / write)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-service-3" data-look="classic" transform="translate(1023.078125, 433.0144271850586)"><rect class="basic label-container" style="" x="-90" y="-39" width="180" height="78"/><g class="label" style="" transform="translate(-60, -24)"><rect/><foreignObject width="120" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>Notebook service and jobs</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-sqlite-4" data-look="classic" transform="translate(1443.984375, 542.0288543701172)"><path d="M0,12.98076923076923 a67.5,12.98076923076923 0,0,0 135,0 a67.5,12.98076923076923 0,0,0 -135,0 l0,123.98076923076923 a67.5,12.98076923076923 0,0,0 135,0 l0,-123.98076923076923" class="basic label-container outer-path" style="" transform="translate(-67.5, -74.97115384615384)"/><g class="label" style="" transform="translate(-60, -38)"><rect/><foreignObject width="120" height="96"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>notebook.db: sources, chunks, FTS5, chat</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-embedder-5" data-look="classic" transform="translate(1708.359375, 390)"><rect class="basic label-container" style="" x="-90" y="-75" width="180" height="150"/><g class="label" style="" transform="translate(-60, -60)"><rect/><foreignObject width="120" height="120"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>Embedding provider semantic.e5 (worker thread, ONNX)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-store-6" data-look="classic" transform="translate(1708.359375, 566)"><rect class="basic label-container" style="" x="-90" y="-51" width="180" height="102"/><g class="label" style="" transform="translate(-60, -36)"><rect/><foreignObject width="120" height="72"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>Vector store semantic.lance (LanceDB)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-port-7" data-look="classic" transform="translate(1443.984375, 82)"><rect class="basic label-container" style="" x="-90" y="-39" width="180" height="78"/><g class="label" style="" transform="translate(-60, -24)"><rect/><foreignObject width="120" height="48"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>api.semantic ports</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-model-8" data-look="classic" transform="translate(1443.984375, 198)"><rect class="basic label-container" style="" x="-99.375" y="-27" width="198.75" height="54"/><g class="label" style="" transform="translate(-69.375, -12)"><rect/><foreignObject width="138.75" height="24"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 120px; text-align: center; width: 120px;"><span class="nodeLabel"><p>api.model.complete</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="my-svg-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs><defs><filter id="my-svg-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="#000000"/></filter></defs></svg>