bluera-knowledge 0.10.1 → 0.11.0
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +13 -0
- package/README.md +25 -0
- package/dist/{chunk-6U45VP5Z.js → chunk-2WBITQWZ.js} +2 -2
- package/dist/{chunk-DP5XBPQV.js → chunk-565OVW3C.js} +629 -2
- package/dist/chunk-565OVW3C.js.map +1 -0
- package/dist/{chunk-UE4ZIJYA.js → chunk-TRDMYKGC.js} +117 -1
- package/dist/chunk-TRDMYKGC.js.map +1 -0
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/package.json +1 -1
- package/src/analysis/adapter-registry.test.ts +211 -0
- package/src/analysis/adapter-registry.ts +155 -0
- package/src/analysis/language-adapter.ts +127 -0
- package/src/analysis/parser-factory.test.ts +79 -1
- package/src/analysis/parser-factory.ts +8 -0
- package/src/analysis/zil/index.ts +34 -0
- package/src/analysis/zil/zil-adapter.test.ts +187 -0
- package/src/analysis/zil/zil-adapter.ts +121 -0
- package/src/analysis/zil/zil-lexer.test.ts +222 -0
- package/src/analysis/zil/zil-lexer.ts +239 -0
- package/src/analysis/zil/zil-parser.test.ts +210 -0
- package/src/analysis/zil/zil-parser.ts +360 -0
- package/src/analysis/zil/zil-special-forms.ts +193 -0
- package/src/index.ts +6 -0
- package/src/mcp/server.ts +9 -1
- package/dist/chunk-DP5XBPQV.js.map +0 -1
- package/dist/chunk-UE4ZIJYA.js.map +0 -1
- /package/dist/{chunk-6U45VP5Z.js.map → chunk-2WBITQWZ.js.map} +0 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZIL Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses ZIL source code into an AST-like structure and extracts:
|
|
5
|
+
* - Symbols (ROUTINE, OBJECT, ROOM, GLOBAL, CONSTANT, SYNTAX)
|
|
6
|
+
* - Imports (INSERT-FILE)
|
|
7
|
+
* - Call relationships (filtering out special forms)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ZilLexer, TokenType, type Token } from './zil-lexer.js';
|
|
11
|
+
import { isSpecialForm, isDefinitionForm } from './zil-special-forms.js';
|
|
12
|
+
import type { ImportInfo } from '../ast-parser.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A ZIL form node (angle-bracket expression)
|
|
16
|
+
*/
|
|
17
|
+
export interface ZilForm {
|
|
18
|
+
/** The head/operator of the form (first atom after <) */
|
|
19
|
+
head: string;
|
|
20
|
+
/** Child nodes (atoms, strings, numbers, nested forms) */
|
|
21
|
+
children: ZilNode[];
|
|
22
|
+
/** Starting line number */
|
|
23
|
+
startLine: number;
|
|
24
|
+
/** Ending line number */
|
|
25
|
+
endLine: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A parenthesized group (used for args lists)
|
|
30
|
+
*/
|
|
31
|
+
export interface ZilGroup {
|
|
32
|
+
type: 'group';
|
|
33
|
+
children: ZilNode[];
|
|
34
|
+
startLine: number;
|
|
35
|
+
endLine: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A leaf node (atom, string, or number)
|
|
40
|
+
*/
|
|
41
|
+
export interface ZilLeaf {
|
|
42
|
+
type: 'atom' | 'string' | 'number';
|
|
43
|
+
value: string;
|
|
44
|
+
line: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type ZilNode = ZilForm | ZilGroup | ZilLeaf;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Extracted symbol from ZIL code
|
|
51
|
+
*/
|
|
52
|
+
export interface ZilSymbol {
|
|
53
|
+
name: string;
|
|
54
|
+
kind: 'routine' | 'object' | 'room' | 'global' | 'constant' | 'syntax' | 'verb';
|
|
55
|
+
startLine: number;
|
|
56
|
+
endLine: number;
|
|
57
|
+
signature?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A function call extracted from ZIL code
|
|
62
|
+
*/
|
|
63
|
+
export interface ZilCall {
|
|
64
|
+
caller: string;
|
|
65
|
+
callee: string;
|
|
66
|
+
line: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Result of parsing a ZIL file
|
|
71
|
+
*/
|
|
72
|
+
export interface ZilParseResult {
|
|
73
|
+
forms: ZilForm[];
|
|
74
|
+
symbols: ZilSymbol[];
|
|
75
|
+
imports: ImportInfo[];
|
|
76
|
+
calls: ZilCall[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parser for ZIL source code
|
|
81
|
+
*/
|
|
82
|
+
export class ZilParser {
|
|
83
|
+
private readonly lexer = new ZilLexer();
|
|
84
|
+
private tokens: Token[] = [];
|
|
85
|
+
private pos = 0;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse ZIL source code
|
|
89
|
+
*/
|
|
90
|
+
parse(input: string): ZilParseResult {
|
|
91
|
+
this.tokens = this.lexer.tokenize(input);
|
|
92
|
+
this.pos = 0;
|
|
93
|
+
|
|
94
|
+
const forms: ZilForm[] = [];
|
|
95
|
+
const symbols: ZilSymbol[] = [];
|
|
96
|
+
const imports: ImportInfo[] = [];
|
|
97
|
+
const calls: ZilCall[] = [];
|
|
98
|
+
|
|
99
|
+
// Parse all top-level forms
|
|
100
|
+
while (!this.isAtEnd()) {
|
|
101
|
+
if (this.check(TokenType.LANGLE)) {
|
|
102
|
+
const form = this.parseForm();
|
|
103
|
+
if (form !== undefined) {
|
|
104
|
+
forms.push(form);
|
|
105
|
+
|
|
106
|
+
// Extract symbols from definition forms
|
|
107
|
+
const symbol = this.extractSymbol(form);
|
|
108
|
+
if (symbol !== undefined) {
|
|
109
|
+
symbols.push(symbol);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Extract imports from INSERT-FILE
|
|
113
|
+
const imp = this.extractImport(form);
|
|
114
|
+
if (imp !== undefined) {
|
|
115
|
+
imports.push(imp);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Extract calls from routines
|
|
119
|
+
if (form.head.toUpperCase() === 'ROUTINE') {
|
|
120
|
+
const routineName = this.getRoutineName(form);
|
|
121
|
+
if (routineName !== undefined) {
|
|
122
|
+
this.extractCalls(form, routineName, calls);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
// Skip non-form tokens at top level
|
|
128
|
+
this.advance();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return { forms, symbols, imports, calls };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private isAtEnd(): boolean {
|
|
136
|
+
return this.pos >= this.tokens.length;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private peek(): Token | undefined {
|
|
140
|
+
return this.tokens[this.pos];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private check(type: TokenType): boolean {
|
|
144
|
+
if (this.isAtEnd()) return false;
|
|
145
|
+
return this.peek()?.type === type;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private advance(): Token | undefined {
|
|
149
|
+
if (!this.isAtEnd()) {
|
|
150
|
+
const token = this.tokens[this.pos];
|
|
151
|
+
this.pos++;
|
|
152
|
+
return token;
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private parseForm(): ZilForm | undefined {
|
|
158
|
+
if (!this.check(TokenType.LANGLE)) return undefined;
|
|
159
|
+
|
|
160
|
+
const startToken = this.advance(); // consume <
|
|
161
|
+
const startLine = startToken?.line ?? 1;
|
|
162
|
+
let endLine = startLine;
|
|
163
|
+
|
|
164
|
+
// Get the head (first element)
|
|
165
|
+
let head = '';
|
|
166
|
+
if (this.check(TokenType.ATOM)) {
|
|
167
|
+
head = this.advance()?.value ?? '';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const children: ZilNode[] = [];
|
|
171
|
+
|
|
172
|
+
// Parse children until >
|
|
173
|
+
while (!this.isAtEnd() && !this.check(TokenType.RANGLE)) {
|
|
174
|
+
const child = this.parseNode();
|
|
175
|
+
if (child !== undefined) {
|
|
176
|
+
children.push(child);
|
|
177
|
+
endLine = this.getNodeEndLine(child);
|
|
178
|
+
} else {
|
|
179
|
+
// Skip unexpected tokens
|
|
180
|
+
this.advance();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (this.check(TokenType.RANGLE)) {
|
|
185
|
+
const closeToken = this.advance();
|
|
186
|
+
endLine = closeToken?.line ?? endLine;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return { head, children, startLine, endLine };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private parseGroup(): ZilGroup | undefined {
|
|
193
|
+
if (!this.check(TokenType.LPAREN)) return undefined;
|
|
194
|
+
|
|
195
|
+
const startToken = this.advance(); // consume (
|
|
196
|
+
const startLine = startToken?.line ?? 1;
|
|
197
|
+
let endLine = startLine;
|
|
198
|
+
|
|
199
|
+
const children: ZilNode[] = [];
|
|
200
|
+
|
|
201
|
+
while (!this.isAtEnd() && !this.check(TokenType.RPAREN)) {
|
|
202
|
+
const child = this.parseNode();
|
|
203
|
+
if (child !== undefined) {
|
|
204
|
+
children.push(child);
|
|
205
|
+
endLine = this.getNodeEndLine(child);
|
|
206
|
+
} else {
|
|
207
|
+
this.advance();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (this.check(TokenType.RPAREN)) {
|
|
212
|
+
const closeToken = this.advance();
|
|
213
|
+
endLine = closeToken?.line ?? endLine;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return { type: 'group', children, startLine, endLine };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private parseNode(): ZilNode | undefined {
|
|
220
|
+
const token = this.peek();
|
|
221
|
+
if (token === undefined) return undefined;
|
|
222
|
+
|
|
223
|
+
switch (token.type) {
|
|
224
|
+
case TokenType.LANGLE:
|
|
225
|
+
return this.parseForm();
|
|
226
|
+
case TokenType.LPAREN:
|
|
227
|
+
return this.parseGroup();
|
|
228
|
+
case TokenType.ATOM:
|
|
229
|
+
this.advance();
|
|
230
|
+
return { type: 'atom', value: token.value, line: token.line };
|
|
231
|
+
case TokenType.STRING:
|
|
232
|
+
this.advance();
|
|
233
|
+
return { type: 'string', value: token.value, line: token.line };
|
|
234
|
+
case TokenType.NUMBER:
|
|
235
|
+
this.advance();
|
|
236
|
+
return { type: 'number', value: token.value, line: token.line };
|
|
237
|
+
default:
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private getNodeEndLine(node: ZilNode): number {
|
|
243
|
+
if ('endLine' in node) {
|
|
244
|
+
return node.endLine;
|
|
245
|
+
}
|
|
246
|
+
return node.line;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private extractSymbol(form: ZilForm): ZilSymbol | undefined {
|
|
250
|
+
const headUpper = form.head.toUpperCase();
|
|
251
|
+
|
|
252
|
+
if (!isDefinitionForm(headUpper)) {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Get the name (first child that's an atom)
|
|
257
|
+
const nameNode = form.children.find((c): c is ZilLeaf => 'type' in c && c.type === 'atom');
|
|
258
|
+
|
|
259
|
+
if (nameNode === undefined) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const kindMap: Record<string, ZilSymbol['kind']> = {
|
|
264
|
+
ROUTINE: 'routine',
|
|
265
|
+
OBJECT: 'object',
|
|
266
|
+
ROOM: 'room',
|
|
267
|
+
GLOBAL: 'global',
|
|
268
|
+
CONSTANT: 'constant',
|
|
269
|
+
SYNTAX: 'syntax',
|
|
270
|
+
VERB: 'verb',
|
|
271
|
+
DEFINE: 'routine',
|
|
272
|
+
DEFMAC: 'routine',
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const kind = kindMap[headUpper];
|
|
276
|
+
if (kind === undefined) {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const result: ZilSymbol = {
|
|
281
|
+
name: nameNode.value,
|
|
282
|
+
kind,
|
|
283
|
+
startLine: form.startLine,
|
|
284
|
+
endLine: form.endLine,
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
if (headUpper === 'ROUTINE' || headUpper === 'DEFINE' || headUpper === 'DEFMAC') {
|
|
288
|
+
result.signature = this.extractRoutineSignature(form, nameNode.value);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private extractRoutineSignature(form: ZilForm, name: string): string {
|
|
295
|
+
// Find args group (first parenthesized group after name)
|
|
296
|
+
const argsGroup = form.children.find((c): c is ZilGroup => 'type' in c && c.type === 'group');
|
|
297
|
+
|
|
298
|
+
if (argsGroup === undefined) {
|
|
299
|
+
return `ROUTINE ${name} ()`;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const args = argsGroup.children
|
|
303
|
+
.filter((c): c is ZilLeaf => 'type' in c && c.type === 'atom')
|
|
304
|
+
.map((c) => c.value)
|
|
305
|
+
.join(' ');
|
|
306
|
+
|
|
307
|
+
return `ROUTINE ${name} (${args})`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private extractImport(form: ZilForm): ImportInfo | undefined {
|
|
311
|
+
if (form.head.toUpperCase() !== 'INSERT-FILE') {
|
|
312
|
+
return undefined;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Get the file name (first string child)
|
|
316
|
+
const fileNode = form.children.find((c): c is ZilLeaf => 'type' in c && c.type === 'string');
|
|
317
|
+
|
|
318
|
+
if (fileNode === undefined) {
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
source: fileNode.value,
|
|
324
|
+
specifiers: [],
|
|
325
|
+
isType: false,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private getRoutineName(form: ZilForm): string | undefined {
|
|
330
|
+
const nameNode = form.children.find((c): c is ZilLeaf => 'type' in c && c.type === 'atom');
|
|
331
|
+
return nameNode?.value;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private extractCalls(node: ZilNode, caller: string, calls: ZilCall[]): void {
|
|
335
|
+
if ('head' in node) {
|
|
336
|
+
// It's a form
|
|
337
|
+
const headUpper = node.head.toUpperCase();
|
|
338
|
+
|
|
339
|
+
// If not a special form and not empty, it's a call
|
|
340
|
+
if (node.head !== '' && !isSpecialForm(headUpper)) {
|
|
341
|
+
calls.push({
|
|
342
|
+
caller,
|
|
343
|
+
callee: node.head,
|
|
344
|
+
line: node.startLine,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Recurse into children
|
|
349
|
+
for (const child of node.children) {
|
|
350
|
+
this.extractCalls(child, caller, calls);
|
|
351
|
+
}
|
|
352
|
+
} else if ('type' in node && node.type === 'group') {
|
|
353
|
+
// Recurse into group children
|
|
354
|
+
for (const child of node.children) {
|
|
355
|
+
this.extractCalls(child, caller, calls);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// Leaf nodes don't contain calls
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZIL Special Forms and Builtins
|
|
3
|
+
*
|
|
4
|
+
* These are NOT treated as function calls when building the call graph.
|
|
5
|
+
* Special forms are control flow, assignment, and predicates.
|
|
6
|
+
* Builtins are runtime primitives.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Special forms - language-level constructs, not function calls
|
|
11
|
+
*/
|
|
12
|
+
export const ZIL_SPECIAL_FORMS = new Set([
|
|
13
|
+
// Conditionals
|
|
14
|
+
'COND',
|
|
15
|
+
'AND',
|
|
16
|
+
'OR',
|
|
17
|
+
'NOT',
|
|
18
|
+
'IF',
|
|
19
|
+
'ELSE',
|
|
20
|
+
|
|
21
|
+
// Assignment
|
|
22
|
+
'SET',
|
|
23
|
+
'SETG',
|
|
24
|
+
'BIND',
|
|
25
|
+
'PROG',
|
|
26
|
+
|
|
27
|
+
// Loops
|
|
28
|
+
'REPEAT',
|
|
29
|
+
'DO',
|
|
30
|
+
'MAP',
|
|
31
|
+
'MAPF',
|
|
32
|
+
'MAPR',
|
|
33
|
+
'MAPRET',
|
|
34
|
+
'MAPLEAVE',
|
|
35
|
+
|
|
36
|
+
// Output
|
|
37
|
+
'TELL',
|
|
38
|
+
'PRINT',
|
|
39
|
+
'PRINTN',
|
|
40
|
+
'PRINTD',
|
|
41
|
+
'PRINTC',
|
|
42
|
+
'PRINTR',
|
|
43
|
+
'CRLF',
|
|
44
|
+
|
|
45
|
+
// Control flow
|
|
46
|
+
'RETURN',
|
|
47
|
+
'AGAIN',
|
|
48
|
+
'RTRUE',
|
|
49
|
+
'RFALSE',
|
|
50
|
+
'QUIT',
|
|
51
|
+
|
|
52
|
+
// Predicates (end with ?)
|
|
53
|
+
'EQUAL?',
|
|
54
|
+
'ZERO?',
|
|
55
|
+
'LESS?',
|
|
56
|
+
'GRTR?',
|
|
57
|
+
'FSET?',
|
|
58
|
+
'IN?',
|
|
59
|
+
'VERB?',
|
|
60
|
+
'PRSO?',
|
|
61
|
+
'PRSI?',
|
|
62
|
+
'HELD?',
|
|
63
|
+
'HERE?',
|
|
64
|
+
'ACCESSIBLE?',
|
|
65
|
+
'VISIBLE?',
|
|
66
|
+
'FIRST?',
|
|
67
|
+
'NEXT?',
|
|
68
|
+
'PROB?',
|
|
69
|
+
'RANDOM',
|
|
70
|
+
|
|
71
|
+
// Property/flag manipulation
|
|
72
|
+
'FSET',
|
|
73
|
+
'FCLEAR',
|
|
74
|
+
'GETP',
|
|
75
|
+
'PUTP',
|
|
76
|
+
'GETPT',
|
|
77
|
+
'PTSIZE',
|
|
78
|
+
|
|
79
|
+
// Object manipulation
|
|
80
|
+
'MOVE',
|
|
81
|
+
'REMOVE',
|
|
82
|
+
'LOC',
|
|
83
|
+
'FIRST',
|
|
84
|
+
'NEXT',
|
|
85
|
+
|
|
86
|
+
// Arithmetic
|
|
87
|
+
'ADD',
|
|
88
|
+
'SUB',
|
|
89
|
+
'MUL',
|
|
90
|
+
'DIV',
|
|
91
|
+
'MOD',
|
|
92
|
+
'BAND',
|
|
93
|
+
'BOR',
|
|
94
|
+
'BCOM',
|
|
95
|
+
'LSH',
|
|
96
|
+
|
|
97
|
+
// Table operations
|
|
98
|
+
'GET',
|
|
99
|
+
'PUT',
|
|
100
|
+
'GETB',
|
|
101
|
+
'PUTB',
|
|
102
|
+
'TABLE',
|
|
103
|
+
'ITABLE',
|
|
104
|
+
'LTABLE',
|
|
105
|
+
'PTABLE',
|
|
106
|
+
|
|
107
|
+
// Stack operations
|
|
108
|
+
'PUSH',
|
|
109
|
+
'POP',
|
|
110
|
+
'FSTACK',
|
|
111
|
+
|
|
112
|
+
// Input
|
|
113
|
+
'READ',
|
|
114
|
+
'INPUT',
|
|
115
|
+
'READLINE',
|
|
116
|
+
|
|
117
|
+
// Definition forms (handled separately for symbol extraction)
|
|
118
|
+
'ROUTINE',
|
|
119
|
+
'OBJECT',
|
|
120
|
+
'ROOM',
|
|
121
|
+
'GLOBAL',
|
|
122
|
+
'CONSTANT',
|
|
123
|
+
'SYNTAX',
|
|
124
|
+
'INSERT-FILE',
|
|
125
|
+
|
|
126
|
+
// Misc builtins
|
|
127
|
+
'VERSION?',
|
|
128
|
+
'ASCII',
|
|
129
|
+
'USL',
|
|
130
|
+
'APPLY',
|
|
131
|
+
'EVAL',
|
|
132
|
+
'FORM',
|
|
133
|
+
'REST',
|
|
134
|
+
'LENGTH',
|
|
135
|
+
'NTH',
|
|
136
|
+
'ZGET',
|
|
137
|
+
'ZPUT',
|
|
138
|
+
'ZWSTR',
|
|
139
|
+
'DIROUT',
|
|
140
|
+
'DIRIN',
|
|
141
|
+
'BUFOUT',
|
|
142
|
+
'HLIGHT',
|
|
143
|
+
'COLOR',
|
|
144
|
+
'FONT',
|
|
145
|
+
'SPLIT',
|
|
146
|
+
'SCREEN',
|
|
147
|
+
'WINGET',
|
|
148
|
+
'WINPUT',
|
|
149
|
+
'WINATTR',
|
|
150
|
+
'PICINF',
|
|
151
|
+
'DISPLAY',
|
|
152
|
+
'DCLEAR',
|
|
153
|
+
'SOUND',
|
|
154
|
+
'INTBL?',
|
|
155
|
+
'CATCH',
|
|
156
|
+
'THROW',
|
|
157
|
+
'LEGAL?',
|
|
158
|
+
'COPYT',
|
|
159
|
+
'VALUE',
|
|
160
|
+
'GASSIGNED?',
|
|
161
|
+
'ASSIGNED?',
|
|
162
|
+
'DEFINE',
|
|
163
|
+
'DEFMAC',
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Check if a form head is a special form or builtin
|
|
168
|
+
*/
|
|
169
|
+
export function isSpecialForm(name: string): boolean {
|
|
170
|
+
return ZIL_SPECIAL_FORMS.has(name.toUpperCase());
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Definition forms that create symbols
|
|
175
|
+
*/
|
|
176
|
+
export const ZIL_DEFINITION_FORMS = new Set([
|
|
177
|
+
'ROUTINE',
|
|
178
|
+
'OBJECT',
|
|
179
|
+
'ROOM',
|
|
180
|
+
'GLOBAL',
|
|
181
|
+
'CONSTANT',
|
|
182
|
+
'SYNTAX',
|
|
183
|
+
'VERB',
|
|
184
|
+
'DEFINE',
|
|
185
|
+
'DEFMAC',
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Check if a form head is a definition form
|
|
190
|
+
*/
|
|
191
|
+
export function isDefinitionForm(name: string): boolean {
|
|
192
|
+
return ZIL_DEFINITION_FORMS.has(name.toUpperCase());
|
|
193
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
+
import { AdapterRegistry } from './analysis/adapter-registry.js';
|
|
7
|
+
import { ZilAdapter } from './analysis/zil/index.js';
|
|
6
8
|
import { createCrawlCommand } from './cli/commands/crawl.js';
|
|
7
9
|
import { createIndexCommand } from './cli/commands/index-cmd.js';
|
|
8
10
|
import { createMCPCommand } from './cli/commands/mcp.js';
|
|
@@ -19,6 +21,10 @@ import { createStoreCommand } from './cli/commands/store.js';
|
|
|
19
21
|
import { createSyncCommand } from './cli/commands/sync.js';
|
|
20
22
|
import { createProgram, getGlobalOptions } from './cli/program.js';
|
|
21
23
|
|
|
24
|
+
// Register built-in language adapters
|
|
25
|
+
const registry = AdapterRegistry.getInstance();
|
|
26
|
+
registry.register(new ZilAdapter());
|
|
27
|
+
|
|
22
28
|
// Default paths
|
|
23
29
|
const DEFAULT_DATA_DIR = join(homedir(), '.bluera', 'bluera-knowledge', 'data');
|
|
24
30
|
const DEFAULT_CONFIG = join(homedir(), '.bluera', 'bluera-knowledge', 'config.json');
|
package/src/mcp/server.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { AdapterRegistry } from '../analysis/adapter-registry.js';
|
|
5
|
+
import { ZilAdapter } from '../analysis/zil/index.js';
|
|
6
|
+
import { createLogger } from '../logging/index.js';
|
|
4
7
|
import { createServices } from '../services/index.js';
|
|
5
8
|
import { handleExecute } from './handlers/execute.handler.js';
|
|
6
9
|
import { tools } from './handlers/index.js';
|
|
7
10
|
import { ExecuteArgsSchema } from './schemas/index.js';
|
|
8
|
-
import { createLogger } from '../logging/index.js';
|
|
9
11
|
import type { MCPServerOptions } from './types.js';
|
|
10
12
|
|
|
11
13
|
const logger = createLogger('mcp-server');
|
|
12
14
|
|
|
15
|
+
// Register built-in language adapters
|
|
16
|
+
const registry = AdapterRegistry.getInstance();
|
|
17
|
+
if (!registry.hasExtension('.zil')) {
|
|
18
|
+
registry.register(new ZilAdapter());
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
14
22
|
export function createMCPServer(options: MCPServerOptions): Server {
|
|
15
23
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|