50c 4.0.0 → 4.1.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 +27 -175
- package/bin/50c.js +62 -2224
- package/package.json +17 -31
- package/LICENSE +0 -31
- package/lib/caz-context.js +0 -461
- package/lib/file-memory.js +0 -301
- package/lib/invent-ui.js +0 -717
- package/lib/mcp-tv.js +0 -1015
- package/lib/pre-publish.js +0 -831
- package/lib/subagent.js +0 -369
- package/lib/team.js +0 -691
- package/lib/tools-registry.js +0 -184
package/package.json
CHANGED
|
@@ -1,40 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "50c",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "
|
|
5
|
-
"scripts_comment": "Run `node test-mcp.js` for smoke tests before publish.",
|
|
3
|
+
"version": "4.1.1",
|
|
4
|
+
"description": "Remote shell for GenXis 50c / 50c-PREVIEW",
|
|
6
5
|
"bin": {
|
|
7
|
-
"50c": "
|
|
6
|
+
"50c": "bin/50c.js"
|
|
8
7
|
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/50c.js",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
11
14
|
},
|
|
15
|
+
"license": "UNLICENSED",
|
|
12
16
|
"keywords": [
|
|
13
|
-
"mcp",
|
|
14
|
-
"ai",
|
|
15
|
-
"llm",
|
|
16
|
-
"cli",
|
|
17
|
-
"agent",
|
|
18
17
|
"50c",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"developer-tools",
|
|
23
|
-
"context",
|
|
24
|
-
"compression",
|
|
25
|
-
"caz",
|
|
26
|
-
"file-memory"
|
|
18
|
+
"50c-preview",
|
|
19
|
+
"cli",
|
|
20
|
+
"mcp"
|
|
27
21
|
],
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"node": ">=18.0.0"
|
|
33
|
-
},
|
|
34
|
-
"files": [
|
|
35
|
-
"bin/",
|
|
36
|
-
"lib/",
|
|
37
|
-
"README.md",
|
|
38
|
-
"LICENSE"
|
|
39
|
-
]
|
|
22
|
+
"homepage": "https://c.50c.ai",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
}
|
|
40
26
|
}
|
package/LICENSE
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
PROPRIETARY SOFTWARE LICENSE
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 genxis. All Rights Reserved.
|
|
4
|
-
|
|
5
|
-
This software and associated documentation files (the "Software") are the
|
|
6
|
-
proprietary property of genxis.
|
|
7
|
-
|
|
8
|
-
USAGE TERMS:
|
|
9
|
-
1. You may install and use this Software only with a valid API key.
|
|
10
|
-
2. Each use of the Software requires credits at published rates.
|
|
11
|
-
3. You may NOT copy, modify, merge, publish, distribute, sublicense, or sell
|
|
12
|
-
copies of the Software.
|
|
13
|
-
4. You may NOT reverse engineer, decompile, or disassemble the Software.
|
|
14
|
-
5. You may NOT remove or bypass the payment/credit system.
|
|
15
|
-
6. You may NOT create derivative works based on the Software.
|
|
16
|
-
|
|
17
|
-
RESTRICTIONS:
|
|
18
|
-
- This is a commercial product. No free usage rights are granted.
|
|
19
|
-
- Source code is provided for transparency only, not for modification.
|
|
20
|
-
- Unauthorized use, reproduction, or distribution is strictly prohibited.
|
|
21
|
-
|
|
22
|
-
WARRANTY DISCLAIMER:
|
|
23
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
26
|
-
|
|
27
|
-
LIMITATION OF LIABILITY:
|
|
28
|
-
IN NO EVENT SHALL GENXIS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
-
LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
|
|
30
|
-
|
|
31
|
-
Contact: https://genxis.one
|
package/lib/caz-context.js
DELETED
|
@@ -1,461 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* 50c-context - Thin client for CAZ context compression
|
|
4
|
-
*
|
|
5
|
-
* LOCAL (FREE): Basic indexing, hash lookup, line retrieval
|
|
6
|
-
* API (PRO): CAZ dedup, SimHash, BM25 ranking, fog detection
|
|
7
|
-
*
|
|
8
|
-
* User sees this. Secret sauce stays on server.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const crypto = require('crypto');
|
|
14
|
-
const os = require('os');
|
|
15
|
-
|
|
16
|
-
const INDEX_DIR = path.join(os.homedir(), '.50c', 'context');
|
|
17
|
-
const API_BASE = process.env.FIFTYC_API_URL || 'https://api.50c.ai';
|
|
18
|
-
|
|
19
|
-
if (!fs.existsSync(INDEX_DIR)) {
|
|
20
|
-
fs.mkdirSync(INDEX_DIR, { recursive: true });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function hash(content) {
|
|
24
|
-
return crypto.createHash('blake2b512').update(content).digest('hex').slice(0, 32);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function hashPath(filepath) {
|
|
28
|
-
return crypto.createHash('md5').update(filepath).digest('hex').slice(0, 12);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function getIndexPath(filepath) {
|
|
32
|
-
return path.join(INDEX_DIR, `${hashPath(filepath)}.json`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function simpleChunk(content, targetSize = 1024) {
|
|
36
|
-
const chunks = [];
|
|
37
|
-
let start = 0;
|
|
38
|
-
while (start < content.length) {
|
|
39
|
-
let end = Math.min(start + targetSize, content.length);
|
|
40
|
-
if (end < content.length) {
|
|
41
|
-
const newline = content.lastIndexOf('\n', end);
|
|
42
|
-
if (newline > start + targetSize / 2) end = newline + 1;
|
|
43
|
-
}
|
|
44
|
-
chunks.push({
|
|
45
|
-
content: content.slice(start, end),
|
|
46
|
-
start,
|
|
47
|
-
end,
|
|
48
|
-
hash: hash(content.slice(start, end))
|
|
49
|
-
});
|
|
50
|
-
start = end;
|
|
51
|
-
}
|
|
52
|
-
return chunks;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function extractSymbols(lines, ext) {
|
|
56
|
-
const symbols = [];
|
|
57
|
-
const isPython = ['.py'].includes(ext);
|
|
58
|
-
const isJS = ['.js', '.ts', '.jsx', '.tsx', '.mjs'].includes(ext);
|
|
59
|
-
|
|
60
|
-
lines.forEach((line, i) => {
|
|
61
|
-
const trimmed = line.trim();
|
|
62
|
-
const lineNum = i + 1;
|
|
63
|
-
|
|
64
|
-
if (isPython) {
|
|
65
|
-
if (trimmed.startsWith('def ')) {
|
|
66
|
-
const name = trimmed.slice(4).split('(')[0].trim();
|
|
67
|
-
symbols.push({ name, type: 'function', line: lineNum });
|
|
68
|
-
}
|
|
69
|
-
else if (trimmed.startsWith('async def ')) {
|
|
70
|
-
const name = trimmed.slice(10).split('(')[0].trim();
|
|
71
|
-
symbols.push({ name, type: 'async_function', line: lineNum });
|
|
72
|
-
}
|
|
73
|
-
else if (trimmed.startsWith('class ')) {
|
|
74
|
-
const name = trimmed.slice(6).split('(')[0].split(':')[0].trim();
|
|
75
|
-
symbols.push({ name, type: 'class', line: lineNum });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (isJS) {
|
|
80
|
-
if (trimmed.match(/^(export\s+)?(async\s+)?function\s+\w+/)) {
|
|
81
|
-
const match = trimmed.match(/function\s+(\w+)/);
|
|
82
|
-
if (match) symbols.push({ name: match[1], type: 'function', line: lineNum });
|
|
83
|
-
}
|
|
84
|
-
else if (trimmed.match(/^(export\s+)?class\s+\w+/)) {
|
|
85
|
-
const match = trimmed.match(/class\s+(\w+)/);
|
|
86
|
-
if (match) symbols.push({ name: match[1], type: 'class', line: lineNum });
|
|
87
|
-
}
|
|
88
|
-
else if (trimmed.match(/^(export\s+)?(const|let|var)\s+\w+\s*=\s*(async\s+)?(\(|function)/)) {
|
|
89
|
-
const match = trimmed.match(/(const|let|var)\s+(\w+)/);
|
|
90
|
-
if (match) symbols.push({ name: match[2], type: 'arrow_fn', line: lineNum });
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
return symbols;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function indexFile(filepath) {
|
|
99
|
-
filepath = path.resolve(filepath);
|
|
100
|
-
if (!fs.existsSync(filepath)) return { error: `File not found: ${filepath}` };
|
|
101
|
-
|
|
102
|
-
const content = fs.readFileSync(filepath, 'utf8');
|
|
103
|
-
const lines = content.split('\n');
|
|
104
|
-
const ext = path.extname(filepath).toLowerCase();
|
|
105
|
-
const symbols = extractSymbols(lines, ext);
|
|
106
|
-
const chunks = simpleChunk(content);
|
|
107
|
-
const fileHash = hash(content);
|
|
108
|
-
|
|
109
|
-
const indexPath = getIndexPath(filepath);
|
|
110
|
-
if (fs.existsSync(indexPath)) {
|
|
111
|
-
try {
|
|
112
|
-
const existing = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
113
|
-
if (existing.hash === fileHash) {
|
|
114
|
-
return { status: 'current', filepath, lines: lines.length };
|
|
115
|
-
}
|
|
116
|
-
} catch (e) {}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const blockHashes = {};
|
|
120
|
-
chunks.forEach(c => {
|
|
121
|
-
if (!blockHashes[c.hash]) blockHashes[c.hash] = [];
|
|
122
|
-
blockHashes[c.hash].push({ start: c.start, end: c.end });
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
const index = {
|
|
126
|
-
filepath,
|
|
127
|
-
filename: path.basename(filepath),
|
|
128
|
-
hash: fileHash,
|
|
129
|
-
totalLines: lines.length,
|
|
130
|
-
indexed: new Date().toISOString(),
|
|
131
|
-
symbols,
|
|
132
|
-
chunks: chunks.map(c => ({ hash: c.hash, start: c.start, end: c.end })),
|
|
133
|
-
uniqueBlocks: Object.keys(blockHashes).length,
|
|
134
|
-
totalBlocks: chunks.length,
|
|
135
|
-
dedupRatio: chunks.length / Object.keys(blockHashes).length
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
fs.writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
|
139
|
-
|
|
140
|
-
return {
|
|
141
|
-
status: 'indexed',
|
|
142
|
-
filepath,
|
|
143
|
-
lines: lines.length,
|
|
144
|
-
symbols: symbols.length,
|
|
145
|
-
uniqueBlocks: index.uniqueBlocks,
|
|
146
|
-
totalBlocks: index.totalBlocks,
|
|
147
|
-
dedupRatio: index.dedupRatio.toFixed(2)
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function findSymbol(name, filepath = null) {
|
|
152
|
-
const indexFiles = filepath
|
|
153
|
-
? [getIndexPath(path.resolve(filepath))]
|
|
154
|
-
: fs.readdirSync(INDEX_DIR).filter(f => f.endsWith('.json')).map(f => path.join(INDEX_DIR, f));
|
|
155
|
-
|
|
156
|
-
const results = [];
|
|
157
|
-
const nameLower = name.toLowerCase();
|
|
158
|
-
|
|
159
|
-
for (const indexFile of indexFiles) {
|
|
160
|
-
if (!fs.existsSync(indexFile)) continue;
|
|
161
|
-
try {
|
|
162
|
-
const index = JSON.parse(fs.readFileSync(indexFile, 'utf8'));
|
|
163
|
-
const matches = index.symbols.filter(s =>
|
|
164
|
-
s.name.toLowerCase().includes(nameLower)
|
|
165
|
-
);
|
|
166
|
-
matches.forEach(m => results.push({
|
|
167
|
-
name: m.name, type: m.type, line: m.line,
|
|
168
|
-
file: index.filename, filepath: index.filepath
|
|
169
|
-
}));
|
|
170
|
-
} catch (e) {}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return results.sort((a, b) => {
|
|
174
|
-
const aExact = a.name.toLowerCase() === nameLower ? 0 : 1;
|
|
175
|
-
const bExact = b.name.toLowerCase() === nameLower ? 0 : 1;
|
|
176
|
-
return aExact - bExact || a.line - b.line;
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function getLines(filepath, start, end) {
|
|
181
|
-
filepath = path.resolve(filepath);
|
|
182
|
-
if (!fs.existsSync(filepath)) return { error: `File not found: ${filepath}` };
|
|
183
|
-
|
|
184
|
-
const lines = fs.readFileSync(filepath, 'utf8').split('\n');
|
|
185
|
-
start = Math.max(1, start);
|
|
186
|
-
end = Math.min(lines.length, end);
|
|
187
|
-
|
|
188
|
-
const result = [];
|
|
189
|
-
for (let i = start - 1; i < end; i++) {
|
|
190
|
-
result.push(`${(i + 1).toString().padStart(5)}| ${lines[i]}`);
|
|
191
|
-
}
|
|
192
|
-
return result.join('\n');
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function getBlocksByQuery(filepath, query) {
|
|
196
|
-
filepath = path.resolve(filepath);
|
|
197
|
-
const indexPath = getIndexPath(filepath);
|
|
198
|
-
|
|
199
|
-
if (!fs.existsSync(indexPath)) indexFile(filepath);
|
|
200
|
-
if (!fs.existsSync(indexPath)) return { error: `Could not index: ${filepath}` };
|
|
201
|
-
|
|
202
|
-
const index = JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
203
|
-
const content = fs.readFileSync(filepath, 'utf8');
|
|
204
|
-
const queryLower = query.toLowerCase();
|
|
205
|
-
|
|
206
|
-
const relevantSymbols = index.symbols.filter(s =>
|
|
207
|
-
s.name.toLowerCase().includes(queryLower)
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
const relevantChunks = [];
|
|
211
|
-
const lines = content.split('\n');
|
|
212
|
-
|
|
213
|
-
for (const sym of relevantSymbols) {
|
|
214
|
-
const startLine = sym.line;
|
|
215
|
-
let endLine = startLine + 50;
|
|
216
|
-
for (let i = startLine; i < Math.min(startLine + 100, lines.length); i++) {
|
|
217
|
-
const line = lines[i];
|
|
218
|
-
if (line && !line.startsWith(' ') && !line.startsWith('\t') && line.trim() && i > startLine) {
|
|
219
|
-
endLine = i;
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
relevantChunks.push({
|
|
224
|
-
symbol: sym.name,
|
|
225
|
-
startLine,
|
|
226
|
-
endLine,
|
|
227
|
-
content: lines.slice(startLine - 1, endLine).join('\n')
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
query,
|
|
233
|
-
file: index.filename,
|
|
234
|
-
matchedSymbols: relevantSymbols.length,
|
|
235
|
-
chunks: relevantChunks.slice(0, 10),
|
|
236
|
-
totalLines: index.totalLines,
|
|
237
|
-
sentLines: relevantChunks.reduce((sum, c) => sum + (c.endLine - c.startLine), 0),
|
|
238
|
-
reduction: ((1 - relevantChunks.reduce((sum, c) => sum + (c.endLine - c.startLine), 0) / index.totalLines) * 100).toFixed(1) + '%'
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async function apiCall(endpoint, data, apiKey) {
|
|
243
|
-
const key = apiKey || process.env.FIFTYC_API_KEY;
|
|
244
|
-
if (!key) return { error: 'No API key. Set FIFTYC_API_KEY' };
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
const fetch = globalThis.fetch || require('node-fetch');
|
|
248
|
-
const res = await fetch(`${API_BASE}${endpoint}`, {
|
|
249
|
-
method: 'POST',
|
|
250
|
-
headers: {
|
|
251
|
-
'Content-Type': 'application/json',
|
|
252
|
-
'X-API-Key': key
|
|
253
|
-
},
|
|
254
|
-
body: JSON.stringify(data)
|
|
255
|
-
});
|
|
256
|
-
return await res.json();
|
|
257
|
-
} catch (e) {
|
|
258
|
-
return { error: e.message };
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
async function cazDedup(filepath, apiKey) {
|
|
263
|
-
filepath = path.resolve(filepath);
|
|
264
|
-
if (!fs.existsSync(filepath)) return { error: `File not found: ${filepath}` };
|
|
265
|
-
|
|
266
|
-
const content = fs.readFileSync(filepath, 'utf8');
|
|
267
|
-
const localIndex = indexFile(filepath);
|
|
268
|
-
|
|
269
|
-
return await apiCall('/tools/caz_dedup', {
|
|
270
|
-
filepath: path.basename(filepath),
|
|
271
|
-
content,
|
|
272
|
-
localStats: localIndex
|
|
273
|
-
}, apiKey);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
async function contextCompress(filepath, query, apiKey) {
|
|
277
|
-
filepath = path.resolve(filepath);
|
|
278
|
-
if (!fs.existsSync(filepath)) return { error: `File not found: ${filepath}` };
|
|
279
|
-
|
|
280
|
-
const content = fs.readFileSync(filepath, 'utf8');
|
|
281
|
-
const localBlocks = getBlocksByQuery(filepath, query);
|
|
282
|
-
|
|
283
|
-
return await apiCall('/tools/context_compress', {
|
|
284
|
-
filepath: path.basename(filepath),
|
|
285
|
-
query,
|
|
286
|
-
localBlocks,
|
|
287
|
-
content
|
|
288
|
-
}, apiKey);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
async function fogCheck(messages, apiKey) {
|
|
292
|
-
return await apiCall('/tools/fog_check', { messages }, apiKey);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
async function fogClear(messages, mode, apiKey) {
|
|
296
|
-
return await apiCall('/tools/fog_clear', { messages, mode }, apiKey);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function listIndexed() {
|
|
300
|
-
const files = fs.readdirSync(INDEX_DIR).filter(f => f.endsWith('.json'));
|
|
301
|
-
const results = [];
|
|
302
|
-
|
|
303
|
-
for (const file of files) {
|
|
304
|
-
try {
|
|
305
|
-
const index = JSON.parse(fs.readFileSync(path.join(INDEX_DIR, file), 'utf8'));
|
|
306
|
-
results.push({
|
|
307
|
-
filename: index.filename,
|
|
308
|
-
filepath: index.filepath,
|
|
309
|
-
lines: index.totalLines,
|
|
310
|
-
symbols: index.symbols.length,
|
|
311
|
-
dedupRatio: index.dedupRatio?.toFixed(2) || 'N/A'
|
|
312
|
-
});
|
|
313
|
-
} catch (e) {}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return results.sort((a, b) => b.lines - a.lines);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
function stats() {
|
|
320
|
-
const files = listIndexed();
|
|
321
|
-
const totalLines = files.reduce((sum, f) => sum + f.lines, 0);
|
|
322
|
-
const totalSymbols = files.reduce((sum, f) => sum + f.symbols, 0);
|
|
323
|
-
|
|
324
|
-
return {
|
|
325
|
-
indexedFiles: files.length,
|
|
326
|
-
totalLines,
|
|
327
|
-
totalSymbols,
|
|
328
|
-
indexDir: INDEX_DIR
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const CONTEXT_TOOLS = {
|
|
333
|
-
ctx_index: {
|
|
334
|
-
description: "Index file for CAZ context compression. FREE.",
|
|
335
|
-
handler: (args) => indexFile(args.filepath)
|
|
336
|
-
},
|
|
337
|
-
ctx_find: {
|
|
338
|
-
description: "Find symbol across indexed files. FREE.",
|
|
339
|
-
handler: (args) => findSymbol(args.name, args.filepath)
|
|
340
|
-
},
|
|
341
|
-
ctx_lines: {
|
|
342
|
-
description: "Get specific line range. FREE.",
|
|
343
|
-
handler: (args) => getLines(args.filepath, args.start, args.end)
|
|
344
|
-
},
|
|
345
|
-
ctx_blocks: {
|
|
346
|
-
description: "Get relevant blocks for query. FREE.",
|
|
347
|
-
handler: (args) => getBlocksByQuery(args.filepath, args.query)
|
|
348
|
-
},
|
|
349
|
-
ctx_list: {
|
|
350
|
-
description: "List indexed files. FREE.",
|
|
351
|
-
handler: () => listIndexed()
|
|
352
|
-
},
|
|
353
|
-
ctx_stats: {
|
|
354
|
-
description: "Get indexing stats. FREE.",
|
|
355
|
-
handler: () => stats()
|
|
356
|
-
},
|
|
357
|
-
caz_dedup: {
|
|
358
|
-
description: "Full CAZ deduplication. PRO $0.02.",
|
|
359
|
-
handler: async (args) => await cazDedup(args.filepath, args.apiKey)
|
|
360
|
-
},
|
|
361
|
-
context_compress: {
|
|
362
|
-
description: "Compress context for query. PRO $0.03.",
|
|
363
|
-
handler: async (args) => await contextCompress(args.filepath, args.query, args.apiKey)
|
|
364
|
-
},
|
|
365
|
-
fog_check: {
|
|
366
|
-
description: "Check fog level. FREE.",
|
|
367
|
-
handler: async (args) => await fogCheck(args.messages, args.apiKey)
|
|
368
|
-
},
|
|
369
|
-
fog_clear: {
|
|
370
|
-
description: "Clear context fog. PRO $0.03.",
|
|
371
|
-
handler: async (args) => await fogClear(args.messages, args.mode, args.apiKey)
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
module.exports = {
|
|
376
|
-
CONTEXT_TOOLS,
|
|
377
|
-
indexFile,
|
|
378
|
-
findSymbol,
|
|
379
|
-
getLines,
|
|
380
|
-
getBlocksByQuery,
|
|
381
|
-
listIndexed,
|
|
382
|
-
stats,
|
|
383
|
-
cazDedup,
|
|
384
|
-
contextCompress,
|
|
385
|
-
fogCheck,
|
|
386
|
-
fogClear
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
if (require.main === module) {
|
|
390
|
-
const args = process.argv.slice(2);
|
|
391
|
-
const cmd = args[0];
|
|
392
|
-
|
|
393
|
-
if (!cmd || cmd === 'help') {
|
|
394
|
-
console.log(`
|
|
395
|
-
50c-context - CAZ Context Compression
|
|
396
|
-
|
|
397
|
-
LOCAL (FREE):
|
|
398
|
-
ctx_index <file> Index file for dedup
|
|
399
|
-
ctx_find <name> [file] Find symbol
|
|
400
|
-
ctx_lines <file> <s> <e> Get line range
|
|
401
|
-
ctx_blocks <file> <query> Get relevant blocks
|
|
402
|
-
ctx_list List indexed files
|
|
403
|
-
ctx_stats Show stats
|
|
404
|
-
|
|
405
|
-
API (PRO):
|
|
406
|
-
caz_dedup <file> Full CAZ deduplication
|
|
407
|
-
context_compress <f> <q> Compress for query
|
|
408
|
-
fog_check Check fog level
|
|
409
|
-
fog_clear Clear context fog
|
|
410
|
-
|
|
411
|
-
Test:
|
|
412
|
-
node caz-context.js test
|
|
413
|
-
`);
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (cmd === 'test') {
|
|
418
|
-
const testFile = 'C:\\Users\\Administrator\\Desktop\\50c\\nj-deploy\\api-unified-v8-FINAL-ALL.py';
|
|
419
|
-
|
|
420
|
-
console.log('='.repeat(60));
|
|
421
|
-
console.log('50c-context TEST');
|
|
422
|
-
console.log('='.repeat(60));
|
|
423
|
-
|
|
424
|
-
console.log('\n[1] Indexing...');
|
|
425
|
-
const idx = indexFile(testFile);
|
|
426
|
-
console.log(idx);
|
|
427
|
-
|
|
428
|
-
console.log('\n[2] Find fog_check...');
|
|
429
|
-
console.log(findSymbol('fog_check'));
|
|
430
|
-
|
|
431
|
-
console.log('\n[3] Get blocks for "fog"...');
|
|
432
|
-
const blocks = getBlocksByQuery(testFile, 'fog');
|
|
433
|
-
console.log(`Matched: ${blocks.matchedSymbols} symbols`);
|
|
434
|
-
console.log(`Sent: ${blocks.sentLines} lines (${blocks.reduction} reduction)`);
|
|
435
|
-
console.log(`First chunk: ${blocks.chunks[0]?.symbol} at line ${blocks.chunks[0]?.startLine}`);
|
|
436
|
-
|
|
437
|
-
console.log('\n[4] Stats...');
|
|
438
|
-
console.log(stats());
|
|
439
|
-
|
|
440
|
-
console.log('\n[5] List indexed...');
|
|
441
|
-
console.log(listIndexed());
|
|
442
|
-
}
|
|
443
|
-
else if (cmd === 'index') {
|
|
444
|
-
console.log(indexFile(args[1]));
|
|
445
|
-
}
|
|
446
|
-
else if (cmd === 'find') {
|
|
447
|
-
console.log(JSON.stringify(findSymbol(args[1], args[2]), null, 2));
|
|
448
|
-
}
|
|
449
|
-
else if (cmd === 'lines') {
|
|
450
|
-
console.log(getLines(args[1], parseInt(args[2]), parseInt(args[3])));
|
|
451
|
-
}
|
|
452
|
-
else if (cmd === 'blocks') {
|
|
453
|
-
console.log(JSON.stringify(getBlocksByQuery(args[1], args[2]), null, 2));
|
|
454
|
-
}
|
|
455
|
-
else if (cmd === 'list') {
|
|
456
|
-
console.log(JSON.stringify(listIndexed(), null, 2));
|
|
457
|
-
}
|
|
458
|
-
else if (cmd === 'stats') {
|
|
459
|
-
console.log(JSON.stringify(stats(), null, 2));
|
|
460
|
-
}
|
|
461
|
-
}
|