@alucard_24/pi-codeindex 0.0.0-stage → 1.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.
- package/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/README.md +442 -2
- package/config.schema.json +19 -0
- package/eval/queries.jsonl +8 -0
- package/package.json +33 -3
- package/scripts/setup-gpu.sh +65 -0
- package/scripts/setup-vulkan.mjs +140 -0
- package/scripts/vulkan-sources.json +29 -0
- package/src/backend.js +120 -0
- package/src/chunker.js +276 -0
- package/src/cli.js +204 -0
- package/src/config-ui.js +37 -0
- package/src/config.js +131 -0
- package/src/doctor.js +101 -0
- package/src/embed.js +57 -0
- package/src/eval.js +72 -0
- package/src/extension.js +522 -0
- package/src/graph.js +306 -0
- package/src/indexer.js +302 -0
- package/src/local-embed.js +51 -0
- package/src/model.js +71 -0
- package/src/present.js +177 -0
- package/src/probe.js +23 -0
- package/src/search.js +189 -0
- package/src/service-client.js +126 -0
- package/src/service-policy.js +33 -0
- package/src/service-protocol.js +122 -0
- package/src/service-worker.js +3 -0
- package/src/service.js +172 -0
- package/src/store.js +142 -0
- package/src/sync.js +110 -0
- package/src/util.js +108 -0
- package/src/vulkan.js +151 -0
- package/src/workspace.js +18 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Novità
|
|
6
|
+
|
|
7
|
+
- Modello di embedding in un servizio locale condiviso tra processi pi e CLI:
|
|
8
|
+
una sola pipeline per endpoint, avvio automatico, inferenze serializzate e
|
|
9
|
+
coda limitata. Nessun fallback in-process in caso di errore del servizio.
|
|
10
|
+
- Rilascio del modello dopo inattività (default 5 minuti), configurabile con
|
|
11
|
+
`serviceIdleMs` / `CODEINDEX_SERVICE_IDLE_MS`.
|
|
12
|
+
- `/codeindex service status` e `/codeindex service stop`, disponibili anche
|
|
13
|
+
dalla CLI. Autenticazione locale, verifica del profilo dopo riconnessione e
|
|
14
|
+
rifiuto dei conflitti di configurazione senza creare un secondo modello.
|
|
15
|
+
- Indicizzazione e sincronizzazione anche nelle cartelle senza repository Git.
|
|
16
|
+
Home e radice del disco richiedono consenso esplicito in ogni sessione.
|
|
17
|
+
- Diagnostica, configurazione e documentazione aggiornate; test di concorrenza,
|
|
18
|
+
crash, shutdown e prove opt-in con modello reale.
|
|
19
|
+
|
|
20
|
+
### Aggiornamento
|
|
21
|
+
|
|
22
|
+
Chiudere e riaprire i vecchi processi pi dopo l'aggiornamento: le copie del
|
|
23
|
+
modello caricate dal vecchio runtime in-process non vengono liberate dal
|
|
24
|
+
nuovo servizio. Per cambiare il profilo di un servizio già attivo usare
|
|
25
|
+
`/codeindex service stop` quando inattivo, oppure attendere il timeout idle.
|
|
26
|
+
I probe espliciti di doctor restano isolati e possono caricare un modello
|
|
27
|
+
aggiuntivo. Endpoint diversi permettono deliberatamente istanze separate.
|
|
28
|
+
|
|
29
|
+
Il servizio è stato verificato su Linux x64 con CPU, CUDA, WebGPU automatico
|
|
30
|
+
e WebGPU/Vulkan; DirectML/Windows e CoreML/macOS restano da verificare sulle
|
|
31
|
+
rispettive piattaforme. Le misure storiche Fase 5–7 non sono nuovi benchmark
|
|
32
|
+
del servizio condiviso.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alucard24
|
|
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.md
CHANGED
|
@@ -1,3 +1,443 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pi-codeindex
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Indice semantico locale del codice per l'agente pi: embedding con
|
|
4
|
+
**EmbeddingGemma 2** (ONNX, servizio locale condiviso) e ricerca ibrida
|
|
5
|
+
(coseno + lessico) che restituisce `path:righe` + simbolo + anteprima.
|
|
6
|
+
Una sola copia del modello fra processi pi/CLI sullo stesso endpoint;
|
|
7
|
+
nessun servizio remoto o database. Indice: due file in
|
|
8
|
+
`~/.cache/pi-codeindex/<sha1(repo)>/`.
|
|
9
|
+
|
|
10
|
+
## Requisiti
|
|
11
|
+
|
|
12
|
+
- Node 22+ (testato su 26.5.1).
|
|
13
|
+
- CPU sempre disponibile come profilo base nelle build native supportate.
|
|
14
|
+
- GPU opzionale: CUDA su Linux x64, WebGPU dove incluso nel binding,
|
|
15
|
+
DirectML su Windows, CoreML su macOS. Non tutte le combinazioni modello,
|
|
16
|
+
driver e hardware sono verificate: vedi la matrice sotto.
|
|
17
|
+
|
|
18
|
+
## Installazione
|
|
19
|
+
|
|
20
|
+
### Da npm, solo su richiesta
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pi -e npm:@alucard_24/pi-codeindex@1.0.0
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Carica il pacchetto per questa invocazione, senza aggiungerlo alle impostazioni
|
|
27
|
+
globali di pi. Dalla sessione puoi usare `/codeindex configure` e
|
|
28
|
+
`/codeindex doctor`. I pesi vengono scaricati solo al primo utilizzo del modello;
|
|
29
|
+
CUDA e Vulkan richiedono i setup opzionali descritti sotto.
|
|
30
|
+
|
|
31
|
+
Il pacchetto npm include codice, setup, schema, README, licenza e query di
|
|
32
|
+
esempio. Il repository GitHub resta privato; piano di lavoro, report completi,
|
|
33
|
+
harness sperimentale e test non sono inclusi nel tarball npm.
|
|
34
|
+
|
|
35
|
+
### Dal sorgente (sviluppo)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install
|
|
39
|
+
npm run setup-gpu # solo GPU NVIDIA: scarica il provider CUDA e lo configura
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`setup-gpu.sh` è **solo Linux x64** e richiede CUDA 13 + `patchelf`.
|
|
43
|
+
Va rieseguito se un aggiornamento/reinstallazione sostituisce il provider.
|
|
44
|
+
DirectML, CoreML e WebGPU usano i provider inclusi nel binding nativo;
|
|
45
|
+
non richiedono questo script CUDA.
|
|
46
|
+
|
|
47
|
+
Il pacchetto espone anche il binario `pi-codeindex`: gli esempi
|
|
48
|
+
`node src/cli.js ...` possono essere eseguiti come `pi-codeindex ...`
|
|
49
|
+
quando il binario è sul PATH. `pi-codeindex setup-gpu` avvia il setup CUDA.
|
|
50
|
+
Nessun postinstall scarica i pesi e nessuna configurazione globale di pi viene
|
|
51
|
+
modificata dal pacchetto.
|
|
52
|
+
|
|
53
|
+
## Embedding e backend
|
|
54
|
+
|
|
55
|
+
Il modello **EmbeddingGemma 2** gira in un servizio locale condiviso avviato
|
|
56
|
+
automaticamente al primo utilizzo, anche dall'indicizzazione automatica.
|
|
57
|
+
I client pi/CLI non caricano una pipeline propria. I soli pesi testo vengono
|
|
58
|
+
scaricati e riutilizzati fra repository; dopo il primo download è possibile
|
|
59
|
+
lavorare offline. Il codice da embeddare viaggia solo sul loopback locale,
|
|
60
|
+
non viene inviato al server dei pesi o a un'API di embedding remota.
|
|
61
|
+
|
|
62
|
+
| `device` | Default `dtype: auto` | Stato |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `cpu` | `q8` | inferenza reale verificata su Linux x64 |
|
|
65
|
+
| `cuda` | `fp16` | inferenza reale verificata su NVIDIA/Linux x64; setup opzionale |
|
|
66
|
+
| `webgpu` | `fp16` | inferenza reale verificata su questa macchina Linux; supporto hardware/driver variabile |
|
|
67
|
+
| `dml` | `fp16` | DirectML/Windows: integrazione e policy testate, hardware non verificato |
|
|
68
|
+
| `coreml` | `fp16` | CoreML/macOS: integrazione e policy testate, hardware non verificato |
|
|
69
|
+
|
|
70
|
+
**Vulkan è selezionabile come backend nativo di WebGPU**, non come provider
|
|
71
|
+
ONNX autonomo: usa `device: "webgpu"` + `webgpuBackend: "vulkan"` dopo il setup
|
|
72
|
+
opzionale sotto. `device: "vulkan"` resta un errore esplicativo. Con
|
|
73
|
+
`webgpuBackend: "auto"` decide Dawn: non si garantisce Vulkan e non lo si
|
|
74
|
+
presenta come forzato. Stato e metadati distinguono `webgpu→vulkan/fp16` da
|
|
75
|
+
`webgpu→auto/fp16`.
|
|
76
|
+
Un provider presente nel binding non garantisce compatibilità, velocità,
|
|
77
|
+
utilizzo della GPU dedicata o copertura totale del grafo: ORT può eseguire
|
|
78
|
+
alcuni operatori su CPU. Gli smoke test non sostituiscono un benchmark di
|
|
79
|
+
retrieval/performance per piattaforma. `q4` è disponibile ma il drift non è
|
|
80
|
+
validato sull'eval.
|
|
81
|
+
|
|
82
|
+
**Auto:** Linux prova CUDA → WebGPU → CPU; Windows DirectML → WebGPU → CPU;
|
|
83
|
+
macOS CoreML → WebGPU → CPU. I provider assenti vengono saltati; una prova del
|
|
84
|
+
modello reale deve riuscire prima che il profilo venga fissato. Tentativi e
|
|
85
|
+
fallback sono visibili nei log e nello stato/avvisi dell'estensione.
|
|
86
|
+
Un device forzato fallisce per default; `fallback: "cpu"` autorizza il ripiego.
|
|
87
|
+
Il fallback avviene solo all'inizializzazione, mai durante l'embedding di un
|
|
88
|
+
indice già iniziato. La prima riconciliazione di un processo inizializza il
|
|
89
|
+
modello anche se l'indice era caldo; i vecchi tempi di re-index sotto indicati
|
|
90
|
+
precedono questo cambiamento.
|
|
91
|
+
|
|
92
|
+
### WebGPU con Vulkan forzato (opzionale, Linux x64)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm run setup-vulkan
|
|
96
|
+
CODEINDEX_OFFLINE=true node src/cli.js doctor --probe --device webgpu --webgpu-backend vulkan
|
|
97
|
+
CODEINDEX_DEVICE=webgpu CODEINDEX_WEBGPU_BACKEND=vulkan pi -e ./src/extension.js
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Il setup richiede **compilatore C++17, header Node/N-API, `tar`, `patchelf` e
|
|
101
|
+
rete** per scaricare i piccoli sorgenti del binding. Non compila ORT/Dawn e
|
|
102
|
+
non richiede CUDA o il Vulkan SDK: riusa il runtime precompilato con WebGPU;
|
|
103
|
+
per eseguire serve il driver Vulkan. Header fuori dai percorsi standard:
|
|
104
|
+
`npm run setup-vulkan -- --node-headers /percorso/include/node`.
|
|
105
|
+
|
|
106
|
+
Il binding Node standard 1.30.0 non espone il selettore Dawn. Il setup
|
|
107
|
+
compila un binding opzionale da un commit ORT fissato e con hash dei sorgenti
|
|
108
|
+
verificati. Binding e copia del runtime (con SONAME distinto) restano in
|
|
109
|
+
`~/.cache/pi-codeindex/native/`: **nessuna modifica a `node_modules`**, nessun
|
|
110
|
+
provider standard sostituito. Il backend aggiunto ha nome unico e priorità
|
|
111
|
+
negativa: viene usato solo da una sessione che lo richiede esplicitamente.
|
|
112
|
+
Prima del caricamento si verificano gli hash; un controllo negativo obbligatorio
|
|
113
|
+
rifiuta i binding che ignorano il selettore. Manca il setup, il runtime è
|
|
114
|
+
cambiato o non esiste un adapter Vulkan? Errore, non WebGPU automatico nascosto.
|
|
115
|
+
Il fallback CPU resta solo quello già autorizzato da `fallback: "cpu"`.
|
|
116
|
+
|
|
117
|
+
Il setup è idempotente; dopo un cambio di runtime può essere necessario
|
|
118
|
+
rieseguirlo. `pi-codeindex setup-vulkan` è equivalente. Riavvia pi dopo setup
|
|
119
|
+
o cambi di profilo. Il backend WebGPU entra nell'identità dell'indice: cambiare
|
|
120
|
+
`auto` ↔ `vulkan` richiede re-index. Con `device: "auto"` il selettore riguarda
|
|
121
|
+
solo l'eventuale tentativo WebGPU: CUDA può ancora essere scelto prima.
|
|
122
|
+
|
|
123
|
+
Windows richiederebbe anche una build ORT/Dawn con Vulkan abilitato: **non
|
|
124
|
+
implementata/verificata** da questo setup. AMD e Intel richiedono prove sulle
|
|
125
|
+
rispettive GPU. Nessuna promessa di vantaggio prestazionale rispetto a CUDA.
|
|
126
|
+
Le prove con il modello completo richiedono VRAM libera; il processo `doctor`
|
|
127
|
+
riporta l'errore e non termina applicazioni GPU altrui per liberarla.
|
|
128
|
+
|
|
129
|
+
Test opzionali reali, dopo setup e download dei pesi fp16:
|
|
130
|
+
`CODEINDEX_TEST_VULKAN=1 node --test test/vulkan-integration.test.js`.
|
|
131
|
+
La suite normale non richiede GPU né compila addon. Verificati su questa
|
|
132
|
+
macchina Linux x64 / RTX 5070 Ti: EmbeddingGemma fp16, indice incrementale,
|
|
133
|
+
ricerca su fixture e coesistenza con i provider standard. Queste prove non
|
|
134
|
+
sostituiscono un benchmark di qualità o prestazioni su altri hardware.
|
|
135
|
+
|
|
136
|
+
## Servizio condiviso e memoria
|
|
137
|
+
|
|
138
|
+
Il primo client sceglie il profilo secondo la configurazione; gli altri
|
|
139
|
+
riutilizzano la stessa pipeline se quel profilo è consentito. Un profilo
|
|
140
|
+
incompatibile, una cache pesi diversa o valori diversi di `cpuThreads` o
|
|
141
|
+
`serviceIdleMs` danno errore: **nessun secondo modello e nessun fallback
|
|
142
|
+
in-process**. Un device forzato può riutilizzare un servizio CPU solo con
|
|
143
|
+
`fallback: cpu`, con avviso esplicito. Le richieste sono serializzate, con
|
|
144
|
+
massimo 16 richieste attive/in coda; ogni batch contiene al massimo 128 testi
|
|
145
|
+
e 2 MiB di testo. La saturazione della coda produce un errore, non un altro
|
|
146
|
+
worker. Un crash interrompe la richiesta corrente; un uso successivo può
|
|
147
|
+
riavviare il servizio, verificando il profilo già fissato dal client.
|
|
148
|
+
|
|
149
|
+
Dopo **5 minuti senza operazioni sul modello** il processo termina e l'OS
|
|
150
|
+
libera RAM/VRAM native. `status` non rinnova il timer. Chiudere/disabilitare
|
|
151
|
+
una singola sessione non arresta un modello che può servire altri processi.
|
|
152
|
+
Per liberarlo subito, quando non ci sono inferenze in corso:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
/codeindex service status
|
|
156
|
+
/codeindex service status --json
|
|
157
|
+
/codeindex service stop
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Gli stessi comandi funzionano come `node src/cli.js service status|stop`.
|
|
161
|
+
Stop viene rifiutato se ci sono richieste attive/in coda; non interrompe altri
|
|
162
|
+
client. Il servizio si riavvierà al prossimo utilizzo del modello. Nessun
|
|
163
|
+
avvio al login, servizio di sistema o modifica alle impostazioni globali di pi.
|
|
164
|
+
|
|
165
|
+
Il listener è solo `127.0.0.1`, con porta deterministica per la directory
|
|
166
|
+
utente e autenticazione tramite token in `~/.cache/pi-codeindex/service/`
|
|
167
|
+
(directory 0700, record 0600 su POSIX). Il binding esclusivo della porta
|
|
168
|
+
impedisce due avvii simultanei. Una porta occupata da un altro programma dà
|
|
169
|
+
un errore: `servicePort` consente una scelta esplicita. Usa gli stessi
|
|
170
|
+
`serviceDir`/`servicePort` in tutti i client: cambiarli crea endpoint distinti
|
|
171
|
+
e permette deliberatamente più modelli. Non condividere il token o la directory.
|
|
172
|
+
|
|
173
|
+
Restano per-processo le cache degli indici, dei vettori e dei grafi: il servizio
|
|
174
|
+
elimina le copie del **modello**, non tutta la memoria di pi. Dopo l'aggiornamento
|
|
175
|
+
**chiudi e riapri i vecchi processi pi**: i modelli già caricati dal vecchio
|
|
176
|
+
codice in-process non possono essere liberati dal nuovo servizio.
|
|
177
|
+
|
|
178
|
+
Verifica reale opt-in, con pesi già in cache (offline), due processi client,
|
|
179
|
+
indice/ricerca e uscita idle:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
CODEINDEX_TEST_SERVICE=1 CODEINDEX_DEVICE=cuda node --test test/service-integration.test.js
|
|
183
|
+
# Oppure cpu/q8, oppure WebGPU con CODEINDEX_WEBGPU_BACKEND=vulkan dopo setup-vulkan.
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Questi test non sono un nuovo benchmark Fase 5–7. La piattaforma iniziale di
|
|
187
|
+
verifica del servizio è Linux x64; Windows/DirectML e macOS/CoreML richiedono
|
|
188
|
+
verifica sulle rispettive macchine.
|
|
189
|
+
|
|
190
|
+
## Configurazione
|
|
191
|
+
|
|
192
|
+
Dentro pi:
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
/codeindex configure menu interattivo + conferma salvataggio
|
|
196
|
+
/codeindex config valori effettivi, provenienza e percorso
|
|
197
|
+
/codeindex config set device webgpu
|
|
198
|
+
/codeindex config set dtype fp16
|
|
199
|
+
/codeindex config set webgpuBackend vulkan solo WebGPU, setup-vulkan richiesto
|
|
200
|
+
/codeindex config set fallback cpu
|
|
201
|
+
/codeindex config unset device ripristina la scelta automatica
|
|
202
|
+
/codeindex service status processo condiviso, profilo e memoria
|
|
203
|
+
/codeindex service stop rilascia il modello quando inattivo
|
|
204
|
+
/codeindex doctor inventario, senza inferenza/download
|
|
205
|
+
/codeindex doctor --probe --device webgpu prova reale isolata (può scaricare i pesi)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
La configurazione è **della macchina**, non della sessione pi:
|
|
209
|
+
`$XDG_CONFIG_HOME/pi-codeindex/config.json` oppure
|
|
210
|
+
`~/.config/pi-codeindex/config.json` (`%APPDATA%/pi-codeindex/config.json`
|
|
211
|
+
su Windows). `CODEINDEX_CONFIG=/percorso/config.json` sceglie un file diverso,
|
|
212
|
+
anche per un singolo progetto; nessun file del repository viene letto
|
|
213
|
+
implicitamente. Non vengono modificate le impostazioni di pi.
|
|
214
|
+
Precedenza: **default < file < ambiente**. Il menu salva solo i campi cambiati,
|
|
215
|
+
non gli override d'ambiente. JSON malformato/chiavi sconosciute producono errori,
|
|
216
|
+
non default silenziosi. Schema per editor: [config.schema.json](config.schema.json).
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"device": "auto",
|
|
221
|
+
"dtype": "auto",
|
|
222
|
+
"fallback": "error",
|
|
223
|
+
"offline": false,
|
|
224
|
+
"cpuThreads": 0
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Campo | Valori | Override ambiente |
|
|
229
|
+
|---|---|---|
|
|
230
|
+
| `device` | `auto`, `cpu`, `cuda`, `webgpu`, `dml`, `coreml` | `CODEINDEX_DEVICE` |
|
|
231
|
+
| `dtype` | `auto`, `q8`, `q4`, `fp16` | `CODEINDEX_DTYPE` |
|
|
232
|
+
| `webgpuBackend` | `auto` (default), `vulkan` forzato; riguarda solo WebGPU | `CODEINDEX_WEBGPU_BACKEND` |
|
|
233
|
+
| `fallback` | `error` (default), `cpu`; riguarda device forzati | `CODEINDEX_FALLBACK` |
|
|
234
|
+
| `offline` | booleano; niente download, errore se mancano pesi | `CODEINDEX_OFFLINE=true\|false\|1\|0` |
|
|
235
|
+
| `cacheDir` | cache pesi, default `~/.cache/pi-codeindex/text-model` | `CODEINDEX_MODEL_CACHE` |
|
|
236
|
+
| `cpuThreads` | 0 = default ORT, oppure 1–256; non limita la GPU | `CODEINDEX_CPU_THREADS` |
|
|
237
|
+
| `serviceIdleMs` | default 300000 (5 min), da 1000 a 86400000 ms | `CODEINDEX_SERVICE_IDLE_MS` |
|
|
238
|
+
| `serviceDir` | directory privata condivisa, default `~/.cache/pi-codeindex/service` | `CODEINDEX_SERVICE_DIR` |
|
|
239
|
+
| `servicePort` | 0 = deterministica, oppure 1024–65535; solo loopback | `CODEINDEX_SERVICE_PORT` |
|
|
240
|
+
|
|
241
|
+
**Riavvia pi con un nuovo processo** dopo una modifica: non si cambia pipeline
|
|
242
|
+
nel mezzo di un run. Se il servizio ha già un profilo/configurazione diversi,
|
|
243
|
+
usa anche `service stop` quando inattivo, oppure attendi l'uscita idle.
|
|
244
|
+
Prima di aggiornare a un protocollo incompatibile, arresta il vecchio servizio.
|
|
245
|
+
Il menu non riavvia né reindicizza da solo. Device, dtype
|
|
246
|
+
e backend WebGPU effettivi sono salvati nell'indice; se diversi, la ricerca rifiuta di mescolare
|
|
247
|
+
i vettori e chiede un re-index. Gli indici precedenti senza `device` vengono
|
|
248
|
+
ricostruiti alla prossima indicizzazione.
|
|
249
|
+
|
|
250
|
+
Da shell, senza avviare pi:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
node src/cli.js config show
|
|
254
|
+
node src/cli.js config set device cpu
|
|
255
|
+
node src/cli.js config set cpuThreads 4
|
|
256
|
+
node src/cli.js doctor --probe --device cpu --json
|
|
257
|
+
node src/cli.js doctor --probe --all # prove sequenziali dei provider presenti
|
|
258
|
+
node src/cli.js doctor --probe --device webgpu --webgpu-backend vulkan
|
|
259
|
+
CODEINDEX_DEVICE=cuda CODEINDEX_DTYPE=fp16 pi -e ./src/extension.js
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`doctor` senza `--probe` non carica/scarica il modello. Le prove reali girano
|
|
263
|
+
in subprocessi isolati con timeout di 120 s per backend; `--all` può scaricare
|
|
264
|
+
più varianti. Ogni provider forzato viene provato senza fallback, per non
|
|
265
|
+
attribuire alla GPU un successo ottenuto in CPU. Usa `offline: true` per provarle solo dalla cache. Un crash nativo
|
|
266
|
+
di una prova non abbatte pi. I probe restano esplicitamente isolati e **possono
|
|
267
|
+
caricare una copia aggiuntiva del modello** mentre il servizio è attivo: arresta
|
|
268
|
+
prima il servizio se vuoi evitare questo picco. Anche la pipeline ordinaria è
|
|
269
|
+
ora isolata, nel worker condiviso. Smoke del menu e dei comandi via RPC, senza
|
|
270
|
+
chiamate LLM e con cache modello temporanea/offline: `CODEINDEX_TEST_RPC=1 node --test test/config-rpc.test.js` (richiede
|
|
271
|
+
`pi` sul PATH; usa un file config temporaneo, non modifica quello utente).
|
|
272
|
+
|
|
273
|
+
## Comandi
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
node src/cli.js index [--root DIR] [--max-files 5000] [--max-bytes 200] [--force]
|
|
277
|
+
node src/cli.js status [--root DIR]
|
|
278
|
+
node src/cli.js search "query" [--k 8] [--path-prefix src/] [--stale] [--bundle] [--json]
|
|
279
|
+
node src/cli.js eval [--file eval/queries.jsonl] [--json]
|
|
280
|
+
node src/cli.js embed-test
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
- `index` è incrementale: confronta l'hash di ogni file e riusa i vettori dei
|
|
284
|
+
chunk invariati. Salvataggio atomico; una cache di ripresa evita di
|
|
285
|
+
ricalcolare tutto se il run viene interrotto.
|
|
286
|
+
- `search` legge il codice dal disco solo per i risultati finali e non esce
|
|
287
|
+
mai dal repo.
|
|
288
|
+
- `eval` misura recall@3/@8 e latenza sulle query della fixture.
|
|
289
|
+
|
|
290
|
+
## Uso dentro pi
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# pacchetto npm: solo questa invocazione, nessuna configurazione globale
|
|
294
|
+
pi -e npm:@alucard_24/pi-codeindex@1.0.0
|
|
295
|
+
|
|
296
|
+
# in sviluppo, dalla directory del progetto
|
|
297
|
+
pi -e ./src/extension.js
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Cosa aggiunge:
|
|
301
|
+
|
|
302
|
+
- **`search_code`** — ricerca semantica (`query`, `k` 1–30, `path_prefix`,
|
|
303
|
+
`context`) che restituisce `path:start-end`, simbolo e anteprima. Non
|
|
304
|
+
sostituisce `grep`.
|
|
305
|
+
- i risultati il cui file è cambiato dopo l'indicizzazione sono marcati
|
|
306
|
+
`STALE` (hash su disco, non fiducia nel watcher);
|
|
307
|
+
- `context: "bundle"` aggiunge import, importatori e fino a 5 chiamanti
|
|
308
|
+
**euristici** dei primi 3 risultati: un round-trip invece di una catena
|
|
309
|
+
`grep`+`read`.
|
|
310
|
+
- **outline su `read`** — se leggi un file > 300 righe con ≥ 5 simboli indicizzati
|
|
311
|
+
e senza `offset`/`limit` mirati, ricevi un blocco `[outline from code index]`
|
|
312
|
+
con i simboli e i loro range (max 40, ~3,5% di caratteri in più).
|
|
313
|
+
- **riga di stato** nel footer (`codeindex: 5.2k chunk`, `codeindex: 1.2k/4.8k`
|
|
314
|
+
durante l'indicizzazione).
|
|
315
|
+
- **`/codeindex status|reindex [--force]|enable|disable|config|configure|doctor`**. `disable` spegne
|
|
316
|
+
tutto: tool, outline, riga di stato, riga nel system prompt, watcher e
|
|
317
|
+
indicizzazione in corso. Lo stato è persistito nel branch della sessione;
|
|
318
|
+
una sessione nuova riparte attiva.
|
|
319
|
+
- **indicizzazione automatica** all'avvio della sessione, in background,
|
|
320
|
+
single-flight, interrompibile, con cap 5.000 file / 200 MB.
|
|
321
|
+
- **sincronizzazione**: watcher ricorsivo con debounce 800 ms, invalidazione
|
|
322
|
+
diretta da `write`/`edit` e controllo dopo `bash`: sweep `git status` nei
|
|
323
|
+
repository, riconciliazione incrementale nelle cartelle senza Git. Una
|
|
324
|
+
riconciliazione riusa i vettori dei file intatti (misurato nei repository:
|
|
325
|
+
1 chunk re-embedded su 3 dopo una modifica, 920 ms fino all'indice aggiornato).
|
|
326
|
+
|
|
327
|
+
Se il modello non è scaricabile o il reindex fallisce, `search_code` risponde
|
|
328
|
+
con lo stato reale e la sessione continua.
|
|
329
|
+
|
|
330
|
+
### Cartelle senza Git
|
|
331
|
+
|
|
332
|
+
Git è opzionale. Nei repository la radice resta quella restituita da Git,
|
|
333
|
+
anche avviando pi da una sottocartella. Altrimenti viene usata **esattamente
|
|
334
|
+
la directory da cui avvii pi**: non viene creato `.git`, non servono commit
|
|
335
|
+
né un remote. `/codeindex status` mostra radice e modalità.
|
|
336
|
+
|
|
337
|
+
In modalità cartella la scansione esclude le directory nascoste e le consuete
|
|
338
|
+
directory di dipendenze/output (`node_modules`, `dist`, `build`, `out`,
|
|
339
|
+
`vendor`, `target`, `coverage`, `venv`, `__pycache__`); non segue i symlink.
|
|
340
|
+
Restano i limiti di estensione, dimensione, 5.000 file e 200 MB. Le esclusioni
|
|
341
|
+
sono quelle fisse della scansione locale: **senza Git i file `.gitignore`
|
|
342
|
+
non vengono interpretati**. Nei repository continua a valere `git ls-files`
|
|
343
|
+
con le esclusioni Git.
|
|
344
|
+
|
|
345
|
+
Il watcher gestisce anche rename/cancellazioni di directory; dopo `bash`
|
|
346
|
+
viene accodata una riconciliazione senza ricalcolare i vettori invariati.
|
|
347
|
+
Se il watcher non è disponibile, la riconciliazione viene accodata anche
|
|
348
|
+
all'inizio di un nuovo prompt. `/codeindex reindex` resta disponibile per
|
|
349
|
+
aggiornare manualmente l'indice; `--force` ricalcola tutti i vettori.
|
|
350
|
+
|
|
351
|
+
Per evitare scansioni involontarie dell'intera macchina, nella **home** e
|
|
352
|
+
nella **radice del disco**, se non sono repository Git, l'indice parte spento.
|
|
353
|
+
Avvia pi dalla cartella del progetto oppure abilitalo esplicitamente con
|
|
354
|
+
`/codeindex enable`; nelle due cartelle protette il consenso va ripetuto a
|
|
355
|
+
ogni avvio della sessione. Nessuna nuova configurazione globale è necessaria.
|
|
356
|
+
|
|
357
|
+
## Cosa indicizza
|
|
358
|
+
|
|
359
|
+
JS/TS/TSX/JSX, Python, Go, Rust, C, C++, C#, PowerBuilder (.srw/.sru/…),
|
|
360
|
+
Markdown. Chunk declaration-aware, con fusione dei chunk piccoli (Markdown fino
|
|
361
|
+
a 80 righe; codice solo micro-chunk ≤6 righe). Esclusi: binari, file >1 MB,
|
|
362
|
+
minified, lockfile, `.pbl`/`.pbt`/`.pbw`.
|
|
363
|
+
|
|
364
|
+
## Numeri misurati (runtime originale in-process, RTX 5070 Ti, fp16)
|
|
365
|
+
|
|
366
|
+
Queste misure precedono il servizio condiviso e non ne misurano memoria,
|
|
367
|
+
latenza IPC o prestazioni con client concorrenti.
|
|
368
|
+
|
|
369
|
+
| Repo | File | Chunk | Primo indice | Re-index |
|
|
370
|
+
|---|---|---|---|---|
|
|
371
|
+
| `pi.dev-ext` | 373 | 5.230 | 44 s | 169 ms |
|
|
372
|
+
| `Strata` | 2.872 | 29.974 | ~2–5 min | 737 ms |
|
|
373
|
+
|
|
374
|
+
Su CPU q8 (`pi.dev-ext`): 18m28s il primo indice, 143 ms il secondo.
|
|
375
|
+
Ricerca a indice caldo: p50 32 ms. Recall@3 sulla fixture: 5/8.
|
|
376
|
+
|
|
377
|
+
Dentro pi: cache in-process dell'indice (stat dei due file come chiave), quindi
|
|
378
|
+
11,5 ms a caldo su `pi.dev-ext` e **40 ms su `Strata`** (30k chunk), contro ~1,2 s
|
|
379
|
+
di caricamento modello alla prima query di un processo nuovo.
|
|
380
|
+
Outline su un file da 3.713 righe: **+3,5% caratteri** sulla read.
|
|
381
|
+
|
|
382
|
+
## Misura (giro completo)
|
|
383
|
+
|
|
384
|
+
I file e i comandi di questa sezione si riferiscono al checkout di sviluppo:
|
|
385
|
+
piano, report completi e harness non vengono distribuiti nel pacchetto npm.
|
|
386
|
+
Il riepilogo e i limiti delle misure sono riportati qui senza estenderne lo scope.
|
|
387
|
+
|
|
388
|
+
`RESULTS.md` riporta l'esperimento A (pi nudo) vs C (pi + indice) su 10 task per
|
|
389
|
+
repo × 3 ripetizioni: mediana dei delta **−25,4% token su `Strata`** e **−9,7% su
|
|
390
|
+
`pi.dev-ext`**, ma costo totale **−12,3%** e **−12,9%**: sotto la soglia del 15%
|
|
391
|
+
del gate primario. Il verdetto è nel file: **gate non superato**, progetto fermo
|
|
392
|
+
per la regola scritta in `PLAN.md`. Il braccio B (OpenLore) non è stato eseguito:
|
|
393
|
+
nessun claim comparativo.
|
|
394
|
+
|
|
395
|
+
La Fase 6 ha ripetuto la misura con un budget di **80 tool call** per sessione
|
|
396
|
+
(`RESULTS-FASE6.md`): costo **−23,2%** su `Strata` e **−19,2%** su `pi.dev-ext`,
|
|
397
|
+
ma successo **27/30 vs 28/30** su `Strata`. Tutti i fallimenti sono run tagliati
|
|
398
|
+
dal cap; il criterio pre-registrato `C ≥ A` non è soddisfatto per una run, quindi
|
|
399
|
+
quel gate resta non superato.
|
|
400
|
+
|
|
401
|
+
La Fase 7 (`RESULTS-FASE7.md`, 80 coppie appaiate per repo, ipotesi più debole
|
|
402
|
+
pre-registrata prima dei run) supera il gate che chiede **solo di non spendere
|
|
403
|
+
più**: costo appaiato **−22,1%** su `Strata` (CI unilaterale [−29,3%, −14,1%]) e
|
|
404
|
+
−21,5% su `pi.dev-ext`, successo **74/80 vs 74/80** e 79/80 vs 80/80. La soglia
|
|
405
|
+
del **15%** resta non misurata: quello che è dimostrato è "in sessione con budget
|
|
406
|
+
di 80 tool call il costo non aumenta e il successo non peggiora oltre 10pp".
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
node scripts/experiment.mjs --repo ~/AI-Projects/Strata --repeat 8 \
|
|
410
|
+
--max-tool-calls 80 --out /tmp/exp5-strata
|
|
411
|
+
node scripts/analyze-experiment.mjs --runs /tmp/exp5-strata --runs /tmp/exp5-pidev
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Limiti noti
|
|
415
|
+
|
|
416
|
+
- Il chunker è euristico (regex per famiglia): nessun parser AST, nessun
|
|
417
|
+
call graph. Gli errori di confine sono possibili e non etichettati.
|
|
418
|
+
- I chiamanti del bundle sono euristici (scansione dell'identificatore, non un
|
|
419
|
+
call graph): su un campione di 61 casi la precisione misurata è 92%. Il livello
|
|
420
|
+
import è più stretto: solo specifiche che risolvono a un unico file, 29/30 edge
|
|
421
|
+
senza ambiguità su `Strata`.
|
|
422
|
+
- I documenti di piano Markdown competono con il codice nella ricerca: il cap
|
|
423
|
+
di 2 risultati per file e il peso maggiore di path/simbolo mitigano, non
|
|
424
|
+
eliminano il problema.
|
|
425
|
+
- Query in italiano su codice con identificatori inglesi funzionano meno bene
|
|
426
|
+
delle query in inglese.
|
|
427
|
+
- Device e `dtype` fanno parte dell'identità dei vettori: cambiarli richiede
|
|
428
|
+
un re-index. Lo storage v2 lega manifest e vettori con SHA-256: anche un
|
|
429
|
+
salvataggio concorrente/incompleto non viene scambiato per un indice valido.
|
|
430
|
+
Gli indici vecchi senza digest richiedono ricostruzione. La directory è
|
|
431
|
+
unica per repo: processi con profili diversi possono sostituirla o renderla
|
|
432
|
+
temporaneamente indisponibile, mai riutilizzare vettori incompatibili.
|
|
433
|
+
- DirectML e CoreML richiedono ancora smoke test su Windows/macOS; WebGPU è
|
|
434
|
+
verificato solo sulla macchina Linux disponibile, non su tutte le GPU.
|
|
435
|
+
- I pesi sono ancora scaricati dalla revisione `main` del modello; il cache non
|
|
436
|
+
viene aggiornato automaticamente. Prima di un rilascio riproducibile occorre
|
|
437
|
+
fissare uno snapshot dei pesi e verificarne l'integrità.
|
|
438
|
+
|
|
439
|
+
## Licenza
|
|
440
|
+
|
|
441
|
+
Il codice di pi-codeindex è distribuito sotto licenza [MIT](LICENSE).
|
|
442
|
+
Dipendenze, sorgenti upstream scaricati dal setup e pesi del modello mantengono
|
|
443
|
+
le rispettive licenze; non sono inclusi nel tarball del pacchetto.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "pi-codeindex — configurazione embedding locali",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": { "type": "string" },
|
|
8
|
+
"device": { "enum": ["auto", "cpu", "cuda", "webgpu", "dml", "coreml"], "default": "auto", "description": "Per Vulkan forzato usa webgpu con webgpuBackend: vulkan. auto prova i provider presenti per piattaforma, poi CPU." },
|
|
9
|
+
"dtype": { "enum": ["auto", "q8", "q4", "fp16"], "default": "auto", "description": "auto: q8 su CPU, fp16 sugli altri provider. Cambiarlo richiede reindex." },
|
|
10
|
+
"webgpuBackend": { "enum": ["auto", "vulkan"], "default": "auto", "description": "Backend Dawn quando il provider effettivo è webgpu. vulkan forza Vulkan e richiede setup-vulkan (inizialmente Linux x64). Non influenza CPU/CUDA/DirectML/CoreML." },
|
|
11
|
+
"fallback": { "enum": ["error", "cpu"], "default": "error", "description": "Fallback consentito per un device forzato; auto include sempre CPU." },
|
|
12
|
+
"offline": { "type": "boolean", "default": false },
|
|
13
|
+
"cacheDir": { "type": "string", "minLength": 1, "pattern": "\\S", "description": "Cache dei pesi. Supporta ~/; i percorsi relativi sono risolti dal cwd." },
|
|
14
|
+
"cpuThreads": { "type": "integer", "minimum": 0, "maximum": 256, "default": 0, "description": "0 usa il default di ONNX Runtime; non limita la GPU." },
|
|
15
|
+
"serviceDir": { "type": "string", "minLength": 1, "pattern": "\\S", "description": "Directory privata del servizio condiviso. Default ~/.cache/pi-codeindex/service; non cambiarla fra sessioni se vuoi condividere il modello." },
|
|
16
|
+
"servicePort": { "type": "integer", "anyOf": [{ "const": 0 }, { "minimum": 1024, "maximum": 65535 }], "default": 0, "description": "0 sceglie una porta loopback deterministica dalla directory del servizio. Cambiarla crea un endpoint distinto." },
|
|
17
|
+
"serviceIdleMs": { "type": "integer", "minimum": 1000, "maximum": 86400000, "default": 300000, "description": "Inattività prima di terminare il processo e liberare il modello (default 5 minuti). Status non rinnova il timer." }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{"query":"dove viene stimato il numero di token BPE di un messaggio","expects":["bpe-token-estimator"],"why":"estimatore token BPE dedicato"}
|
|
2
|
+
{"query":"come viene applicata una modifica ancorata a un file","expects":["anchored-edit"],"why":"motore delle modifiche ancorate"}
|
|
3
|
+
{"query":"ricerca nella history canonica delle sessioni","expects":["history-service","history-source-reader","context-history-tool"],"why":"lettura e ricerca della history"}
|
|
4
|
+
{"query":"coordinamento della compaction tra più sessioni","expects":["compaction-coordinator"],"why":"coordinatore della compaction"}
|
|
5
|
+
{"query":"lock per evitare rebase concorrenti di una sessione","expects":["rebase-lock"],"why":"lock di rebase"}
|
|
6
|
+
{"query":"quali artefatti vengono conservati e per quanto tempo","expects":["ARTIFACTS.md","artifacts"],"why":"documentazione sugli artefatti"}
|
|
7
|
+
{"query":"marker di omissione per non riesportare dati già visti","expects":["egress"],"why":"gestione egress e marker di omissione"}
|
|
8
|
+
{"query":"indicizzazione incrementale delle sessioni salvate","expects":["session-indexer"],"why":"indice incrementale delle sessioni"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alucard_24/pi-codeindex",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Indice semantico locale del codice per pi (EmbeddingGemma 2, ONNX)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Alucard24",
|
|
7
|
+
"repository": { "type": "git", "url": "git+https://github.com/Alucard24/pi-codeindex.git" },
|
|
8
|
+
"homepage": "https://www.npmjs.com/package/@alucard_24/pi-codeindex",
|
|
9
|
+
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
|
|
10
|
+
"main": "./src/extension.js",
|
|
11
|
+
"bin": { "pi-codeindex": "src/cli.js" },
|
|
12
|
+
"files": ["src", "scripts/setup-gpu.sh", "scripts/setup-vulkan.mjs", "scripts/vulkan-sources.json", "eval/queries.jsonl", "config.schema.json", "README.md", "CHANGELOG.md", "LICENSE"],
|
|
13
|
+
"engines": { "node": ">=22" },
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test 'test/*.test.js'",
|
|
16
|
+
"embed-test": "node src/cli.js embed-test",
|
|
17
|
+
"setup-gpu": "bash scripts/setup-gpu.sh",
|
|
18
|
+
"setup-vulkan": "node scripts/setup-vulkan.mjs",
|
|
19
|
+
"doctor": "node src/cli.js doctor"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["pi-package", "embeddings", "code-search"],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"pi": {
|
|
24
|
+
"extensions": [
|
|
25
|
+
"./src/extension.js"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@huggingface/transformers": "4.3.2",
|
|
30
|
+
"onnxruntime-node": "1.30.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@earendil-works/pi-ai": "*",
|
|
34
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
35
|
+
}
|
|
6
36
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Abilita il provider CUDA di onnxruntime-node (Linux x64, GPU NVIDIA).
|
|
3
|
+
#
|
|
4
|
+
# 1. scarica i binari del provider CUDA se mancano (script ufficiale ORT);
|
|
5
|
+
# 2. trova le librerie CUDA 13 richieste dal provider 1.30 (libcublasLt.so.13,
|
|
6
|
+
# libcudart.so.13, libcurand.so.10, ...);
|
|
7
|
+
# 3. scrive un RUNPATH nel .so del provider: così la GPU funziona senza
|
|
8
|
+
# esportare LD_LIBRARY_PATH (necessario perché l'estensione pi gira
|
|
9
|
+
# dentro un processo già avviato).
|
|
10
|
+
#
|
|
11
|
+
# Idempotente. Da rieseguire dopo `npm install` (node_modules viene ricreato).
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
15
|
+
if ! node -e 'process.exit(process.platform === "linux" && process.arch === "x64" ? 0 : 1)'; then
|
|
16
|
+
echo "[gpu] setup CUDA disponibile solo su Linux x64; usa doctor per i backend della tua piattaforma." >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
# Funziona anche con dipendenze npm hoisted, non solo con node_modules locale.
|
|
20
|
+
ORT="$(node --input-type=module - "$ROOT/package.json" <<'JS'
|
|
21
|
+
import { createRequire } from 'node:module';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
console.log(path.dirname(createRequire(process.argv[2]).resolve('onnxruntime-node/package.json')));
|
|
24
|
+
JS
|
|
25
|
+
)"
|
|
26
|
+
PROVIDER="$(find "$ORT/bin" -path '*/linux/x64/libonnxruntime_providers_cuda.so' | head -1 || true)"
|
|
27
|
+
BIN_DIR="$(dirname "${PROVIDER:-$ORT/bin/napi-v6/linux/x64/x}")"
|
|
28
|
+
|
|
29
|
+
if [[ ! -f "$PROVIDER" ]]; then
|
|
30
|
+
echo "[gpu] provider CUDA assente: lo scarico (≈270 MB)…"
|
|
31
|
+
node "$ORT/script/install.js" --onnxruntime-node-install=cuda12
|
|
32
|
+
PROVIDER="$BIN_DIR/libonnxruntime_providers_cuda.so"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
find_cuda_lib() {
|
|
36
|
+
local d
|
|
37
|
+
for d in \
|
|
38
|
+
"${CUDA13_LIB:-}" \
|
|
39
|
+
"$HOME"/.local/cuda-13*/targets/*/lib \
|
|
40
|
+
/usr/local/cuda-13*/targets/*/lib \
|
|
41
|
+
/usr/local/cuda/lib64 \
|
|
42
|
+
"$HOME"/.local/venv-cu13/lib/python*/site-packages/nvidia/cu13/lib \
|
|
43
|
+
/opt/cuda/lib64; do
|
|
44
|
+
[[ -n "$d" && -e "$d/libcublasLt.so.13" ]] && { echo "$d"; return 0; }
|
|
45
|
+
done
|
|
46
|
+
return 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
CUDA_LIB="$(find_cuda_lib || true)"
|
|
50
|
+
if [[ -z "$CUDA_LIB" ]]; then
|
|
51
|
+
echo "[gpu] ERRORE: non trovo libcublasLt.so.13 (serve il runtime CUDA 13)." >&2
|
|
52
|
+
echo " Installa CUDA 13 o imposta CUDA13_LIB=/percorso/lib." >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
command -v patchelf >/dev/null || { echo "[gpu] ERRORE: patchelf non installato." >&2; exit 1; }
|
|
57
|
+
|
|
58
|
+
echo "[gpu] CUDA libs: $CUDA_LIB"
|
|
59
|
+
patchelf --set-rpath "$CUDA_LIB" "$PROVIDER"
|
|
60
|
+
if LD_LIBRARY_PATH= ldd "$PROVIDER" | grep -q "not found"; then
|
|
61
|
+
echo "[gpu] ERRORE: dipendenze non risolte:" >&2
|
|
62
|
+
LD_LIBRARY_PATH= ldd "$PROVIDER" | grep "not found" >&2
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
echo "[gpu] ok: provider CUDA pronto (nessun LD_LIBRARY_PATH richiesto)"
|