gitnexus 1.4.0 → 1.4.1
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/README.md +194 -214
- package/dist/cli/ai-context.d.ts +1 -2
- package/dist/cli/ai-context.js +90 -117
- package/dist/cli/analyze.d.ts +0 -2
- package/dist/cli/analyze.js +2 -20
- package/dist/cli/index.js +25 -17
- package/dist/cli/setup.js +19 -17
- package/dist/core/augmentation/engine.js +20 -20
- package/dist/core/embeddings/embedding-pipeline.js +26 -26
- package/dist/core/graph/types.d.ts +2 -5
- package/dist/core/ingestion/ast-cache.js +2 -3
- package/dist/core/ingestion/call-processor.d.ts +5 -5
- package/dist/core/ingestion/call-processor.js +258 -173
- package/dist/core/ingestion/cluster-enricher.js +16 -16
- package/dist/core/ingestion/entry-point-scoring.d.ts +1 -2
- package/dist/core/ingestion/entry-point-scoring.js +22 -81
- package/dist/core/ingestion/framework-detection.d.ts +1 -5
- package/dist/core/ingestion/framework-detection.js +8 -39
- package/dist/core/ingestion/heritage-processor.d.ts +4 -13
- package/dist/core/ingestion/heritage-processor.js +28 -92
- package/dist/core/ingestion/import-processor.d.ts +19 -17
- package/dist/core/ingestion/import-processor.js +695 -170
- package/dist/core/ingestion/parsing-processor.d.ts +10 -1
- package/dist/core/ingestion/parsing-processor.js +177 -41
- package/dist/core/ingestion/pipeline.js +26 -49
- package/dist/core/ingestion/process-processor.js +1 -2
- package/dist/core/ingestion/symbol-table.d.ts +1 -12
- package/dist/core/ingestion/symbol-table.js +12 -19
- package/dist/core/ingestion/tree-sitter-queries.d.ts +11 -11
- package/dist/core/ingestion/tree-sitter-queries.js +485 -590
- package/dist/core/ingestion/utils.d.ts +0 -67
- package/dist/core/ingestion/utils.js +9 -692
- package/dist/core/ingestion/workers/parse-worker.d.ts +3 -20
- package/dist/core/ingestion/workers/parse-worker.js +345 -84
- package/dist/core/ingestion/workers/worker-pool.js +0 -8
- package/dist/core/kuzu/csv-generator.js +3 -19
- package/dist/core/kuzu/kuzu-adapter.js +19 -14
- package/dist/core/kuzu/schema.d.ts +3 -3
- package/dist/core/kuzu/schema.js +288 -303
- package/dist/core/search/bm25-index.js +6 -7
- package/dist/core/search/hybrid-search.js +3 -3
- package/dist/core/wiki/diagrams.d.ts +27 -0
- package/dist/core/wiki/diagrams.js +163 -0
- package/dist/core/wiki/generator.d.ts +50 -2
- package/dist/core/wiki/generator.js +548 -49
- package/dist/core/wiki/graph-queries.d.ts +42 -0
- package/dist/core/wiki/graph-queries.js +276 -97
- package/dist/core/wiki/html-viewer.js +192 -192
- package/dist/core/wiki/llm-client.js +73 -11
- package/dist/core/wiki/prompts.d.ts +52 -8
- package/dist/core/wiki/prompts.js +200 -86
- package/dist/mcp/core/kuzu-adapter.d.ts +3 -1
- package/dist/mcp/core/kuzu-adapter.js +44 -13
- package/dist/mcp/local/local-backend.js +128 -128
- package/dist/mcp/resources.js +42 -42
- package/dist/mcp/server.js +19 -18
- package/dist/mcp/tools.js +104 -103
- package/hooks/claude/gitnexus-hook.cjs +155 -238
- package/hooks/claude/pre-tool-use.sh +79 -79
- package/hooks/claude/session-start.sh +42 -42
- package/package.json +96 -96
- package/scripts/patch-tree-sitter-swift.cjs +74 -74
- package/skills/gitnexus-cli.md +82 -82
- package/skills/gitnexus-debugging.md +89 -89
- package/skills/gitnexus-exploring.md +78 -78
- package/skills/gitnexus-guide.md +64 -64
- package/skills/gitnexus-impact-analysis.md +97 -97
- package/skills/gitnexus-pr-review.md +163 -163
- package/skills/gitnexus-refactoring.md +121 -121
- package/vendor/leiden/index.cjs +355 -355
- package/vendor/leiden/utils.cjs +392 -392
- package/dist/cli/lazy-action.d.ts +0 -6
- package/dist/cli/lazy-action.js +0 -18
- package/dist/cli/skill-gen.d.ts +0 -26
- package/dist/cli/skill-gen.js +0 -549
- package/dist/core/ingestion/constants.d.ts +0 -16
- package/dist/core/ingestion/constants.js +0 -16
- package/dist/core/ingestion/export-detection.d.ts +0 -18
- package/dist/core/ingestion/export-detection.js +0 -230
- package/dist/core/ingestion/language-config.d.ts +0 -46
- package/dist/core/ingestion/language-config.js +0 -167
- package/dist/core/ingestion/mro-processor.d.ts +0 -45
- package/dist/core/ingestion/mro-processor.js +0 -369
- package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
- package/dist/core/ingestion/named-binding-extraction.js +0 -363
- package/dist/core/ingestion/resolvers/csharp.d.ts +0 -22
- package/dist/core/ingestion/resolvers/csharp.js +0 -109
- package/dist/core/ingestion/resolvers/go.d.ts +0 -19
- package/dist/core/ingestion/resolvers/go.js +0 -42
- package/dist/core/ingestion/resolvers/index.d.ts +0 -16
- package/dist/core/ingestion/resolvers/index.js +0 -11
- package/dist/core/ingestion/resolvers/jvm.d.ts +0 -23
- package/dist/core/ingestion/resolvers/jvm.js +0 -87
- package/dist/core/ingestion/resolvers/php.d.ts +0 -15
- package/dist/core/ingestion/resolvers/php.js +0 -35
- package/dist/core/ingestion/resolvers/rust.d.ts +0 -15
- package/dist/core/ingestion/resolvers/rust.js +0 -73
- package/dist/core/ingestion/resolvers/standard.d.ts +0 -28
- package/dist/core/ingestion/resolvers/standard.js +0 -145
- package/dist/core/ingestion/resolvers/utils.d.ts +0 -33
- package/dist/core/ingestion/resolvers/utils.js +0 -120
- package/dist/core/ingestion/symbol-resolver.d.ts +0 -32
- package/dist/core/ingestion/symbol-resolver.js +0 -83
- package/dist/core/ingestion/type-env.d.ts +0 -27
- package/dist/core/ingestion/type-env.js +0 -86
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/c-cpp.js +0 -60
- package/dist/core/ingestion/type-extractors/csharp.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/csharp.js +0 -89
- package/dist/core/ingestion/type-extractors/go.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/go.js +0 -105
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -21
- package/dist/core/ingestion/type-extractors/index.js +0 -29
- package/dist/core/ingestion/type-extractors/jvm.d.ts +0 -3
- package/dist/core/ingestion/type-extractors/jvm.js +0 -121
- package/dist/core/ingestion/type-extractors/php.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/php.js +0 -31
- package/dist/core/ingestion/type-extractors/python.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/python.js +0 -41
- package/dist/core/ingestion/type-extractors/rust.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/rust.js +0 -39
- package/dist/core/ingestion/type-extractors/shared.d.ts +0 -17
- package/dist/core/ingestion/type-extractors/shared.js +0 -97
- package/dist/core/ingestion/type-extractors/swift.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/swift.js +0 -43
- package/dist/core/ingestion/type-extractors/types.d.ts +0 -14
- package/dist/core/ingestion/type-extractors/types.js +0 -1
- package/dist/core/ingestion/type-extractors/typescript.d.ts +0 -2
- package/dist/core/ingestion/type-extractors/typescript.js +0 -46
- package/dist/mcp/compatible-stdio-transport.d.ts +0 -25
- package/dist/mcp/compatible-stdio-transport.js +0 -200
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { extractSimpleTypeName, extractVarName } from './shared.js';
|
|
2
|
-
// PHP has no local variable type annotations; only params carry types
|
|
3
|
-
const DECLARATION_NODE_TYPES = new Set();
|
|
4
|
-
/** PHP: no typed local variable declarations */
|
|
5
|
-
const extractDeclaration = (_node, _env) => {
|
|
6
|
-
// PHP has no local variable type annotations
|
|
7
|
-
};
|
|
8
|
-
/** PHP: simple_parameter → type $name */
|
|
9
|
-
const extractParameter = (node, env) => {
|
|
10
|
-
let nameNode = null;
|
|
11
|
-
let typeNode = null;
|
|
12
|
-
if (node.type === 'simple_parameter') {
|
|
13
|
-
typeNode = node.childForFieldName('type');
|
|
14
|
-
nameNode = node.childForFieldName('name');
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
18
|
-
typeNode = node.childForFieldName('type');
|
|
19
|
-
}
|
|
20
|
-
if (!nameNode || !typeNode)
|
|
21
|
-
return;
|
|
22
|
-
const varName = extractVarName(nameNode);
|
|
23
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
24
|
-
if (varName && typeName)
|
|
25
|
-
env.set(varName, typeName);
|
|
26
|
-
};
|
|
27
|
-
export const typeConfig = {
|
|
28
|
-
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
29
|
-
extractDeclaration,
|
|
30
|
-
extractParameter,
|
|
31
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { extractSimpleTypeName, extractVarName } from './shared.js';
|
|
2
|
-
const DECLARATION_NODE_TYPES = new Set([
|
|
3
|
-
'assignment',
|
|
4
|
-
]);
|
|
5
|
-
/** Python: x: Foo = ... (PEP 484 annotations) */
|
|
6
|
-
const extractDeclaration = (node, env) => {
|
|
7
|
-
// Python annotated assignment: left : type = value
|
|
8
|
-
// tree-sitter represents this differently based on grammar version
|
|
9
|
-
const left = node.childForFieldName('left');
|
|
10
|
-
const typeNode = node.childForFieldName('type');
|
|
11
|
-
if (!left || !typeNode)
|
|
12
|
-
return;
|
|
13
|
-
const varName = extractVarName(left);
|
|
14
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
15
|
-
if (varName && typeName)
|
|
16
|
-
env.set(varName, typeName);
|
|
17
|
-
};
|
|
18
|
-
/** Python: parameter with type annotation */
|
|
19
|
-
const extractParameter = (node, env) => {
|
|
20
|
-
let nameNode = null;
|
|
21
|
-
let typeNode = null;
|
|
22
|
-
if (node.type === 'parameter') {
|
|
23
|
-
nameNode = node.childForFieldName('name');
|
|
24
|
-
typeNode = node.childForFieldName('type');
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
28
|
-
typeNode = node.childForFieldName('type');
|
|
29
|
-
}
|
|
30
|
-
if (!nameNode || !typeNode)
|
|
31
|
-
return;
|
|
32
|
-
const varName = extractVarName(nameNode);
|
|
33
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
34
|
-
if (varName && typeName)
|
|
35
|
-
env.set(varName, typeName);
|
|
36
|
-
};
|
|
37
|
-
export const typeConfig = {
|
|
38
|
-
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
39
|
-
extractDeclaration,
|
|
40
|
-
extractParameter,
|
|
41
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { extractSimpleTypeName, extractVarName } from './shared.js';
|
|
2
|
-
const DECLARATION_NODE_TYPES = new Set([
|
|
3
|
-
'let_declaration',
|
|
4
|
-
]);
|
|
5
|
-
/** Rust: let x: Foo = ... */
|
|
6
|
-
const extractDeclaration = (node, env) => {
|
|
7
|
-
const pattern = node.childForFieldName('pattern');
|
|
8
|
-
const typeNode = node.childForFieldName('type');
|
|
9
|
-
if (!pattern || !typeNode)
|
|
10
|
-
return;
|
|
11
|
-
const varName = extractVarName(pattern);
|
|
12
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
13
|
-
if (varName && typeName)
|
|
14
|
-
env.set(varName, typeName);
|
|
15
|
-
};
|
|
16
|
-
/** Rust: parameter → pattern: type */
|
|
17
|
-
const extractParameter = (node, env) => {
|
|
18
|
-
let nameNode = null;
|
|
19
|
-
let typeNode = null;
|
|
20
|
-
if (node.type === 'parameter') {
|
|
21
|
-
nameNode = node.childForFieldName('pattern');
|
|
22
|
-
typeNode = node.childForFieldName('type');
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
26
|
-
typeNode = node.childForFieldName('type');
|
|
27
|
-
}
|
|
28
|
-
if (!nameNode || !typeNode)
|
|
29
|
-
return;
|
|
30
|
-
const varName = extractVarName(nameNode);
|
|
31
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
32
|
-
if (varName && typeName)
|
|
33
|
-
env.set(varName, typeName);
|
|
34
|
-
};
|
|
35
|
-
export const typeConfig = {
|
|
36
|
-
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
37
|
-
extractDeclaration,
|
|
38
|
-
extractParameter,
|
|
39
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { SyntaxNode } from '../utils.js';
|
|
2
|
-
/**
|
|
3
|
-
* Extract the simple type name from a type AST node.
|
|
4
|
-
* Handles generic types (e.g., List<User> → List), qualified names
|
|
5
|
-
* (e.g., models.User → User), and nullable types (e.g., User? → User).
|
|
6
|
-
* Returns undefined for complex types (unions, intersections, function types).
|
|
7
|
-
*/
|
|
8
|
-
export declare const extractSimpleTypeName: (typeNode: SyntaxNode) => string | undefined;
|
|
9
|
-
/**
|
|
10
|
-
* Extract variable name from a declarator or pattern node.
|
|
11
|
-
* Returns the simple identifier text, or undefined for destructuring/complex patterns.
|
|
12
|
-
*/
|
|
13
|
-
export declare const extractVarName: (node: SyntaxNode) => string | undefined;
|
|
14
|
-
/** Node types for function/method parameters with type annotations */
|
|
15
|
-
export declare const TYPED_PARAMETER_TYPES: Set<string>;
|
|
16
|
-
/** Find the first named child with the given node type */
|
|
17
|
-
export declare const findChildByType: (node: SyntaxNode, type: string) => SyntaxNode | null;
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract the simple type name from a type AST node.
|
|
3
|
-
* Handles generic types (e.g., List<User> → List), qualified names
|
|
4
|
-
* (e.g., models.User → User), and nullable types (e.g., User? → User).
|
|
5
|
-
* Returns undefined for complex types (unions, intersections, function types).
|
|
6
|
-
*/
|
|
7
|
-
export const extractSimpleTypeName = (typeNode) => {
|
|
8
|
-
// Direct type identifier
|
|
9
|
-
if (typeNode.type === 'type_identifier' || typeNode.type === 'identifier'
|
|
10
|
-
|| typeNode.type === 'simple_identifier') {
|
|
11
|
-
return typeNode.text;
|
|
12
|
-
}
|
|
13
|
-
// Qualified/scoped names: take the last segment (e.g., models.User → User)
|
|
14
|
-
if (typeNode.type === 'scoped_identifier' || typeNode.type === 'qualified_identifier'
|
|
15
|
-
|| typeNode.type === 'scoped_type_identifier' || typeNode.type === 'qualified_name'
|
|
16
|
-
|| typeNode.type === 'qualified_type'
|
|
17
|
-
|| typeNode.type === 'member_expression' || typeNode.type === 'attribute') {
|
|
18
|
-
const last = typeNode.lastNamedChild;
|
|
19
|
-
if (last && (last.type === 'type_identifier' || last.type === 'identifier'
|
|
20
|
-
|| last.type === 'simple_identifier' || last.type === 'name')) {
|
|
21
|
-
return last.text;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
// Generic types: extract the base type (e.g., List<User> → List)
|
|
25
|
-
if (typeNode.type === 'generic_type' || typeNode.type === 'parameterized_type') {
|
|
26
|
-
const base = typeNode.childForFieldName('name')
|
|
27
|
-
?? typeNode.childForFieldName('type')
|
|
28
|
-
?? typeNode.firstNamedChild;
|
|
29
|
-
if (base)
|
|
30
|
-
return extractSimpleTypeName(base);
|
|
31
|
-
}
|
|
32
|
-
// Nullable types (Kotlin User?, C# User?)
|
|
33
|
-
if (typeNode.type === 'nullable_type') {
|
|
34
|
-
const inner = typeNode.firstNamedChild;
|
|
35
|
-
if (inner)
|
|
36
|
-
return extractSimpleTypeName(inner);
|
|
37
|
-
}
|
|
38
|
-
// Type annotations that wrap the actual type (TS/Python: `: Foo`, Kotlin: user_type)
|
|
39
|
-
if (typeNode.type === 'type_annotation' || typeNode.type === 'type'
|
|
40
|
-
|| typeNode.type === 'user_type') {
|
|
41
|
-
const inner = typeNode.firstNamedChild;
|
|
42
|
-
if (inner)
|
|
43
|
-
return extractSimpleTypeName(inner);
|
|
44
|
-
}
|
|
45
|
-
// Pointer/reference types (C++, Rust): User*, &User, &mut User
|
|
46
|
-
if (typeNode.type === 'pointer_type' || typeNode.type === 'reference_type') {
|
|
47
|
-
const inner = typeNode.firstNamedChild;
|
|
48
|
-
if (inner)
|
|
49
|
-
return extractSimpleTypeName(inner);
|
|
50
|
-
}
|
|
51
|
-
// PHP named_type / optional_type
|
|
52
|
-
if (typeNode.type === 'named_type' || typeNode.type === 'optional_type') {
|
|
53
|
-
const inner = typeNode.childForFieldName('name') ?? typeNode.firstNamedChild;
|
|
54
|
-
if (inner)
|
|
55
|
-
return extractSimpleTypeName(inner);
|
|
56
|
-
}
|
|
57
|
-
// Name node (PHP)
|
|
58
|
-
if (typeNode.type === 'name') {
|
|
59
|
-
return typeNode.text;
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* Extract variable name from a declarator or pattern node.
|
|
65
|
-
* Returns the simple identifier text, or undefined for destructuring/complex patterns.
|
|
66
|
-
*/
|
|
67
|
-
export const extractVarName = (node) => {
|
|
68
|
-
if (node.type === 'identifier' || node.type === 'simple_identifier'
|
|
69
|
-
|| node.type === 'variable_name' || node.type === 'name') {
|
|
70
|
-
return node.text;
|
|
71
|
-
}
|
|
72
|
-
// variable_declarator (Java/C#): has a 'name' field
|
|
73
|
-
if (node.type === 'variable_declarator') {
|
|
74
|
-
const nameChild = node.childForFieldName('name');
|
|
75
|
-
if (nameChild)
|
|
76
|
-
return extractVarName(nameChild);
|
|
77
|
-
}
|
|
78
|
-
return undefined;
|
|
79
|
-
};
|
|
80
|
-
/** Node types for function/method parameters with type annotations */
|
|
81
|
-
export const TYPED_PARAMETER_TYPES = new Set([
|
|
82
|
-
'required_parameter', // TS: (x: Foo)
|
|
83
|
-
'optional_parameter', // TS: (x?: Foo)
|
|
84
|
-
'formal_parameter', // Java/Kotlin
|
|
85
|
-
'parameter', // C#/Rust/Go/Python/Swift
|
|
86
|
-
'parameter_declaration', // C/C++ void f(Type name)
|
|
87
|
-
'simple_parameter', // PHP function(Foo $x)
|
|
88
|
-
]);
|
|
89
|
-
/** Find the first named child with the given node type */
|
|
90
|
-
export const findChildByType = (node, type) => {
|
|
91
|
-
for (let i = 0; i < node.namedChildCount; i++) {
|
|
92
|
-
const child = node.namedChild(i);
|
|
93
|
-
if (child?.type === type)
|
|
94
|
-
return child;
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { extractSimpleTypeName, extractVarName, findChildByType } from './shared.js';
|
|
2
|
-
const DECLARATION_NODE_TYPES = new Set([
|
|
3
|
-
'property_declaration',
|
|
4
|
-
]);
|
|
5
|
-
/** Swift: let x: Foo = ... */
|
|
6
|
-
const extractDeclaration = (node, env) => {
|
|
7
|
-
// Swift property_declaration has pattern and type_annotation
|
|
8
|
-
const pattern = node.childForFieldName('pattern')
|
|
9
|
-
?? findChildByType(node, 'pattern');
|
|
10
|
-
const typeAnnotation = node.childForFieldName('type')
|
|
11
|
-
?? findChildByType(node, 'type_annotation');
|
|
12
|
-
if (!pattern || !typeAnnotation)
|
|
13
|
-
return;
|
|
14
|
-
const varName = extractVarName(pattern) ?? pattern.text;
|
|
15
|
-
const typeName = extractSimpleTypeName(typeAnnotation);
|
|
16
|
-
if (varName && typeName)
|
|
17
|
-
env.set(varName, typeName);
|
|
18
|
-
};
|
|
19
|
-
/** Swift: parameter → name: type */
|
|
20
|
-
const extractParameter = (node, env) => {
|
|
21
|
-
let nameNode = null;
|
|
22
|
-
let typeNode = null;
|
|
23
|
-
if (node.type === 'parameter') {
|
|
24
|
-
nameNode = node.childForFieldName('name')
|
|
25
|
-
?? node.childForFieldName('internal_name');
|
|
26
|
-
typeNode = node.childForFieldName('type');
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
30
|
-
typeNode = node.childForFieldName('type');
|
|
31
|
-
}
|
|
32
|
-
if (!nameNode || !typeNode)
|
|
33
|
-
return;
|
|
34
|
-
const varName = extractVarName(nameNode);
|
|
35
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
36
|
-
if (varName && typeName)
|
|
37
|
-
env.set(varName, typeName);
|
|
38
|
-
};
|
|
39
|
-
export const typeConfig = {
|
|
40
|
-
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
41
|
-
extractDeclaration,
|
|
42
|
-
extractParameter,
|
|
43
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { SyntaxNode } from '../utils.js';
|
|
2
|
-
/** Extracts type bindings from a declaration node into the env map */
|
|
3
|
-
export type TypeBindingExtractor = (node: SyntaxNode, env: Map<string, string>) => void;
|
|
4
|
-
/** Extracts type bindings from a parameter node into the env map */
|
|
5
|
-
export type ParameterExtractor = (node: SyntaxNode, env: Map<string, string>) => void;
|
|
6
|
-
/** Per-language type extraction configuration */
|
|
7
|
-
export interface LanguageTypeConfig {
|
|
8
|
-
/** Node types that represent typed declarations for this language */
|
|
9
|
-
declarationNodeTypes: ReadonlySet<string>;
|
|
10
|
-
/** Extract a (varName → typeName) binding from a declaration node */
|
|
11
|
-
extractDeclaration: TypeBindingExtractor;
|
|
12
|
-
/** Extract a (varName → typeName) binding from a parameter node */
|
|
13
|
-
extractParameter: ParameterExtractor;
|
|
14
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { extractSimpleTypeName, extractVarName } from './shared.js';
|
|
2
|
-
const DECLARATION_NODE_TYPES = new Set([
|
|
3
|
-
'lexical_declaration',
|
|
4
|
-
'variable_declaration',
|
|
5
|
-
]);
|
|
6
|
-
/** TypeScript: const x: Foo = ..., let x: Foo */
|
|
7
|
-
const extractDeclaration = (node, env) => {
|
|
8
|
-
for (let i = 0; i < node.namedChildCount; i++) {
|
|
9
|
-
const declarator = node.namedChild(i);
|
|
10
|
-
if (declarator?.type !== 'variable_declarator')
|
|
11
|
-
continue;
|
|
12
|
-
const nameNode = declarator.childForFieldName('name');
|
|
13
|
-
const typeAnnotation = declarator.childForFieldName('type');
|
|
14
|
-
if (!nameNode || !typeAnnotation)
|
|
15
|
-
continue;
|
|
16
|
-
const varName = extractVarName(nameNode);
|
|
17
|
-
const typeName = extractSimpleTypeName(typeAnnotation);
|
|
18
|
-
if (varName && typeName)
|
|
19
|
-
env.set(varName, typeName);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
/** TypeScript: required_parameter / optional_parameter → name: type */
|
|
23
|
-
const extractParameter = (node, env) => {
|
|
24
|
-
let nameNode = null;
|
|
25
|
-
let typeNode = null;
|
|
26
|
-
if (node.type === 'required_parameter' || node.type === 'optional_parameter') {
|
|
27
|
-
nameNode = node.childForFieldName('pattern') ?? node.childForFieldName('name');
|
|
28
|
-
typeNode = node.childForFieldName('type');
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// Generic fallback
|
|
32
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
33
|
-
typeNode = node.childForFieldName('type');
|
|
34
|
-
}
|
|
35
|
-
if (!nameNode || !typeNode)
|
|
36
|
-
return;
|
|
37
|
-
const varName = extractVarName(nameNode);
|
|
38
|
-
const typeName = extractSimpleTypeName(typeNode);
|
|
39
|
-
if (varName && typeName)
|
|
40
|
-
env.set(varName, typeName);
|
|
41
|
-
};
|
|
42
|
-
export const typeConfig = {
|
|
43
|
-
declarationNodeTypes: DECLARATION_NODE_TYPES,
|
|
44
|
-
extractDeclaration,
|
|
45
|
-
extractParameter,
|
|
46
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Transport, TransportSendOptions } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
2
|
-
import { type JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
-
export type StdioFraming = 'content-length' | 'newline';
|
|
4
|
-
export declare class CompatibleStdioServerTransport implements Transport {
|
|
5
|
-
private readonly _stdin;
|
|
6
|
-
private readonly _stdout;
|
|
7
|
-
private _readBuffer;
|
|
8
|
-
private _started;
|
|
9
|
-
private _framing;
|
|
10
|
-
onmessage?: (message: JSONRPCMessage) => void;
|
|
11
|
-
onerror?: (error: Error) => void;
|
|
12
|
-
onclose?: () => void;
|
|
13
|
-
constructor(_stdin?: NodeJS.ReadableStream, _stdout?: NodeJS.WritableStream);
|
|
14
|
-
private readonly _ondata;
|
|
15
|
-
private readonly _onerror;
|
|
16
|
-
start(): Promise<void>;
|
|
17
|
-
private detectFraming;
|
|
18
|
-
private discardBufferedInput;
|
|
19
|
-
private readContentLengthMessage;
|
|
20
|
-
private readNewlineMessage;
|
|
21
|
-
private readMessage;
|
|
22
|
-
private processReadBuffer;
|
|
23
|
-
close(): Promise<void>;
|
|
24
|
-
send(message: JSONRPCMessage, _options?: TransportSendOptions): Promise<void>;
|
|
25
|
-
}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import process from 'node:process';
|
|
2
|
-
import { JSONRPCMessageSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
-
function deserializeMessage(raw) {
|
|
4
|
-
return JSONRPCMessageSchema.parse(JSON.parse(raw));
|
|
5
|
-
}
|
|
6
|
-
function serializeNewlineMessage(message) {
|
|
7
|
-
return `${JSON.stringify(message)}\n`;
|
|
8
|
-
}
|
|
9
|
-
function serializeContentLengthMessage(message) {
|
|
10
|
-
const body = JSON.stringify(message);
|
|
11
|
-
return `Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`;
|
|
12
|
-
}
|
|
13
|
-
function findHeaderEnd(buffer) {
|
|
14
|
-
const crlfEnd = buffer.indexOf('\r\n\r\n');
|
|
15
|
-
if (crlfEnd !== -1) {
|
|
16
|
-
return { index: crlfEnd, separatorLength: 4 };
|
|
17
|
-
}
|
|
18
|
-
const lfEnd = buffer.indexOf('\n\n');
|
|
19
|
-
if (lfEnd !== -1) {
|
|
20
|
-
return { index: lfEnd, separatorLength: 2 };
|
|
21
|
-
}
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
function looksLikeContentLength(buffer) {
|
|
25
|
-
if (buffer.length < 14) {
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
const probe = buffer.toString('utf8', 0, Math.min(buffer.length, 32));
|
|
29
|
-
return /^content-length\s*:/i.test(probe);
|
|
30
|
-
}
|
|
31
|
-
const MAX_BUFFER_SIZE = 10 * 1024 * 1024; // 10 MB — generous for JSON-RPC
|
|
32
|
-
export class CompatibleStdioServerTransport {
|
|
33
|
-
_stdin;
|
|
34
|
-
_stdout;
|
|
35
|
-
_readBuffer;
|
|
36
|
-
_started = false;
|
|
37
|
-
_framing = null;
|
|
38
|
-
onmessage;
|
|
39
|
-
onerror;
|
|
40
|
-
onclose;
|
|
41
|
-
constructor(_stdin = process.stdin, _stdout = process.stdout) {
|
|
42
|
-
this._stdin = _stdin;
|
|
43
|
-
this._stdout = _stdout;
|
|
44
|
-
}
|
|
45
|
-
_ondata = (chunk) => {
|
|
46
|
-
this._readBuffer = this._readBuffer ? Buffer.concat([this._readBuffer, chunk]) : chunk;
|
|
47
|
-
if (this._readBuffer.length > MAX_BUFFER_SIZE) {
|
|
48
|
-
this.onerror?.(new Error(`Read buffer exceeded maximum size (${MAX_BUFFER_SIZE} bytes)`));
|
|
49
|
-
this.discardBufferedInput();
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
this.processReadBuffer();
|
|
53
|
-
};
|
|
54
|
-
_onerror = (error) => {
|
|
55
|
-
this.onerror?.(error);
|
|
56
|
-
};
|
|
57
|
-
async start() {
|
|
58
|
-
if (this._started) {
|
|
59
|
-
throw new Error('CompatibleStdioServerTransport already started!');
|
|
60
|
-
}
|
|
61
|
-
this._started = true;
|
|
62
|
-
this._stdin.on('data', this._ondata);
|
|
63
|
-
this._stdin.on('error', this._onerror);
|
|
64
|
-
}
|
|
65
|
-
detectFraming() {
|
|
66
|
-
if (!this._readBuffer || this._readBuffer.length === 0) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const firstByte = this._readBuffer[0];
|
|
70
|
-
if (firstByte === 0x7b || firstByte === 0x5b) {
|
|
71
|
-
return 'newline';
|
|
72
|
-
}
|
|
73
|
-
if (looksLikeContentLength(this._readBuffer)) {
|
|
74
|
-
return 'content-length';
|
|
75
|
-
}
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
discardBufferedInput() {
|
|
79
|
-
this._readBuffer = undefined;
|
|
80
|
-
this._framing = null;
|
|
81
|
-
}
|
|
82
|
-
readContentLengthMessage() {
|
|
83
|
-
if (!this._readBuffer) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
const header = findHeaderEnd(this._readBuffer);
|
|
87
|
-
if (header === null) {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
const headerText = this._readBuffer
|
|
91
|
-
.toString('utf8', 0, header.index)
|
|
92
|
-
.replace(/\r\n/g, '\n')
|
|
93
|
-
.replace(/\r/g, '\n');
|
|
94
|
-
const match = headerText.match(/(?:^|\n)content-length\s*:\s*(\d+)/i);
|
|
95
|
-
if (!match) {
|
|
96
|
-
this.discardBufferedInput();
|
|
97
|
-
throw new Error('Missing Content-Length header from MCP client');
|
|
98
|
-
}
|
|
99
|
-
const contentLength = Number.parseInt(match[1], 10);
|
|
100
|
-
if (!Number.isFinite(contentLength) || contentLength < 0) {
|
|
101
|
-
this.discardBufferedInput();
|
|
102
|
-
throw new Error('Invalid Content-Length header from MCP client');
|
|
103
|
-
}
|
|
104
|
-
if (contentLength > MAX_BUFFER_SIZE) {
|
|
105
|
-
this.discardBufferedInput();
|
|
106
|
-
throw new Error(`Content-Length ${contentLength} exceeds maximum allowed size (${MAX_BUFFER_SIZE} bytes)`);
|
|
107
|
-
}
|
|
108
|
-
const bodyStart = header.index + header.separatorLength;
|
|
109
|
-
const bodyEnd = bodyStart + contentLength;
|
|
110
|
-
if (this._readBuffer.length < bodyEnd) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
const body = this._readBuffer.toString('utf8', bodyStart, bodyEnd);
|
|
114
|
-
this._readBuffer = this._readBuffer.subarray(bodyEnd);
|
|
115
|
-
return deserializeMessage(body);
|
|
116
|
-
}
|
|
117
|
-
readNewlineMessage() {
|
|
118
|
-
if (!this._readBuffer) {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
while (true) {
|
|
122
|
-
const newlineIndex = this._readBuffer.indexOf('\n');
|
|
123
|
-
if (newlineIndex === -1) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
const line = this._readBuffer.toString('utf8', 0, newlineIndex).replace(/\r$/, '');
|
|
127
|
-
this._readBuffer = this._readBuffer.subarray(newlineIndex + 1);
|
|
128
|
-
if (line.trim().length === 0) {
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
return deserializeMessage(line);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
readMessage() {
|
|
135
|
-
if (!this._readBuffer || this._readBuffer.length === 0) {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
if (this._framing === null) {
|
|
139
|
-
this._framing = this.detectFraming();
|
|
140
|
-
if (this._framing === null) {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return this._framing === 'content-length'
|
|
145
|
-
? this.readContentLengthMessage()
|
|
146
|
-
: this.readNewlineMessage();
|
|
147
|
-
}
|
|
148
|
-
processReadBuffer() {
|
|
149
|
-
while (true) {
|
|
150
|
-
try {
|
|
151
|
-
const message = this.readMessage();
|
|
152
|
-
if (message === null) {
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
this.onmessage?.(message);
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
this.onerror?.(error);
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
async close() {
|
|
164
|
-
this._stdin.off('data', this._ondata);
|
|
165
|
-
this._stdin.off('error', this._onerror);
|
|
166
|
-
const remainingDataListeners = this._stdin.listenerCount('data');
|
|
167
|
-
if (remainingDataListeners === 0) {
|
|
168
|
-
this._stdin.pause();
|
|
169
|
-
}
|
|
170
|
-
this._started = false;
|
|
171
|
-
this._readBuffer = undefined;
|
|
172
|
-
this.onclose?.();
|
|
173
|
-
}
|
|
174
|
-
send(message, _options) {
|
|
175
|
-
return new Promise((resolve, reject) => {
|
|
176
|
-
if (!this._started) {
|
|
177
|
-
reject(new Error('Transport is closed'));
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const payload = this._framing === 'newline'
|
|
181
|
-
? serializeNewlineMessage(message)
|
|
182
|
-
: serializeContentLengthMessage(message);
|
|
183
|
-
const onError = (error) => {
|
|
184
|
-
this._stdout.removeListener('error', onError);
|
|
185
|
-
reject(error);
|
|
186
|
-
};
|
|
187
|
-
this._stdout.on('error', onError);
|
|
188
|
-
if (this._stdout.write(payload)) {
|
|
189
|
-
this._stdout.removeListener('error', onError);
|
|
190
|
-
resolve();
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
this._stdout.once('drain', () => {
|
|
194
|
-
this._stdout.removeListener('error', onError);
|
|
195
|
-
resolve();
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
}
|