gitnexus 1.6.4-rc.98 → 1.6.4
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/_shared/index.d.ts +8 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +9 -0
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/integrations/circuit-breaker.d.ts +183 -0
- package/dist/_shared/integrations/circuit-breaker.d.ts.map +1 -0
- package/dist/_shared/integrations/circuit-breaker.js +236 -0
- package/dist/_shared/integrations/circuit-breaker.js.map +1 -0
- package/dist/_shared/integrations/resilient-fetch.d.ts +99 -0
- package/dist/_shared/integrations/resilient-fetch.d.ts.map +1 -0
- package/dist/_shared/integrations/resilient-fetch.js +204 -0
- package/dist/_shared/integrations/resilient-fetch.js.map +1 -0
- package/dist/_shared/integrations/retry.d.ts +60 -0
- package/dist/_shared/integrations/retry.d.ts.map +1 -0
- package/dist/_shared/integrations/retry.js +67 -0
- package/dist/_shared/integrations/retry.js.map +1 -0
- package/dist/_shared/integrations/understand-quickly.d.ts +79 -0
- package/dist/_shared/integrations/understand-quickly.d.ts.map +1 -0
- package/dist/_shared/integrations/understand-quickly.js +139 -0
- package/dist/_shared/integrations/understand-quickly.js.map +1 -0
- package/dist/_shared/test-helpers.d.ts +13 -0
- package/dist/_shared/test-helpers.d.ts.map +1 -0
- package/dist/_shared/test-helpers.js +13 -0
- package/dist/_shared/test-helpers.js.map +1 -0
- package/dist/cli/index.js +9 -0
- package/dist/cli/publish.d.ts +29 -0
- package/dist/cli/publish.js +174 -0
- package/dist/config/ignore-service.js +2 -0
- package/dist/core/embeddings/hf-env.d.ts +9 -37
- package/dist/core/embeddings/hf-env.js +65 -83
- package/dist/core/embeddings/http-client.d.ts +6 -0
- package/dist/core/embeddings/http-client.js +22 -18
- package/dist/core/group/bridge-db.js +7 -6
- package/dist/core/group/config-parser.js +19 -1
- package/dist/core/group/extractors/include-extractor.d.ts +39 -0
- package/dist/core/group/extractors/include-extractor.js +565 -0
- package/dist/core/group/extractors/manifest-extractor.js +8 -0
- package/dist/core/group/extractors/thrift-extractor.js +8 -0
- package/dist/core/group/matching.js +2 -0
- package/dist/core/group/storage.js +8 -1
- package/dist/core/group/sync.js +33 -0
- package/dist/core/group/types.d.ts +2 -1
- package/dist/core/ingestion/call-processor.js +6 -4
- package/dist/core/ingestion/cpp-ue-preprocessor.d.ts +12 -0
- package/dist/core/ingestion/cpp-ue-preprocessor.js +260 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +8 -3
- package/dist/core/ingestion/heritage-processor.js +9 -4
- package/dist/core/ingestion/import-processor.js +3 -2
- package/dist/core/ingestion/language-provider.d.ts +32 -0
- package/dist/core/ingestion/languages/c-cpp.js +2 -0
- package/dist/core/ingestion/languages/csharp/captures.js +93 -0
- package/dist/core/ingestion/languages/csharp/query.js +6 -0
- package/dist/core/ingestion/parsing-processor.js +4 -0
- package/dist/core/ingestion/workers/parse-worker.js +4 -0
- package/dist/core/lbug/csv-generator.js +5 -1
- package/dist/core/lbug/lbug-adapter.js +15 -0
- package/dist/core/lbug/schema.d.ts +1 -1
- package/dist/core/lbug/schema.js +12 -1
- package/dist/core/wiki/llm-client.d.ts +16 -0
- package/dist/core/wiki/llm-client.js +101 -63
- package/dist/mcp/local/local-backend.js +73 -7
- package/dist/server/api.js +7 -2
- package/package.json +2 -2
- package/vendor/node_modules/node-addon-api/node_addon_api.target.mk +16 -14
- package/vendor/node_modules/node-addon-api/node_addon_api_except.target.mk +16 -14
- package/vendor/node_modules/node-addon-api/node_addon_api_except_all.target.mk +16 -14
- package/vendor/node_modules/node-addon-api/node_addon_api_maybe.target.mk +16 -14
- package/web/assets/{agent-Dl2d-mDi.js → agent-BpHQleHE.js} +17 -17
- package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BUzkWgDl.js +1 -0
- package/web/assets/{architectureDiagram-EMZXCZ2Q-uiiIna83.js → architectureDiagram-EMZXCZ2Q-CXbzok1G.js} +3 -3
- package/web/assets/{blockDiagram-IGV67L2C-uBKdDzXA.js → blockDiagram-IGV67L2C-DA1QJ4ZB.js} +4 -4
- package/web/assets/{c4Diagram-DFAF54RM-DTxaX43T.js → c4Diagram-DFAF54RM-DeJV1rCn.js} +2 -2
- package/web/assets/{chunk-3GS5O3IE-BxKKu7d7.js → chunk-3GS5O3IE-B8hpnia8.js} +2 -2
- package/web/assets/{chunk-3YCYZ6SJ-BJZnGFjg.js → chunk-3YCYZ6SJ-B-BVu21C.js} +1 -1
- package/web/assets/{chunk-6NTNNK5N-CIL_eO2d.js → chunk-6NTNNK5N-DW-jYSDr.js} +1 -1
- package/web/assets/{chunk-A34GCYZU-Dv4Vkem9.js → chunk-A34GCYZU-BbZl-IKy.js} +1 -1
- package/web/assets/{chunk-DJ7UZH7F-Cskl-nb3.js → chunk-DJ7UZH7F-B5tMfF87.js} +1 -1
- package/web/assets/{chunk-DKKBVRCY-D3S2BD56.js → chunk-DKKBVRCY-Djm-6K_e.js} +2 -2
- package/web/assets/{chunk-DU5LTGQ6-B8Zh51LG.js → chunk-DU5LTGQ6-QPoynYcp.js} +1 -1
- package/web/assets/{chunk-FXACKDTF-Cb4xHVUz.js → chunk-FXACKDTF-jieSmbe2.js} +3 -3
- package/web/assets/chunk-H3VCZNTA-8EMHZ3SV.js +1 -0
- package/web/assets/chunk-HN6EAY2L-CgE_agsD.js +1 -0
- package/web/assets/{chunk-O5ABG6QK-V3sk7Bps.js → chunk-O5ABG6QK-DEZV1O19.js} +1 -1
- package/web/assets/{chunk-PK6DOVAG-FvG7aKfZ.js → chunk-PK6DOVAG-BXv0JnsJ.js} +3 -3
- package/web/assets/{chunk-RNJOYNJ4-BPANsy8V.js → chunk-RNJOYNJ4-BiBkF9dN.js} +1 -1
- package/web/assets/chunk-RWUO3TPN-DTWzAhQ1.js +1 -0
- package/web/assets/chunk-TBF5ZNIQ-BSl6s9lT.js +1 -0
- package/web/assets/{chunk-TYMNRAUI-BnMe6HfP.js → chunk-TYMNRAUI-D1NDLIMG.js} +1 -1
- package/web/assets/{chunk-W7ZLLLMY-BqZFKM5j.js → chunk-W7ZLLLMY-Bu-cdLzs.js} +1 -1
- package/web/assets/{chunk-WSB5WSVC-EKS7-Nnc.js → chunk-WSB5WSVC-Dor71SOz.js} +1 -1
- package/web/assets/{chunk-XGPFEOL4-BBab-enK.js → chunk-XGPFEOL4-CUonLRle.js} +1 -1
- package/web/assets/classDiagram-PPOCWD7C-Cdd6UdVv.js +1 -0
- package/web/assets/classDiagram-v2-23LJLIIU-DNhxY2Ib.js +1 -0
- package/web/assets/{cose-bilkent-PNC4W37J-DjEQkTZ4.js → cose-bilkent-PNC4W37J-DdZq7Qz_.js} +1 -1
- package/web/assets/dagre-E77IOHMT-Cfj_6e17.js +4 -0
- package/web/assets/{diagram-H7BISOXX-CMuISoJL.js → diagram-H7BISOXX-BNvpsrBv.js} +2 -2
- package/web/assets/{diagram-JC5VWROH-DHq_eoeM.js → diagram-JC5VWROH-Cn0rtDbJ.js} +1 -1
- package/web/assets/{diagram-LXUTUG65-C0NczIgW.js → diagram-LXUTUG65-CHfoVKNm.js} +2 -2
- package/web/assets/{diagram-WEHSV5V5-WsBnpSuc.js → diagram-WEHSV5V5-BLxHksnu.js} +1 -1
- package/web/assets/{erDiagram-GCSMX5X6-DxHFHFR6.js → erDiagram-GCSMX5X6-DfdN6iqF.js} +2 -2
- package/web/assets/flowDiagram-OTCZ4VVT-aAZw4c_M.js +162 -0
- package/web/assets/ganttDiagram-MUNLMDZQ-BEfC_7Or.js +292 -0
- package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-B6ZeRLP0.js +1 -0
- package/web/assets/gitGraphDiagram-3HKGZ4G3-CG0kC8Q5.js +106 -0
- package/web/assets/{index-DDcYO1IJ.js → index-3NUCUW2s.js} +119 -119
- package/web/assets/info-OMHHGYJF-BF2H5H6G-BIOsZy0W.js +1 -0
- package/web/assets/infoDiagram-MN7RKWGX-DUoMH-pq.js +2 -0
- package/web/assets/{ishikawaDiagram-YMYX4NHK-C-JI2Ih7.js → ishikawaDiagram-YMYX4NHK-BF8AtDaj.js} +2 -2
- package/web/assets/{journeyDiagram-SO5T7YLQ-IPX4h3iD.js → journeyDiagram-SO5T7YLQ-BW8oKa3N.js} +3 -3
- package/web/assets/{kanban-definition-LJHFXRCJ-B23LtshQ.js → kanban-definition-LJHFXRCJ-DzbOsR-2.js} +6 -6
- package/web/assets/{mindmap-definition-2EUWGEK5-DJKUsrCo.js → mindmap-definition-2EUWGEK5-BIXGQALq.js} +25 -25
- package/web/assets/packet-4T2RLAQJ-EV4IVRXR-Bs7ysNMU.js +1 -0
- package/web/assets/pie-ZZUOXDRM-N23DN5KN-Csi8nnbH.js +1 -0
- package/web/assets/{pieDiagram-3IATQBI2-Bj26KTKk.js → pieDiagram-3IATQBI2-QY-u7P6a.js} +3 -3
- package/web/assets/{quadrantDiagram-E256RVCF-VAk5oIRr.js → quadrantDiagram-E256RVCF-Di4aNiU8.js} +3 -3
- package/web/assets/radar-PYXPWWZC-P6TP7ZYP-DJlyXh2-.js +1 -0
- package/web/assets/{requirementDiagram-M5DCFWZL-CmlTJ_vQ.js → requirementDiagram-M5DCFWZL-CzUUrhQD.js} +4 -4
- package/web/assets/{sankeyDiagram-L3NBLAOT-C-f_DdcX.js → sankeyDiagram-L3NBLAOT-D2fbMiIU.js} +3 -3
- package/web/assets/{sequenceDiagram-ZOUHS735-DmtNf1NF.js → sequenceDiagram-ZOUHS735-BNdkqguh.js} +6 -6
- package/web/assets/stateDiagram-MLPALWAM-51_Q2w2L.js +1 -0
- package/web/assets/stateDiagram-v2-B5LQ5ZB2-8nHs2aNE.js +1 -0
- package/web/assets/{timeline-definition-5SPVSISX-BkpqZxt2.js → timeline-definition-5SPVSISX-DkMiGj4Z.js} +9 -9
- package/web/assets/treeView-SZITEDCU-5DXDK3XO-Cy6P0_CZ.js +1 -0
- package/web/assets/treemap-W4RFUUIX-WYLRDWKO-C_pp1R7A.js +1 -0
- package/web/assets/{vennDiagram-IE5QUKF5-iAJ08JBe.js → vennDiagram-IE5QUKF5-BCxMmf9q.js} +3 -3
- package/web/assets/wardley-RL74JXVD-BCRCBASE-CMStJhpn.js +1 -0
- package/web/assets/{wardleyDiagram-XU3VSMPF-BDiKTkL4.js → wardleyDiagram-XU3VSMPF-ijlLF77s.js} +4 -4
- package/web/assets/{xychartDiagram-ZHJ5623Y-CknyZyQK.js → xychartDiagram-ZHJ5623Y-DZ7fP1_3.js} +3 -3
- package/web/index.html +1 -1
- package/web/assets/architecture-YZFGNWBL-S5CXDPWN-BYXnTu07.js +0 -1
- package/web/assets/chunk-H3VCZNTA-BOGhqvxW.js +0 -1
- package/web/assets/chunk-HN6EAY2L-CitKFy1e.js +0 -1
- package/web/assets/chunk-RWUO3TPN-BHusg2jI.js +0 -1
- package/web/assets/chunk-TBF5ZNIQ-CXamrpH3.js +0 -1
- package/web/assets/classDiagram-PPOCWD7C-B-LkKU0P.js +0 -1
- package/web/assets/classDiagram-v2-23LJLIIU-_NGI4VEh.js +0 -1
- package/web/assets/dagre-E77IOHMT-D6Xacg1x.js +0 -4
- package/web/assets/flowDiagram-OTCZ4VVT-_G1VxyQS.js +0 -162
- package/web/assets/ganttDiagram-MUNLMDZQ-BIHObj0t.js +0 -292
- package/web/assets/gitGraph-7Q5UKJZL-54BCDZD5-BXJXsixL.js +0 -1
- package/web/assets/gitGraphDiagram-3HKGZ4G3-COZUkHTD.js +0 -106
- package/web/assets/info-OMHHGYJF-BF2H5H6G-C820LK0J.js +0 -1
- package/web/assets/infoDiagram-MN7RKWGX-BeOjfPc_.js +0 -2
- package/web/assets/packet-4T2RLAQJ-EV4IVRXR-BvWtM5jq.js +0 -1
- package/web/assets/pie-ZZUOXDRM-N23DN5KN-BnDgj0TQ.js +0 -1
- package/web/assets/radar-PYXPWWZC-P6TP7ZYP-2IuDlZ6r.js +0 -1
- package/web/assets/stateDiagram-MLPALWAM-Lq7UVrkj.js +0 -1
- package/web/assets/stateDiagram-v2-B5LQ5ZB2-DCiXBPeS.js +0 -1
- package/web/assets/treeView-SZITEDCU-5DXDK3XO-Ipq1EIaF.js +0 -1
- package/web/assets/treemap-W4RFUUIX-WYLRDWKO-DESFxovu.js +0 -1
- package/web/assets/wardley-RL74JXVD-BCRCBASE-BVkhckBY.js +0 -1
|
@@ -237,9 +237,10 @@ export const streamAllCSVsToDisk = async (graph, repoPath, csvDir) => {
|
|
|
237
237
|
'Template',
|
|
238
238
|
'Module',
|
|
239
239
|
];
|
|
240
|
+
const propertyHeader = 'id,name,filePath,startLine,endLine,content,description,declaredType';
|
|
240
241
|
const multiLangWriters = new Map();
|
|
241
242
|
for (const t of MULTI_LANG_TYPES) {
|
|
242
|
-
multiLangWriters.set(t, new BufferedCSVWriter(path.join(csvDir, `${t.toLowerCase()}.csv`), multiLangHeader));
|
|
243
|
+
multiLangWriters.set(t, new BufferedCSVWriter(path.join(csvDir, `${t.toLowerCase()}.csv`), t === 'Property' ? propertyHeader : multiLangHeader));
|
|
243
244
|
}
|
|
244
245
|
const codeWriterMap = {
|
|
245
246
|
Function: functionWriter,
|
|
@@ -390,6 +391,9 @@ export const streamAllCSVsToDisk = async (graph, repoPath, csvDir) => {
|
|
|
390
391
|
escapeCSVNumber(node.properties.endLine, -1),
|
|
391
392
|
escapeCSVField(content),
|
|
392
393
|
escapeCSVField(node.properties.description || ''),
|
|
394
|
+
...(node.label === 'Property'
|
|
395
|
+
? [escapeCSVField(node.properties.declaredType || '')]
|
|
396
|
+
: []),
|
|
393
397
|
].join(','));
|
|
394
398
|
}
|
|
395
399
|
}
|
|
@@ -520,6 +520,9 @@ const getCopyQuery = (table, filePath) => {
|
|
|
520
520
|
if (table === 'Method') {
|
|
521
521
|
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description, parameterCount, returnType) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
522
522
|
}
|
|
523
|
+
if (table === 'Property') {
|
|
524
|
+
return `COPY ${t}(id, name, filePath, startLine, endLine, content, description, declaredType) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
525
|
+
}
|
|
523
526
|
// TypeScript/JS code element tables have isExported; multi-language tables do not
|
|
524
527
|
if (TABLES_WITH_EXPORTED.has(table)) {
|
|
525
528
|
return `COPY ${t}(id, name, filePath, startLine, endLine, isExported, content, description) FROM "${filePath}" ${COPY_CSV_OPTS}`;
|
|
@@ -569,6 +572,12 @@ export const insertNodeToLbug = async (label, properties, dbPath) => {
|
|
|
569
572
|
: '';
|
|
570
573
|
query = `CREATE (n:${t} {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, isExported: ${!!properties.isExported}, content: ${escapeValue(properties.content || '')}${descPart}})`;
|
|
571
574
|
}
|
|
575
|
+
else if (label === 'Property') {
|
|
576
|
+
const descPart = properties.description
|
|
577
|
+
? `, description: ${escapeValue(properties.description)}`
|
|
578
|
+
: '';
|
|
579
|
+
query = `CREATE (n:${t} {id: ${escapeValue(properties.id)}, name: ${escapeValue(properties.name)}, filePath: ${escapeValue(properties.filePath)}, startLine: ${properties.startLine || 0}, endLine: ${properties.endLine || 0}, content: ${escapeValue(properties.content || '')}${descPart}, declaredType: ${escapeValue(properties.declaredType || '')}})`;
|
|
580
|
+
}
|
|
572
581
|
else {
|
|
573
582
|
// Multi-language tables (Struct, Impl, Trait, Macro, etc.) — no isExported
|
|
574
583
|
const descPart = properties.description
|
|
@@ -646,6 +655,12 @@ export const batchInsertNodesToLbug = async (nodes, dbPath) => {
|
|
|
646
655
|
: '';
|
|
647
656
|
query = `MERGE (n:${t} {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.isExported = ${!!properties.isExported}, n.content = ${escapeValue(properties.content || '')}${descPart}`;
|
|
648
657
|
}
|
|
658
|
+
else if (label === 'Property') {
|
|
659
|
+
const descPart = properties.description
|
|
660
|
+
? `, n.description = ${escapeValue(properties.description)}`
|
|
661
|
+
: '';
|
|
662
|
+
query = `MERGE (n:${t} {id: ${escapeValue(properties.id)}}) SET n.name = ${escapeValue(properties.name)}, n.filePath = ${escapeValue(properties.filePath)}, n.startLine = ${properties.startLine || 0}, n.endLine = ${properties.endLine || 0}, n.content = ${escapeValue(properties.content || '')}${descPart}, n.declaredType = ${escapeValue(properties.declaredType || '')}`;
|
|
663
|
+
}
|
|
649
664
|
else {
|
|
650
665
|
const descPart = properties.description
|
|
651
666
|
? `, n.description = ${escapeValue(properties.description)}`
|
|
@@ -32,7 +32,7 @@ export declare const TYPE_ALIAS_SCHEMA: string;
|
|
|
32
32
|
export declare const CONST_SCHEMA: string;
|
|
33
33
|
export declare const STATIC_SCHEMA: string;
|
|
34
34
|
export declare const VARIABLE_SCHEMA: string;
|
|
35
|
-
export declare const PROPERTY_SCHEMA
|
|
35
|
+
export declare const PROPERTY_SCHEMA = "\nCREATE NODE TABLE `Property` (\n id STRING,\n name STRING,\n filePath STRING,\n startLine INT64,\n endLine INT64,\n content STRING,\n description STRING,\n declaredType STRING,\n PRIMARY KEY (id)\n)";
|
|
36
36
|
export declare const RECORD_SCHEMA: string;
|
|
37
37
|
export declare const DELEGATE_SCHEMA: string;
|
|
38
38
|
export declare const ANNOTATION_SCHEMA: string;
|
package/dist/core/lbug/schema.js
CHANGED
|
@@ -150,7 +150,18 @@ export const TYPE_ALIAS_SCHEMA = CODE_ELEMENT_BASE('TypeAlias');
|
|
|
150
150
|
export const CONST_SCHEMA = CODE_ELEMENT_BASE('Const');
|
|
151
151
|
export const STATIC_SCHEMA = CODE_ELEMENT_BASE('Static');
|
|
152
152
|
export const VARIABLE_SCHEMA = CODE_ELEMENT_BASE('Variable');
|
|
153
|
-
export const PROPERTY_SCHEMA =
|
|
153
|
+
export const PROPERTY_SCHEMA = `
|
|
154
|
+
CREATE NODE TABLE \`Property\` (
|
|
155
|
+
id STRING,
|
|
156
|
+
name STRING,
|
|
157
|
+
filePath STRING,
|
|
158
|
+
startLine INT64,
|
|
159
|
+
endLine INT64,
|
|
160
|
+
content STRING,
|
|
161
|
+
description STRING,
|
|
162
|
+
declaredType STRING,
|
|
163
|
+
PRIMARY KEY (id)
|
|
164
|
+
)`;
|
|
154
165
|
export const RECORD_SCHEMA = CODE_ELEMENT_BASE('Record');
|
|
155
166
|
export const DELEGATE_SCHEMA = CODE_ELEMENT_BASE('Delegate');
|
|
156
167
|
export const ANNOTATION_SCHEMA = CODE_ELEMENT_BASE('Annotation');
|
|
@@ -36,6 +36,22 @@ export declare function resolveLLMConfig(overrides?: Partial<LLMConfig>): Promis
|
|
|
36
36
|
* Estimate token count from text (rough heuristic: ~4 chars per token).
|
|
37
37
|
*/
|
|
38
38
|
export declare function estimateTokens(text: string): number;
|
|
39
|
+
/**
|
|
40
|
+
* Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
|
|
41
|
+
* endpoint (CWE-918 / CodeQL js/http-to-file-access).
|
|
42
|
+
*
|
|
43
|
+
* Allowed:
|
|
44
|
+
* - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
|
|
45
|
+
* - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
|
|
46
|
+
*
|
|
47
|
+
* Rejected:
|
|
48
|
+
* - file://, data:, javascript:, and any other non-HTTP scheme
|
|
49
|
+
* - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
|
|
50
|
+
*
|
|
51
|
+
* Throws with a descriptive message on validation failure so callers surface a
|
|
52
|
+
* clear error rather than an opaque network error.
|
|
53
|
+
*/
|
|
54
|
+
export declare function validateLLMBaseUrl(baseUrl: string): void;
|
|
39
55
|
/**
|
|
40
56
|
* Returns true if the given base URL is an Azure OpenAI endpoint.
|
|
41
57
|
* Uses proper hostname matching to avoid spoofed URLs like
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { logger } from '../logger.js';
|
|
2
|
+
import { CircuitOpenError, ResilientFetchExhaustedError, resilientFetch } from '../../_shared/index.js';
|
|
2
3
|
/**
|
|
3
4
|
* Resolve LLM configuration from env vars, saved config, and optional overrides.
|
|
4
5
|
* Priority: overrides (CLI flags) > env vars > ~/.gitnexus/config.json > error
|
|
@@ -37,6 +38,45 @@ export async function resolveLLMConfig(overrides) {
|
|
|
37
38
|
export function estimateTokens(text) {
|
|
38
39
|
return Math.ceil(text.length / 4);
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
|
|
43
|
+
* endpoint (CWE-918 / CodeQL js/http-to-file-access).
|
|
44
|
+
*
|
|
45
|
+
* Allowed:
|
|
46
|
+
* - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
|
|
47
|
+
* - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
|
|
48
|
+
*
|
|
49
|
+
* Rejected:
|
|
50
|
+
* - file://, data:, javascript:, and any other non-HTTP scheme
|
|
51
|
+
* - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
|
|
52
|
+
*
|
|
53
|
+
* Throws with a descriptive message on validation failure so callers surface a
|
|
54
|
+
* clear error rather than an opaque network error.
|
|
55
|
+
*/
|
|
56
|
+
export function validateLLMBaseUrl(baseUrl) {
|
|
57
|
+
let parsed;
|
|
58
|
+
try {
|
|
59
|
+
parsed = new URL(baseUrl);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Do not include the raw input in the message — it may contain credentials.
|
|
63
|
+
throw new Error('Invalid LLM base URL: must be a well-formed http:// or https:// URL');
|
|
64
|
+
}
|
|
65
|
+
if (!['https:', 'http:'].includes(parsed.protocol)) {
|
|
66
|
+
// Use parsed.protocol only (scheme), not the full URL, to avoid leaking credentials.
|
|
67
|
+
throw new Error(`LLM base URL must use http:// or https:// (got ${parsed.protocol})`);
|
|
68
|
+
}
|
|
69
|
+
if (parsed.protocol === 'http:') {
|
|
70
|
+
// Node's URL parser preserves IPv6 brackets in hostname (e.g. "[::1]"),
|
|
71
|
+
// so strip them before comparing to bare address literals.
|
|
72
|
+
const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
|
73
|
+
if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1') {
|
|
74
|
+
// Use parsed.origin (scheme+host+port, no credentials) instead of the full URL.
|
|
75
|
+
throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1. ` +
|
|
76
|
+
`Use https:// for remote endpoints (got ${parsed.origin})`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
40
80
|
/**
|
|
41
81
|
* Returns true if the given base URL is an Azure OpenAI endpoint.
|
|
42
82
|
* Uses proper hostname matching to avoid spoofed URLs like
|
|
@@ -78,6 +118,8 @@ export function buildRequestUrl(baseUrl, apiVersion) {
|
|
|
78
118
|
* Retries up to 3 times on transient failures (429, 5xx, network errors).
|
|
79
119
|
*/
|
|
80
120
|
export async function callLLM(prompt, config, systemPrompt, options) {
|
|
121
|
+
// Validate base URL before any fetch (CodeQL js/http-to-file-access)
|
|
122
|
+
validateLLMBaseUrl(config.baseUrl);
|
|
81
123
|
const messages = [];
|
|
82
124
|
if (systemPrompt) {
|
|
83
125
|
messages.push({ role: 'system', content: systemPrompt });
|
|
@@ -110,69 +152,68 @@ export async function callLLM(prompt, config, systemPrompt, options) {
|
|
|
110
152
|
const authHeaders = azure
|
|
111
153
|
? { 'api-key': config.apiKey }
|
|
112
154
|
: { Authorization: `Bearer ${config.apiKey}` };
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// Server error — retry with backoff
|
|
142
|
-
if (response.status >= 500 && attempt < MAX_RETRIES - 1) {
|
|
143
|
-
await sleep((attempt + 1) * 2000);
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
throw new Error(`LLM API error (${response.status}): ${errorText.slice(0, 500)}`);
|
|
147
|
-
}
|
|
148
|
-
// Streaming path
|
|
149
|
-
if (useStream && response.body) {
|
|
150
|
-
return await readSSEStream(response.body, options.onChunk);
|
|
151
|
-
}
|
|
152
|
-
// Non-streaming path
|
|
153
|
-
const json = (await response.json());
|
|
154
|
-
const choice = json.choices?.[0];
|
|
155
|
-
if (!choice?.message?.content) {
|
|
156
|
-
throw new Error('LLM returned empty response');
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
content: choice.message.content,
|
|
160
|
-
promptTokens: json.usage?.prompt_tokens,
|
|
161
|
-
completionTokens: json.usage?.completion_tokens,
|
|
162
|
-
};
|
|
155
|
+
// Network resilience (bounded retries with exponential-backoff jitter,
|
|
156
|
+
// 5xx + 429 + Retry-After handling, in-process circuit breaker on the
|
|
157
|
+
// LLM endpoint) is delegated to resilientFetch. Provider-specific
|
|
158
|
+
// error parsing (Azure content filter, empty-content checks) stays
|
|
159
|
+
// here since it requires response-body inspection.
|
|
160
|
+
let response;
|
|
161
|
+
try {
|
|
162
|
+
response = await resilientFetch(url, {
|
|
163
|
+
method: 'POST',
|
|
164
|
+
headers: {
|
|
165
|
+
'Content-Type': 'application/json',
|
|
166
|
+
...authHeaders,
|
|
167
|
+
},
|
|
168
|
+
body: JSON.stringify(body),
|
|
169
|
+
// Per-attempt timeout. Without this each retry can hang
|
|
170
|
+
// indefinitely on a frozen TCP connection — the per-call
|
|
171
|
+
// signal is the only timeout `resilientFetch` honors;
|
|
172
|
+
// `capDelayMs` only bounds the *backoff* between attempts.
|
|
173
|
+
// 60s matches typical LLM completion budgets.
|
|
174
|
+
signal: AbortSignal.timeout(60_000),
|
|
175
|
+
}, {
|
|
176
|
+
breakerKey: `wiki-llm-${new URL(url).host}`,
|
|
177
|
+
retry: { maxAttempts: 3, baseDelayMs: 2_000, capDelayMs: 30_000 },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
if (err instanceof CircuitOpenError) {
|
|
182
|
+
throw new Error(`LLM endpoint circuit open: retry in ${Math.ceil(err.retryAfterMs / 1000)}s. ${err.message}`);
|
|
163
183
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
184
|
+
if (err instanceof ResilientFetchExhaustedError) {
|
|
185
|
+
const errorText = await err.response.text().catch(() => 'unknown error');
|
|
186
|
+
throw new Error(`LLM API error (${err.response.status} after retries): ${errorText.slice(0, 500)}`);
|
|
187
|
+
}
|
|
188
|
+
throw err;
|
|
189
|
+
}
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
const errorText = await response.text().catch(() => 'unknown error');
|
|
192
|
+
// Azure content filter — surface a clear message instead of a generic API error.
|
|
193
|
+
if (azure &&
|
|
194
|
+
response.status === 400 &&
|
|
195
|
+
(errorText.includes('content_filter') || errorText.includes('ResponsibleAIPolicyViolation'))) {
|
|
196
|
+
throw new Error(`Azure content filter blocked this request. The prompt triggered content policy. Details: ${errorText.slice(0, 300)}`);
|
|
173
197
|
}
|
|
198
|
+
// Any other non-OK response here is a terminal 4xx — resilientFetch
|
|
199
|
+
// already retried 5xx/429 to exhaustion and would have thrown above.
|
|
200
|
+
throw new Error(`LLM API error (${response.status}): ${errorText.slice(0, 500)}`);
|
|
201
|
+
}
|
|
202
|
+
// Streaming path
|
|
203
|
+
if (useStream && response.body) {
|
|
204
|
+
return await readSSEStream(response.body, options.onChunk);
|
|
174
205
|
}
|
|
175
|
-
|
|
206
|
+
// Non-streaming path
|
|
207
|
+
const json = (await response.json());
|
|
208
|
+
const choice = json.choices?.[0];
|
|
209
|
+
if (!choice?.message?.content) {
|
|
210
|
+
throw new Error('LLM returned empty response');
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
content: choice.message.content,
|
|
214
|
+
promptTokens: json.usage?.prompt_tokens,
|
|
215
|
+
completionTokens: json.usage?.completion_tokens,
|
|
216
|
+
};
|
|
176
217
|
}
|
|
177
218
|
/**
|
|
178
219
|
* Read an SSE stream from an OpenAI-compatible streaming response.
|
|
@@ -224,6 +265,3 @@ async function readSSEStream(body, onChunk) {
|
|
|
224
265
|
}
|
|
225
266
|
return { content };
|
|
226
267
|
}
|
|
227
|
-
function sleep(ms) {
|
|
228
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
229
|
-
}
|
|
@@ -1443,10 +1443,11 @@ export class LocalBackend {
|
|
|
1443
1443
|
// Categorized incoming refs
|
|
1444
1444
|
const incomingRows = await executeParameterized(repo.id, `
|
|
1445
1445
|
MATCH (caller)-[r:CodeRelation]->(n {id: $symId})
|
|
1446
|
-
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1446
|
+
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1447
1447
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1448
1448
|
LIMIT 30
|
|
1449
1449
|
`, { symId });
|
|
1450
|
+
let typedPropertyRows = [];
|
|
1450
1451
|
// Fix #480: Class/Interface nodes have no direct CALLS/IMPORTS edges —
|
|
1451
1452
|
// those point to Constructor and File nodes respectively. Fetch those
|
|
1452
1453
|
// extra incoming refs and merge them in so context() shows real callers.
|
|
@@ -1476,13 +1477,13 @@ export class LocalBackend {
|
|
|
1476
1477
|
}
|
|
1477
1478
|
if (isClassLike) {
|
|
1478
1479
|
try {
|
|
1479
|
-
// Run
|
|
1480
|
-
const [ctorIncoming, fileIncoming] = await Promise.all([
|
|
1480
|
+
// Run incoming-ref queries in parallel — they are independent.
|
|
1481
|
+
const [ctorIncoming, fileIncoming, typedPropertyIncoming, typedProperties] = await Promise.all([
|
|
1481
1482
|
executeParameterized(repo.id, `
|
|
1482
1483
|
MATCH (n)-[hm:CodeRelation]->(ctor:Constructor)
|
|
1483
1484
|
WHERE n.id = $symId AND hm.type = 'HAS_METHOD'
|
|
1484
1485
|
MATCH (caller)-[r:CodeRelation]->(ctor)
|
|
1485
|
-
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'ACCESSES']
|
|
1486
|
+
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'ACCESSES']
|
|
1486
1487
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1487
1488
|
LIMIT 30
|
|
1488
1489
|
`, { symId }),
|
|
@@ -1494,12 +1495,40 @@ export class LocalBackend {
|
|
|
1494
1495
|
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1495
1496
|
LIMIT 30
|
|
1496
1497
|
`, { symId }),
|
|
1498
|
+
executeParameterized(repo.id, `
|
|
1499
|
+
MATCH (p:\`Property\`)
|
|
1500
|
+
WHERE p.declaredType = $name
|
|
1501
|
+
OR p.declaredType STARTS WITH $genericPrefix
|
|
1502
|
+
OR p.declaredType CONTAINS $genericArg
|
|
1503
|
+
MATCH (caller)-[r:CodeRelation]->(p)
|
|
1504
|
+
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'ACCESSES']
|
|
1505
|
+
RETURN r.type AS relType, caller.id AS uid, caller.name AS name, caller.filePath AS filePath, labels(caller)[0] AS kind
|
|
1506
|
+
LIMIT 30
|
|
1507
|
+
`, {
|
|
1508
|
+
name: sym.name,
|
|
1509
|
+
genericPrefix: `${sym.name}<`,
|
|
1510
|
+
genericArg: `<${sym.name}>`,
|
|
1511
|
+
}),
|
|
1512
|
+
executeParameterized(repo.id, `
|
|
1513
|
+
MATCH (p:\`Property\`)
|
|
1514
|
+
WHERE p.declaredType = $name
|
|
1515
|
+
OR p.declaredType STARTS WITH $genericPrefix
|
|
1516
|
+
OR p.declaredType CONTAINS $genericArg
|
|
1517
|
+
RETURN p.id AS uid, p.name AS name, p.filePath AS filePath, labels(p)[0] AS kind,
|
|
1518
|
+
p.declaredType AS declaredType
|
|
1519
|
+
LIMIT 30
|
|
1520
|
+
`, {
|
|
1521
|
+
name: sym.name,
|
|
1522
|
+
genericPrefix: `${sym.name}<`,
|
|
1523
|
+
genericArg: `<${sym.name}>`,
|
|
1524
|
+
}),
|
|
1497
1525
|
]);
|
|
1526
|
+
typedPropertyRows = typedProperties;
|
|
1498
1527
|
// Deduplicate by (relType, uid) — a caller can have multiple relation
|
|
1499
1528
|
// types to the same target (e.g. both IMPORTS and CALLS), and each
|
|
1500
1529
|
// must be preserved so every category appears in the output.
|
|
1501
1530
|
const seenKeys = new Set(incomingRows.map((r) => `${r.relType || r[0]}:${r.uid || r[1]}`));
|
|
1502
|
-
for (const r of [...ctorIncoming, ...fileIncoming]) {
|
|
1531
|
+
for (const r of [...ctorIncoming, ...fileIncoming, ...typedPropertyIncoming]) {
|
|
1503
1532
|
const key = `${r.relType || r[0]}:${r.uid || r[1]}`;
|
|
1504
1533
|
if (!seenKeys.has(key)) {
|
|
1505
1534
|
seenKeys.add(key);
|
|
@@ -1514,7 +1543,7 @@ export class LocalBackend {
|
|
|
1514
1543
|
// Categorized outgoing refs
|
|
1515
1544
|
const outgoingRows = await executeParameterized(repo.id, `
|
|
1516
1545
|
MATCH (n {id: $symId})-[r:CodeRelation]->(target)
|
|
1517
|
-
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1546
|
+
WHERE r.type IN ['CALLS', 'IMPORTS', 'EXTENDS', 'IMPLEMENTS', 'USES', 'HAS_METHOD', 'HAS_PROPERTY', 'METHOD_OVERRIDES', 'OVERRIDES', 'METHOD_IMPLEMENTS', 'ACCESSES']
|
|
1518
1547
|
RETURN r.type AS relType, target.id AS uid, target.name AS name, target.filePath AS filePath, labels(target)[0] AS kind
|
|
1519
1548
|
LIMIT 30
|
|
1520
1549
|
`, { symId });
|
|
@@ -1593,6 +1622,17 @@ export class LocalBackend {
|
|
|
1593
1622
|
},
|
|
1594
1623
|
incoming: categorize(incomingRows),
|
|
1595
1624
|
outgoing: categorize(outgoingRows),
|
|
1625
|
+
...(typedPropertyRows.length > 0
|
|
1626
|
+
? {
|
|
1627
|
+
typed_properties: typedPropertyRows.map((r) => ({
|
|
1628
|
+
uid: r.uid || r[0],
|
|
1629
|
+
name: r.name || r[1],
|
|
1630
|
+
filePath: r.filePath || r[2],
|
|
1631
|
+
kind: r.kind || r[3],
|
|
1632
|
+
declaredType: r.declaredType || r[4],
|
|
1633
|
+
})),
|
|
1634
|
+
}
|
|
1635
|
+
: {}),
|
|
1596
1636
|
processes: processRows.map((r) => ({
|
|
1597
1637
|
id: r.pid || r[0],
|
|
1598
1638
|
name: r.label || r[1],
|
|
@@ -2024,6 +2064,7 @@ export class LocalBackend {
|
|
|
2024
2064
|
const maxDepth = params.maxDepth || 3;
|
|
2025
2065
|
// Map legacy relation type names before filtering (backward compat for OVERRIDES → METHOD_OVERRIDES)
|
|
2026
2066
|
const mappedRelTypes = params.relationTypes?.flatMap((t) => t === 'OVERRIDES' ? ['OVERRIDES', 'METHOD_OVERRIDES'] : [t]);
|
|
2067
|
+
const hasExplicitRelationTypes = mappedRelTypes !== undefined && mappedRelTypes.length > 0;
|
|
2027
2068
|
const rawRelTypes = mappedRelTypes && mappedRelTypes.length > 0
|
|
2028
2069
|
? mappedRelTypes.filter((t) => VALID_RELATION_TYPES.has(t))
|
|
2029
2070
|
: [
|
|
@@ -2031,6 +2072,7 @@ export class LocalBackend {
|
|
|
2031
2072
|
'IMPORTS',
|
|
2032
2073
|
'EXTENDS',
|
|
2033
2074
|
'IMPLEMENTS',
|
|
2075
|
+
'USES',
|
|
2034
2076
|
'METHOD_OVERRIDES',
|
|
2035
2077
|
'OVERRIDES',
|
|
2036
2078
|
'METHOD_IMPLEMENTS',
|
|
@@ -2042,6 +2084,7 @@ export class LocalBackend {
|
|
|
2042
2084
|
'IMPORTS',
|
|
2043
2085
|
'EXTENDS',
|
|
2044
2086
|
'IMPLEMENTS',
|
|
2087
|
+
'USES',
|
|
2045
2088
|
'METHOD_OVERRIDES',
|
|
2046
2089
|
'OVERRIDES',
|
|
2047
2090
|
'METHOD_IMPLEMENTS',
|
|
@@ -2092,9 +2135,14 @@ export class LocalBackend {
|
|
|
2092
2135
|
filePath: outcome.symbol.filePath,
|
|
2093
2136
|
};
|
|
2094
2137
|
const symType = outcome.resolvedLabel || outcome.symbol.type || '';
|
|
2138
|
+
const effectiveRelationTypes = (symType === 'Class' || symType === 'Interface') &&
|
|
2139
|
+
!hasExplicitRelationTypes &&
|
|
2140
|
+
!relationTypes.includes('ACCESSES')
|
|
2141
|
+
? [...relationTypes, 'ACCESSES']
|
|
2142
|
+
: relationTypes;
|
|
2095
2143
|
return this._runImpactBFS(repo, sym, symType, direction, {
|
|
2096
2144
|
maxDepth,
|
|
2097
|
-
relationTypes,
|
|
2145
|
+
relationTypes: effectiveRelationTypes,
|
|
2098
2146
|
includeTests,
|
|
2099
2147
|
minConfidence,
|
|
2100
2148
|
});
|
|
@@ -2149,6 +2197,24 @@ export class LocalBackend {
|
|
|
2149
2197
|
frontier.push(rid);
|
|
2150
2198
|
}
|
|
2151
2199
|
}
|
|
2200
|
+
const typedPropertyRows = await executeParameterized(repo.id, `
|
|
2201
|
+
MATCH (p:\`Property\`)
|
|
2202
|
+
WHERE p.declaredType = $name
|
|
2203
|
+
OR p.declaredType STARTS WITH $genericPrefix
|
|
2204
|
+
OR p.declaredType CONTAINS $genericArg
|
|
2205
|
+
RETURN p.id AS id, p.name AS name, labels(p)[0] AS type, p.filePath AS filePath
|
|
2206
|
+
`, {
|
|
2207
|
+
name: sym.name,
|
|
2208
|
+
genericPrefix: `${sym.name}<`,
|
|
2209
|
+
genericArg: `<${sym.name}>`,
|
|
2210
|
+
});
|
|
2211
|
+
for (const r of typedPropertyRows) {
|
|
2212
|
+
const rid = r.id || r[0];
|
|
2213
|
+
if (rid && !visited.has(rid)) {
|
|
2214
|
+
visited.add(rid);
|
|
2215
|
+
frontier.push(rid);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2152
2218
|
}
|
|
2153
2219
|
catch (e) {
|
|
2154
2220
|
logQueryError('impact:class-node-expansion', e);
|
package/dist/server/api.js
CHANGED
|
@@ -638,7 +638,11 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
638
638
|
(job.repoPath && path.basename(job.repoPath).toLowerCase() === lower);
|
|
639
639
|
if (isMatch && ['queued', 'cloning', 'analyzing'].includes(job.status)) {
|
|
640
640
|
if (process.env.DEBUG) {
|
|
641
|
-
|
|
641
|
+
// Sanitize user-controlled values to prevent log injection (CodeQL js/log-injection).
|
|
642
|
+
logger.debug({
|
|
643
|
+
jobId: String(job.id).replace(/[\r\n]/g, ' '),
|
|
644
|
+
repoName: String(normalizedName).replace(/[\r\n]/g, ' '),
|
|
645
|
+
}, '[debug] resolveRepo waiting for active job');
|
|
642
646
|
}
|
|
643
647
|
for (let wait = 0; wait < HOLD_QUEUE_TIMEOUT_SECS; wait++) {
|
|
644
648
|
if (clientGone)
|
|
@@ -662,7 +666,8 @@ export const createServer = async (port, host = '127.0.0.1') => {
|
|
|
662
666
|
// (e.g. registry file not yet flushed after clone completes).
|
|
663
667
|
if (!found && normalizedName && !isRetry) {
|
|
664
668
|
if (process.env.DEBUG) {
|
|
665
|
-
|
|
669
|
+
// Sanitize user-controlled values to prevent log injection (CodeQL js/log-injection).
|
|
670
|
+
logger.debug({ repoName: String(normalizedName).replace(/[\r\n]/g, ' ') }, '[debug] resolveRepo 404, triggering deep init');
|
|
666
671
|
}
|
|
667
672
|
await backend.init();
|
|
668
673
|
return await resolveRepo(normalizedName, true, req);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitnexus",
|
|
3
|
-
"version": "1.6.4
|
|
3
|
+
"version": "1.6.4",
|
|
4
4
|
"description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
|
|
5
5
|
"author": "Abhigyan Patwari",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
@@ -116,6 +116,6 @@
|
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
"engines": {
|
|
119
|
-
"node": ">=
|
|
119
|
+
"node": ">=22.0.0"
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -34,16 +34,17 @@ CFLAGS_C_Debug :=
|
|
|
34
34
|
CFLAGS_CC_Debug := \
|
|
35
35
|
-fno-rtti \
|
|
36
36
|
-fno-exceptions \
|
|
37
|
+
-fno-strict-aliasing \
|
|
37
38
|
-std=gnu++17
|
|
38
39
|
|
|
39
40
|
INCS_Debug := \
|
|
40
|
-
-I/home/runner/.cache/node-gyp/
|
|
41
|
-
-I/home/runner/.cache/node-gyp/
|
|
42
|
-
-I/home/runner/.cache/node-gyp/
|
|
43
|
-
-I/home/runner/.cache/node-gyp/
|
|
44
|
-
-I/home/runner/.cache/node-gyp/
|
|
45
|
-
-I/home/runner/.cache/node-gyp/
|
|
46
|
-
-I/home/runner/.cache/node-gyp/
|
|
41
|
+
-I/home/runner/.cache/node-gyp/22.22.2/include/node \
|
|
42
|
+
-I/home/runner/.cache/node-gyp/22.22.2/src \
|
|
43
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/config \
|
|
44
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/openssl/include \
|
|
45
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/uv/include \
|
|
46
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/zlib \
|
|
47
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/v8/include
|
|
47
48
|
|
|
48
49
|
DEFS_Release := \
|
|
49
50
|
'-DNODE_GYP_MODULE_NAME=node_addon_api' \
|
|
@@ -75,16 +76,17 @@ CFLAGS_C_Release :=
|
|
|
75
76
|
CFLAGS_CC_Release := \
|
|
76
77
|
-fno-rtti \
|
|
77
78
|
-fno-exceptions \
|
|
79
|
+
-fno-strict-aliasing \
|
|
78
80
|
-std=gnu++17
|
|
79
81
|
|
|
80
82
|
INCS_Release := \
|
|
81
|
-
-I/home/runner/.cache/node-gyp/
|
|
82
|
-
-I/home/runner/.cache/node-gyp/
|
|
83
|
-
-I/home/runner/.cache/node-gyp/
|
|
84
|
-
-I/home/runner/.cache/node-gyp/
|
|
85
|
-
-I/home/runner/.cache/node-gyp/
|
|
86
|
-
-I/home/runner/.cache/node-gyp/
|
|
87
|
-
-I/home/runner/.cache/node-gyp/
|
|
83
|
+
-I/home/runner/.cache/node-gyp/22.22.2/include/node \
|
|
84
|
+
-I/home/runner/.cache/node-gyp/22.22.2/src \
|
|
85
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/config \
|
|
86
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/openssl/include \
|
|
87
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/uv/include \
|
|
88
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/zlib \
|
|
89
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/v8/include
|
|
88
90
|
|
|
89
91
|
OBJS :=
|
|
90
92
|
|
|
@@ -34,16 +34,17 @@ CFLAGS_C_Debug :=
|
|
|
34
34
|
CFLAGS_CC_Debug := \
|
|
35
35
|
-fno-rtti \
|
|
36
36
|
-fno-exceptions \
|
|
37
|
+
-fno-strict-aliasing \
|
|
37
38
|
-std=gnu++17
|
|
38
39
|
|
|
39
40
|
INCS_Debug := \
|
|
40
|
-
-I/home/runner/.cache/node-gyp/
|
|
41
|
-
-I/home/runner/.cache/node-gyp/
|
|
42
|
-
-I/home/runner/.cache/node-gyp/
|
|
43
|
-
-I/home/runner/.cache/node-gyp/
|
|
44
|
-
-I/home/runner/.cache/node-gyp/
|
|
45
|
-
-I/home/runner/.cache/node-gyp/
|
|
46
|
-
-I/home/runner/.cache/node-gyp/
|
|
41
|
+
-I/home/runner/.cache/node-gyp/22.22.2/include/node \
|
|
42
|
+
-I/home/runner/.cache/node-gyp/22.22.2/src \
|
|
43
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/config \
|
|
44
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/openssl/include \
|
|
45
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/uv/include \
|
|
46
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/zlib \
|
|
47
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/v8/include
|
|
47
48
|
|
|
48
49
|
DEFS_Release := \
|
|
49
50
|
'-DNODE_GYP_MODULE_NAME=node_addon_api_except' \
|
|
@@ -75,16 +76,17 @@ CFLAGS_C_Release :=
|
|
|
75
76
|
CFLAGS_CC_Release := \
|
|
76
77
|
-fno-rtti \
|
|
77
78
|
-fno-exceptions \
|
|
79
|
+
-fno-strict-aliasing \
|
|
78
80
|
-std=gnu++17
|
|
79
81
|
|
|
80
82
|
INCS_Release := \
|
|
81
|
-
-I/home/runner/.cache/node-gyp/
|
|
82
|
-
-I/home/runner/.cache/node-gyp/
|
|
83
|
-
-I/home/runner/.cache/node-gyp/
|
|
84
|
-
-I/home/runner/.cache/node-gyp/
|
|
85
|
-
-I/home/runner/.cache/node-gyp/
|
|
86
|
-
-I/home/runner/.cache/node-gyp/
|
|
87
|
-
-I/home/runner/.cache/node-gyp/
|
|
83
|
+
-I/home/runner/.cache/node-gyp/22.22.2/include/node \
|
|
84
|
+
-I/home/runner/.cache/node-gyp/22.22.2/src \
|
|
85
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/config \
|
|
86
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/openssl/openssl/include \
|
|
87
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/uv/include \
|
|
88
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/zlib \
|
|
89
|
+
-I/home/runner/.cache/node-gyp/22.22.2/deps/v8/include
|
|
88
90
|
|
|
89
91
|
OBJS :=
|
|
90
92
|
|