@piecemaker-legal/piecemaker 2.0.9 → 2.0.11
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/FindReplaceDialog-KU5TEIBJ-BucOHLdm.js +1 -0
- package/dist/assets/FootnotePropertiesDialog-W3YHM4BV-D5UqbelV.js +1 -0
- package/dist/assets/HyperlinkDialog-ZYH7ZHRF-8yEhLigd.js +144 -0
- package/dist/assets/HyperlinkDialog-ZYH7ZHRF-qIPBOssF.css +1 -0
- package/dist/assets/ImagePositionDialog-HEWYR6Q3-wGIBYxCm.js +1 -0
- package/dist/assets/ImagePropertiesDialog-RAB47C6M-D86PckZ2.js +1 -0
- package/dist/assets/PageSetupDialog-AIGIXO3E-DLETP-7v.js +1 -0
- package/dist/assets/SplitCellDialog-IFBKYCD6-CwdQBXeb.js +1 -0
- package/dist/assets/TablePropertiesDialog-TMLKGOOW-j2nA7KJs.js +1 -0
- package/dist/assets/WatermarkDialog-KRL7WMIS-XFJ9gTkC.js +1 -0
- package/dist/assets/{abnfDiagram-VCTEODGH-WrsSAHOe.js → abnfDiagram-VCTEODGH-DiCrND_Y.js} +1 -1
- package/dist/assets/arc-DOjgbMYz.js +1 -0
- package/dist/assets/architectureDiagram-5GKGNRK7-brzIFVhl.js +36 -0
- package/dist/assets/{blockDiagram-I7D4REHJ-zGMnF7Ox.js → blockDiagram-I7D4REHJ-C8JhTjQQ.js} +1 -1
- package/dist/assets/{c4Diagram-7LVT6UL2-ClWw3bqt.js → c4Diagram-7LVT6UL2-jfYxccyk.js} +1 -1
- package/dist/assets/channel-Dajzu2W1.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-C-9ICPHv.js → chunk-2Q5K7J3B-CrlEShp9.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-Bawy3teT.js → chunk-5VM5RSS4-DzPlUHGq.js} +1 -1
- package/dist/assets/{chunk-F27PBJKO-DQ375RQO.js → chunk-F27PBJKO-Cp9cpeWU.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-CflNF2f6.js → chunk-IMKFNOWR-BifUldEN.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CIXQv0gc.js → chunk-JWPE2WC7-ggPEIkWu.js} +1 -1
- package/dist/assets/{chunk-POPQ4Y6H-Cza5j6Qw.js → chunk-POPQ4Y6H-3h_nayRX.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-GQ_VvWZR.js → chunk-SVP7TREG-CH29aG6J.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-BEmU16W5.js → chunk-TICWLB2K-PluJUM5k.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-C1KpkLYH.js → chunk-XXDRQBXY-DXU39Vwg.js} +1 -1
- package/dist/assets/classDiagram-ZZMXUADV-dDEP_giv.js +1 -0
- package/dist/assets/classDiagram-v2-VYDZK3BY-dDEP_giv.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-CZE48TRG.js → cose-bilkent-JH36ORCC-Dz6roYrN.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-L-tx1eC-.js → cynefin-OW5HDTMX-BLzrpSit.js} +1 -1
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-Coa8oJwR.js → cynefinDiagram-5FMLGOSQ-kfxnERDZ.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-Bu_3Y75K.js → dagre-GXQ25YYZ-DP57bp-N.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-CFiiV4es.js → diagram-S7CK7UJ4-DAlsrQVW.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-CCXheGAA.js → diagram-UQ7AKVKN-By5yrMer.js} +1 -1
- package/dist/assets/{diagram-VSXAHHWV-B70m4lr_.js → diagram-VSXAHHWV-Dx89kryN.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-CHkiMOVA.js → diagram-VX7I27RA-B9fARitZ.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-_awpc4Bs.js → diagram-Z3DM3KII-DC15CEH1.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-CZzjH86H.js → ebnfDiagram-PWID7BFC-BKQzghGF.js} +1 -1
- package/dist/assets/{erDiagram-RLTQ6QDP-9DgiHZg9.js → erDiagram-RLTQ6QDP-CPY6RM7G.js} +1 -1
- package/dist/assets/{flowDiagram-HODETNUW-DHY_503b.js → flowDiagram-HODETNUW-4dL4GJcf.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-DPiiYZ_l.js → ganttDiagram-EL5Y4UJY-D4-cVcfb.js} +1 -1
- package/dist/assets/{gitGraphDiagram-WWUBYQGX-Ddd_evm7.js → gitGraphDiagram-WWUBYQGX-BMeVIEiX.js} +1 -1
- package/dist/assets/{index-tibHq7Qp.js → index-DNtFDOni.js} +140 -140
- package/dist/assets/index-Dc9wNuS4.css +1 -0
- package/dist/assets/{infoDiagram-27XIBGKW-BPRNhfwb.js → infoDiagram-27XIBGKW-D5qMSUEU.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-BXx6aqkq.js → ishikawaDiagram-5VMMS53U-BDnyKRHm.js} +1 -1
- package/dist/assets/{journeyDiagram-3NMN7TZE-BK8TZM29.js → journeyDiagram-3NMN7TZE-dGz5ZGzq.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-CHioRmxz.js → kanban-definition-UXKFOSKX-D7UAz7o_.js} +6 -6
- package/dist/assets/layout-DKrmEGrz.js +1 -0
- package/dist/assets/{linear-CTEhUcKG.js → linear-CrTdMY-p.js} +1 -1
- package/dist/assets/{mermaid.core-DYUb_UUB.js → mermaid.core-CXQOT5G6.js} +7 -7
- package/dist/assets/{mindmap-definition-YA3MSWOX-D7ODZ4oS.js → mindmap-definition-YA3MSWOX-VgEiYfay.js} +1 -1
- package/dist/assets/{pegDiagram-XKGWAZYB-8J-_2_kw.js → pegDiagram-XKGWAZYB-9IqT8gGx.js} +1 -1
- package/dist/assets/{pieDiagram-E7YTZNPT-ebg0yfMi.js → pieDiagram-E7YTZNPT-D98pRE-t.js} +1 -1
- package/dist/assets/processTemplate-GPFDLQMX-B1sVV2O0.js +22 -0
- package/dist/assets/{quadrantDiagram-AXDQQJYC-BoWkDiFb.js → quadrantDiagram-AXDQQJYC-b9PwkYzL.js} +1 -1
- package/dist/assets/{railroadDiagram-O6MQD6OU-BRJ77ldz.js → railroadDiagram-O6MQD6OU-Dz87hsPE.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-Z0JJgktA.js → requirementDiagram-BXWQKSXE-CkcV73dK.js} +1 -1
- package/dist/assets/sankeyDiagram-P5KCCOFB-UBN31Yrs.js +40 -0
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-BPAjtXwp.js → sequenceDiagram-WJ2MYXX4-CpQxd5Za.js} +1 -1
- package/dist/assets/{server.browser-BzI1jrZw.js → server.browser-BY3bL-IX.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-BGZPCzM4.js → sizeCapture-INFHLROL-mCsFmyzw.js} +1 -1
- package/dist/assets/stateDiagram-D77RDMKH-B0MTBN-3.js +1 -0
- package/dist/assets/stateDiagram-v2-MP3YSRHH-DzBPN39W.js +1 -0
- package/dist/assets/{swimlanes-42K2YHIH-DvuB15qF.js → swimlanes-42K2YHIH-Dzydjm0e.js} +1 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-BXQpbUMD.js +8 -0
- package/dist/assets/{timeline-definition-24CTP7MA-ZIziYCIF.js → timeline-definition-24CTP7MA-Dz0toOLu.js} +3 -3
- package/dist/assets/{vendor-codemirror-CjW0lHR5.js → vendor-codemirror-CN-sJePf.js} +2 -2
- package/dist/assets/{vendor-react-D809iwXR.js → vendor-react-B22wqN3J.js} +5 -5
- package/dist/assets/{vennDiagram-4TSXK5OY-C5_B9gWa.js → vennDiagram-4TSXK5OY-DOWp7dkf.js} +4 -4
- package/dist/assets/{wardleyDiagram-VM6X3IG4-DMlH9Afw.js → wardleyDiagram-VM6X3IG4-CUxsztUB.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-BldhJt7i.js → xychartDiagram-S5SC5T6Z-DS96vNED.js} +1 -1
- package/dist/index.html +4 -4
- package/dist/sw.js +1 -1
- package/dist-server/server/modules/providers/list/mistral/mistral-models.provider.js +4 -53
- package/dist-server/server/modules/providers/list/mistral/mistral-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/mistral/mistral-runtime.provider.js +2 -3
- package/dist-server/server/modules/providers/list/mistral/mistral-runtime.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/mistral/mistral-vibe-models.js +30 -0
- package/dist-server/server/modules/providers/list/mistral/mistral-vibe-models.js.map +1 -0
- package/dist-server/server/modules/providers/tests/mistral-vibe-models.test.js +24 -0
- package/dist-server/server/modules/providers/tests/mistral-vibe-models.test.js.map +1 -0
- package/dist-server/server/piecemaker/agent-instructions.js +148 -0
- package/dist-server/server/piecemaker/agent-instructions.js.map +1 -0
- package/dist-server/server/piecemaker/anonymizer/lifecycle.js +2 -3
- package/dist-server/server/piecemaker/anonymizer/lifecycle.js.map +1 -1
- package/dist-server/server/piecemaker/docx-document.js +50 -0
- package/dist-server/server/piecemaker/docx-document.js.map +1 -0
- package/dist-server/server/piecemaker/index.js +13 -2
- package/dist-server/server/piecemaker/index.js.map +1 -1
- package/dist-server/server/piecemaker/model-discovery/codex-catalog.js +46 -0
- package/dist-server/server/piecemaker/model-discovery/codex-catalog.js.map +1 -0
- package/dist-server/server/piecemaker/model-discovery/index.js +42 -0
- package/dist-server/server/piecemaker/model-discovery/index.js.map +1 -0
- package/dist-server/server/piecemaker/model-discovery/mistral-catalog.js +19 -0
- package/dist-server/server/piecemaker/model-discovery/mistral-catalog.js.map +1 -0
- package/dist-server/server/piecemaker/model-discovery/stdio-rpc.js +61 -0
- package/dist-server/server/piecemaker/model-discovery/stdio-rpc.js.map +1 -0
- package/dist-server/server/piecemaker/project-registry.js +29 -0
- package/dist-server/server/piecemaker/project-registry.js.map +1 -0
- package/package.json +12 -1
- package/scripts/piecemaker/cli/disable-anonymizer.mjs +19 -0
- package/scripts/piecemaker/cli/lib/config.mjs +0 -1
- package/scripts/piecemaker/cli/lib/plugins.mjs +1 -0
- package/scripts/piecemaker/cli/lib/services.mjs +1 -10
- package/scripts/piecemaker/cli/piecemaker.mjs +0 -3
- package/server/modules/providers/list/mistral/mistral-models.provider.ts +4 -53
- package/server/modules/providers/list/mistral/mistral-runtime.provider.ts +2 -3
- package/server/modules/providers/list/mistral/mistral-vibe-models.ts +43 -0
- package/server/modules/providers/tests/mistral-vibe-models.test.ts +27 -0
- package/server/piecemaker/agent-instructions.ts +148 -0
- package/server/piecemaker/anonymizer/client-config.cjs +92 -92
- package/server/piecemaker/anonymizer/dictionary.cjs +34 -3
- package/server/piecemaker/anonymizer/hudsucker-fixture.cjs +9 -16
- package/server/piecemaker/anonymizer/hudsucker-proxy/Cargo.toml +1 -1
- package/server/piecemaker/anonymizer/hudsucker-proxy/src/main.rs +251 -268
- package/server/piecemaker/anonymizer/hudsucker-smoke.cjs +343 -0
- package/server/piecemaker/anonymizer/lifecycle.ts +2 -3
- package/server/piecemaker/anonymizer/rewriter-bridge.cjs +13 -4
- package/server/piecemaker/anonymizer/rewriter-worker.cjs +85 -0
- package/server/piecemaker/anonymizer/service.cjs +109 -179
- package/server/piecemaker/anonymizer/sqlite-dictionary.cjs +12 -1
- package/server/piecemaker/docx-document.ts +54 -0
- package/server/piecemaker/harness/decisions.cjs +1 -1
- package/server/piecemaker/harness/index.cjs +2 -3
- package/server/piecemaker/harness/verification.cjs +1 -1
- package/server/piecemaker/index.ts +15 -3
- package/server/piecemaker/model-discovery/codex-catalog.ts +67 -0
- package/server/piecemaker/model-discovery/index.ts +69 -0
- package/server/piecemaker/model-discovery/mistral-catalog.ts +36 -0
- package/server/piecemaker/model-discovery/stdio-rpc.ts +79 -0
- package/server/piecemaker/project-registry.ts +34 -0
- package/server/piecemaker/router.cjs +6 -8
- package/server/piecemaker/vendor/installer/bin/piecemaker.mjs +31 -77
- package/server/piecemaker/vendor/installer/lib/codex-skills.mjs +2 -84
- package/server/piecemaker/vendor/installer/lib/service.mjs +4 -24
- package/server/piecemaker/vendor/installer/steps/02-dependances-node.mjs +5 -5
- package/server/piecemaker/vendor/installer/steps/06-hooks.mjs +10 -21
- package/server/piecemaker/vendor/installer/steps/09-claude-assets.mjs +0 -11
- package/server/piecemaker/vendor/installer/steps/09-codex-plugin.mjs +6 -36
- package/server/piecemaker/vendor/installer/steps/13-garde-secrets.mjs +30 -12
- package/server/piecemaker/vendor/piecemaker-plugin/README.md +2 -9
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/billing-track.mjs +5 -5
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/classify-ai-documents.mjs +8 -8
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/commit-track.mjs +2 -2
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/compile-recherche.mjs +4 -6
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folder-structure.cjs +2 -90
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/case-folders.cjs +71 -38
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/mapping.cjs +8 -38
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/protection.cjs +82 -61
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/substitution.cjs +189 -41
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/protect-originals.mjs +4 -55
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/statusline.mjs +24 -117
- package/server/piecemaker/vendor/piecemaker-plugin/skills/ajout-de-fonctionnalites/SKILL.md +4 -18
- package/server/piecemaker/vendor/piecemaker-plugin/skills/tamponnage/SKILL.md +2 -2
- package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +14 -148
- package/server/piecemaker/vendor/websocket-server/case-registry.cjs +16 -42
- package/server/piecemaker/vendor/websocket-server/claude-hooks.cjs +0 -73
- package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +0 -7
- package/server/piecemaker/vendor/websocket-server/stamping-routes.cjs +3 -12
- package/server/piecemaker/vendor/websocket-server/workspace-paths.cjs +6 -6
- package/dist/assets/arc-DAA6wH-C.js +0 -1
- package/dist/assets/architectureDiagram-5GKGNRK7-BGNHr7ef.js +0 -36
- package/dist/assets/channel-BAQyfMll.js +0 -1
- package/dist/assets/classDiagram-ZZMXUADV-BNGCuvrR.js +0 -1
- package/dist/assets/classDiagram-v2-VYDZK3BY-BNGCuvrR.js +0 -1
- package/dist/assets/index-WwknP0l4.css +0 -1
- package/dist/assets/layout-DEnkyfTY.js +0 -1
- package/dist/assets/sankeyDiagram-P5KCCOFB-4PW5HTOP.js +0 -40
- package/dist/assets/stateDiagram-D77RDMKH-o-vEcKwz.js +0 -1
- package/dist/assets/stateDiagram-v2-MP3YSRHH-BsuDaKkN.js +0 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-DcCAyKlT.js +0 -8
- package/scripts/piecemaker/cli/lib/piecemaker-anonymizer.mjs +0 -78
- package/scripts/piecemaker/hooks/proxy-guard.mjs +0 -251
- package/server/piecemaker/anonymizer/providers.cjs +0 -120
- package/server/piecemaker/vendor/installer/steps/08-telegram.mjs +0 -482
- package/server/piecemaker/vendor/piecemaker-plugin/scripts/lib/central-mapping.cjs +0 -0
- package/server/piecemaker/vendor/websocket-server/telegram-admin.cjs +0 -602
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { removeLegacyProxyConfig } from '../../../server/piecemaker/anonymizer/client-config.cjs';
|
|
6
|
+
|
|
7
|
+
const userHome = os.homedir();
|
|
8
|
+
const homeDir = path.join(userHome, '.piecemaker');
|
|
9
|
+
const configFile = path.join(homeDir, 'config.json');
|
|
10
|
+
const config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
11
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) throw new Error('Configuration PieceMaker invalide');
|
|
12
|
+
|
|
13
|
+
const next = { ...config, anonymizer: { ...config.anonymizer, enabled: false } };
|
|
14
|
+
const temporary = `${configFile}.piecemaker-${process.pid}-${Date.now()}`;
|
|
15
|
+
fs.writeFileSync(temporary, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
|
|
16
|
+
fs.renameSync(temporary, configFile);
|
|
17
|
+
|
|
18
|
+
removeLegacyProxyConfig({ userHome, homeDir });
|
|
19
|
+
process.stdout.write('Proxy PII PieceMaker désactivé.\n');
|
|
@@ -25,7 +25,6 @@ export const INSTALLER_ENTRY = path.join(APP.directory, 'server', 'piecemaker',
|
|
|
25
25
|
export const PORTS = {
|
|
26
26
|
appServer: numberFromEnv('PIECEMAKER_APP_PORT', 3003),
|
|
27
27
|
appClient: numberFromEnv('PIECEMAKER_VITE_PORT', 5173),
|
|
28
|
-
anonymizer: numberFromEnv('PIECEMAKER_PII_PORT', 4111),
|
|
29
28
|
};
|
|
30
29
|
|
|
31
30
|
export const APP_URL = `http://localhost:${PORTS.appClient}`;
|
|
@@ -12,6 +12,7 @@ export const PLUGINS = [
|
|
|
12
12
|
{ id: 'piecemaker-tampon', label: 'Plugin Bordereau' },
|
|
13
13
|
{ id: 'piecemaker-dossier', label: 'Plugin Dossier' },
|
|
14
14
|
{ id: 'piecemaker-library', label: 'Plugin Bibliothèque' },
|
|
15
|
+
{ id: 'piecemaker-telegram', label: 'Plugin Telegram' },
|
|
15
16
|
];
|
|
16
17
|
|
|
17
18
|
export async function installPlugins(runtime, report) {
|
|
@@ -33,15 +33,6 @@ export function appClientReachable() {
|
|
|
33
33
|
return httpReachable(`http://127.0.0.1:${PORTS.appClient}/`);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function anonymizerPort() {
|
|
37
|
-
try {
|
|
38
|
-
const port = Number.parseInt(JSON.parse(fs.readFileSync(path.join(PIECEMAKER_HOME, 'config.json'), 'utf8')).mikePiiPort, 10);
|
|
39
|
-
if (Number.isInteger(port) && port > 0) return port;
|
|
40
|
-
} catch {
|
|
41
|
-
}
|
|
42
|
-
return PORTS.anonymizer;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
36
|
function stopPid(pid) {
|
|
46
37
|
if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
|
|
47
38
|
if (process.platform === 'win32') {
|
|
@@ -61,7 +52,7 @@ export async function stopApplication() {
|
|
|
61
52
|
} catch {
|
|
62
53
|
}
|
|
63
54
|
|
|
64
|
-
for (const port of [PORTS.appClient, PORTS.appServer
|
|
55
|
+
for (const port of [PORTS.appClient, PORTS.appServer]) {
|
|
65
56
|
const result = await freePort(port);
|
|
66
57
|
killed.push(...result.killed);
|
|
67
58
|
if (!result.released) occupied.push(port);
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { installPiecemakerCommand, piecemakerExecutable } from './install-command.mjs';
|
|
4
4
|
import { APP, APP_URL, PORTS } from './lib/config.mjs';
|
|
5
|
-
import { repairClientProxies } from './lib/piecemaker-anonymizer.mjs';
|
|
6
5
|
import { installComponents } from './lib/composants.mjs';
|
|
7
6
|
import { installPlugins } from './lib/plugins.mjs';
|
|
8
7
|
import { gitAvailable, resolveNodeRuntime } from './lib/node-runtime.mjs';
|
|
@@ -130,8 +129,6 @@ async function main() {
|
|
|
130
129
|
if (command.shims.length) ok(`installée : ${command.executable}`);
|
|
131
130
|
else warn('commande absente du PATH — relancez node scripts/piecemaker/cli/install-command.mjs');
|
|
132
131
|
|
|
133
|
-
await repairClientProxies({ appDir: APP.directory, report });
|
|
134
|
-
|
|
135
132
|
if (!options.launchOnly || !(await applicationIsRunning())) {
|
|
136
133
|
const running = await resetAndLaunch(runtime);
|
|
137
134
|
if (!running) return 1;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VIBE_MODEL_PRESETS, vibeModelOption } from '@/modules/providers/list/mistral/mistral-vibe-models.js';
|
|
1
2
|
import type { IProviderModels } from '@/shared/interfaces.js';
|
|
2
3
|
import type {
|
|
3
4
|
ProviderCurrentActiveModel,
|
|
@@ -8,60 +9,10 @@ import { buildDefaultProviderCurrentActiveModel } from '@/shared/utils.js';
|
|
|
8
9
|
/** Curated Mistral catalog shipped as immutable CloudCLI defaults. */
|
|
9
10
|
export const MISTRAL_PREDEFINED_MODELS: ProviderModelsDefinition = {
|
|
10
11
|
OPTIONS: [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
label: 'Mistral Large',
|
|
14
|
-
description: 'Most powerful Mistral model for complex reasoning and advanced tasks.',
|
|
15
|
-
effort: {
|
|
16
|
-
default: 'medium',
|
|
17
|
-
values: [
|
|
18
|
-
{ value: 'low' },
|
|
19
|
-
{ value: 'medium' },
|
|
20
|
-
{ value: 'high' },
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
value: 'mistral-medium-latest',
|
|
26
|
-
label: 'Mistral Medium',
|
|
27
|
-
description: 'Balanced model for everyday tasks and coding.',
|
|
28
|
-
effort: {
|
|
29
|
-
default: 'medium',
|
|
30
|
-
values: [
|
|
31
|
-
{ value: 'low' },
|
|
32
|
-
{ value: 'medium' },
|
|
33
|
-
{ value: 'high' },
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
value: 'mistral-small-latest',
|
|
39
|
-
label: 'Mistral Small',
|
|
40
|
-
description: 'Fast and efficient model for simpler tasks.',
|
|
41
|
-
effort: {
|
|
42
|
-
default: 'medium',
|
|
43
|
-
values: [
|
|
44
|
-
{ value: 'low' },
|
|
45
|
-
{ value: 'medium' },
|
|
46
|
-
{ value: 'high' },
|
|
47
|
-
],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
value: 'codestral-latest',
|
|
52
|
-
label: 'Codestral',
|
|
53
|
-
description: 'Mistral model specialized for coding and development tasks.',
|
|
54
|
-
effort: {
|
|
55
|
-
default: 'medium',
|
|
56
|
-
values: [
|
|
57
|
-
{ value: 'low' },
|
|
58
|
-
{ value: 'medium' },
|
|
59
|
-
{ value: 'high' },
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
},
|
|
12
|
+
...VIBE_MODEL_PRESETS.map((preset) => vibeModelOption(preset.alias, preset.display_name, preset.name)),
|
|
13
|
+
vibeModelOption('local', 'Devstral (local)', 'devstral'),
|
|
63
14
|
],
|
|
64
|
-
DEFAULT: 'mistral-
|
|
15
|
+
DEFAULT: 'mistral-medium-3.5',
|
|
65
16
|
};
|
|
66
17
|
|
|
67
18
|
/** Provider registry model adapter for Mistral predefined models. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import crossSpawn from 'cross-spawn';
|
|
2
2
|
|
|
3
|
+
import { buildVibeModelsEnvironment } from '@/modules/providers/list/mistral/mistral-vibe-models.js';
|
|
3
4
|
import { notifyRunFailed, notifyRunStopped } from '@/modules/notifications/index.js';
|
|
4
5
|
import type { IProviderRuntime } from '@/shared/interfaces.js';
|
|
5
6
|
import type { AnyRecord, ProviderRuntimeContext, ProviderRuntimeWriter } from '@/shared/types.js';
|
|
@@ -300,9 +301,7 @@ async function spawnVibe(
|
|
|
300
301
|
if (resolvedModel) {
|
|
301
302
|
env.VIBE_ACTIVE_MODEL = resolvedModel;
|
|
302
303
|
}
|
|
303
|
-
|
|
304
|
-
env.VIBE_EFFORT = resolvedEffort;
|
|
305
|
-
}
|
|
304
|
+
env.VIBE_MODELS = buildVibeModelsEnvironment(resolvedModel ?? undefined, resolvedEffort);
|
|
306
305
|
|
|
307
306
|
vibeProcess = spawnFunction('vibe', args, {
|
|
308
307
|
cwd: workingDir,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ProviderModelOption } from '@/shared/types.js';
|
|
2
|
+
|
|
3
|
+
type VibeModelPreset = {
|
|
4
|
+
name: string;
|
|
5
|
+
provider: string;
|
|
6
|
+
alias: string;
|
|
7
|
+
display_name: string;
|
|
8
|
+
adjustableReasoning: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const VIBE_MODEL_PRESETS: readonly VibeModelPreset[] = [
|
|
12
|
+
{ name: 'mistral-vibe-cli-latest', provider: 'mistral', alias: 'mistral-medium-3.5', display_name: 'Mistral Medium 3.5', adjustableReasoning: true },
|
|
13
|
+
{ name: 'zai-glm-5-3', provider: 'mistral', alias: 'glm-5.3', display_name: 'Z.ai GLM 5.3', adjustableReasoning: false },
|
|
14
|
+
{ name: 'zai-glm-5-2', provider: 'mistral', alias: 'glm-5.2', display_name: 'Z.ai GLM 5.2', adjustableReasoning: false },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export const VIBE_REASONING_EFFORT: NonNullable<ProviderModelOption['effort']> = {
|
|
18
|
+
default: 'high',
|
|
19
|
+
values: [
|
|
20
|
+
{ value: 'none', description: 'Minimal thinking, no reasoning trace.' },
|
|
21
|
+
{ value: 'high', description: 'Full reasoning before answering.' },
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const VIBE_THINKING_BY_EFFORT: Record<string, string> = { none: 'low', high: 'high' };
|
|
26
|
+
|
|
27
|
+
export function vibeModelOption(alias: string, label: string, description?: string): ProviderModelOption {
|
|
28
|
+
const preset = VIBE_MODEL_PRESETS.find((candidate) => candidate.alias === alias);
|
|
29
|
+
return {
|
|
30
|
+
value: alias,
|
|
31
|
+
label,
|
|
32
|
+
...(description ? { description } : {}),
|
|
33
|
+
...(preset?.adjustableReasoning ? { effort: VIBE_REASONING_EFFORT } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function buildVibeModelsEnvironment(selectedAlias?: string, effort?: string): string {
|
|
38
|
+
const thinking = effort ? VIBE_THINKING_BY_EFFORT[effort] : undefined;
|
|
39
|
+
return JSON.stringify(Object.fromEntries(VIBE_MODEL_PRESETS.map(({ adjustableReasoning, ...model }) => [
|
|
40
|
+
model.alias,
|
|
41
|
+
adjustableReasoning && thinking && model.alias === selectedAlias ? { ...model, thinking } : model,
|
|
42
|
+
])));
|
|
43
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { MISTRAL_PREDEFINED_MODELS } from '@/modules/providers/list/mistral/mistral-models.provider.js';
|
|
5
|
+
import { buildVibeModelsEnvironment } from '@/modules/providers/list/mistral/mistral-vibe-models.js';
|
|
6
|
+
|
|
7
|
+
test('Vibe receives the GLM models alongside Mistral Medium without overriding thinking by default', () => {
|
|
8
|
+
const models = JSON.parse(buildVibeModelsEnvironment());
|
|
9
|
+
assert.deepEqual(Object.keys(models), ['mistral-medium-3.5', 'glm-5.3', 'glm-5.2']);
|
|
10
|
+
assert.deepEqual(models['glm-5.3'], { name: 'zai-glm-5-3', provider: 'mistral', alias: 'glm-5.3', display_name: 'Z.ai GLM 5.3' });
|
|
11
|
+
assert.equal(models['mistral-medium-3.5'].thinking, undefined);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('the selected effort becomes Vibe thinking only on models with adjustable reasoning', () => {
|
|
15
|
+
assert.equal(JSON.parse(buildVibeModelsEnvironment('mistral-medium-3.5', 'none'))['mistral-medium-3.5'].thinking, 'low');
|
|
16
|
+
assert.equal(JSON.parse(buildVibeModelsEnvironment('mistral-medium-3.5', 'high'))['mistral-medium-3.5'].thinking, 'high');
|
|
17
|
+
assert.equal(JSON.parse(buildVibeModelsEnvironment('glm-5.3', 'high'))['glm-5.3'].thinking, undefined);
|
|
18
|
+
assert.equal(JSON.parse(buildVibeModelsEnvironment('mistral-medium-3.5', 'bogus'))['mistral-medium-3.5'].thinking, undefined);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('the curated Mistral catalog lists GLM 5.3 and 5.2 and offers effort on Medium 3.5 only', () => {
|
|
22
|
+
const byValue = Object.fromEntries(MISTRAL_PREDEFINED_MODELS.OPTIONS.map((option) => [option.value, option]));
|
|
23
|
+
assert.deepEqual(Object.keys(byValue), ['mistral-medium-3.5', 'glm-5.3', 'glm-5.2', 'local']);
|
|
24
|
+
assert.deepEqual(byValue['mistral-medium-3.5'].effort?.values.map((value) => value.value), ['none', 'high']);
|
|
25
|
+
assert.equal(byValue['glm-5.3'].effort, undefined);
|
|
26
|
+
assert.equal(MISTRAL_PREDEFINED_MODELS.DEFAULT, 'mistral-medium-3.5');
|
|
27
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { constants, watch, type FSWatcher } from 'fs';
|
|
2
|
+
import { copyFile, lstat, readFile, realpath, rename, stat, writeFile } from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
import express, { type Request, type Response } from 'express';
|
|
6
|
+
|
|
7
|
+
import { projectsDb } from '@/modules/database/index.js';
|
|
8
|
+
|
|
9
|
+
const CLAUDE_FILE = 'CLAUDE.md';
|
|
10
|
+
const AGENTS_FILE = 'AGENTS.md';
|
|
11
|
+
const WATCHED_FILES = new Set([CLAUDE_FILE, AGENTS_FILE]);
|
|
12
|
+
const PROJECT_REFRESH_INTERVAL_MS = 5000;
|
|
13
|
+
const MIRROR_DEBOUNCE_MS = 300;
|
|
14
|
+
|
|
15
|
+
async function isPresent(filePath: string): Promise<boolean> {
|
|
16
|
+
try {
|
|
17
|
+
await lstat(filePath);
|
|
18
|
+
return true;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function agentInstructionsTemplate(sharedInstructionsFile: string): string {
|
|
25
|
+
return [
|
|
26
|
+
`@${sharedInstructionsFile}`,
|
|
27
|
+
'',
|
|
28
|
+
'# Ce dossier',
|
|
29
|
+
'<!-- Éléments propres à ce dossier : parties, juridiction, échéances, particularités. À compléter. -->',
|
|
30
|
+
'',
|
|
31
|
+
].join('\n');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function ensureAgentInstructionFiles(projectRoot: string, sharedInstructionsFile: string): Promise<string[]> {
|
|
35
|
+
const claudePath = path.join(projectRoot, CLAUDE_FILE);
|
|
36
|
+
const agentsPath = path.join(projectRoot, AGENTS_FILE);
|
|
37
|
+
const [hasClaude, hasAgents] = await Promise.all([isPresent(claudePath), isPresent(agentsPath)]);
|
|
38
|
+
if (hasClaude && hasAgents) return [];
|
|
39
|
+
if (hasClaude) {
|
|
40
|
+
await copyFile(claudePath, agentsPath, constants.COPYFILE_EXCL);
|
|
41
|
+
return [AGENTS_FILE];
|
|
42
|
+
}
|
|
43
|
+
if (hasAgents) {
|
|
44
|
+
await copyFile(agentsPath, claudePath, constants.COPYFILE_EXCL);
|
|
45
|
+
return [CLAUDE_FILE];
|
|
46
|
+
}
|
|
47
|
+
const template = agentInstructionsTemplate(sharedInstructionsFile);
|
|
48
|
+
await writeFile(claudePath, template, { flag: 'wx' });
|
|
49
|
+
await writeFile(agentsPath, template, { flag: 'wx' });
|
|
50
|
+
return [CLAUDE_FILE, AGENTS_FILE];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const lastMirroredContents = new Map<string, Buffer>();
|
|
54
|
+
|
|
55
|
+
export async function mirrorAgentInstructionFiles(projectRoot: string): Promise<void> {
|
|
56
|
+
try {
|
|
57
|
+
const claudePath = path.join(projectRoot, CLAUDE_FILE);
|
|
58
|
+
const agentsPath = path.join(projectRoot, AGENTS_FILE);
|
|
59
|
+
await Promise.all([stat(claudePath), stat(agentsPath)]);
|
|
60
|
+
if ((await realpath(claudePath)) === (await realpath(agentsPath))) return;
|
|
61
|
+
const [claudeContent, agentsContent] = await Promise.all([readFile(claudePath), readFile(agentsPath)]);
|
|
62
|
+
if (claudeContent.equals(agentsContent)) {
|
|
63
|
+
lastMirroredContents.set(projectRoot, claudeContent);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const lastMirrored = lastMirroredContents.get(projectRoot);
|
|
67
|
+
if (!lastMirrored) return;
|
|
68
|
+
const claudeChanged = agentsContent.equals(lastMirrored);
|
|
69
|
+
if (!claudeChanged && !claudeContent.equals(lastMirrored)) return;
|
|
70
|
+
const [content, targetPath] = claudeChanged ? [claudeContent, agentsPath] : [agentsContent, claudePath];
|
|
71
|
+
const temporaryPath = `${targetPath}.piecemaker-${process.pid}.tmp`;
|
|
72
|
+
await writeFile(temporaryPath, content);
|
|
73
|
+
await rename(temporaryPath, targetPath);
|
|
74
|
+
lastMirroredContents.set(projectRoot, content);
|
|
75
|
+
} catch {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function startAgentInstructionsMirror(listProjectRoots: () => string[]): () => void {
|
|
81
|
+
const watchers = new Map<string, FSWatcher>();
|
|
82
|
+
const pendingMirrors = new Map<string, NodeJS.Timeout>();
|
|
83
|
+
|
|
84
|
+
const scheduleMirror = (projectRoot: string) => {
|
|
85
|
+
clearTimeout(pendingMirrors.get(projectRoot));
|
|
86
|
+
pendingMirrors.set(projectRoot, setTimeout(() => {
|
|
87
|
+
pendingMirrors.delete(projectRoot);
|
|
88
|
+
void mirrorAgentInstructionFiles(projectRoot);
|
|
89
|
+
}, MIRROR_DEBOUNCE_MS).unref());
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const forget = (projectRoot: string) => {
|
|
93
|
+
watchers.get(projectRoot)?.close();
|
|
94
|
+
watchers.delete(projectRoot);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const refreshWatchers = () => {
|
|
98
|
+
let projectRoots: Set<string>;
|
|
99
|
+
try {
|
|
100
|
+
projectRoots = new Set(listProjectRoots().map((projectRoot) => path.resolve(projectRoot)));
|
|
101
|
+
} catch {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
for (const projectRoot of watchers.keys()) {
|
|
105
|
+
if (!projectRoots.has(projectRoot)) forget(projectRoot);
|
|
106
|
+
}
|
|
107
|
+
for (const projectRoot of projectRoots) {
|
|
108
|
+
if (watchers.has(projectRoot)) continue;
|
|
109
|
+
try {
|
|
110
|
+
const watcher = watch(projectRoot, { persistent: false }, (_event, fileName) => {
|
|
111
|
+
if (!fileName || WATCHED_FILES.has(fileName.toString())) scheduleMirror(projectRoot);
|
|
112
|
+
});
|
|
113
|
+
watcher.on('error', () => forget(projectRoot));
|
|
114
|
+
watchers.set(projectRoot, watcher);
|
|
115
|
+
scheduleMirror(projectRoot);
|
|
116
|
+
} catch {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
refreshWatchers();
|
|
123
|
+
const interval = setInterval(refreshWatchers, PROJECT_REFRESH_INTERVAL_MS).unref();
|
|
124
|
+
return () => {
|
|
125
|
+
clearInterval(interval);
|
|
126
|
+
for (const timer of pendingMirrors.values()) clearTimeout(timer);
|
|
127
|
+
for (const projectRoot of [...watchers.keys()]) forget(projectRoot);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createAgentInstructionsRouter(sharedInstructionsFile: string) {
|
|
132
|
+
const router = express.Router();
|
|
133
|
+
|
|
134
|
+
router.post('/agent-instructions', async (request: Request, response: Response) => {
|
|
135
|
+
const projectId = typeof request.body?.projectId === 'string' ? request.body.projectId : '';
|
|
136
|
+
const projectRoot = projectId ? projectsDb.getProjectPathById(projectId) : null;
|
|
137
|
+
if (!projectRoot) return response.status(404).json({ error: 'Projet introuvable.' });
|
|
138
|
+
try {
|
|
139
|
+
const created = await ensureAgentInstructionFiles(projectRoot, sharedInstructionsFile);
|
|
140
|
+
await mirrorAgentInstructionFiles(projectRoot);
|
|
141
|
+
response.json({ ok: true, created });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
response.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return router;
|
|
148
|
+
}
|
|
@@ -1,119 +1,119 @@
|
|
|
1
1
|
const fs = require('node:fs');
|
|
2
|
-
const os = require('node:os');
|
|
3
2
|
const path = require('node:path');
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const LEGACY_PROXY_KEYS = [
|
|
5
|
+
'HTTPS_PROXY', 'HTTP_PROXY', 'ALL_PROXY', 'NO_PROXY', 'NODE_USE_ENV_PROXY',
|
|
6
|
+
'NODE_EXTRA_CA_CERTS', 'SSL_CERT_FILE', 'CODEX_CA_CERTIFICATE', 'REQUESTS_CA_BUNDLE',
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
function readObject(file) {
|
|
10
|
+
try {
|
|
11
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
12
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function writeObject(file, value) {
|
|
7
19
|
const temporary = `${file}.piecemaker-${process.pid}-${Date.now()}`;
|
|
8
|
-
fs.writeFileSync(temporary,
|
|
20
|
+
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
|
|
9
21
|
fs.renameSync(temporary, file);
|
|
10
22
|
}
|
|
11
23
|
|
|
12
|
-
|
|
13
|
-
HTTPS_PROXY: (proxyUrl) => proxyUrl,
|
|
14
|
-
HTTP_PROXY: (proxyUrl) => proxyUrl,
|
|
15
|
-
ALL_PROXY: (proxyUrl) => proxyUrl,
|
|
16
|
-
NO_PROXY: () => 'localhost,127.0.0.1,::1',
|
|
17
|
-
NODE_USE_ENV_PROXY: () => '1',
|
|
18
|
-
NODE_EXTRA_CA_CERTS: (_proxyUrl, caFile) => caFile,
|
|
19
|
-
SSL_CERT_FILE: (_proxyUrl, caFile, trustBundle) => trustBundle || caFile,
|
|
20
|
-
CODEX_CA_CERTIFICATE: (_proxyUrl, caFile) => caFile,
|
|
21
|
-
REQUESTS_CA_BUNDLE: (_proxyUrl, caFile, trustBundle) => trustBundle || caFile,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
function isLoopbackProxy(value) {
|
|
24
|
+
function isLoopback(value) {
|
|
25
25
|
try {
|
|
26
|
-
|
|
27
|
-
return ['127.0.0.1', 'localhost'].includes(url.hostname);
|
|
26
|
+
return ['127.0.0.1', 'localhost'].includes(new URL(String(value || '')).hostname);
|
|
28
27
|
} catch {
|
|
29
28
|
return false;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
if (fs.existsSync(settingsFile)) {
|
|
38
|
-
const parsed = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
39
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('objet JSON attendu');
|
|
40
|
-
settings = parsed;
|
|
41
|
-
}
|
|
42
|
-
} catch {
|
|
43
|
-
return { configured: false, changed: false, conflict: true, file: settingsFile, reason: 'settings-invalid' };
|
|
44
|
-
}
|
|
32
|
+
function isProxyGuard(hook) {
|
|
33
|
+
return [hook?.command, hook?.commandWindows].some((command) => typeof command === 'string' && command.includes('proxy-guard.mjs'));
|
|
34
|
+
}
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (existingProxy && existingProxy !== proxyUrl && !isLoopbackProxy(existingProxy)) {
|
|
53
|
-
return { configured: false, changed: false, conflict: true, file: settingsFile, reason: 'proxy-conflict' };
|
|
54
|
-
}
|
|
36
|
+
function withoutProxyGuard(groups) {
|
|
37
|
+
if (!Array.isArray(groups)) return groups;
|
|
38
|
+
return groups
|
|
39
|
+
.map((group) => (Array.isArray(group?.hooks) ? { ...group, hooks: group.hooks.filter((hook) => !isProxyGuard(hook)) } : group))
|
|
40
|
+
.filter((group) => !Array.isArray(group?.hooks) || group.hooks.length);
|
|
41
|
+
}
|
|
55
42
|
|
|
43
|
+
function cleanClaudeSettings(file) {
|
|
44
|
+
const settings = readObject(file);
|
|
45
|
+
if (!settings) return false;
|
|
56
46
|
let changed = false;
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
if (!
|
|
60
|
-
|
|
61
|
-
settings.env[key] = value;
|
|
62
|
-
changed = true;
|
|
63
|
-
}
|
|
47
|
+
if (settings.env && isLoopback(settings.env.HTTPS_PROXY)) {
|
|
48
|
+
for (const key of LEGACY_PROXY_KEYS) delete settings.env[key];
|
|
49
|
+
if (!Object.keys(settings.env).length) delete settings.env;
|
|
50
|
+
changed = true;
|
|
64
51
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const settingsFile = path.join(userHome, '.claude', 'settings.json');
|
|
72
|
-
if (!fs.existsSync(settingsFile)) {
|
|
73
|
-
return { bypassed: true, changed: false, conflict: false, file: settingsFile };
|
|
52
|
+
const current = settings.hooks?.SessionStart;
|
|
53
|
+
const sessionStart = withoutProxyGuard(current);
|
|
54
|
+
if (Array.isArray(current) && JSON.stringify(sessionStart) !== JSON.stringify(current)) {
|
|
55
|
+
if (sessionStart.length) settings.hooks.SessionStart = sessionStart;
|
|
56
|
+
else delete settings.hooks.SessionStart;
|
|
57
|
+
changed = true;
|
|
74
58
|
}
|
|
59
|
+
if (changed) writeObject(file, settings);
|
|
60
|
+
return changed;
|
|
61
|
+
}
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
63
|
+
function cleanCodexHooks(file) {
|
|
64
|
+
const document = readObject(file);
|
|
65
|
+
const current = document?.hooks?.SessionStart;
|
|
66
|
+
const sessionStart = withoutProxyGuard(current);
|
|
67
|
+
if (!Array.isArray(current) || JSON.stringify(sessionStart) === JSON.stringify(current)) return false;
|
|
68
|
+
if (sessionStart.length) document.hooks.SessionStart = sessionStart;
|
|
69
|
+
else delete document.hooks.SessionStart;
|
|
70
|
+
writeObject(file, document);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
83
73
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
74
|
+
const LEGACY_CONFIG_KEYS = [
|
|
75
|
+
'mikePiiPort',
|
|
76
|
+
'caseFolders',
|
|
77
|
+
'anonymization',
|
|
78
|
+
'litellmPort',
|
|
79
|
+
'litellmVenvPath',
|
|
80
|
+
'mxcPath',
|
|
81
|
+
'mxcEnabled',
|
|
82
|
+
'adminTheme',
|
|
83
|
+
'port',
|
|
84
|
+
];
|
|
90
85
|
|
|
86
|
+
function cleanPieceMakerConfig(homeDir) {
|
|
87
|
+
const file = path.join(homeDir, 'config.json');
|
|
88
|
+
const config = readObject(file);
|
|
91
89
|
let changed = false;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
}
|
|
90
|
+
const legacyKeys = config ? LEGACY_CONFIG_KEYS.filter((key) => key in config) : [];
|
|
91
|
+
if (legacyKeys.length) {
|
|
92
|
+
for (const key of legacyKeys) delete config[key];
|
|
93
|
+
writeObject(file, config);
|
|
94
|
+
changed = true;
|
|
99
95
|
}
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function configureCodexProxy() {
|
|
107
|
-
return { configured: true, changed: false, conflict: false, file: null };
|
|
96
|
+
const statuslineCache = path.join(homeDir, 'proxy-statusline.json');
|
|
97
|
+
if (fs.existsSync(statuslineCache)) {
|
|
98
|
+
fs.rmSync(statuslineCache, { force: true });
|
|
99
|
+
changed = true;
|
|
100
|
+
}
|
|
101
|
+
return changed;
|
|
108
102
|
}
|
|
109
103
|
|
|
110
|
-
function
|
|
111
|
-
|
|
104
|
+
function removeLegacyProxyConfig({ userHome, homeDir = path.join(userHome, '.piecemaker') }) {
|
|
105
|
+
const cleaned = [];
|
|
106
|
+
const attempt = (name, run) => {
|
|
107
|
+
try {
|
|
108
|
+
if (run()) cleaned.push(name);
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
attempt('claude', () => cleanClaudeSettings(path.join(userHome, '.claude', 'settings.json')));
|
|
114
|
+
attempt('codex', () => cleanCodexHooks(path.join(process.env.CODEX_HOME || path.join(userHome, '.codex'), 'hooks.json')));
|
|
115
|
+
attempt('piecemaker', () => cleanPieceMakerConfig(homeDir));
|
|
116
|
+
return cleaned;
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
module.exports = {
|
|
115
|
-
configureClaudeCodeProxy,
|
|
116
|
-
bypassClaudeCodeProxy,
|
|
117
|
-
configureCodexProxy,
|
|
118
|
-
bypassCodexProxy,
|
|
119
|
-
};
|
|
119
|
+
module.exports = { removeLegacyProxyConfig };
|
|
@@ -30,6 +30,19 @@ const EMPTY = Object.freeze({
|
|
|
30
30
|
empty: true,
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
+
const MEMO_MIN_LENGTH = 256;
|
|
34
|
+
const MEMO_BUDGET = 16 * 1024 * 1024;
|
|
35
|
+
const memos = new WeakMap();
|
|
36
|
+
|
|
37
|
+
function memoFor(dictionary) {
|
|
38
|
+
let memo = memos.get(dictionary);
|
|
39
|
+
if (!memo) {
|
|
40
|
+
memo = { entries: new Map(), size: 0 };
|
|
41
|
+
memos.set(dictionary, memo);
|
|
42
|
+
}
|
|
43
|
+
return memo;
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
function plainObject(value) {
|
|
34
47
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
35
48
|
}
|
|
@@ -49,8 +62,9 @@ function plainObject(value) {
|
|
|
49
62
|
* ne part pas codé serait un mensonge à l'écran.
|
|
50
63
|
*/
|
|
51
64
|
function buildDictionary(document, stamp) {
|
|
52
|
-
const mapping = plainObject(document?.mapping);
|
|
53
|
-
const reverse = plainObject(document?.reverse_mapping)
|
|
65
|
+
const mapping = Object.freeze({ ...plainObject(document?.mapping) });
|
|
66
|
+
const reverse = Object.freeze(Object.fromEntries(Object.entries(plainObject(document?.reverse_mapping))
|
|
67
|
+
.map(([code, variants]) => [code, Array.isArray(variants) ? Object.freeze([...variants]) : variants])));
|
|
54
68
|
const canonical = {};
|
|
55
69
|
for (const [code, variants] of Object.entries(reverse)) {
|
|
56
70
|
const name = Array.isArray(variants) ? variants[0] : variants;
|
|
@@ -89,7 +103,24 @@ function buildDictionary(document, stamp) {
|
|
|
89
103
|
|
|
90
104
|
/** Nom réel → code, sur tout ce qui part vers l'API. */
|
|
91
105
|
function anonymize(text, dictionary) {
|
|
92
|
-
|
|
106
|
+
if (dictionary.empty) return text;
|
|
107
|
+
if (typeof text !== 'string' || text.length < MEMO_MIN_LENGTH) return applyMapping(text, dictionary.mapping);
|
|
108
|
+
const memo = memoFor(dictionary);
|
|
109
|
+
const cached = memo.entries.get(text);
|
|
110
|
+
if (cached !== undefined) {
|
|
111
|
+
memo.entries.delete(text);
|
|
112
|
+
memo.entries.set(text, cached);
|
|
113
|
+
return cached;
|
|
114
|
+
}
|
|
115
|
+
const result = applyMapping(text, dictionary.mapping);
|
|
116
|
+
memo.entries.set(text, result);
|
|
117
|
+
memo.size += text.length + (result === text ? 0 : result.length);
|
|
118
|
+
for (const [key, value] of memo.entries) {
|
|
119
|
+
if (memo.size <= MEMO_BUDGET) break;
|
|
120
|
+
memo.entries.delete(key);
|
|
121
|
+
memo.size -= key.length + (value === key ? 0 : value.length);
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
93
124
|
}
|
|
94
125
|
|
|
95
126
|
/** Code → nom réel, sur tout ce qui revient de l'API vers la machine. */
|