gitnexus 1.5.2 → 1.5.3
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/cli/wiki.js +15 -44
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +5 -1
- package/dist/core/ingestion/field-extractors/configs/helpers.js +13 -3
- package/dist/core/ingestion/languages/typescript.js +4 -0
- package/dist/core/ingestion/method-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/method-extractors/configs/typescript-javascript.js +261 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +16 -0
- package/dist/core/ingestion/utils/ast-helpers.js +7 -0
- package/dist/core/wiki/html-viewer.js +6 -4
- package/dist/core/wiki/llm-client.js +4 -6
- package/package.json +1 -1
package/dist/cli/wiki.js
CHANGED
|
@@ -197,47 +197,23 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
197
197
|
llmConfig = { ...llmConfig, provider: 'cursor', model, apiKey: '', baseUrl: '' };
|
|
198
198
|
}
|
|
199
199
|
else if (choice === '3') {
|
|
200
|
-
// Azure OpenAI guided setup
|
|
201
|
-
console.log('\n Azure OpenAI setup
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
// Azure OpenAI guided setup — minimal prompts
|
|
201
|
+
console.log('\n Azure OpenAI setup.\n');
|
|
202
|
+
const endpoint = (await prompt(' Endpoint URL (e.g. https://my-resource.openai.azure.com): '))
|
|
203
|
+
.trim()
|
|
204
|
+
.replace(/\/+$/, '');
|
|
205
|
+
if (!endpoint) {
|
|
206
|
+
console.log('\n No endpoint provided. Aborting.\n');
|
|
206
207
|
process.exitCode = 1;
|
|
207
208
|
return;
|
|
208
209
|
}
|
|
209
|
-
const deploymentName = (await prompt(' Deployment name
|
|
210
|
+
const deploymentName = (await prompt(' Deployment name: ')).trim();
|
|
210
211
|
if (!deploymentName) {
|
|
211
212
|
console.log('\n No deployment name provided. Aborting.\n');
|
|
212
213
|
process.exitCode = 1;
|
|
213
214
|
return;
|
|
214
215
|
}
|
|
215
|
-
//
|
|
216
|
-
console.log('\n API format:');
|
|
217
|
-
console.log(' [1] v1 API — recommended (no api-version needed)');
|
|
218
|
-
console.log(' [2] Legacy — uses api-version query param\n');
|
|
219
|
-
const apiFormat = await prompt(' Select format (1/2, default: 1): ');
|
|
220
|
-
let azureApiVersion;
|
|
221
|
-
let azureBaseUrl;
|
|
222
|
-
if (apiFormat === '2') {
|
|
223
|
-
const versionInput = await prompt(' api-version (default: 2024-10-21): ');
|
|
224
|
-
azureApiVersion = versionInput || '2024-10-21';
|
|
225
|
-
azureBaseUrl = `https://${resourceName}.openai.azure.com/openai/deployments/${deploymentName}`;
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
azureBaseUrl = `https://${resourceName}.openai.azure.com/openai/v1`;
|
|
229
|
-
azureApiVersion = undefined;
|
|
230
|
-
}
|
|
231
|
-
defaultModel = deploymentName;
|
|
232
|
-
// Ask if this is a reasoning model deployment
|
|
233
|
-
const reasoningAnswer = await prompt(' Is this a reasoning model (o1, o3, o4-mini)? (y/N): ');
|
|
234
|
-
const isReasoningModelDeployment = ['y', 'yes'].includes(reasoningAnswer.toLowerCase());
|
|
235
|
-
if (isReasoningModelDeployment) {
|
|
236
|
-
console.log(' Note: temperature and max_tokens will be omitted for this deployment (Azure reasoning model requirement).\n');
|
|
237
|
-
}
|
|
238
|
-
const modelInput = await prompt(` Model / deployment name (default: ${defaultModel}): `);
|
|
239
|
-
const model = modelInput || defaultModel;
|
|
240
|
-
// API key
|
|
216
|
+
// API key — use env var if available
|
|
241
217
|
const envKey = process.env.GITNEXUS_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
242
218
|
let azureKey;
|
|
243
219
|
if (envKey) {
|
|
@@ -258,26 +234,21 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
258
234
|
process.exitCode = 1;
|
|
259
235
|
return;
|
|
260
236
|
}
|
|
261
|
-
//
|
|
262
|
-
const
|
|
237
|
+
// Always use v1 API format — no need for api-version
|
|
238
|
+
const azureBaseUrl = `${endpoint}/openai/v1`;
|
|
239
|
+
await saveCLIConfig({
|
|
263
240
|
apiKey: azureKey,
|
|
264
241
|
baseUrl: azureBaseUrl,
|
|
265
|
-
model,
|
|
242
|
+
model: deploymentName,
|
|
266
243
|
provider: 'azure',
|
|
267
|
-
|
|
268
|
-
};
|
|
269
|
-
if (azureApiVersion)
|
|
270
|
-
azureConfig.apiVersion = azureApiVersion;
|
|
271
|
-
await saveCLIConfig(azureConfig);
|
|
244
|
+
});
|
|
272
245
|
console.log(' Config saved to ~/.gitnexus/config.json\n');
|
|
273
246
|
llmConfig = {
|
|
274
247
|
...llmConfig,
|
|
275
248
|
apiKey: azureKey,
|
|
276
249
|
baseUrl: azureBaseUrl,
|
|
277
|
-
model,
|
|
250
|
+
model: deploymentName,
|
|
278
251
|
provider: 'azure',
|
|
279
|
-
apiVersion: azureApiVersion,
|
|
280
|
-
isReasoningModel: isReasoningModelDeployment,
|
|
281
252
|
};
|
|
282
253
|
}
|
|
283
254
|
else {
|
|
@@ -6,7 +6,10 @@ import type { SyntaxNode } from '../../utils/ast-helpers.js';
|
|
|
6
6
|
import type { FieldVisibility } from '../../field-types.js';
|
|
7
7
|
/**
|
|
8
8
|
* Check whether any child of `node` (named or unnamed) has .text matching
|
|
9
|
-
*
|
|
9
|
+
* the given `keyword`.
|
|
10
|
+
*
|
|
11
|
+
* Skips the `name` field child to avoid false positives when a method is
|
|
12
|
+
* named after a contextual keyword (e.g. `abstract()` in TypeScript).
|
|
10
13
|
*/
|
|
11
14
|
export declare function hasKeyword(node: SyntaxNode, keyword: string): boolean;
|
|
12
15
|
/**
|
|
@@ -18,6 +21,7 @@ export declare function hasModifier(node: SyntaxNode, modifierType: string, keyw
|
|
|
18
21
|
/**
|
|
19
22
|
* Return the first matching visibility keyword found either as a direct keyword
|
|
20
23
|
* child or inside a modifier wrapper node.
|
|
24
|
+
* Skips the `name` field child (same rationale as hasKeyword).
|
|
21
25
|
*/
|
|
22
26
|
export declare function findVisibility(node: SyntaxNode, keywords: ReadonlySet<FieldVisibility>, defaultVis: FieldVisibility, modifierNodeType?: string): FieldVisibility;
|
|
23
27
|
/**
|
|
@@ -5,12 +5,18 @@ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
6
|
/**
|
|
7
7
|
* Check whether any child of `node` (named or unnamed) has .text matching
|
|
8
|
-
*
|
|
8
|
+
* the given `keyword`.
|
|
9
|
+
*
|
|
10
|
+
* Skips the `name` field child to avoid false positives when a method is
|
|
11
|
+
* named after a contextual keyword (e.g. `abstract()` in TypeScript).
|
|
9
12
|
*/
|
|
10
13
|
export function hasKeyword(node, keyword) {
|
|
14
|
+
const nameNode = node.childForFieldName('name');
|
|
11
15
|
for (let i = 0; i < node.childCount; i++) {
|
|
12
16
|
const child = node.child(i);
|
|
13
|
-
if (child
|
|
17
|
+
if (!child || child === nameNode)
|
|
18
|
+
continue;
|
|
19
|
+
if (child.text.trim() === keyword)
|
|
14
20
|
return true;
|
|
15
21
|
}
|
|
16
22
|
return false;
|
|
@@ -36,12 +42,16 @@ export function hasModifier(node, modifierType, keyword) {
|
|
|
36
42
|
/**
|
|
37
43
|
* Return the first matching visibility keyword found either as a direct keyword
|
|
38
44
|
* child or inside a modifier wrapper node.
|
|
45
|
+
* Skips the `name` field child (same rationale as hasKeyword).
|
|
39
46
|
*/
|
|
40
47
|
export function findVisibility(node, keywords, defaultVis, modifierNodeType) {
|
|
48
|
+
const nameNode = node.childForFieldName('name');
|
|
41
49
|
// Direct keyword children
|
|
42
50
|
for (let i = 0; i < node.childCount; i++) {
|
|
43
51
|
const child = node.child(i);
|
|
44
|
-
|
|
52
|
+
if (!child || child === nameNode)
|
|
53
|
+
continue;
|
|
54
|
+
const text = child.text.trim();
|
|
45
55
|
if (text && keywords.has(text))
|
|
46
56
|
return text;
|
|
47
57
|
}
|
|
@@ -16,6 +16,8 @@ import { TYPESCRIPT_QUERIES, JAVASCRIPT_QUERIES } from '../tree-sitter-queries.j
|
|
|
16
16
|
import { typescriptFieldExtractor } from '../field-extractors/typescript.js';
|
|
17
17
|
import { createFieldExtractor } from '../field-extractors/generic.js';
|
|
18
18
|
import { javascriptConfig } from '../field-extractors/configs/typescript-javascript.js';
|
|
19
|
+
import { createMethodExtractor } from '../method-extractors/generic.js';
|
|
20
|
+
import { typescriptMethodConfig, javascriptMethodConfig, } from '../method-extractors/configs/typescript-javascript.js';
|
|
19
21
|
const BUILT_INS = new Set([
|
|
20
22
|
'console',
|
|
21
23
|
'log',
|
|
@@ -121,6 +123,7 @@ export const typescriptProvider = defineLanguage({
|
|
|
121
123
|
importResolver: resolveTypescriptImport,
|
|
122
124
|
namedBindingExtractor: extractTsNamedBindings,
|
|
123
125
|
fieldExtractor: typescriptFieldExtractor,
|
|
126
|
+
methodExtractor: createMethodExtractor(typescriptMethodConfig),
|
|
124
127
|
builtInNames: BUILT_INS,
|
|
125
128
|
});
|
|
126
129
|
export const javascriptProvider = defineLanguage({
|
|
@@ -132,5 +135,6 @@ export const javascriptProvider = defineLanguage({
|
|
|
132
135
|
importResolver: resolveJavascriptImport,
|
|
133
136
|
namedBindingExtractor: extractTsNamedBindings,
|
|
134
137
|
fieldExtractor: createFieldExtractor(javascriptConfig),
|
|
138
|
+
methodExtractor: createMethodExtractor(javascriptMethodConfig),
|
|
135
139
|
builtInNames: BUILT_INS,
|
|
136
140
|
});
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// gitnexus/src/core/ingestion/method-extractors/configs/typescript-javascript.ts
|
|
2
|
+
// Verified against tree-sitter-typescript ^0.23.2, tree-sitter-javascript ^0.23.0
|
|
3
|
+
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
4
|
+
import { hasKeyword } from '../../field-extractors/configs/helpers.js';
|
|
5
|
+
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// TS/JS helpers
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const VISIBILITY_KEYWORDS = new Set(['public', 'private', 'protected']);
|
|
10
|
+
/**
|
|
11
|
+
* Extract parameters from formal_parameters.
|
|
12
|
+
*
|
|
13
|
+
* Handles both TS node types (required_parameter, optional_parameter, rest_parameter)
|
|
14
|
+
* and JS node types (identifier, assignment_pattern, rest_pattern), plus destructured
|
|
15
|
+
* parameters (object_pattern, array_pattern) in both grammars.
|
|
16
|
+
*/
|
|
17
|
+
function extractTsJsParameters(node) {
|
|
18
|
+
const paramList = node.childForFieldName('parameters');
|
|
19
|
+
if (!paramList)
|
|
20
|
+
return [];
|
|
21
|
+
const params = [];
|
|
22
|
+
for (let i = 0; i < paramList.namedChildCount; i++) {
|
|
23
|
+
const param = paramList.namedChild(i);
|
|
24
|
+
if (!param)
|
|
25
|
+
continue;
|
|
26
|
+
switch (param.type) {
|
|
27
|
+
case 'required_parameter': {
|
|
28
|
+
const patternNode = param.childForFieldName('pattern');
|
|
29
|
+
if (!patternNode)
|
|
30
|
+
break;
|
|
31
|
+
// Skip TS `this` parameter — it's a compile-time type constraint, not a real param
|
|
32
|
+
if (patternNode.type === 'this')
|
|
33
|
+
break;
|
|
34
|
+
// Rest parameter: pattern is a rest_pattern (...args) — extract inner identifier
|
|
35
|
+
const isRest = patternNode.type === 'rest_pattern';
|
|
36
|
+
const nameNode = isRest ? patternNode.firstNamedChild : patternNode;
|
|
37
|
+
if (!nameNode)
|
|
38
|
+
break;
|
|
39
|
+
// type field is a type_annotation — unwrap to get the inner type node
|
|
40
|
+
const typeAnnotation = param.childForFieldName('type');
|
|
41
|
+
const typeNode = typeAnnotation?.firstNamedChild;
|
|
42
|
+
// Default value: presence of a 'value' field means isOptional
|
|
43
|
+
const hasDefault = !!param.childForFieldName('value');
|
|
44
|
+
params.push({
|
|
45
|
+
name: nameNode.text,
|
|
46
|
+
type: typeNode
|
|
47
|
+
? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
|
|
48
|
+
: null,
|
|
49
|
+
isOptional: hasDefault,
|
|
50
|
+
isVariadic: isRest,
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'optional_parameter': {
|
|
55
|
+
const nameNode = param.childForFieldName('pattern');
|
|
56
|
+
if (!nameNode)
|
|
57
|
+
break;
|
|
58
|
+
const typeAnnotation = param.childForFieldName('type');
|
|
59
|
+
const typeNode = typeAnnotation?.firstNamedChild;
|
|
60
|
+
params.push({
|
|
61
|
+
name: nameNode.text,
|
|
62
|
+
type: typeNode
|
|
63
|
+
? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
|
|
64
|
+
: null,
|
|
65
|
+
isOptional: true,
|
|
66
|
+
isVariadic: false,
|
|
67
|
+
});
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'rest_parameter': {
|
|
71
|
+
const nameNode = param.childForFieldName('pattern');
|
|
72
|
+
if (!nameNode)
|
|
73
|
+
break;
|
|
74
|
+
const typeAnnotation = param.childForFieldName('type');
|
|
75
|
+
const typeNode = typeAnnotation?.firstNamedChild;
|
|
76
|
+
params.push({
|
|
77
|
+
name: nameNode.text,
|
|
78
|
+
type: typeNode
|
|
79
|
+
? (extractSimpleTypeName(typeNode) ?? typeNode.text?.trim() ?? null)
|
|
80
|
+
: null,
|
|
81
|
+
isOptional: false,
|
|
82
|
+
isVariadic: true,
|
|
83
|
+
});
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case 'identifier': {
|
|
87
|
+
// JS: bare parameter name, no type info
|
|
88
|
+
params.push({ name: param.text, type: null, isOptional: false, isVariadic: false });
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'assignment_pattern': {
|
|
92
|
+
// JS: param = defaultValue — the left side is the name, isOptional = true
|
|
93
|
+
const left = param.childForFieldName('left');
|
|
94
|
+
if (left) {
|
|
95
|
+
params.push({ name: left.text, type: null, isOptional: true, isVariadic: false });
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'rest_pattern': {
|
|
100
|
+
// JS: ...args
|
|
101
|
+
const inner = param.firstNamedChild;
|
|
102
|
+
if (inner) {
|
|
103
|
+
params.push({ name: inner.text, type: null, isOptional: false, isVariadic: true });
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case 'object_pattern':
|
|
108
|
+
case 'array_pattern': {
|
|
109
|
+
// Destructured parameter — use full text as name
|
|
110
|
+
params.push({ name: param.text, type: null, isOptional: false, isVariadic: false });
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return params;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Extract return type from return_type field, unwrapping type_annotation.
|
|
119
|
+
*
|
|
120
|
+
* tree-sitter-typescript uses `return_type` as the field name (not `type` like JVM).
|
|
121
|
+
* The return_type field points to a type_annotation node that must be unwrapped.
|
|
122
|
+
*/
|
|
123
|
+
function extractTsJsReturnType(node) {
|
|
124
|
+
const returnType = node.childForFieldName('return_type');
|
|
125
|
+
if (returnType) {
|
|
126
|
+
if (returnType.type === 'type_annotation') {
|
|
127
|
+
const inner = returnType.firstNamedChild;
|
|
128
|
+
if (inner)
|
|
129
|
+
return extractSimpleTypeName(inner) ?? inner.text?.trim();
|
|
130
|
+
}
|
|
131
|
+
return extractSimpleTypeName(returnType) ?? returnType.text?.trim();
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Extract visibility from accessibility_modifier or #private name.
|
|
137
|
+
*
|
|
138
|
+
* tree-sitter-typescript emits accessibility_modifier as a named child of method nodes
|
|
139
|
+
* (not as a modifiers wrapper like JVM). Pass 1 scans for that child; pass 2 checks for
|
|
140
|
+
* ES2022 private_property_identifier (#name). Default: public.
|
|
141
|
+
*/
|
|
142
|
+
function extractTsJsVisibility(node) {
|
|
143
|
+
// Pass 1: check for accessibility_modifier named child (TS-specific)
|
|
144
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
145
|
+
const child = node.namedChild(i);
|
|
146
|
+
if (child && child.type === 'accessibility_modifier') {
|
|
147
|
+
const t = child.text.trim();
|
|
148
|
+
if (VISIBILITY_KEYWORDS.has(t))
|
|
149
|
+
return t;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Pass 2: ES2022 private methods (#name) are inherently private
|
|
153
|
+
const nameNode = node.childForFieldName('name');
|
|
154
|
+
if (nameNode && nameNode.type === 'private_property_identifier')
|
|
155
|
+
return 'private';
|
|
156
|
+
// No accessibility_modifier found — default to public.
|
|
157
|
+
// Note: tree-sitter-typescript does not wrap modifiers in a 'modifiers' node
|
|
158
|
+
// (unlike JVM), so there is no wrapper to scan.
|
|
159
|
+
return 'public';
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Extract decorator names, prefixed with '@'.
|
|
163
|
+
*
|
|
164
|
+
* In tree-sitter-typescript, decorators are **siblings** of the method_definition in the
|
|
165
|
+
* class_body — they are NOT children of the method node. We find them by walking backwards
|
|
166
|
+
* from the method node through its preceding siblings in the parent body.
|
|
167
|
+
*/
|
|
168
|
+
function extractTsJsDecorators(node) {
|
|
169
|
+
const decorators = [];
|
|
170
|
+
// Walk backwards via previousNamedSibling to collect consecutive decorator siblings.
|
|
171
|
+
// This avoids the O(N) index-finding scan through the parent's children.
|
|
172
|
+
let sibling = node.previousNamedSibling;
|
|
173
|
+
while (sibling && sibling.type === 'decorator') {
|
|
174
|
+
const name = extractDecoratorName(sibling);
|
|
175
|
+
if (name)
|
|
176
|
+
decorators.unshift(name);
|
|
177
|
+
sibling = sibling.previousNamedSibling;
|
|
178
|
+
}
|
|
179
|
+
return decorators;
|
|
180
|
+
}
|
|
181
|
+
function extractDecoratorName(decorator) {
|
|
182
|
+
const expr = decorator.firstNamedChild;
|
|
183
|
+
if (!expr)
|
|
184
|
+
return undefined;
|
|
185
|
+
if (expr.type === 'call_expression') {
|
|
186
|
+
const fn = expr.childForFieldName('function');
|
|
187
|
+
return fn ? '@' + fn.text : undefined;
|
|
188
|
+
}
|
|
189
|
+
if (expr.type === 'identifier')
|
|
190
|
+
return '@' + expr.text;
|
|
191
|
+
if (expr.type === 'member_expression')
|
|
192
|
+
return '@' + expr.text;
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
// Config
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// TS and JS share the same config base. TS-only node types (abstract_class_declaration,
|
|
199
|
+
// interface_declaration, abstract_method_signature, method_signature, interface_body) are
|
|
200
|
+
// included because the JS grammar never produces these nodes — they are harmless no-ops.
|
|
201
|
+
// This mirrors the field extractor's typescript-javascript.ts shared pattern.
|
|
202
|
+
//
|
|
203
|
+
// Note: TS and JS share a method config but NOT a field extractor because the TS field
|
|
204
|
+
// extractor needs a hand-written class for type_alias_declaration object literals and
|
|
205
|
+
// nested type discovery. Methods have no such requirement.
|
|
206
|
+
const shared = {
|
|
207
|
+
typeDeclarationNodes: [
|
|
208
|
+
'class_declaration',
|
|
209
|
+
'abstract_class_declaration',
|
|
210
|
+
'interface_declaration',
|
|
211
|
+
],
|
|
212
|
+
// Note: TS constructors are method_definition nodes (name = 'constructor'), so no
|
|
213
|
+
// explicit constructor_declaration entry is needed (unlike JVM/C# configs).
|
|
214
|
+
// Known gaps:
|
|
215
|
+
// - call_signature and construct_signature (e.g., interface Fn { (x: string): void; })
|
|
216
|
+
// are not extracted — they have no name field and are uncommon in practice.
|
|
217
|
+
// - class_expression (const Foo = class { ... }) — methods inside class expressions
|
|
218
|
+
// are not discovered because class_expression is not in typeDeclarationNodes.
|
|
219
|
+
// - declare module / declare global augmentations — methods inside ambient_module_declaration
|
|
220
|
+
// wrappers are not surfaced because the top-level walker doesn't descend into them.
|
|
221
|
+
methodNodeTypes: ['method_definition', 'method_signature', 'abstract_method_signature'],
|
|
222
|
+
bodyNodeTypes: ['class_body', 'interface_body'],
|
|
223
|
+
extractName(node) {
|
|
224
|
+
const nameNode = node.childForFieldName('name');
|
|
225
|
+
return nameNode?.text;
|
|
226
|
+
},
|
|
227
|
+
extractReturnType: extractTsJsReturnType,
|
|
228
|
+
extractParameters: extractTsJsParameters,
|
|
229
|
+
extractVisibility: extractTsJsVisibility,
|
|
230
|
+
isStatic(node) {
|
|
231
|
+
return hasKeyword(node, 'static');
|
|
232
|
+
},
|
|
233
|
+
isAbstract(node, ownerNode) {
|
|
234
|
+
// Explicit abstract keyword on the method itself
|
|
235
|
+
if (hasKeyword(node, 'abstract'))
|
|
236
|
+
return true;
|
|
237
|
+
// Interface methods are implicitly abstract — TS interfaces never have method bodies
|
|
238
|
+
// (unlike Java default methods), so no !body check needed
|
|
239
|
+
if (ownerNode.type === 'interface_declaration')
|
|
240
|
+
return true;
|
|
241
|
+
return false;
|
|
242
|
+
},
|
|
243
|
+
isFinal(_node) {
|
|
244
|
+
return false; // TS/JS has no final/sealed methods
|
|
245
|
+
},
|
|
246
|
+
extractAnnotations: extractTsJsDecorators,
|
|
247
|
+
isAsync(node) {
|
|
248
|
+
return hasKeyword(node, 'async');
|
|
249
|
+
},
|
|
250
|
+
isOverride(node) {
|
|
251
|
+
return hasKeyword(node, 'override');
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
export const typescriptMethodConfig = {
|
|
255
|
+
...shared,
|
|
256
|
+
language: SupportedLanguages.TypeScript,
|
|
257
|
+
};
|
|
258
|
+
export const javascriptMethodConfig = {
|
|
259
|
+
...shared,
|
|
260
|
+
language: SupportedLanguages.JavaScript,
|
|
261
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_identifier) @name) @definition.class\n\n(interface_declaration\n name: (type_identifier) @name) @definition.interface\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n; TypeScript overload signatures (function_signature is a separate node type from function_declaration)\n(function_signature\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class properties \u2014 public_field_definition covers most TS class fields\n(public_field_definition\n name: (property_identifier) @name) @definition.property\n\n; Private class fields: #address: Address\n(public_field_definition\n name: (private_property_identifier) @name) @definition.property\n\n; Constructor parameter properties: constructor(public address: Address)\n(required_parameter\n (accessibility_modifier)\n pattern: (identifier) @name) @definition.property\n\n; Heritage queries - class extends\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (extends_clause\n value: (identifier) @heritage.extends))) @heritage\n\n; Heritage queries - class implements interface\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (implements_clause\n (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n; fetch() \u2014 global function\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post/put/delete/patch('/path'), $.get/post/ajax({url:'/path'})\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Decorators: @Controller, @Get, @Post, etc.\n(decorator\n (call_expression\n function: (identifier) @decorator.name\n arguments: (arguments (string (string_fragment) @decorator.arg)?))) @decorator\n\n; Express/Hono route registration: app.get('/path', handler), router.post('/path', fn)\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
|
|
2
|
-
export declare const JAVASCRIPT_QUERIES = "\n(class_declaration\n name: (identifier) @name) @definition.class\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class fields \u2014 field_definition captures JS class fields (class User { address = ... })\n(field_definition\n property: (property_identifier) @name) @definition.property\n\n; Heritage queries - class extends (JavaScript uses different AST than TypeScript)\n; In tree-sitter-javascript, class_heritage directly contains the parent identifier\n(class_declaration\n name: (identifier) @heritage.class\n (class_heritage\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post, $.get/post/ajax\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Express/Hono route registration\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
|
|
1
|
+
export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_identifier) @name) @definition.class\n\n(interface_declaration\n name: (type_identifier) @name) @definition.interface\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n; TypeScript overload signatures (function_signature is a separate node type from function_declaration)\n(function_signature\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods (private_property_identifier not matched by property_identifier)\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n; Abstract method signatures in abstract classes\n(abstract_method_signature\n name: (property_identifier) @name) @definition.method\n\n; Interface method signatures\n(method_signature\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class properties \u2014 public_field_definition covers most TS class fields\n(public_field_definition\n name: (property_identifier) @name) @definition.property\n\n; Private class fields: #address: Address\n(public_field_definition\n name: (private_property_identifier) @name) @definition.property\n\n; Constructor parameter properties: constructor(public address: Address)\n(required_parameter\n (accessibility_modifier)\n pattern: (identifier) @name) @definition.property\n\n; Heritage queries - class extends\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (extends_clause\n value: (identifier) @heritage.extends))) @heritage\n\n; Heritage queries - class implements interface\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (implements_clause\n (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n; fetch() \u2014 global function\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post/put/delete/patch('/path'), $.get/post/ajax({url:'/path'})\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Decorators: @Controller, @Get, @Post, etc.\n(decorator\n (call_expression\n function: (identifier) @decorator.name\n arguments: (arguments (string (string_fragment) @decorator.arg)?))) @decorator\n\n; Express/Hono route registration: app.get('/path', handler), router.post('/path', fn)\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
|
|
2
|
+
export declare const JAVASCRIPT_QUERIES = "\n(class_declaration\n name: (identifier) @name) @definition.class\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class fields \u2014 field_definition captures JS class fields (class User { address = ... })\n(field_definition\n property: (property_identifier) @name) @definition.property\n\n; Heritage queries - class extends (JavaScript uses different AST than TypeScript)\n; In tree-sitter-javascript, class_heritage directly contains the parent identifier\n(class_declaration\n name: (identifier) @heritage.class\n (class_heritage\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post, $.get/post/ajax\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Express/Hono route registration\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
|
|
3
3
|
export declare const PYTHON_QUERIES = "\n(class_definition\n name: (identifier) @name) @definition.class\n\n(function_definition\n name: (identifier) @name) @definition.function\n\n(import_statement\n name: (dotted_name) @import.source) @import\n\n; import numpy as np \u2192 aliased_import captures the module name so the\n; import path is resolved and named-binding extraction stores \"np\" \u2192 \"numpy\".\n(import_statement\n name: (aliased_import\n name: (dotted_name) @import.source)) @import\n\n(import_from_statement\n module_name: (dotted_name) @import.source) @import\n\n(import_from_statement\n module_name: (relative_import) @import.source) @import\n\n(call\n function: (identifier) @call.name) @call\n\n(call\n function: (attribute\n attribute: (identifier) @call.name)) @call\n\n; Class attribute type annotations \u2014 PEP 526: address: Address or address: Address = Address()\n; Both bare annotations (address: Address) and annotated assignments (name: str = \"test\")\n; are parsed as (assignment left: ... type: ...) in tree-sitter-python.\n(expression_statement\n (assignment\n left: (identifier) @name\n type: (type)) @definition.property)\n\n; Heritage queries - Python class inheritance\n(class_definition\n name: (identifier) @heritage.class\n superclasses: (argument_list\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment\n left: (attribute\n object: (_) @assignment.receiver\n attribute: (identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment\n left: (attribute\n object: (_) @assignment.receiver\n attribute: (identifier) @assignment.property)\n right: (_)) @assignment\n\n; Python HTTP clients: requests.get('/path'), httpx.post('/path'), session.get('/path')\n(call\n function: (attribute\n attribute: (identifier) @http_client.method)\n arguments: (argument_list\n (string (string_content) @http_client.url))) @http_client\n\n; Python decorators: @app.route, @router.get, etc.\n(decorator\n (call\n function: (attribute\n object: (identifier) @decorator.receiver\n attribute: (identifier) @decorator.name)\n arguments: (argument_list\n (string (string_content) @decorator.arg)?))) @decorator\n";
|
|
4
4
|
export declare const JAVA_QUERIES = "\n; Classes, Interfaces, Enums, Annotations\n(class_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n(enum_declaration name: (identifier) @name) @definition.enum\n(annotation_type_declaration name: (identifier) @name) @definition.annotation\n\n; Methods & Constructors\n(method_declaration name: (identifier) @name) @definition.method\n(constructor_declaration name: (identifier) @name) @definition.constructor\n\n; Fields \u2014 typed field declarations inside class bodies\n(field_declaration\n declarator: (variable_declarator\n name: (identifier) @name)) @definition.property\n\n; Imports - capture any import declaration child as source\n(import_declaration (_) @import.source) @import\n\n; Calls\n(method_invocation name: (identifier) @call.name) @call\n(method_invocation object: (_) name: (identifier) @call.name) @call\n\n; Constructor calls: new Foo()\n(object_creation_expression type: (type_identifier) @call.name) @call\n\n; Heritage - extends class\n(class_declaration name: (identifier) @heritage.class\n (superclass (type_identifier) @heritage.extends)) @heritage\n\n; Heritage - implements interfaces\n(class_declaration name: (identifier) @heritage.class\n (super_interfaces (type_list (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (field_access\n object: (_) @assignment.receiver\n field: (identifier) @assignment.property)\n right: (_)) @assignment\n";
|
|
5
5
|
export declare const C_QUERIES = "\n; Functions (direct declarator)\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n\n; Functions returning pointers (pointer_declarator wraps function_declarator)\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n\n; Functions returning double pointers (nested pointer_declarator)\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function\n\n; Structs, Unions, Enums, Typedefs\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(union_specifier name: (type_identifier) @name) @definition.union\n(enum_specifier name: (type_identifier) @name) @definition.enum\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n";
|
|
@@ -23,6 +23,18 @@ export const TYPESCRIPT_QUERIES = `
|
|
|
23
23
|
(method_definition
|
|
24
24
|
name: (property_identifier) @name) @definition.method
|
|
25
25
|
|
|
26
|
+
; ES2022 #private methods (private_property_identifier not matched by property_identifier)
|
|
27
|
+
(method_definition
|
|
28
|
+
name: (private_property_identifier) @name) @definition.method
|
|
29
|
+
|
|
30
|
+
; Abstract method signatures in abstract classes
|
|
31
|
+
(abstract_method_signature
|
|
32
|
+
name: (property_identifier) @name) @definition.method
|
|
33
|
+
|
|
34
|
+
; Interface method signatures
|
|
35
|
+
(method_signature
|
|
36
|
+
name: (property_identifier) @name) @definition.method
|
|
37
|
+
|
|
26
38
|
(lexical_declaration
|
|
27
39
|
(variable_declarator
|
|
28
40
|
name: (identifier) @name
|
|
@@ -143,6 +155,10 @@ export const JAVASCRIPT_QUERIES = `
|
|
|
143
155
|
(method_definition
|
|
144
156
|
name: (property_identifier) @name) @definition.method
|
|
145
157
|
|
|
158
|
+
; ES2022 #private methods
|
|
159
|
+
(method_definition
|
|
160
|
+
name: (private_property_identifier) @name) @definition.method
|
|
161
|
+
|
|
146
162
|
(lexical_declaration
|
|
147
163
|
(variable_declarator
|
|
148
164
|
name: (identifier) @name
|
|
@@ -632,6 +632,13 @@ export const extractMethodSignature = (node) => {
|
|
|
632
632
|
param.type === 'self_parameter') {
|
|
633
633
|
continue;
|
|
634
634
|
}
|
|
635
|
+
// TypeScript: `this` parameter is a compile-time type constraint, not a real param
|
|
636
|
+
// e.g., handle(this: void, event: Event) — only count 'event'
|
|
637
|
+
if (param.type === 'required_parameter') {
|
|
638
|
+
const patternNode = param.childForFieldName('pattern');
|
|
639
|
+
if (patternNode?.type === 'this')
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
635
642
|
// Kotlin: default values are siblings of the parameter node inside
|
|
636
643
|
// function_value_parameters, so they appear as named children (e.g.
|
|
637
644
|
// string_literal, integer_literal, boolean_literal, call_expression).
|
|
@@ -49,10 +49,12 @@ function esc(text) {
|
|
|
49
49
|
.replace(/"/g, '"');
|
|
50
50
|
}
|
|
51
51
|
function buildHTML(projectName, moduleTree, pages, meta) {
|
|
52
|
-
// Embed data as JSON inside the HTML
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
52
|
+
// Embed data as JSON inside the HTML.
|
|
53
|
+
// Escape </script> sequences so they don't prematurely close the <script> tag.
|
|
54
|
+
const escScript = (s) => s.replace(/<\//g, '<\\/');
|
|
55
|
+
const pagesJSON = escScript(JSON.stringify(pages));
|
|
56
|
+
const treeJSON = escScript(JSON.stringify(moduleTree));
|
|
57
|
+
const metaJSON = escScript(JSON.stringify(meta));
|
|
56
58
|
const parts = [];
|
|
57
59
|
// ── Head ──
|
|
58
60
|
parts.push('<!DOCTYPE html>');
|
|
@@ -103,12 +103,10 @@ export async function callLLM(prompt, config, systemPrompt, options) {
|
|
|
103
103
|
model: config.model,
|
|
104
104
|
messages,
|
|
105
105
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
else {
|
|
111
|
-
body.max_tokens = config.maxTokens;
|
|
106
|
+
// max_tokens is deprecated; use max_completion_tokens for all models
|
|
107
|
+
body.max_completion_tokens = config.maxTokens;
|
|
108
|
+
// Only send temperature for non-Azure providers — some Azure models reject non-default values
|
|
109
|
+
if (!reasoning && !azure && config.temperature !== undefined) {
|
|
112
110
|
body.temperature = config.temperature;
|
|
113
111
|
}
|
|
114
112
|
if (useStream)
|
package/package.json
CHANGED