@piecemaker-legal/piecemaker 1.0.6 → 1.0.8
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/dist/assets/{abnfDiagram-VCTEODGH-DF7LFtT-.js → abnfDiagram-VCTEODGH-K8VucbQ5.js} +1 -1
- package/dist/assets/{arc-xOmjWeVH.js → arc-DUmCdRoC.js} +1 -1
- package/dist/assets/{architectureDiagram-5GKGNRK7-CESzNPwa.js → architectureDiagram-5GKGNRK7-DYhs5vqD.js} +1 -1
- package/dist/assets/{blockDiagram-I7D4REHJ-BjdN78Ad.js → blockDiagram-I7D4REHJ-DaXJ9nve.js} +1 -1
- package/dist/assets/{c4Diagram-7LVT6UL2-BcK9EDWT.js → c4Diagram-7LVT6UL2-BLbi-zPT.js} +1 -1
- package/dist/assets/channel-CJIq1vqf.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-DGUN1JFP.js → chunk-2Q5K7J3B-Bzs3gxaq.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-BG3BBcFr.js → chunk-5VM5RSS4-CQNzml7k.js} +1 -1
- package/dist/assets/{chunk-F27PBJKO-CLIOfrF5.js → chunk-F27PBJKO-B8xedWWH.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-D6lGkqij.js → chunk-IMKFNOWR-CjBGlNOu.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-BmF9vLBT.js → chunk-JWPE2WC7-vfnYEpgA.js} +1 -1
- package/dist/assets/{chunk-POPQ4Y6H-C_0SR3ak.js → chunk-POPQ4Y6H-Btl98tE8.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-rT20Wfpp.js → chunk-SVP7TREG-Bp6-pLjR.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-Cn2hkmcf.js → chunk-TICWLB2K-DvmznW2q.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-Dm_eP1_v.js → chunk-XXDRQBXY-QSHJTsI3.js} +1 -1
- package/dist/assets/classDiagram-ZZMXUADV-BYkEWggn.js +1 -0
- package/dist/assets/classDiagram-v2-VYDZK3BY-BYkEWggn.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-cJeeJsep.js → cose-bilkent-JH36ORCC-DxpyZoe2.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-DX2ePIXe.js → cynefin-OW5HDTMX-B9GRp2Gn.js} +1 -1
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-BvWXN-RR.js → cynefinDiagram-5FMLGOSQ-Q-2tz5GW.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-CkwPRhGR.js → dagre-GXQ25YYZ-3Rl3NqNe.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-CBGNzYyv.js → diagram-S7CK7UJ4-CreeWCO1.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-CiwCU0SJ.js → diagram-UQ7AKVKN-DNBoIyDJ.js} +1 -1
- package/dist/assets/{diagram-VSXAHHWV-Aekg4nTk.js → diagram-VSXAHHWV-ZkcE_cRk.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-DPFP5K7r.js → diagram-VX7I27RA-Dzdf7N2Q.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-BHJkxoey.js → diagram-Z3DM3KII-M6b-nr1u.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-2rV1P32T.js → ebnfDiagram-PWID7BFC-DunIw64n.js} +1 -1
- package/dist/assets/{erDiagram-RLTQ6QDP-C4BjyS_H.js → erDiagram-RLTQ6QDP-kN0Se5uc.js} +1 -1
- package/dist/assets/{flowDiagram-HODETNUW-DL1TBlAG.js → flowDiagram-HODETNUW-24YCovut.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-MKjvzCWz.js → ganttDiagram-EL5Y4UJY-DTUUEEy6.js} +1 -1
- package/dist/assets/{gitGraphDiagram-WWUBYQGX-CS_oTGK5.js → gitGraphDiagram-WWUBYQGX-BitrqhMr.js} +1 -1
- package/dist/assets/{index-XOGQDqU3.js → index-CG9hW1GU.js} +120 -120
- package/dist/assets/index-D_Dc_nQv.css +1 -0
- package/dist/assets/{infoDiagram-27XIBGKW-ihUr2GjN.js → infoDiagram-27XIBGKW-BNHN5Mby.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-D2YAnuir.js → ishikawaDiagram-5VMMS53U-De3IQKso.js} +1 -1
- package/dist/assets/{journeyDiagram-3NMN7TZE-Bc2hSZGD.js → journeyDiagram-3NMN7TZE-CWlkZ25T.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-LRMGNonX.js → kanban-definition-UXKFOSKX-2o_ax-Nk.js} +1 -1
- package/dist/assets/{layout-CcfWOlPV.js → layout-Btga9ZYP.js} +1 -1
- package/dist/assets/{linear-7JoS2gQO.js → linear-BoGGmqPG.js} +1 -1
- package/dist/assets/{mermaid.core-ijh_SsuN.js → mermaid.core-M308jnLQ.js} +6 -6
- package/dist/assets/{mindmap-definition-YA3MSWOX-DCE4nzfF.js → mindmap-definition-YA3MSWOX-BJ6C_grh.js} +1 -1
- package/dist/assets/{pegDiagram-XKGWAZYB-SjaGa7lE.js → pegDiagram-XKGWAZYB-qcdYX0Xe.js} +1 -1
- package/dist/assets/{pieDiagram-E7YTZNPT-1xcRidSZ.js → pieDiagram-E7YTZNPT-XPrSlt1M.js} +1 -1
- package/dist/assets/{quadrantDiagram-AXDQQJYC-obHAHnYV.js → quadrantDiagram-AXDQQJYC-COhHhra5.js} +1 -1
- package/dist/assets/{railroadDiagram-O6MQD6OU-BsCVcRZb.js → railroadDiagram-O6MQD6OU-Mw_KF6gb.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-CUNkhvqb.js → requirementDiagram-BXWQKSXE-DPbt7jUM.js} +1 -1
- package/dist/assets/{sankeyDiagram-P5KCCOFB-DhezXMKm.js → sankeyDiagram-P5KCCOFB-B6HzL6Gh.js} +1 -1
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-CL9VswXH.js → sequenceDiagram-WJ2MYXX4-B_dXXCC0.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-t0g9jiEz.js → sizeCapture-INFHLROL-DwODubWN.js} +1 -1
- package/dist/assets/{stateDiagram-D77RDMKH-BW-g-IOz.js → stateDiagram-D77RDMKH-5AUnOL3S.js} +1 -1
- package/dist/assets/stateDiagram-v2-MP3YSRHH-CFM_nDL9.js +1 -0
- package/dist/assets/{swimlanes-42K2YHIH-LsuyeBte.js → swimlanes-42K2YHIH-BLnIwbnd.js} +1 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-BRQJYnDN.js +8 -0
- package/dist/assets/{timeline-definition-24CTP7MA-B0cFka1R.js → timeline-definition-24CTP7MA-B1Yc7-na.js} +1 -1
- package/dist/assets/{vendor-codemirror-C5qqu4R7.js → vendor-codemirror-CjW0lHR5.js} +5 -5
- package/dist/assets/{vennDiagram-4TSXK5OY-D3HNCDR3.js → vennDiagram-4TSXK5OY-BFRtl-NI.js} +1 -1
- package/dist/assets/{wardleyDiagram-VM6X3IG4-DJ3Co8nb.js → wardleyDiagram-VM6X3IG4-BsR8iaD_.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-Cz5E9New.js → xychartDiagram-S5SC5T6Z-Crh1SwrA.js} +1 -1
- package/dist/favicon.png +0 -0
- package/dist/favicon.svg +1 -9
- package/dist/generate-icons.js +47 -46
- package/dist/icons/icon-128x128.png +0 -0
- package/dist/icons/icon-128x128.svg +1 -12
- package/dist/icons/icon-144x144.png +0 -0
- package/dist/icons/icon-144x144.svg +1 -12
- package/dist/icons/icon-152x152.png +0 -0
- package/dist/icons/icon-152x152.svg +1 -12
- package/dist/icons/icon-192x192.png +0 -0
- package/dist/icons/icon-192x192.svg +1 -12
- package/dist/icons/icon-384x384.png +0 -0
- package/dist/icons/icon-384x384.svg +1 -12
- package/dist/icons/icon-512x512.png +0 -0
- package/dist/icons/icon-512x512.svg +1 -12
- package/dist/icons/icon-72x72.png +0 -0
- package/dist/icons/icon-72x72.svg +1 -12
- package/dist/icons/icon-96x96.png +0 -0
- package/dist/icons/icon-96x96.svg +1 -12
- package/dist/index.html +3 -3
- package/dist/logo-128.png +0 -0
- package/dist/logo-256.png +0 -0
- package/dist/logo-32.png +0 -0
- package/dist/logo-512.png +0 -0
- package/dist/logo-64.png +0 -0
- package/dist/logo-sources/logo-black.png +0 -0
- package/dist/logo-sources/logo-white.png +0 -0
- package/dist/logo.svg +1 -17
- package/dist/sw.js +1 -1
- package/dist-server/plugins/piecemaker-dossier/src/institutional-terms.js +91 -0
- package/dist-server/plugins/piecemaker-dossier/src/institutional-terms.js.map +1 -0
- package/dist-server/plugins/piecemaker-dossier/src/knowledge.js +112 -10
- package/dist-server/plugins/piecemaker-dossier/src/knowledge.js.map +1 -1
- package/dist-server/plugins/piecemaker-dossier/src/scan-result.js +5 -1
- package/dist-server/plugins/piecemaker-dossier/src/scan-result.js.map +1 -1
- package/dist-server/server/index.js +60 -26
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/cli/desktop-shortcut.js +80 -0
- package/dist-server/server/modules/cli/desktop-shortcut.js.map +1 -0
- package/dist-server/server/modules/cli/pwa-launcher.js +27 -4
- package/dist-server/server/modules/cli/pwa-launcher.js.map +1 -1
- package/dist-server/server/modules/database/repositories/projects.db.js +28 -6
- package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -1
- package/dist-server/server/modules/database/tests/projects.db.integration.test.js +58 -1
- package/dist-server/server/modules/database/tests/projects.db.integration.test.js.map +1 -1
- package/dist-server/server/modules/plugins/plugins.routes.js +8 -1
- package/dist-server/server/modules/plugins/plugins.routes.js.map +1 -1
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +2 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
- package/dist-server/server/piecemaker/bodacc-search.js +191 -0
- package/dist-server/server/piecemaker/bodacc-search.js.map +1 -0
- package/dist-server/server/piecemaker/company-search.js +145 -0
- package/dist-server/server/piecemaker/company-search.js.map +1 -0
- package/dist-server/server/piecemaker/company-search.test.js +18 -0
- package/dist-server/server/piecemaker/company-search.test.js.map +1 -0
- package/dist-server/server/piecemaker/index.js +6 -2
- package/dist-server/server/piecemaker/index.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/index.js +9 -4
- package/dist-server/server/piecemaker/knowledge/index.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/pipeline.js +68 -58
- package/dist-server/server/piecemaker/knowledge/pipeline.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/routes.js +2 -4
- package/dist-server/server/piecemaker/knowledge/routes.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/scan-jobs.js +91 -0
- package/dist-server/server/piecemaker/knowledge/scan-jobs.js.map +1 -0
- package/dist-server/server/piecemaker/knowledge/service.js +18 -36
- package/dist-server/server/piecemaker/knowledge/service.js.map +1 -1
- package/dist-server/server/piecemaker/library/connector-installation.js +224 -0
- package/dist-server/server/piecemaker/library/connector-installation.js.map +1 -0
- package/dist-server/server/piecemaker/library/index.js +11 -1
- package/dist-server/server/piecemaker/library/index.js.map +1 -1
- package/dist-server/server/piecemaker/library/marketplace.js +102 -43
- package/dist-server/server/piecemaker/library/marketplace.js.map +1 -1
- package/dist-server/server/piecemaker/library/migrate.js +8 -1
- package/dist-server/server/piecemaker/library/migrate.js.map +1 -1
- package/dist-server/server/piecemaker/library/provider-agents.js +50 -0
- package/dist-server/server/piecemaker/library/provider-agents.js.map +1 -0
- package/dist-server/server/piecemaker/library/provider-connectors.js +80 -0
- package/dist-server/server/piecemaker/library/provider-connectors.js.map +1 -0
- package/dist-server/server/piecemaker/library/provider-skills.js +11 -2
- package/dist-server/server/piecemaker/library/provider-skills.js.map +1 -1
- package/dist-server/server/piecemaker/library/store.js +125 -35
- package/dist-server/server/piecemaker/library/store.js.map +1 -1
- package/dist-server/server/piecemaker/library/workspace-installation.js +53 -29
- package/dist-server/server/piecemaker/library/workspace-installation.js.map +1 -1
- package/dist-server/server/piecemaker/timesheet/service.js +4 -21
- package/dist-server/server/piecemaker/timesheet/service.js.map +1 -1
- package/package.json +3 -2
- package/product.config.json +1 -0
- package/scripts/piecemaker/cli/install-command.mjs +35 -9
- package/scripts/piecemaker/cli/lib/app-window.mjs +47 -0
- package/scripts/piecemaker/cli/lib/config.mjs +1 -0
- package/scripts/piecemaker/cli/lib/piecemaker-anonymizer.mjs +78 -0
- package/scripts/piecemaker/cli/lib/plugins.mjs +2 -0
- package/scripts/piecemaker/cli/lib/pwa.mjs +49 -13
- package/scripts/piecemaker/cli/lib/services.mjs +65 -4
- package/scripts/piecemaker/cli/piecemaker-command.test.mjs +25 -0
- package/scripts/piecemaker/cli/piecemaker.mjs +60 -45
- package/scripts/piecemaker/cli/piecemaker.ps1 +8 -0
- package/scripts/piecemaker/cli/piecemaker.sh +6 -1
- package/server/index.ts +52 -23
- package/server/modules/cli/desktop-shortcut.ts +89 -0
- package/server/modules/cli/pwa-launcher.ts +29 -4
- package/server/modules/database/repositories/projects.db.ts +28 -6
- package/server/modules/database/tests/projects.db.integration.test.ts +63 -1
- package/server/modules/plugins/plugins.routes.ts +8 -1
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +5 -0
- package/server/piecemaker/anonymizer/client-config.cjs +10 -2
- package/server/piecemaker/anonymizer/dictionary.cjs +6 -72
- package/server/piecemaker/bodacc-search.ts +205 -0
- package/server/piecemaker/company-search.test.ts +26 -0
- package/server/piecemaker/company-search.ts +183 -0
- package/server/piecemaker/index.ts +8 -2
- package/server/piecemaker/knowledge/index.ts +9 -4
- package/server/piecemaker/knowledge/pipeline.ts +89 -57
- package/server/piecemaker/knowledge/routes.ts +2 -4
- package/server/piecemaker/knowledge/scan-jobs.ts +111 -0
- package/server/piecemaker/knowledge/service.ts +18 -33
- package/server/piecemaker/library/connector-installation.ts +248 -0
- package/server/piecemaker/library/index.ts +5 -1
- package/server/piecemaker/library/marketplace.ts +104 -39
- package/server/piecemaker/library/migrate.ts +8 -1
- package/server/piecemaker/library/provider-agents.ts +49 -0
- package/server/piecemaker/library/provider-connectors.ts +89 -0
- package/server/piecemaker/library/provider-skills.ts +10 -1
- package/server/piecemaker/library/store.ts +129 -36
- package/server/piecemaker/library/workspace-installation.ts +54 -29
- package/server/piecemaker/router.cjs +2 -1
- package/server/piecemaker/timesheet/service.ts +4 -16
- package/server/piecemaker/vendor/installer/steps/03-python-gliner.mjs +0 -27
- package/server/piecemaker/vendor/installer/steps/14-mxc-sandbox.mjs +1 -1
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs +2 -3
- package/server/piecemaker/vendor/piecemaker-plugin/skills/conversion-md/SKILL.md +3 -3
- package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +3 -10
- package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +135 -4
- package/server/piecemaker/vendor/websocket-server/process-group.cjs +95 -0
- package/server/piecemaker/vendor/websocket-server/scripts/__pycache__/scan_utils.cpython-312.pyc +0 -0
- package/server/piecemaker/vendor/websocket-server/scripts/convert_and_scan_pipeline.py +280 -149
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/__pycache__/model_config.cpython-312.pyc +0 -0
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/__pycache__/scanner_worker.cpython-312.pyc +0 -0
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/scanner_worker.py +35 -29
- package/server/piecemaker/vendor/websocket-server/scripts/requirements.txt +0 -5
- package/server/shared/types.ts +1 -0
- package/dist/assets/channel-Dz3eE5vU.js +0 -1
- package/dist/assets/classDiagram-ZZMXUADV-BC1eKV2j.js +0 -1
- package/dist/assets/classDiagram-v2-VYDZK3BY-BC1eKV2j.js +0 -1
- package/dist/assets/index-DhwJpHCq.css +0 -1
- package/dist/assets/stateDiagram-v2-MP3YSRHH-BXuT4zDG.js +0 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-B0eYrB4U.js +0 -8
- package/server/piecemaker/vendor/websocket-server/case-instructions.cjs +0 -111
- package/server/piecemaker/vendor/websocket-server/scripts/ADDRESS_ANONYMIZATION.md +0 -216
- package/server/piecemaker/vendor/websocket-server/scripts/DEDUPLICATION_CHANGES.md +0 -134
- package/server/piecemaker/vendor/websocket-server/scripts/GLINER2_README.md +0 -138
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/AUDIT_PERF_QUALITE.md +0 -246
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/MODELE_COREML.md +0 -62
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/__pycache__/coreml_runtime.cpython-312.pyc +0 -0
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/build_coreml.py +0 -118
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/coreml_runtime.py +0 -164
- package/server/piecemaker/vendor/websocket-server/scripts/presidio-gliner/presidio-gliner.py +0 -479
|
@@ -559,10 +559,21 @@ const waiting = [];
|
|
|
559
559
|
let reservedBytes = 0;
|
|
560
560
|
let acceptingJobs = true;
|
|
561
561
|
|
|
562
|
+
/**
|
|
563
|
+
* Jobs admis via `runManagedPythonJob` (pas de `legalCase`, donc absents de
|
|
564
|
+
* `jobs`) : `runningAnonymize` doit les voir pour que l'exclusivité GLiNER
|
|
565
|
+
* reste vraie dans les deux sens, quel que soit le consommateur qui a lancé
|
|
566
|
+
* le traitement en cours.
|
|
567
|
+
*/
|
|
568
|
+
const runningManaged = new Set();
|
|
569
|
+
|
|
562
570
|
function runningAnonymize() {
|
|
563
571
|
for (const job of jobs.values()) {
|
|
564
572
|
if (job.state === 'running' && job.action === 'anonymize') return true;
|
|
565
573
|
}
|
|
574
|
+
for (const job of runningManaged) {
|
|
575
|
+
if (job.action === 'anonymize') return true;
|
|
576
|
+
}
|
|
566
577
|
return false;
|
|
567
578
|
}
|
|
568
579
|
|
|
@@ -577,7 +588,12 @@ function canAdmit(job) {
|
|
|
577
588
|
return true;
|
|
578
589
|
}
|
|
579
590
|
|
|
580
|
-
/**
|
|
591
|
+
/**
|
|
592
|
+
* Admet les traitements en file qui rentrent désormais, du plus ancien au plus
|
|
593
|
+
* récent. Un descripteur `runManagedPythonJob` (identifié par la présence de
|
|
594
|
+
* `run`, sans `legalCase`) suit son propre lancement : même file, même
|
|
595
|
+
* contrôle d'admission, exécution différente.
|
|
596
|
+
*/
|
|
581
597
|
function pumpQueue() {
|
|
582
598
|
if (!acceptingJobs) return;
|
|
583
599
|
for (let index = 0; index < waiting.length; index += 1) {
|
|
@@ -585,7 +601,8 @@ function pumpQueue() {
|
|
|
585
601
|
if (!canAdmit(descriptor.job)) continue;
|
|
586
602
|
waiting.splice(index, 1);
|
|
587
603
|
index -= 1;
|
|
588
|
-
|
|
604
|
+
if (descriptor.run) launchManagedJob(descriptor);
|
|
605
|
+
else launchJob(descriptor);
|
|
589
606
|
}
|
|
590
607
|
}
|
|
591
608
|
|
|
@@ -749,6 +766,108 @@ function spawnTracked(job, script, args, progressScale = {}) {
|
|
|
749
766
|
});
|
|
750
767
|
}
|
|
751
768
|
|
|
769
|
+
/**
|
|
770
|
+
* Point d'entrée générique pour tout traitement devant passer par le même
|
|
771
|
+
* contrôle d'admission que les pièces originales (exclusivité GLiNER, budget
|
|
772
|
+
* RAM, file d'attente, nice, timeout, arrêt propre du groupe de process).
|
|
773
|
+
*
|
|
774
|
+
* Contrairement à `startOriginalsJob`, cette fonction ne connaît aucune
|
|
775
|
+
* notion de dossier juridique enregistré (`legalCase`, mapping, commit) :
|
|
776
|
+
* elle sert les consommateurs qui ont leur propre gestion du résultat (le
|
|
777
|
+
* pipeline `knowledge`, dont le `projectId` n'est pas un dossier juridique du
|
|
778
|
+
* registre) mais qui doivent néanmoins partager le même verrou GLiNER et le
|
|
779
|
+
* même budget RAM que l'administration — sinon rien n'empêche deux scans
|
|
780
|
+
* simultanés de charger chacun leur propre modèle et de figer la machine.
|
|
781
|
+
*
|
|
782
|
+
* Lance directement `script` avec `args` via `spawnTracked` (même parseur de
|
|
783
|
+
* lignes `PROGRESS:`, même gestion du groupe de process, même priorité nice).
|
|
784
|
+
* `onProgress`, si fourni, est appelé à chaque mise à jour de la progression
|
|
785
|
+
* avec `{ phase, percent, processed, total }`.
|
|
786
|
+
*/
|
|
787
|
+
function runManagedPythonJob({ action, script, args, onProgress, signal } = {}) {
|
|
788
|
+
if (!['convert', 'anonymize'].includes(action)) throw new Error('Action inconnue.');
|
|
789
|
+
if (!acceptingJobs) throw new Error('Le serveur est en cours d’arrêt : aucun nouveau traitement ne peut démarrer.');
|
|
790
|
+
const job = {
|
|
791
|
+
action,
|
|
792
|
+
cancelled: false,
|
|
793
|
+
cancelReason: null,
|
|
794
|
+
child: null,
|
|
795
|
+
processGroupId: null,
|
|
796
|
+
stopPromise: null,
|
|
797
|
+
phase: 'convert',
|
|
798
|
+
percent: 0,
|
|
799
|
+
processed: 0,
|
|
800
|
+
total: 0,
|
|
801
|
+
log: [],
|
|
802
|
+
reserveBytes: JOB_RESERVE_BYTES(action),
|
|
803
|
+
};
|
|
804
|
+
if (onProgress) {
|
|
805
|
+
for (const key of ['phase', 'percent', 'processed', 'total']) {
|
|
806
|
+
let value = job[key];
|
|
807
|
+
Object.defineProperty(job, key, {
|
|
808
|
+
get: () => value,
|
|
809
|
+
set: (next) => {
|
|
810
|
+
value = next;
|
|
811
|
+
onProgress({ phase: job.phase, percent: job.percent, processed: job.processed, total: job.total });
|
|
812
|
+
},
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
const abort = () => { void stopRunningJob(job, 'user-cancellation'); };
|
|
817
|
+
if (signal) {
|
|
818
|
+
if (signal.aborted) abort();
|
|
819
|
+
else signal.addEventListener('abort', abort, { once: true });
|
|
820
|
+
}
|
|
821
|
+
const run = () => spawnTracked(job, script, args);
|
|
822
|
+
const descriptor = { job, run };
|
|
823
|
+
const completion = new Promise((resolve, reject) => {
|
|
824
|
+
descriptor.resolve = resolve;
|
|
825
|
+
descriptor.reject = reject;
|
|
826
|
+
});
|
|
827
|
+
runningManaged.add(job);
|
|
828
|
+
if (canAdmit(job)) {
|
|
829
|
+
launchManagedJob(descriptor);
|
|
830
|
+
} else {
|
|
831
|
+
waiting.push(descriptor);
|
|
832
|
+
}
|
|
833
|
+
return completion.finally(() => {
|
|
834
|
+
signal?.removeEventListener('abort', abort);
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/** Variante de `launchJob` pour un descripteur `runManagedPythonJob` (pas de `legalCase`/commit à gérer ici). */
|
|
839
|
+
function launchManagedJob(descriptor) {
|
|
840
|
+
const { job, run, resolve, reject } = descriptor;
|
|
841
|
+
reservedBytes += job.reserveBytes;
|
|
842
|
+
const timeoutId = setTimeout(() => {
|
|
843
|
+
void stopRunningJob(job, 'timeout');
|
|
844
|
+
}, JOB_TIMEOUT_MS());
|
|
845
|
+
(async () => {
|
|
846
|
+
try {
|
|
847
|
+
if (job.cancelled) throw cancellationError(job);
|
|
848
|
+
const result = await run(job);
|
|
849
|
+
if (job.cancelled) throw cancellationError(job);
|
|
850
|
+
resolve(result);
|
|
851
|
+
} catch (error) {
|
|
852
|
+
reject(error);
|
|
853
|
+
} finally {
|
|
854
|
+
clearTimeout(timeoutId);
|
|
855
|
+
const processGroupId = job.processGroupId;
|
|
856
|
+
try {
|
|
857
|
+
await verifyJobProcessTreeStopped(job, processGroupId);
|
|
858
|
+
} catch {
|
|
859
|
+
// Best-effort : une erreur de nettoyage ne doit pas masquer le résultat déjà tranché ci-dessus.
|
|
860
|
+
}
|
|
861
|
+
job.child = null;
|
|
862
|
+
job.processGroupId = null;
|
|
863
|
+
job.stopPromise = null;
|
|
864
|
+
runningManaged.delete(job);
|
|
865
|
+
reservedBytes -= job.reserveBytes;
|
|
866
|
+
pumpQueue();
|
|
867
|
+
}
|
|
868
|
+
})();
|
|
869
|
+
}
|
|
870
|
+
|
|
752
871
|
/**
|
|
753
872
|
* Migration « au prochain traitement », rattachée aux pièces du lot : range dans
|
|
754
873
|
* le dossier de conversion métier le Markdown que d'anciennes versions ont laissé à la racine
|
|
@@ -1092,14 +1211,22 @@ function stopOriginalsJobs() {
|
|
|
1092
1211
|
const { job } = descriptor;
|
|
1093
1212
|
job.cancelled = true;
|
|
1094
1213
|
job.cancelReason = 'server-shutdown';
|
|
1214
|
+
if (descriptor.run) {
|
|
1215
|
+
// Descripteur `runManagedPythonJob` : rejeter sa promesse est le seul
|
|
1216
|
+
// moyen de le débloquer, il n'a pas d'état `job.state`/`jobs` propre.
|
|
1217
|
+
descriptor.reject(cancellationError(job));
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1095
1220
|
job.state = 'error';
|
|
1096
1221
|
job.error = 'Traitement interrompu par l’arrêt du serveur.';
|
|
1097
1222
|
job.finishedAt = new Date().toISOString();
|
|
1098
1223
|
}
|
|
1099
1224
|
|
|
1100
1225
|
const running = [...jobs.values()].filter((job) => job.state === 'running');
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1226
|
+
const managedRunning = [...runningManaged];
|
|
1227
|
+
const allRunning = [...running, ...managedRunning];
|
|
1228
|
+
const groups = [...new Set(allRunning.map((job) => job.processGroupId).filter(Boolean))];
|
|
1229
|
+
await Promise.allSettled(allRunning.map((job) => stopRunningJob(job, 'server-shutdown')));
|
|
1103
1230
|
await Promise.allSettled(running.map((job) => job.completion).filter(Boolean));
|
|
1104
1231
|
|
|
1105
1232
|
// Contrôle défensif final, y compris si un enfant a fermé ses pipes avant
|
|
@@ -1135,6 +1262,10 @@ function cancelOriginalsJob(jobId) {
|
|
|
1135
1262
|
module.exports = {
|
|
1136
1263
|
cancelOriginalsJob,
|
|
1137
1264
|
groupEntityHits,
|
|
1265
|
+
// Point d'entrée partagé : tout consommateur d'un pipeline GLiNER/markitdown
|
|
1266
|
+
// (même hors dossier juridique enregistré, ex. `knowledge/pipeline.ts`) doit
|
|
1267
|
+
// passer par ici pour rester sous l'exclusivité GLiNER et le budget RAM.
|
|
1268
|
+
runManagedPythonJob,
|
|
1138
1269
|
stopOriginalsJobs,
|
|
1139
1270
|
// Ré-exportés pour les routes de l'administration : l'implémentation vit
|
|
1140
1271
|
// désormais dans `piecemaker-plugin/scripts/lib/mapping.cjs`.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const { spawn } = require('node:child_process');
|
|
2
|
+
|
|
3
|
+
const wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
4
|
+
|
|
5
|
+
function posixProcessGroupExists(processGroupId) {
|
|
6
|
+
if (!Number.isInteger(processGroupId) || processGroupId <= 0) return false;
|
|
7
|
+
try {
|
|
8
|
+
process.kill(-processGroupId, 0);
|
|
9
|
+
return true;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
if (error?.code === 'EPERM') return true;
|
|
12
|
+
if (error?.code === 'ESRCH') return false;
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function signalPosixProcessGroup(processGroupId, signal) {
|
|
18
|
+
try {
|
|
19
|
+
process.kill(-processGroupId, signal);
|
|
20
|
+
return true;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
if (error?.code === 'ESRCH') return false;
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function waitForPosixProcessGroupExit(processGroupId, timeoutMs, pollIntervalMs = 25) {
|
|
28
|
+
const deadline = Date.now() + timeoutMs;
|
|
29
|
+
while (posixProcessGroupExists(processGroupId)) {
|
|
30
|
+
if (Date.now() >= deadline) return false;
|
|
31
|
+
await wait(Math.min(pollIntervalMs, Math.max(1, deadline - Date.now())));
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function taskkillProcessTree(processId) {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const killer = spawn('taskkill.exe', ['/PID', String(processId), '/T', '/F'], {
|
|
39
|
+
stdio: 'ignore',
|
|
40
|
+
windowsHide: true,
|
|
41
|
+
});
|
|
42
|
+
killer.once('error', reject);
|
|
43
|
+
killer.once('close', (code) => {
|
|
44
|
+
if (code === 0 || code === 128) resolve();
|
|
45
|
+
else reject(new Error(`taskkill a échoué avec le code ${code}.`));
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Terminates a complete processing tree and confirms that it disappeared.
|
|
52
|
+
* On POSIX, the pipeline is its process-group leader. On Windows, taskkill /T
|
|
53
|
+
* performs the recursive termination while the root process still exists.
|
|
54
|
+
*/
|
|
55
|
+
async function terminateProcessTree(processGroupId, {
|
|
56
|
+
graceMs = 2_000,
|
|
57
|
+
platform = process.platform,
|
|
58
|
+
} = {}) {
|
|
59
|
+
if (!Number.isInteger(processGroupId) || processGroupId <= 0) return;
|
|
60
|
+
|
|
61
|
+
if (platform === 'win32') {
|
|
62
|
+
await taskkillProcessTree(processGroupId);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!posixProcessGroupExists(processGroupId)) return;
|
|
67
|
+
signalPosixProcessGroup(processGroupId, 'SIGTERM');
|
|
68
|
+
if (await waitForPosixProcessGroupExit(processGroupId, graceMs)) return;
|
|
69
|
+
|
|
70
|
+
signalPosixProcessGroup(processGroupId, 'SIGKILL');
|
|
71
|
+
if (!(await waitForPosixProcessGroupExit(processGroupId, graceMs))) {
|
|
72
|
+
throw new Error(`Le groupe de processus ${processGroupId} est toujours actif après SIGKILL.`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Post-job guard: a successful direct child exit is insufficient because one
|
|
78
|
+
* of its descendants may still own CPU, memory, or inherited pipes.
|
|
79
|
+
*/
|
|
80
|
+
async function ensureProcessTreeStopped(processGroupId, options) {
|
|
81
|
+
if (process.platform === 'win32') return;
|
|
82
|
+
if (posixProcessGroupExists(processGroupId)) {
|
|
83
|
+
await terminateProcessTree(processGroupId, options);
|
|
84
|
+
}
|
|
85
|
+
if (posixProcessGroupExists(processGroupId)) {
|
|
86
|
+
throw new Error(`Nettoyage incomplet du groupe de processus ${processGroupId}.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = {
|
|
91
|
+
ensureProcessTreeStopped,
|
|
92
|
+
posixProcessGroupExists,
|
|
93
|
+
terminateProcessTree,
|
|
94
|
+
waitForPosixProcessGroupExit,
|
|
95
|
+
};
|