@contextos/core 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +886 -91
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -29,10 +29,27 @@ var ConstraintSchema = z.object({
|
|
|
29
29
|
suggestion: z.string().optional(),
|
|
30
30
|
related: z.array(z.string()).optional()
|
|
31
31
|
});
|
|
32
|
+
var isValidGlobPattern = (pattern) => {
|
|
33
|
+
const dangerousPatterns = [
|
|
34
|
+
/\.\./,
|
|
35
|
+
// Directory traversal
|
|
36
|
+
/^~/,
|
|
37
|
+
// Home directory access
|
|
38
|
+
/^\//
|
|
39
|
+
// Absolute path (may be too restrictive)
|
|
40
|
+
];
|
|
41
|
+
return !dangerousPatterns.some((p) => p.test(pattern));
|
|
42
|
+
};
|
|
32
43
|
var BoundarySchema = z.object({
|
|
33
44
|
name: z.string().min(1),
|
|
34
|
-
allow: z.array(z.string())
|
|
35
|
-
|
|
45
|
+
allow: z.array(z.string()).refine(
|
|
46
|
+
(patterns) => patterns.every(isValidGlobPattern),
|
|
47
|
+
{ message: "Boundary patterns must not contain directory traversal (..) or absolute paths" }
|
|
48
|
+
),
|
|
49
|
+
deny: z.array(z.string()).refine(
|
|
50
|
+
(patterns) => patterns.every(isValidGlobPattern),
|
|
51
|
+
{ message: "Boundary patterns must not contain directory traversal (..) or absolute paths" }
|
|
52
|
+
)
|
|
36
53
|
});
|
|
37
54
|
var MetaSchema = z.object({
|
|
38
55
|
last_indexed: z.string().datetime().optional(),
|
|
@@ -48,6 +65,7 @@ var ContextYamlSchema = z.object({
|
|
|
48
65
|
boundaries: z.array(BoundarySchema).optional().default([]),
|
|
49
66
|
meta: MetaSchema.optional()
|
|
50
67
|
});
|
|
68
|
+
var fileSizePattern = /^\d+(\.\d+)?\s*(B|KB|MB|GB|TB)$/i;
|
|
51
69
|
var IndexingConfigSchema = z.object({
|
|
52
70
|
watch_mode: z.boolean().default(true),
|
|
53
71
|
ignore_patterns: z.array(z.string()).default([
|
|
@@ -57,7 +75,9 @@ var IndexingConfigSchema = z.object({
|
|
|
57
75
|
"dist/**",
|
|
58
76
|
".git/**"
|
|
59
77
|
]),
|
|
60
|
-
file_size_limit: z.string().default("1MB")
|
|
78
|
+
file_size_limit: z.string().default("1MB").refine((val) => fileSizePattern.test(val), {
|
|
79
|
+
message: 'File size limit must be in format like "1MB", "500KB", "2GB", etc.'
|
|
80
|
+
})
|
|
61
81
|
});
|
|
62
82
|
var GraphConfigSchema = z.object({
|
|
63
83
|
max_depth: z.number().int().min(1).max(10).default(2),
|
|
@@ -1183,6 +1203,17 @@ var DependencyGraph = class {
|
|
|
1183
1203
|
import Database from "better-sqlite3";
|
|
1184
1204
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1185
1205
|
import { dirname as dirname3 } from "path";
|
|
1206
|
+
|
|
1207
|
+
// src/constants.ts
|
|
1208
|
+
var DEFAULT_TIMEOUT = 1e4;
|
|
1209
|
+
var SANDBOX_TIMEOUT_RATIO = 10;
|
|
1210
|
+
var MAX_VISITED_PATHS = 50;
|
|
1211
|
+
var PATH_CLEANUP_BATCH_SIZE = 10;
|
|
1212
|
+
var VECTOR_PAGE_SIZE = 1e3;
|
|
1213
|
+
var CHARS_PER_TOKEN_CODE = 4;
|
|
1214
|
+
var GIT_MAX_BUFFER = 1024 * 1024;
|
|
1215
|
+
|
|
1216
|
+
// src/embedding/vector-store.ts
|
|
1186
1217
|
var VectorStore = class {
|
|
1187
1218
|
db = null;
|
|
1188
1219
|
embedder = null;
|
|
@@ -1306,7 +1337,7 @@ var VectorStore = class {
|
|
|
1306
1337
|
*/
|
|
1307
1338
|
vectorSearch(queryEmbedding, limit) {
|
|
1308
1339
|
if (!this.db) throw new Error("VectorStore not initialized");
|
|
1309
|
-
const pageSize =
|
|
1340
|
+
const pageSize = VECTOR_PAGE_SIZE;
|
|
1310
1341
|
let offset = 0;
|
|
1311
1342
|
const allResults = [];
|
|
1312
1343
|
while (allResults.length < limit * 2) {
|
|
@@ -1341,7 +1372,7 @@ var VectorStore = class {
|
|
|
1341
1372
|
textSearch(query, limit) {
|
|
1342
1373
|
if (!this.db) throw new Error("VectorStore not initialized");
|
|
1343
1374
|
const terms = query.toLowerCase().split(/\s+/);
|
|
1344
|
-
const pageSize =
|
|
1375
|
+
const pageSize = VECTOR_PAGE_SIZE;
|
|
1345
1376
|
let offset = 0;
|
|
1346
1377
|
const allResults = [];
|
|
1347
1378
|
while (allResults.length < limit * 2) {
|
|
@@ -1739,11 +1770,15 @@ var TokenBudget = class {
|
|
|
1739
1770
|
this.maxTokens = maxTokens || MODEL_LIMITS[modelName] || 32e3;
|
|
1740
1771
|
}
|
|
1741
1772
|
/**
|
|
1742
|
-
* Count tokens in text (
|
|
1743
|
-
*
|
|
1773
|
+
* Count tokens in text (improved approximation)
|
|
1774
|
+
* Uses CHARS_PER_TOKEN_CODE constant for code-dense content
|
|
1775
|
+
*
|
|
1776
|
+
* Note: For production use, consider integrating tiktoken for accurate counts.
|
|
1777
|
+
* This approximation works well for most code scenarios.
|
|
1744
1778
|
*/
|
|
1745
1779
|
count(text) {
|
|
1746
|
-
|
|
1780
|
+
if (!text) return 0;
|
|
1781
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN_CODE);
|
|
1747
1782
|
}
|
|
1748
1783
|
/**
|
|
1749
1784
|
* Get allocation percentages based on budget size
|
|
@@ -1865,7 +1900,7 @@ var TokenBudget = class {
|
|
|
1865
1900
|
* Truncate text to fit within token limit
|
|
1866
1901
|
*/
|
|
1867
1902
|
truncateToTokens(text, maxTokens) {
|
|
1868
|
-
const estimatedChars = maxTokens *
|
|
1903
|
+
const estimatedChars = maxTokens * CHARS_PER_TOKEN_CODE;
|
|
1869
1904
|
if (text.length <= estimatedChars) return text;
|
|
1870
1905
|
const truncated = text.slice(0, estimatedChars);
|
|
1871
1906
|
const lastNewline = truncated.lastIndexOf("\n");
|
|
@@ -2331,24 +2366,24 @@ var ContextBuilder = class {
|
|
|
2331
2366
|
}
|
|
2332
2367
|
/**
|
|
2333
2368
|
* Execute git diff with proper sanitization and error handling
|
|
2369
|
+
* SECURITY: Uses safe command strings with shell:false to prevent injection
|
|
2334
2370
|
*/
|
|
2335
2371
|
async getGitDiff(type) {
|
|
2336
2372
|
try {
|
|
2337
2373
|
const { execSync: execSync2 } = await import("child_process");
|
|
2338
2374
|
const cwd = this.sanitizeGitPath(this.config?.rootDir);
|
|
2339
|
-
const
|
|
2340
|
-
return execSync2(
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
).trim();
|
|
2375
|
+
const command = type === "cached" ? "git diff --cached --name-only" : "git diff --name-only";
|
|
2376
|
+
return execSync2(command, {
|
|
2377
|
+
cwd,
|
|
2378
|
+
encoding: "utf-8",
|
|
2379
|
+
maxBuffer: 1024 * 1024,
|
|
2380
|
+
// 1MB
|
|
2381
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2382
|
+
timeout: 5e3,
|
|
2383
|
+
// 5 second timeout
|
|
2384
|
+
shell: false
|
|
2385
|
+
// Explicitly disable shell to prevent injection
|
|
2386
|
+
}).trim();
|
|
2352
2387
|
} catch (error) {
|
|
2353
2388
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2354
2389
|
console.warn(`Git command failed: ${errorMessage}`);
|
|
@@ -2491,14 +2526,18 @@ var ContextBuilder = class {
|
|
|
2491
2526
|
encoding: "utf-8",
|
|
2492
2527
|
maxBuffer: 1024 * 1024,
|
|
2493
2528
|
// 1MB max
|
|
2494
|
-
timeout: 5e3
|
|
2529
|
+
timeout: 5e3,
|
|
2530
|
+
shell: false
|
|
2531
|
+
// Prevent command injection
|
|
2495
2532
|
});
|
|
2496
2533
|
if (!gitDiff) {
|
|
2497
2534
|
gitDiff = execSync2("git diff", {
|
|
2498
2535
|
cwd,
|
|
2499
2536
|
encoding: "utf-8",
|
|
2500
2537
|
maxBuffer: 1024 * 1024,
|
|
2501
|
-
timeout: 5e3
|
|
2538
|
+
timeout: 5e3,
|
|
2539
|
+
shell: false
|
|
2540
|
+
// Prevent command injection
|
|
2502
2541
|
});
|
|
2503
2542
|
}
|
|
2504
2543
|
} catch {
|
|
@@ -3241,6 +3280,25 @@ var DEFAULT_RLM_CONFIG = {
|
|
|
3241
3280
|
};
|
|
3242
3281
|
|
|
3243
3282
|
// src/rlm/context-api.ts
|
|
3283
|
+
var patternCache = /* @__PURE__ */ new Map();
|
|
3284
|
+
function getCachedPattern(key, pattern, flags = "") {
|
|
3285
|
+
const cacheKey = `${key}:${flags}`;
|
|
3286
|
+
if (!patternCache.has(cacheKey)) {
|
|
3287
|
+
patternCache.set(cacheKey, new RegExp(pattern, flags));
|
|
3288
|
+
}
|
|
3289
|
+
return patternCache.get(cacheKey);
|
|
3290
|
+
}
|
|
3291
|
+
var CACHED_IMPORT_PATTERNS = [
|
|
3292
|
+
getCachedPattern("import-es6", "^import\\s+.+", ""),
|
|
3293
|
+
getCachedPattern("import-python", "^from\\s+.+\\s+import\\s+.+", ""),
|
|
3294
|
+
getCachedPattern("import-commonjs1", "^const\\s+.+=\\s*require\\(", ""),
|
|
3295
|
+
getCachedPattern("import-commonjs2", "^require\\s*\\(", "")
|
|
3296
|
+
];
|
|
3297
|
+
var CACHED_EXPORT_PATTERNS = [
|
|
3298
|
+
getCachedPattern("export-default", "^export\\s+(default\\s+)?(class|function|const|let|interface|type|enum)", ""),
|
|
3299
|
+
getCachedPattern("export-named", "^export\\s*\\{", ""),
|
|
3300
|
+
getCachedPattern("export-commonjs", "^module\\.exports\\s*=", "")
|
|
3301
|
+
];
|
|
3244
3302
|
function createContextAPI(rawContext) {
|
|
3245
3303
|
const lines = rawContext.split("\n");
|
|
3246
3304
|
return {
|
|
@@ -3354,19 +3412,9 @@ function createContextAPI(rawContext) {
|
|
|
3354
3412
|
},
|
|
3355
3413
|
getImports: () => {
|
|
3356
3414
|
const imports = [];
|
|
3357
|
-
const importPatterns = [
|
|
3358
|
-
/^import\s+.+/,
|
|
3359
|
-
// ES6 import
|
|
3360
|
-
/^from\s+.+\s+import\s+.+/,
|
|
3361
|
-
// Python from import
|
|
3362
|
-
/^const\s+.+=\s*require\(/,
|
|
3363
|
-
// CommonJS require
|
|
3364
|
-
/^require\s*\(/
|
|
3365
|
-
// require()
|
|
3366
|
-
];
|
|
3367
3415
|
for (const line of lines) {
|
|
3368
3416
|
const trimmed = line.trim();
|
|
3369
|
-
for (const pattern of
|
|
3417
|
+
for (const pattern of CACHED_IMPORT_PATTERNS) {
|
|
3370
3418
|
if (pattern.test(trimmed)) {
|
|
3371
3419
|
imports.push(trimmed);
|
|
3372
3420
|
break;
|
|
@@ -3377,14 +3425,9 @@ function createContextAPI(rawContext) {
|
|
|
3377
3425
|
},
|
|
3378
3426
|
getExports: () => {
|
|
3379
3427
|
const exports = [];
|
|
3380
|
-
const exportPatterns = [
|
|
3381
|
-
/^export\s+(default\s+)?(class|function|const|let|interface|type|enum)/,
|
|
3382
|
-
/^export\s*\{/,
|
|
3383
|
-
/^module\.exports\s*=/
|
|
3384
|
-
];
|
|
3385
3428
|
for (const line of lines) {
|
|
3386
3429
|
const trimmed = line.trim();
|
|
3387
|
-
for (const pattern of
|
|
3430
|
+
for (const pattern of CACHED_EXPORT_PATTERNS) {
|
|
3388
3431
|
if (pattern.test(trimmed)) {
|
|
3389
3432
|
exports.push(trimmed);
|
|
3390
3433
|
break;
|
|
@@ -3397,17 +3440,17 @@ function createContextAPI(rawContext) {
|
|
|
3397
3440
|
const outline = [];
|
|
3398
3441
|
const patterns = {
|
|
3399
3442
|
function: [
|
|
3400
|
-
|
|
3401
|
-
|
|
3443
|
+
getCachedPattern("outline-fn1", "^(?:export\\s+)?(?:async\\s+)?function\\s+(\\w+)\\s*\\(([^)]*)\\)"),
|
|
3444
|
+
getCachedPattern("outline-fn2", "^(?:export\\s+)?(?:const|let)\\s+(\\w+)\\s*=\\s*(?:async\\s+)?\\([^)]*\\)\\s*=>")
|
|
3402
3445
|
],
|
|
3403
3446
|
class: [
|
|
3404
|
-
|
|
3447
|
+
getCachedPattern("outline-class", "^(?:export\\s+)?(?:abstract\\s+)?class\\s+(\\w+)")
|
|
3405
3448
|
],
|
|
3406
3449
|
interface: [
|
|
3407
|
-
|
|
3450
|
+
getCachedPattern("outline-interface", "^(?:export\\s+)?interface\\s+(\\w+)")
|
|
3408
3451
|
],
|
|
3409
3452
|
type: [
|
|
3410
|
-
|
|
3453
|
+
getCachedPattern("outline-type", "^(?:export\\s+)?type\\s+(\\w+)")
|
|
3411
3454
|
]
|
|
3412
3455
|
};
|
|
3413
3456
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -3665,19 +3708,57 @@ function prepareSandboxVariables(rawContext, additionalVariables = {}) {
|
|
|
3665
3708
|
function validateCode(code) {
|
|
3666
3709
|
const issues = [];
|
|
3667
3710
|
const dangerousPatterns = [
|
|
3711
|
+
// Module system bypasses
|
|
3668
3712
|
{ pattern: /\brequire\s*\(/, message: "require() is not allowed" },
|
|
3669
3713
|
{ pattern: /\bimport\s*\(/, message: "Dynamic import() is not allowed" },
|
|
3670
|
-
{ pattern: /\
|
|
3671
|
-
|
|
3672
|
-
{ pattern: /\
|
|
3714
|
+
{ pattern: /\bimport\s+\.+/, message: "Relative import is not allowed" },
|
|
3715
|
+
// Global object access
|
|
3716
|
+
{ pattern: /\bprocess\s*\./, message: "process property access is not allowed" },
|
|
3717
|
+
{ pattern: /\bprocess\s*$/, message: "process variable access is not allowed" },
|
|
3718
|
+
{ pattern: /\bglobal\s*\./, message: "global access is not allowed" },
|
|
3719
|
+
{ pattern: /\bglobal\s*$/, message: "global variable access is not allowed" },
|
|
3720
|
+
{ pattern: /\bglobalThis\s*\./, message: "globalThis access is not allowed" },
|
|
3721
|
+
{ pattern: /\bglobalThis\s*$/, message: "globalThis variable access is not allowed" },
|
|
3722
|
+
// Code execution
|
|
3673
3723
|
{ pattern: /\beval\s*\(/, message: "eval() is not allowed" },
|
|
3674
3724
|
{ pattern: /\bFunction\s*\(/, message: "Function constructor is not allowed" },
|
|
3675
|
-
{ pattern: /\
|
|
3676
|
-
{ pattern: /\
|
|
3725
|
+
{ pattern: /\bnew\s+Function\s*\(/, message: "new Function() is not allowed" },
|
|
3726
|
+
{ pattern: /\bsetTimeout\s*\(/, message: "setTimeout() is not allowed" },
|
|
3727
|
+
{ pattern: /\bsetInterval\s*\(/, message: "setInterval() is not allowed" },
|
|
3728
|
+
{ pattern: /\bsetImmediate\s*\(/, message: "setImmediate() is not allowed" },
|
|
3729
|
+
// Child process and system access
|
|
3730
|
+
{ pattern: /\bchild_process/, message: "child_process module is not allowed" },
|
|
3677
3731
|
{ pattern: /\bexec\s*\(/, message: "exec() is not allowed" },
|
|
3678
3732
|
{ pattern: /\bspawn\s*\(/, message: "spawn() is not allowed" },
|
|
3733
|
+
{ pattern: /\bfork\s*\(/, message: "fork() is not allowed" },
|
|
3734
|
+
{ pattern: /\bexecSync\s*\(/, message: "execSync() is not allowed" },
|
|
3735
|
+
// File system access
|
|
3736
|
+
{ pattern: /\bfs\s*\./, message: "fs module access is not allowed" },
|
|
3737
|
+
{ pattern: /\bfs\s*$/, message: "fs module variable is not allowed" },
|
|
3738
|
+
{ pattern: /\brequire\s*\(\s*['"]fs['"]/, message: "fs module require is not allowed" },
|
|
3739
|
+
// Directory traversal
|
|
3740
|
+
{ pattern: /\bprocess\s*\.\s*chdir\s*\(/, message: "process.chdir() is not allowed" },
|
|
3741
|
+
{ pattern: /\bprocess\s*\.\s*cwd\s*\(/, message: "process.cwd() is not allowed" },
|
|
3742
|
+
// Buffer exploits
|
|
3743
|
+
{ pattern: /\bBuffer\s*\./, message: "Buffer static methods are not allowed" },
|
|
3744
|
+
{ pattern: /\bnew\s+Buffer\s*\(/, message: "new Buffer() is not allowed" },
|
|
3745
|
+
// Prototype pollution
|
|
3679
3746
|
{ pattern: /\b__proto__/, message: "__proto__ access is not allowed" },
|
|
3680
|
-
{ pattern: /\bconstructor\s*\[/, message: "constructor access is not allowed" }
|
|
3747
|
+
{ pattern: /\bconstructor\s*\[/, message: "constructor array access is not allowed" },
|
|
3748
|
+
{ pattern: /\bprototype\s*\./, message: "prototype modification is not allowed" },
|
|
3749
|
+
{ pattern: /\bObject\s*\.\s*prototype/, message: "Object.prototype modification is not allowed" },
|
|
3750
|
+
// Reflect and Proxy exploits
|
|
3751
|
+
{ pattern: /\bReflect\s*\.\s*set\s*\(/, message: "Reflect.set() is not allowed" },
|
|
3752
|
+
{ pattern: /\bnew\s+Proxy\s*\(/, message: "Proxy constructor is not allowed" },
|
|
3753
|
+
// Async function exploits
|
|
3754
|
+
{ pattern: /\basync\s+Function\s*\(/, message: "async Function constructor is not allowed" },
|
|
3755
|
+
// Module and namespace access
|
|
3756
|
+
{ pattern: /\bmodule\s*\./, message: "module access is not allowed" },
|
|
3757
|
+
{ pattern: /\bmodule\s*$/, message: "module variable access is not allowed" },
|
|
3758
|
+
{ pattern: /\bexports\s*\./, message: "exports access is not allowed" },
|
|
3759
|
+
{ pattern: /\bexports\s*$/, message: "exports variable access is not allowed" },
|
|
3760
|
+
{ pattern: /\b__dirname/, message: "__dirname access is not allowed" },
|
|
3761
|
+
{ pattern: /\b__filename/, message: "__filename access is not allowed" }
|
|
3681
3762
|
];
|
|
3682
3763
|
for (const { pattern, message } of dangerousPatterns) {
|
|
3683
3764
|
if (pattern.test(code)) {
|
|
@@ -3902,7 +3983,7 @@ var RLMEngine = class {
|
|
|
3902
3983
|
constructor(options = {}) {
|
|
3903
3984
|
this.config = { ...DEFAULT_RLM_CONFIG, ...options };
|
|
3904
3985
|
this.sandbox = createSandbox(this.config.environment, {
|
|
3905
|
-
timeout: Math.min(
|
|
3986
|
+
timeout: Math.min(DEFAULT_TIMEOUT, this.config.timeoutMs / SANDBOX_TIMEOUT_RATIO)
|
|
3906
3987
|
});
|
|
3907
3988
|
this.executionId = this.generateExecutionId();
|
|
3908
3989
|
}
|
|
@@ -4045,10 +4126,10 @@ Depth: ${depth}/${this.config.maxDepth}`
|
|
|
4045
4126
|
continue;
|
|
4046
4127
|
}
|
|
4047
4128
|
state.visitedPaths.set(pathKey, now);
|
|
4048
|
-
if (state.visitedPaths.size >
|
|
4129
|
+
if (state.visitedPaths.size > MAX_VISITED_PATHS) {
|
|
4049
4130
|
const entries = Array.from(state.visitedPaths.entries());
|
|
4050
4131
|
entries.sort((a, b) => a[1] - b[1]);
|
|
4051
|
-
for (let i = 0; i <
|
|
4132
|
+
for (let i = 0; i < PATH_CLEANUP_BATCH_SIZE; i++) {
|
|
4052
4133
|
state.visitedPaths.delete(entries[i][0]);
|
|
4053
4134
|
}
|
|
4054
4135
|
}
|
|
@@ -4872,15 +4953,17 @@ var ScopeManager = class {
|
|
|
4872
4953
|
switch (condition.type) {
|
|
4873
4954
|
case "always":
|
|
4874
4955
|
return true;
|
|
4875
|
-
case "goal_contains":
|
|
4956
|
+
case "goal_contains": {
|
|
4876
4957
|
const values = Array.isArray(condition.value) ? condition.value : [condition.value || ""];
|
|
4877
4958
|
return values.some((v) => goalLower.includes(v.toLowerCase()));
|
|
4878
|
-
|
|
4959
|
+
}
|
|
4960
|
+
case "file_in": {
|
|
4879
4961
|
if (!targetFiles) return false;
|
|
4880
4962
|
const patterns = Array.isArray(condition.value) ? condition.value : [condition.value || ""];
|
|
4881
4963
|
return targetFiles.some(
|
|
4882
4964
|
(file) => patterns.some((pattern) => this.matchGlob(file, pattern))
|
|
4883
4965
|
);
|
|
4966
|
+
}
|
|
4884
4967
|
case "tag_is":
|
|
4885
4968
|
return false;
|
|
4886
4969
|
default:
|
|
@@ -5056,7 +5139,7 @@ function createWatchdog(config) {
|
|
|
5056
5139
|
|
|
5057
5140
|
// src/sync/team-sync.ts
|
|
5058
5141
|
import { execSync } from "child_process";
|
|
5059
|
-
import { readFileSync as
|
|
5142
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
5060
5143
|
import { join as join5 } from "path";
|
|
5061
5144
|
import { parse, stringify as stringify2 } from "yaml";
|
|
5062
5145
|
function validateGitBranchName(branch) {
|
|
@@ -5096,7 +5179,7 @@ var TeamSync = class {
|
|
|
5096
5179
|
loadSyncConfig() {
|
|
5097
5180
|
const configPath = join5(this.contextosDir, "sync.yaml");
|
|
5098
5181
|
if (existsSync5(configPath)) {
|
|
5099
|
-
const content =
|
|
5182
|
+
const content = readFileSync4(configPath, "utf-8");
|
|
5100
5183
|
return { ...DEFAULT_SYNC_CONFIG, ...parse(content) };
|
|
5101
5184
|
}
|
|
5102
5185
|
return DEFAULT_SYNC_CONFIG;
|
|
@@ -5230,7 +5313,7 @@ var TemplateManager = class {
|
|
|
5230
5313
|
const files = __require("fs").readdirSync(this.templatesDir);
|
|
5231
5314
|
for (const file of files) {
|
|
5232
5315
|
if (file.endsWith(".yaml")) {
|
|
5233
|
-
const content =
|
|
5316
|
+
const content = readFileSync4(join5(this.templatesDir, file), "utf-8");
|
|
5234
5317
|
templates.push(parse(content));
|
|
5235
5318
|
}
|
|
5236
5319
|
}
|
|
@@ -5249,8 +5332,8 @@ var TemplateManager = class {
|
|
|
5249
5332
|
description,
|
|
5250
5333
|
author,
|
|
5251
5334
|
version: "1.0.0",
|
|
5252
|
-
context: existsSync5(contextPath) ? parse(
|
|
5253
|
-
config: existsSync5(configPath) ? parse(
|
|
5335
|
+
context: existsSync5(contextPath) ? parse(readFileSync4(contextPath, "utf-8")) : {},
|
|
5336
|
+
config: existsSync5(configPath) ? parse(readFileSync4(configPath, "utf-8")) : {}
|
|
5254
5337
|
};
|
|
5255
5338
|
const templatePath = join5(this.templatesDir, `${name}.yaml`);
|
|
5256
5339
|
writeFileSync2(templatePath, stringify2(template, { indent: 2 }), "utf-8");
|
|
@@ -5263,7 +5346,7 @@ var TemplateManager = class {
|
|
|
5263
5346
|
if (!existsSync5(templatePath)) {
|
|
5264
5347
|
throw new Error(`Template '${name}' not found`);
|
|
5265
5348
|
}
|
|
5266
|
-
const template = parse(
|
|
5349
|
+
const template = parse(readFileSync4(templatePath, "utf-8"));
|
|
5267
5350
|
const contextPath = join5(this.templatesDir, "..", "context.yaml");
|
|
5268
5351
|
const configPath = join5(this.templatesDir, "..", "config.yaml");
|
|
5269
5352
|
if (template.context && Object.keys(template.context).length > 0) {
|
|
@@ -5483,7 +5566,7 @@ var CloudSync = class {
|
|
|
5483
5566
|
};
|
|
5484
5567
|
|
|
5485
5568
|
// src/analytics/analytics.ts
|
|
5486
|
-
import { existsSync as existsSync7, readFileSync as
|
|
5569
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
5487
5570
|
import { join as join7 } from "path";
|
|
5488
5571
|
var AnalyticsCollector = class {
|
|
5489
5572
|
analyticsDir;
|
|
@@ -5534,7 +5617,7 @@ var AnalyticsCollector = class {
|
|
|
5534
5617
|
loadEvents() {
|
|
5535
5618
|
if (existsSync7(this.eventsFile)) {
|
|
5536
5619
|
try {
|
|
5537
|
-
return JSON.parse(
|
|
5620
|
+
return JSON.parse(readFileSync6(this.eventsFile, "utf-8"));
|
|
5538
5621
|
} catch {
|
|
5539
5622
|
return [];
|
|
5540
5623
|
}
|
|
@@ -5562,7 +5645,7 @@ var AnalyticsCollector = class {
|
|
|
5562
5645
|
loadDailyStats() {
|
|
5563
5646
|
if (existsSync7(this.statsFile)) {
|
|
5564
5647
|
try {
|
|
5565
|
-
return JSON.parse(
|
|
5648
|
+
return JSON.parse(readFileSync6(this.statsFile, "utf-8"));
|
|
5566
5649
|
} catch {
|
|
5567
5650
|
return [];
|
|
5568
5651
|
}
|
|
@@ -5628,7 +5711,7 @@ var AnalyticsCollector = class {
|
|
|
5628
5711
|
};
|
|
5629
5712
|
|
|
5630
5713
|
// src/compliance/rbac.ts
|
|
5631
|
-
import { readFileSync as
|
|
5714
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
|
|
5632
5715
|
import { join as join8 } from "path";
|
|
5633
5716
|
import crypto2 from "crypto";
|
|
5634
5717
|
var BUILT_IN_ROLES = [
|
|
@@ -5704,7 +5787,7 @@ var RBACManager = class {
|
|
|
5704
5787
|
}
|
|
5705
5788
|
if (existsSync8(this.rolesFile)) {
|
|
5706
5789
|
try {
|
|
5707
|
-
const customRoles = JSON.parse(
|
|
5790
|
+
const customRoles = JSON.parse(readFileSync7(this.rolesFile, "utf-8"));
|
|
5708
5791
|
for (const role of customRoles) {
|
|
5709
5792
|
this.roles.set(role.id, role);
|
|
5710
5793
|
}
|
|
@@ -5713,7 +5796,7 @@ var RBACManager = class {
|
|
|
5713
5796
|
}
|
|
5714
5797
|
if (existsSync8(this.usersFile)) {
|
|
5715
5798
|
try {
|
|
5716
|
-
const users = JSON.parse(
|
|
5799
|
+
const users = JSON.parse(readFileSync7(this.usersFile, "utf-8"));
|
|
5717
5800
|
for (const user of users) {
|
|
5718
5801
|
this.users.set(user.id, user);
|
|
5719
5802
|
}
|
|
@@ -5722,7 +5805,7 @@ var RBACManager = class {
|
|
|
5722
5805
|
}
|
|
5723
5806
|
if (existsSync8(this.policiesFile)) {
|
|
5724
5807
|
try {
|
|
5725
|
-
this.policies = JSON.parse(
|
|
5808
|
+
this.policies = JSON.parse(readFileSync7(this.policiesFile, "utf-8"));
|
|
5726
5809
|
} catch {
|
|
5727
5810
|
}
|
|
5728
5811
|
}
|
|
@@ -5883,7 +5966,7 @@ var RBACManager = class {
|
|
|
5883
5966
|
};
|
|
5884
5967
|
|
|
5885
5968
|
// src/compliance/audit.ts
|
|
5886
|
-
import { existsSync as existsSync9, readFileSync as
|
|
5969
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6, appendFileSync, mkdirSync as mkdirSync6 } from "fs";
|
|
5887
5970
|
import { join as join9 } from "path";
|
|
5888
5971
|
import crypto3 from "crypto";
|
|
5889
5972
|
var AuditLogger = class {
|
|
@@ -5945,7 +6028,7 @@ var AuditLogger = class {
|
|
|
5945
6028
|
loadIndex() {
|
|
5946
6029
|
if (existsSync9(this.indexFile)) {
|
|
5947
6030
|
try {
|
|
5948
|
-
return JSON.parse(
|
|
6031
|
+
return JSON.parse(readFileSync8(this.indexFile, "utf-8"));
|
|
5949
6032
|
} catch {
|
|
5950
6033
|
return {};
|
|
5951
6034
|
}
|
|
@@ -5962,7 +6045,7 @@ var AuditLogger = class {
|
|
|
5962
6045
|
for (const logFile of logFiles) {
|
|
5963
6046
|
if (entries.length >= limit) break;
|
|
5964
6047
|
const filePath = join9(this.auditDir, logFile);
|
|
5965
|
-
const content =
|
|
6048
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
5966
6049
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
5967
6050
|
for (const line of lines.reverse()) {
|
|
5968
6051
|
if (entries.length >= limit) break;
|
|
@@ -5999,7 +6082,7 @@ var AuditLogger = class {
|
|
|
5999
6082
|
*/
|
|
6000
6083
|
verifyLogFile(filename) {
|
|
6001
6084
|
const filePath = join9(this.auditDir, filename);
|
|
6002
|
-
const content =
|
|
6085
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
6003
6086
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
6004
6087
|
const result = { valid: 0, invalid: 0, entries: [] };
|
|
6005
6088
|
for (const line of lines) {
|
|
@@ -6053,7 +6136,7 @@ var AuditLogger = class {
|
|
|
6053
6136
|
};
|
|
6054
6137
|
|
|
6055
6138
|
// src/plugins/manager.ts
|
|
6056
|
-
import { existsSync as existsSync10, readdirSync, readFileSync as
|
|
6139
|
+
import { existsSync as existsSync10, readdirSync, readFileSync as readFileSync9, mkdirSync as mkdirSync7, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
6057
6140
|
import { join as join10, resolve, normalize as normalize2 } from "path";
|
|
6058
6141
|
var PluginManager = class {
|
|
6059
6142
|
plugins = /* @__PURE__ */ new Map();
|
|
@@ -6107,7 +6190,7 @@ var PluginManager = class {
|
|
|
6107
6190
|
if (!existsSync10(manifestPath)) {
|
|
6108
6191
|
throw new Error(`Plugin manifest not found: ${manifestPath}`);
|
|
6109
6192
|
}
|
|
6110
|
-
const manifestContent =
|
|
6193
|
+
const manifestContent = readFileSync9(manifestPath, "utf-8");
|
|
6111
6194
|
let manifest;
|
|
6112
6195
|
try {
|
|
6113
6196
|
manifest = JSON.parse(manifestContent);
|
|
@@ -6202,7 +6285,7 @@ The file may contain invalid JSON.`
|
|
|
6202
6285
|
mkdirSync7(targetDir, { recursive: true });
|
|
6203
6286
|
let manifest;
|
|
6204
6287
|
try {
|
|
6205
|
-
const manifestContent =
|
|
6288
|
+
const manifestContent = readFileSync9(join10(sourcePath, "package.json"), "utf-8");
|
|
6206
6289
|
manifest = JSON.parse(manifestContent);
|
|
6207
6290
|
} catch (error) {
|
|
6208
6291
|
throw new Error(
|
|
@@ -6210,7 +6293,7 @@ The file may contain invalid JSON.`
|
|
|
6210
6293
|
);
|
|
6211
6294
|
}
|
|
6212
6295
|
writeFileSync7(join10(targetDir, "package.json"), JSON.stringify(manifest, null, 2));
|
|
6213
|
-
const mainContent =
|
|
6296
|
+
const mainContent = readFileSync9(join10(sourcePath, manifest.main), "utf-8");
|
|
6214
6297
|
writeFileSync7(join10(targetDir, manifest.main), mainContent);
|
|
6215
6298
|
} else {
|
|
6216
6299
|
throw new Error("Remote plugin installation not yet implemented");
|
|
@@ -6370,7 +6453,7 @@ ${commandsCode}
|
|
|
6370
6453
|
if (!normalized.startsWith(rootNormalized)) {
|
|
6371
6454
|
throw new Error(`Path traversal detected: "${path}" escapes project boundaries`);
|
|
6372
6455
|
}
|
|
6373
|
-
return
|
|
6456
|
+
return readFileSync9(normalized, "utf-8");
|
|
6374
6457
|
},
|
|
6375
6458
|
getDependencies: async (_path, _depth = 2) => {
|
|
6376
6459
|
return [];
|
|
@@ -6390,7 +6473,7 @@ function createPluginManager(projectRoot) {
|
|
|
6390
6473
|
}
|
|
6391
6474
|
|
|
6392
6475
|
// src/plugins/registry.ts
|
|
6393
|
-
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as
|
|
6476
|
+
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync10 } from "fs";
|
|
6394
6477
|
import { join as join11 } from "path";
|
|
6395
6478
|
var PluginRegistry = class {
|
|
6396
6479
|
config;
|
|
@@ -6414,7 +6497,7 @@ var PluginRegistry = class {
|
|
|
6414
6497
|
if (!existsSync11(manifestPath)) continue;
|
|
6415
6498
|
try {
|
|
6416
6499
|
const manifest = JSON.parse(
|
|
6417
|
-
|
|
6500
|
+
readFileSync10(manifestPath, "utf-8")
|
|
6418
6501
|
);
|
|
6419
6502
|
const disabledPath = join11(pluginPath, ".disabled");
|
|
6420
6503
|
const enabled = !existsSync11(disabledPath);
|
|
@@ -6555,7 +6638,7 @@ function createPluginRegistry(projectRoot) {
|
|
|
6555
6638
|
}
|
|
6556
6639
|
|
|
6557
6640
|
// src/finetuning/collector.ts
|
|
6558
|
-
import { existsSync as existsSync12, readFileSync as
|
|
6641
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
|
|
6559
6642
|
import { join as join12 } from "path";
|
|
6560
6643
|
import { createHash as createHash4 } from "crypto";
|
|
6561
6644
|
var TrainingDataCollector = class {
|
|
@@ -6576,7 +6659,7 @@ var TrainingDataCollector = class {
|
|
|
6576
6659
|
const dataFile = join12(this.dataDir, "examples.json");
|
|
6577
6660
|
if (existsSync12(dataFile)) {
|
|
6578
6661
|
try {
|
|
6579
|
-
const data = JSON.parse(
|
|
6662
|
+
const data = JSON.parse(readFileSync11(dataFile, "utf-8"));
|
|
6580
6663
|
this.examples = data.examples || [];
|
|
6581
6664
|
} catch {
|
|
6582
6665
|
this.examples = [];
|
|
@@ -7591,12 +7674,711 @@ function setGlobalLogger(logger) {
|
|
|
7591
7674
|
globalLogger = logger;
|
|
7592
7675
|
}
|
|
7593
7676
|
|
|
7677
|
+
// src/telemetry/metrics.ts
|
|
7678
|
+
var MetricsCollector = class {
|
|
7679
|
+
counters = /* @__PURE__ */ new Map();
|
|
7680
|
+
gauges = /* @__PURE__ */ new Map();
|
|
7681
|
+
histograms = /* @__PURE__ */ new Map();
|
|
7682
|
+
enabled;
|
|
7683
|
+
flushInterval = null;
|
|
7684
|
+
onFlush;
|
|
7685
|
+
constructor(options = {}) {
|
|
7686
|
+
this.enabled = options.enabled ?? process.env.CONTEXTOS_TELEMETRY !== "false";
|
|
7687
|
+
this.onFlush = options.onFlush;
|
|
7688
|
+
if (options.flushIntervalMs && options.flushIntervalMs > 0) {
|
|
7689
|
+
this.flushInterval = setInterval(() => {
|
|
7690
|
+
this.flush();
|
|
7691
|
+
}, options.flushIntervalMs);
|
|
7692
|
+
}
|
|
7693
|
+
}
|
|
7694
|
+
/**
|
|
7695
|
+
* Increment a counter
|
|
7696
|
+
*/
|
|
7697
|
+
increment(name, value = 1, labels) {
|
|
7698
|
+
if (!this.enabled) return;
|
|
7699
|
+
const key = this.makeKey(name, labels);
|
|
7700
|
+
const current = this.counters.get(key) || 0;
|
|
7701
|
+
this.counters.set(key, current + value);
|
|
7702
|
+
}
|
|
7703
|
+
/**
|
|
7704
|
+
* Set a gauge value
|
|
7705
|
+
*/
|
|
7706
|
+
gauge(name, value, labels) {
|
|
7707
|
+
if (!this.enabled) return;
|
|
7708
|
+
const key = this.makeKey(name, labels);
|
|
7709
|
+
this.gauges.set(key, value);
|
|
7710
|
+
}
|
|
7711
|
+
/**
|
|
7712
|
+
* Record a histogram value (typically timing)
|
|
7713
|
+
*/
|
|
7714
|
+
histogram(name, value, labels) {
|
|
7715
|
+
if (!this.enabled) return;
|
|
7716
|
+
const key = this.makeKey(name, labels);
|
|
7717
|
+
const values = this.histograms.get(key) || [];
|
|
7718
|
+
values.push(value);
|
|
7719
|
+
this.histograms.set(key, values);
|
|
7720
|
+
}
|
|
7721
|
+
/**
|
|
7722
|
+
* Time a function execution
|
|
7723
|
+
*/
|
|
7724
|
+
async time(name, fn, labels) {
|
|
7725
|
+
const start = performance.now();
|
|
7726
|
+
try {
|
|
7727
|
+
return await fn();
|
|
7728
|
+
} finally {
|
|
7729
|
+
const duration = performance.now() - start;
|
|
7730
|
+
this.histogram(name, duration, labels);
|
|
7731
|
+
}
|
|
7732
|
+
}
|
|
7733
|
+
/**
|
|
7734
|
+
* Time a synchronous function execution
|
|
7735
|
+
*/
|
|
7736
|
+
timeSync(name, fn, labels) {
|
|
7737
|
+
const start = performance.now();
|
|
7738
|
+
try {
|
|
7739
|
+
return fn();
|
|
7740
|
+
} finally {
|
|
7741
|
+
const duration = performance.now() - start;
|
|
7742
|
+
this.histogram(name, duration, labels);
|
|
7743
|
+
}
|
|
7744
|
+
}
|
|
7745
|
+
/**
|
|
7746
|
+
* Get current snapshot of all metrics
|
|
7747
|
+
*/
|
|
7748
|
+
getSnapshot() {
|
|
7749
|
+
const snapshot = {
|
|
7750
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
7751
|
+
counters: Object.fromEntries(this.counters),
|
|
7752
|
+
gauges: Object.fromEntries(this.gauges),
|
|
7753
|
+
histograms: {}
|
|
7754
|
+
};
|
|
7755
|
+
for (const [key, values] of this.histograms) {
|
|
7756
|
+
if (values.length === 0) continue;
|
|
7757
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
7758
|
+
snapshot.histograms[key] = {
|
|
7759
|
+
count: values.length,
|
|
7760
|
+
sum: values.reduce((a, b) => a + b, 0),
|
|
7761
|
+
min: sorted[0],
|
|
7762
|
+
max: sorted[sorted.length - 1],
|
|
7763
|
+
avg: values.reduce((a, b) => a + b, 0) / values.length,
|
|
7764
|
+
p50: this.percentile(sorted, 50),
|
|
7765
|
+
p90: this.percentile(sorted, 90),
|
|
7766
|
+
p99: this.percentile(sorted, 99)
|
|
7767
|
+
};
|
|
7768
|
+
}
|
|
7769
|
+
return snapshot;
|
|
7770
|
+
}
|
|
7771
|
+
/**
|
|
7772
|
+
* Flush metrics and reset
|
|
7773
|
+
*/
|
|
7774
|
+
flush() {
|
|
7775
|
+
const snapshot = this.getSnapshot();
|
|
7776
|
+
if (this.onFlush) {
|
|
7777
|
+
this.onFlush(snapshot);
|
|
7778
|
+
}
|
|
7779
|
+
this.counters.clear();
|
|
7780
|
+
this.histograms.clear();
|
|
7781
|
+
return snapshot;
|
|
7782
|
+
}
|
|
7783
|
+
/**
|
|
7784
|
+
* Stop the flush interval
|
|
7785
|
+
*/
|
|
7786
|
+
stop() {
|
|
7787
|
+
if (this.flushInterval) {
|
|
7788
|
+
clearInterval(this.flushInterval);
|
|
7789
|
+
this.flushInterval = null;
|
|
7790
|
+
}
|
|
7791
|
+
}
|
|
7792
|
+
makeKey(name, labels) {
|
|
7793
|
+
if (!labels || Object.keys(labels).length === 0) {
|
|
7794
|
+
return name;
|
|
7795
|
+
}
|
|
7796
|
+
const labelStr = Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
|
|
7797
|
+
return `${name}{${labelStr}}`;
|
|
7798
|
+
}
|
|
7799
|
+
percentile(sorted, p) {
|
|
7800
|
+
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
7801
|
+
return sorted[Math.max(0, index)];
|
|
7802
|
+
}
|
|
7803
|
+
};
|
|
7804
|
+
var METRICS = {
|
|
7805
|
+
// Indexing
|
|
7806
|
+
INDEX_FILES_TOTAL: "contextos_index_files_total",
|
|
7807
|
+
INDEX_DURATION_MS: "contextos_index_duration_ms",
|
|
7808
|
+
INDEX_ERRORS: "contextos_index_errors_total",
|
|
7809
|
+
// Context building
|
|
7810
|
+
CONTEXT_BUILD_DURATION_MS: "contextos_context_build_duration_ms",
|
|
7811
|
+
CONTEXT_FILES_INCLUDED: "contextos_context_files_included",
|
|
7812
|
+
CONTEXT_TOKENS: "contextos_context_tokens",
|
|
7813
|
+
// API calls
|
|
7814
|
+
API_CALLS_TOTAL: "contextos_api_calls_total",
|
|
7815
|
+
API_DURATION_MS: "contextos_api_duration_ms",
|
|
7816
|
+
API_ERRORS: "contextos_api_errors_total",
|
|
7817
|
+
API_TOKENS_USED: "contextos_api_tokens_used",
|
|
7818
|
+
// RLM
|
|
7819
|
+
RLM_EXECUTIONS: "contextos_rlm_executions_total",
|
|
7820
|
+
RLM_DURATION_MS: "contextos_rlm_duration_ms",
|
|
7821
|
+
RLM_DEPTH: "contextos_rlm_depth",
|
|
7822
|
+
RLM_WATCHDOG_TERMINATIONS: "contextos_rlm_watchdog_terminations",
|
|
7823
|
+
// Cache
|
|
7824
|
+
CACHE_HITS: "contextos_cache_hits_total",
|
|
7825
|
+
CACHE_MISSES: "contextos_cache_misses_total",
|
|
7826
|
+
CACHE_SIZE_BYTES: "contextos_cache_size_bytes",
|
|
7827
|
+
// Memory
|
|
7828
|
+
MEMORY_HEAP_USED: "contextos_memory_heap_used_bytes",
|
|
7829
|
+
MEMORY_HEAP_TOTAL: "contextos_memory_heap_total_bytes"
|
|
7830
|
+
};
|
|
7831
|
+
|
|
7832
|
+
// src/telemetry/tracer.ts
|
|
7833
|
+
var Span = class _Span {
|
|
7834
|
+
context;
|
|
7835
|
+
name;
|
|
7836
|
+
startTime;
|
|
7837
|
+
endTime;
|
|
7838
|
+
status = "unset";
|
|
7839
|
+
statusMessage;
|
|
7840
|
+
attributes = {};
|
|
7841
|
+
events = [];
|
|
7842
|
+
children = [];
|
|
7843
|
+
constructor(name, parentContext, attributes) {
|
|
7844
|
+
this.name = name;
|
|
7845
|
+
this.startTime = /* @__PURE__ */ new Date();
|
|
7846
|
+
this.context = {
|
|
7847
|
+
traceId: parentContext?.traceId || this.generateId(32),
|
|
7848
|
+
spanId: this.generateId(16),
|
|
7849
|
+
parentSpanId: parentContext?.spanId
|
|
7850
|
+
};
|
|
7851
|
+
if (attributes) {
|
|
7852
|
+
this.attributes = { ...attributes };
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7855
|
+
/**
|
|
7856
|
+
* Set an attribute on the span
|
|
7857
|
+
*/
|
|
7858
|
+
setAttribute(key, value) {
|
|
7859
|
+
this.attributes[key] = value;
|
|
7860
|
+
return this;
|
|
7861
|
+
}
|
|
7862
|
+
/**
|
|
7863
|
+
* Set multiple attributes
|
|
7864
|
+
*/
|
|
7865
|
+
setAttributes(attributes) {
|
|
7866
|
+
Object.assign(this.attributes, attributes);
|
|
7867
|
+
return this;
|
|
7868
|
+
}
|
|
7869
|
+
/**
|
|
7870
|
+
* Add an event to the span
|
|
7871
|
+
*/
|
|
7872
|
+
addEvent(name, attributes) {
|
|
7873
|
+
this.events.push({
|
|
7874
|
+
name,
|
|
7875
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
7876
|
+
attributes
|
|
7877
|
+
});
|
|
7878
|
+
return this;
|
|
7879
|
+
}
|
|
7880
|
+
/**
|
|
7881
|
+
* Set the span status
|
|
7882
|
+
*/
|
|
7883
|
+
setStatus(status, message) {
|
|
7884
|
+
this.status = status;
|
|
7885
|
+
this.statusMessage = message;
|
|
7886
|
+
return this;
|
|
7887
|
+
}
|
|
7888
|
+
/**
|
|
7889
|
+
* Record an exception
|
|
7890
|
+
*/
|
|
7891
|
+
recordException(error) {
|
|
7892
|
+
this.addEvent("exception", {
|
|
7893
|
+
"exception.type": error.name,
|
|
7894
|
+
"exception.message": error.message,
|
|
7895
|
+
"exception.stacktrace": error.stack
|
|
7896
|
+
});
|
|
7897
|
+
this.setStatus("error", error.message);
|
|
7898
|
+
return this;
|
|
7899
|
+
}
|
|
7900
|
+
/**
|
|
7901
|
+
* End the span
|
|
7902
|
+
*/
|
|
7903
|
+
end() {
|
|
7904
|
+
if (!this.endTime) {
|
|
7905
|
+
this.endTime = /* @__PURE__ */ new Date();
|
|
7906
|
+
if (this.status === "unset") {
|
|
7907
|
+
this.status = "ok";
|
|
7908
|
+
}
|
|
7909
|
+
}
|
|
7910
|
+
return this;
|
|
7911
|
+
}
|
|
7912
|
+
/**
|
|
7913
|
+
* Get span duration in milliseconds
|
|
7914
|
+
*/
|
|
7915
|
+
getDuration() {
|
|
7916
|
+
const end = this.endTime || /* @__PURE__ */ new Date();
|
|
7917
|
+
return end.getTime() - this.startTime.getTime();
|
|
7918
|
+
}
|
|
7919
|
+
/**
|
|
7920
|
+
* Check if span has ended
|
|
7921
|
+
*/
|
|
7922
|
+
isEnded() {
|
|
7923
|
+
return !!this.endTime;
|
|
7924
|
+
}
|
|
7925
|
+
/**
|
|
7926
|
+
* Create a child span
|
|
7927
|
+
*/
|
|
7928
|
+
startChild(name, attributes) {
|
|
7929
|
+
const child = new _Span(name, this.context, attributes);
|
|
7930
|
+
this.children.push(child);
|
|
7931
|
+
return child;
|
|
7932
|
+
}
|
|
7933
|
+
/**
|
|
7934
|
+
* Convert to JSON for logging/export
|
|
7935
|
+
*/
|
|
7936
|
+
toJSON() {
|
|
7937
|
+
return {
|
|
7938
|
+
traceId: this.context.traceId,
|
|
7939
|
+
spanId: this.context.spanId,
|
|
7940
|
+
parentSpanId: this.context.parentSpanId,
|
|
7941
|
+
name: this.name,
|
|
7942
|
+
startTime: this.startTime.toISOString(),
|
|
7943
|
+
endTime: this.endTime?.toISOString(),
|
|
7944
|
+
duration: this.getDuration(),
|
|
7945
|
+
status: this.status,
|
|
7946
|
+
statusMessage: this.statusMessage,
|
|
7947
|
+
attributes: this.attributes,
|
|
7948
|
+
events: this.events.map((e) => ({
|
|
7949
|
+
name: e.name,
|
|
7950
|
+
timestamp: e.timestamp.toISOString(),
|
|
7951
|
+
attributes: e.attributes
|
|
7952
|
+
})),
|
|
7953
|
+
children: this.children.map((c) => c.toJSON())
|
|
7954
|
+
};
|
|
7955
|
+
}
|
|
7956
|
+
generateId(length) {
|
|
7957
|
+
const chars = "0123456789abcdef";
|
|
7958
|
+
let result = "";
|
|
7959
|
+
for (let i = 0; i < length; i++) {
|
|
7960
|
+
result += chars[Math.floor(Math.random() * chars.length)];
|
|
7961
|
+
}
|
|
7962
|
+
return result;
|
|
7963
|
+
}
|
|
7964
|
+
};
|
|
7965
|
+
var Tracer = class {
|
|
7966
|
+
name;
|
|
7967
|
+
version;
|
|
7968
|
+
activeSpan = null;
|
|
7969
|
+
spans = [];
|
|
7970
|
+
enabled;
|
|
7971
|
+
onSpanEnd;
|
|
7972
|
+
constructor(options) {
|
|
7973
|
+
this.name = options.name;
|
|
7974
|
+
this.version = options.version || "1.0.0";
|
|
7975
|
+
this.enabled = options.enabled ?? process.env.CONTEXTOS_TRACING !== "false";
|
|
7976
|
+
this.onSpanEnd = options.onSpanEnd;
|
|
7977
|
+
}
|
|
7978
|
+
/**
|
|
7979
|
+
* Start a new span
|
|
7980
|
+
*/
|
|
7981
|
+
startSpan(name, attributes) {
|
|
7982
|
+
const parentContext = this.activeSpan?.context;
|
|
7983
|
+
const span = new Span(name, parentContext, {
|
|
7984
|
+
"service.name": this.name,
|
|
7985
|
+
"service.version": this.version,
|
|
7986
|
+
...attributes
|
|
7987
|
+
});
|
|
7988
|
+
if (this.enabled) {
|
|
7989
|
+
this.spans.push(span);
|
|
7990
|
+
this.activeSpan = span;
|
|
7991
|
+
}
|
|
7992
|
+
return span;
|
|
7993
|
+
}
|
|
7994
|
+
/**
|
|
7995
|
+
* End a span and optionally export it
|
|
7996
|
+
*/
|
|
7997
|
+
endSpan(span) {
|
|
7998
|
+
span.end();
|
|
7999
|
+
if (this.enabled && this.onSpanEnd) {
|
|
8000
|
+
this.onSpanEnd(span);
|
|
8001
|
+
}
|
|
8002
|
+
if (this.activeSpan === span && span.context.parentSpanId) {
|
|
8003
|
+
this.activeSpan = this.spans.find(
|
|
8004
|
+
(s) => s.context.spanId === span.context.parentSpanId
|
|
8005
|
+
) || null;
|
|
8006
|
+
}
|
|
8007
|
+
}
|
|
8008
|
+
/**
|
|
8009
|
+
* Execute a function within a span
|
|
8010
|
+
*/
|
|
8011
|
+
async withSpan(name, fn, attributes) {
|
|
8012
|
+
const span = this.startSpan(name, attributes);
|
|
8013
|
+
try {
|
|
8014
|
+
const result = await fn(span);
|
|
8015
|
+
span.setStatus("ok");
|
|
8016
|
+
return result;
|
|
8017
|
+
} catch (error) {
|
|
8018
|
+
if (error instanceof Error) {
|
|
8019
|
+
span.recordException(error);
|
|
8020
|
+
}
|
|
8021
|
+
throw error;
|
|
8022
|
+
} finally {
|
|
8023
|
+
this.endSpan(span);
|
|
8024
|
+
}
|
|
8025
|
+
}
|
|
8026
|
+
/**
|
|
8027
|
+
* Execute a sync function within a span
|
|
8028
|
+
*/
|
|
8029
|
+
withSpanSync(name, fn, attributes) {
|
|
8030
|
+
const span = this.startSpan(name, attributes);
|
|
8031
|
+
try {
|
|
8032
|
+
const result = fn(span);
|
|
8033
|
+
span.setStatus("ok");
|
|
8034
|
+
return result;
|
|
8035
|
+
} catch (error) {
|
|
8036
|
+
if (error instanceof Error) {
|
|
8037
|
+
span.recordException(error);
|
|
8038
|
+
}
|
|
8039
|
+
throw error;
|
|
8040
|
+
} finally {
|
|
8041
|
+
this.endSpan(span);
|
|
8042
|
+
}
|
|
8043
|
+
}
|
|
8044
|
+
/**
|
|
8045
|
+
* Get all recorded spans
|
|
8046
|
+
*/
|
|
8047
|
+
getSpans() {
|
|
8048
|
+
return [...this.spans];
|
|
8049
|
+
}
|
|
8050
|
+
/**
|
|
8051
|
+
* Clear recorded spans
|
|
8052
|
+
*/
|
|
8053
|
+
clear() {
|
|
8054
|
+
this.spans = [];
|
|
8055
|
+
this.activeSpan = null;
|
|
8056
|
+
}
|
|
8057
|
+
/**
|
|
8058
|
+
* Get active span
|
|
8059
|
+
*/
|
|
8060
|
+
getActiveSpan() {
|
|
8061
|
+
return this.activeSpan;
|
|
8062
|
+
}
|
|
8063
|
+
};
|
|
8064
|
+
var SPAN_NAMES = {
|
|
8065
|
+
// CLI operations
|
|
8066
|
+
CLI_INIT: "cli.init",
|
|
8067
|
+
CLI_INDEX: "cli.index",
|
|
8068
|
+
CLI_BUILD: "cli.build",
|
|
8069
|
+
CLI_ANALYZE: "cli.analyze",
|
|
8070
|
+
// Core operations
|
|
8071
|
+
PARSE_FILE: "core.parse_file",
|
|
8072
|
+
BUILD_GRAPH: "core.build_graph",
|
|
8073
|
+
COMPUTE_EMBEDDINGS: "core.compute_embeddings",
|
|
8074
|
+
RANK_FILES: "core.rank_files",
|
|
8075
|
+
BUILD_CONTEXT: "core.build_context",
|
|
8076
|
+
// RLM operations
|
|
8077
|
+
RLM_EXECUTE: "rlm.execute",
|
|
8078
|
+
RLM_SPAWN_AGENT: "rlm.spawn_agent",
|
|
8079
|
+
RLM_SANDBOX_RUN: "rlm.sandbox_run",
|
|
8080
|
+
// API operations
|
|
8081
|
+
API_COMPLETION: "api.completion",
|
|
8082
|
+
API_EMBEDDING: "api.embedding",
|
|
8083
|
+
// MCP operations
|
|
8084
|
+
MCP_TOOL_CALL: "mcp.tool_call",
|
|
8085
|
+
MCP_RESOURCE_READ: "mcp.resource_read"
|
|
8086
|
+
};
|
|
8087
|
+
|
|
8088
|
+
// src/telemetry/error-reporter.ts
|
|
8089
|
+
var ErrorReporter = class {
|
|
8090
|
+
enabled;
|
|
8091
|
+
handlers = [];
|
|
8092
|
+
breadcrumbs = [];
|
|
8093
|
+
maxBreadcrumbs = 50;
|
|
8094
|
+
globalTags = {};
|
|
8095
|
+
globalExtra = {};
|
|
8096
|
+
version;
|
|
8097
|
+
constructor(options = {}) {
|
|
8098
|
+
this.enabled = options.enabled ?? process.env.CONTEXTOS_ERROR_REPORTING !== "false";
|
|
8099
|
+
this.version = options.version || "2.0.0";
|
|
8100
|
+
this.maxBreadcrumbs = options.maxBreadcrumbs || 50;
|
|
8101
|
+
if (options.handlers) {
|
|
8102
|
+
this.handlers = options.handlers;
|
|
8103
|
+
}
|
|
8104
|
+
if (process.env.NODE_ENV === "development") {
|
|
8105
|
+
this.addHandler((report) => {
|
|
8106
|
+
console.error("[ErrorReporter]", report.error.name, report.error.message);
|
|
8107
|
+
});
|
|
8108
|
+
}
|
|
8109
|
+
}
|
|
8110
|
+
/**
|
|
8111
|
+
* Add an error report handler
|
|
8112
|
+
*/
|
|
8113
|
+
addHandler(handler) {
|
|
8114
|
+
this.handlers.push(handler);
|
|
8115
|
+
}
|
|
8116
|
+
/**
|
|
8117
|
+
* Set global tags for all reports
|
|
8118
|
+
*/
|
|
8119
|
+
setTags(tags) {
|
|
8120
|
+
Object.assign(this.globalTags, tags);
|
|
8121
|
+
}
|
|
8122
|
+
/**
|
|
8123
|
+
* Set global extra data for all reports
|
|
8124
|
+
*/
|
|
8125
|
+
setExtra(extra) {
|
|
8126
|
+
Object.assign(this.globalExtra, extra);
|
|
8127
|
+
}
|
|
8128
|
+
/**
|
|
8129
|
+
* Add a breadcrumb
|
|
8130
|
+
*/
|
|
8131
|
+
addBreadcrumb(breadcrumb) {
|
|
8132
|
+
this.breadcrumbs.push({
|
|
8133
|
+
...breadcrumb,
|
|
8134
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
8135
|
+
});
|
|
8136
|
+
if (this.breadcrumbs.length > this.maxBreadcrumbs) {
|
|
8137
|
+
this.breadcrumbs = this.breadcrumbs.slice(-this.maxBreadcrumbs);
|
|
8138
|
+
}
|
|
8139
|
+
}
|
|
8140
|
+
/**
|
|
8141
|
+
* Capture and report an error
|
|
8142
|
+
*/
|
|
8143
|
+
async captureException(error, context) {
|
|
8144
|
+
if (!this.enabled) return null;
|
|
8145
|
+
const report = this.createReport(error, context);
|
|
8146
|
+
for (const handler of this.handlers) {
|
|
8147
|
+
try {
|
|
8148
|
+
await handler(report);
|
|
8149
|
+
} catch (handlerError) {
|
|
8150
|
+
console.error("[ErrorReporter] Handler failed:", handlerError);
|
|
8151
|
+
}
|
|
8152
|
+
}
|
|
8153
|
+
return report.id;
|
|
8154
|
+
}
|
|
8155
|
+
/**
|
|
8156
|
+
* Capture a message as an error
|
|
8157
|
+
*/
|
|
8158
|
+
async captureMessage(message, level = "error", context) {
|
|
8159
|
+
const error = new Error(message);
|
|
8160
|
+
error.name = `Message.${level}`;
|
|
8161
|
+
return this.captureException(error, context);
|
|
8162
|
+
}
|
|
8163
|
+
/**
|
|
8164
|
+
* Wrap a function to auto-capture errors
|
|
8165
|
+
*/
|
|
8166
|
+
wrap(fn, context) {
|
|
8167
|
+
const reporter = this;
|
|
8168
|
+
return ((...args) => {
|
|
8169
|
+
try {
|
|
8170
|
+
const result = fn(...args);
|
|
8171
|
+
if (result instanceof Promise) {
|
|
8172
|
+
return result.catch((error) => {
|
|
8173
|
+
reporter.captureException(error, context);
|
|
8174
|
+
throw error;
|
|
8175
|
+
});
|
|
8176
|
+
}
|
|
8177
|
+
return result;
|
|
8178
|
+
} catch (error) {
|
|
8179
|
+
if (error instanceof Error) {
|
|
8180
|
+
reporter.captureException(error, context);
|
|
8181
|
+
}
|
|
8182
|
+
throw error;
|
|
8183
|
+
}
|
|
8184
|
+
});
|
|
8185
|
+
}
|
|
8186
|
+
/**
|
|
8187
|
+
* Clear breadcrumbs
|
|
8188
|
+
*/
|
|
8189
|
+
clearBreadcrumbs() {
|
|
8190
|
+
this.breadcrumbs = [];
|
|
8191
|
+
}
|
|
8192
|
+
/**
|
|
8193
|
+
* Get recent reports (for debugging)
|
|
8194
|
+
*/
|
|
8195
|
+
getRecentBreadcrumbs() {
|
|
8196
|
+
return [...this.breadcrumbs];
|
|
8197
|
+
}
|
|
8198
|
+
createReport(error, context) {
|
|
8199
|
+
const isContextOSError = error instanceof ContextOSError;
|
|
8200
|
+
return {
|
|
8201
|
+
id: this.generateId(),
|
|
8202
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
8203
|
+
error: {
|
|
8204
|
+
name: error.name,
|
|
8205
|
+
message: error.message,
|
|
8206
|
+
stack: error.stack,
|
|
8207
|
+
code: isContextOSError ? error.code : void 0
|
|
8208
|
+
},
|
|
8209
|
+
context: {
|
|
8210
|
+
tags: { ...this.globalTags, ...context?.tags },
|
|
8211
|
+
extra: {
|
|
8212
|
+
...this.globalExtra,
|
|
8213
|
+
...context?.extra,
|
|
8214
|
+
...isContextOSError ? error.context : {}
|
|
8215
|
+
},
|
|
8216
|
+
user: context?.user,
|
|
8217
|
+
operation: context?.operation,
|
|
8218
|
+
breadcrumbs: [...this.breadcrumbs, ...context?.breadcrumbs || []]
|
|
8219
|
+
},
|
|
8220
|
+
environment: {
|
|
8221
|
+
nodeVersion: process.version,
|
|
8222
|
+
platform: process.platform,
|
|
8223
|
+
arch: process.arch,
|
|
8224
|
+
contextosVersion: this.version
|
|
8225
|
+
}
|
|
8226
|
+
};
|
|
8227
|
+
}
|
|
8228
|
+
generateId() {
|
|
8229
|
+
return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
8230
|
+
}
|
|
8231
|
+
};
|
|
8232
|
+
function createSentryHandler(dsn) {
|
|
8233
|
+
return async (report) => {
|
|
8234
|
+
if (process.env.NODE_ENV === "development") {
|
|
8235
|
+
console.log("[Sentry Mock] Would send to:", dsn);
|
|
8236
|
+
console.log("[Sentry Mock] Report:", JSON.stringify(report, null, 2));
|
|
8237
|
+
}
|
|
8238
|
+
};
|
|
8239
|
+
}
|
|
8240
|
+
function createConsoleHandler() {
|
|
8241
|
+
return (report) => {
|
|
8242
|
+
console.error(`
|
|
8243
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
8244
|
+
\u2551 ERROR REPORT: ${report.id.padEnd(43)}\u2551
|
|
8245
|
+
\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
8246
|
+
\u2551 ${report.error.name}: ${report.error.message.substring(0, 50).padEnd(50)}\u2551
|
|
8247
|
+
\u2551 Code: ${(report.error.code || "N/A").padEnd(53)}\u2551
|
|
8248
|
+
\u2551 Time: ${report.timestamp.toISOString().padEnd(53)}\u2551
|
|
8249
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
8250
|
+
`);
|
|
8251
|
+
};
|
|
8252
|
+
}
|
|
8253
|
+
function createFileHandler(logPath) {
|
|
8254
|
+
return async (report) => {
|
|
8255
|
+
const fs = await import("fs/promises");
|
|
8256
|
+
const line = JSON.stringify(report) + "\n";
|
|
8257
|
+
await fs.appendFile(logPath, line);
|
|
8258
|
+
};
|
|
8259
|
+
}
|
|
8260
|
+
|
|
8261
|
+
// src/telemetry/index.ts
|
|
8262
|
+
var Telemetry = class {
|
|
8263
|
+
metrics;
|
|
8264
|
+
tracer;
|
|
8265
|
+
errors;
|
|
8266
|
+
config;
|
|
8267
|
+
constructor(config = {}) {
|
|
8268
|
+
this.config = {
|
|
8269
|
+
enabled: true,
|
|
8270
|
+
serviceName: "contextos",
|
|
8271
|
+
serviceVersion: "2.0.0",
|
|
8272
|
+
metricsFlushIntervalMs: 6e4,
|
|
8273
|
+
// 1 minute
|
|
8274
|
+
...config
|
|
8275
|
+
};
|
|
8276
|
+
this.metrics = new MetricsCollector({
|
|
8277
|
+
enabled: this.config.enabled,
|
|
8278
|
+
flushIntervalMs: this.config.metricsFlushIntervalMs,
|
|
8279
|
+
onFlush: this.config.onMetricsFlush
|
|
8280
|
+
});
|
|
8281
|
+
this.tracer = new Tracer({
|
|
8282
|
+
name: this.config.serviceName,
|
|
8283
|
+
version: this.config.serviceVersion,
|
|
8284
|
+
enabled: this.config.enabled,
|
|
8285
|
+
onSpanEnd: this.config.onSpanEnd
|
|
8286
|
+
});
|
|
8287
|
+
this.errors = new ErrorReporter({
|
|
8288
|
+
enabled: this.config.enabled,
|
|
8289
|
+
version: this.config.serviceVersion,
|
|
8290
|
+
handlers: this.config.errorHandlers || [createConsoleHandler()]
|
|
8291
|
+
});
|
|
8292
|
+
if (this.config.enabled) {
|
|
8293
|
+
this.setupGlobalHandlers();
|
|
8294
|
+
}
|
|
8295
|
+
}
|
|
8296
|
+
/**
|
|
8297
|
+
* Execute an operation with full telemetry
|
|
8298
|
+
*/
|
|
8299
|
+
async traced(name, operation, options) {
|
|
8300
|
+
const span = this.tracer.startSpan(name, options?.attributes);
|
|
8301
|
+
const startTime = performance.now();
|
|
8302
|
+
try {
|
|
8303
|
+
const result = await operation(span);
|
|
8304
|
+
span.setStatus("ok");
|
|
8305
|
+
this.metrics.histogram(`${name}_duration_ms`, performance.now() - startTime);
|
|
8306
|
+
this.metrics.increment(`${name}_success`);
|
|
8307
|
+
return result;
|
|
8308
|
+
} catch (error) {
|
|
8309
|
+
if (error instanceof Error) {
|
|
8310
|
+
span.recordException(error);
|
|
8311
|
+
await this.errors.captureException(error, options?.errorContext);
|
|
8312
|
+
}
|
|
8313
|
+
this.metrics.increment(`${name}_error`);
|
|
8314
|
+
throw error;
|
|
8315
|
+
} finally {
|
|
8316
|
+
this.tracer.endSpan(span);
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
/**
|
|
8320
|
+
* Record memory usage
|
|
8321
|
+
*/
|
|
8322
|
+
recordMemoryUsage() {
|
|
8323
|
+
const usage = process.memoryUsage();
|
|
8324
|
+
this.metrics.gauge(METRICS.MEMORY_HEAP_USED, usage.heapUsed);
|
|
8325
|
+
this.metrics.gauge(METRICS.MEMORY_HEAP_TOTAL, usage.heapTotal);
|
|
8326
|
+
}
|
|
8327
|
+
/**
|
|
8328
|
+
* Flush all metrics
|
|
8329
|
+
*/
|
|
8330
|
+
flush() {
|
|
8331
|
+
return this.metrics.flush();
|
|
8332
|
+
}
|
|
8333
|
+
/**
|
|
8334
|
+
* Shutdown telemetry
|
|
8335
|
+
*/
|
|
8336
|
+
shutdown() {
|
|
8337
|
+
this.metrics.stop();
|
|
8338
|
+
this.tracer.clear();
|
|
8339
|
+
}
|
|
8340
|
+
setupGlobalHandlers() {
|
|
8341
|
+
process.on("unhandledRejection", (reason) => {
|
|
8342
|
+
if (reason instanceof Error) {
|
|
8343
|
+
this.errors.captureException(reason, {
|
|
8344
|
+
tags: { type: "unhandledRejection" }
|
|
8345
|
+
});
|
|
8346
|
+
}
|
|
8347
|
+
});
|
|
8348
|
+
process.on("uncaughtException", (error) => {
|
|
8349
|
+
this.errors.captureException(error, {
|
|
8350
|
+
tags: { type: "uncaughtException" }
|
|
8351
|
+
});
|
|
8352
|
+
});
|
|
8353
|
+
}
|
|
8354
|
+
};
|
|
8355
|
+
var globalTelemetry = null;
|
|
8356
|
+
function getTelemetry(config) {
|
|
8357
|
+
if (!globalTelemetry) {
|
|
8358
|
+
globalTelemetry = new Telemetry(config);
|
|
8359
|
+
}
|
|
8360
|
+
return globalTelemetry;
|
|
8361
|
+
}
|
|
8362
|
+
function initTelemetry(config) {
|
|
8363
|
+
if (globalTelemetry) {
|
|
8364
|
+
globalTelemetry.shutdown();
|
|
8365
|
+
}
|
|
8366
|
+
globalTelemetry = new Telemetry(config);
|
|
8367
|
+
return globalTelemetry;
|
|
8368
|
+
}
|
|
8369
|
+
function shutdownTelemetry() {
|
|
8370
|
+
if (globalTelemetry) {
|
|
8371
|
+
globalTelemetry.shutdown();
|
|
8372
|
+
globalTelemetry = null;
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
|
|
7594
8376
|
// src/generator/index.ts
|
|
7595
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readFileSync as
|
|
8377
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, readFileSync as readFileSync14 } from "fs";
|
|
7596
8378
|
import { dirname as dirname5, join as join15, resolve as resolve2, normalize as normalize3 } from "path";
|
|
7597
8379
|
|
|
7598
8380
|
// src/generator/shadow-fs.ts
|
|
7599
|
-
import { existsSync as existsSync14, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as
|
|
8381
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync12, rmSync as rmSync2, renameSync, copyFileSync } from "fs";
|
|
7600
8382
|
import { join as join13, dirname as dirname4 } from "path";
|
|
7601
8383
|
import { randomUUID } from "crypto";
|
|
7602
8384
|
var ShadowFileSystem = class {
|
|
@@ -7661,11 +8443,11 @@ var ShadowFileSystem = class {
|
|
|
7661
8443
|
if (tx && tx.files.has(realPath)) {
|
|
7662
8444
|
const shadowPath = tx.files.get(realPath);
|
|
7663
8445
|
if (existsSync14(shadowPath)) {
|
|
7664
|
-
return
|
|
8446
|
+
return readFileSync12(shadowPath, "utf-8");
|
|
7665
8447
|
}
|
|
7666
8448
|
}
|
|
7667
8449
|
if (existsSync14(realPath)) {
|
|
7668
|
-
return
|
|
8450
|
+
return readFileSync12(realPath, "utf-8");
|
|
7669
8451
|
}
|
|
7670
8452
|
return null;
|
|
7671
8453
|
}
|
|
@@ -7765,7 +8547,7 @@ function createShadowFS(rootDir) {
|
|
|
7765
8547
|
}
|
|
7766
8548
|
|
|
7767
8549
|
// src/context/negative-context.ts
|
|
7768
|
-
import { existsSync as existsSync15, readFileSync as
|
|
8550
|
+
import { existsSync as existsSync15, readFileSync as readFileSync13, writeFileSync as writeFileSync10 } from "fs";
|
|
7769
8551
|
import { join as join14 } from "path";
|
|
7770
8552
|
var NegativeContextManager = class {
|
|
7771
8553
|
contextIgnorePath;
|
|
@@ -7783,7 +8565,7 @@ var NegativeContextManager = class {
|
|
|
7783
8565
|
return;
|
|
7784
8566
|
}
|
|
7785
8567
|
try {
|
|
7786
|
-
const content =
|
|
8568
|
+
const content = readFileSync13(this.contextIgnorePath, "utf-8");
|
|
7787
8569
|
const lines = content.split("\n").filter((line) => line.trim() && !line.startsWith("#"));
|
|
7788
8570
|
this.rules = lines.map((line) => {
|
|
7789
8571
|
const match = line.match(/^(\w+):(.+?)\|(.+)$/);
|
|
@@ -8073,7 +8855,7 @@ var AIGenerator = class {
|
|
|
8073
8855
|
for (const prdPath of prdPaths) {
|
|
8074
8856
|
const fullPath = join15(this.rootDir, prdPath);
|
|
8075
8857
|
if (existsSync16(fullPath)) {
|
|
8076
|
-
const content =
|
|
8858
|
+
const content = readFileSync14(fullPath, "utf-8");
|
|
8077
8859
|
parts.push(`## ${prdPath}
|
|
8078
8860
|
|
|
8079
8861
|
${content}`);
|
|
@@ -8188,7 +8970,7 @@ Generate the files now:`;
|
|
|
8188
8970
|
}
|
|
8189
8971
|
if (!file.isNew && options.backupBeforeOverwrite) {
|
|
8190
8972
|
const backupPath = `${fullPath}.bak`;
|
|
8191
|
-
const existingContent =
|
|
8973
|
+
const existingContent = readFileSync14(fullPath, "utf-8");
|
|
8192
8974
|
writeFileSync11(backupPath, existingContent);
|
|
8193
8975
|
}
|
|
8194
8976
|
writeFileSync11(fullPath, file.content, "utf-8");
|
|
@@ -8225,6 +9007,7 @@ export {
|
|
|
8225
9007
|
E2EEncryption,
|
|
8226
9008
|
EmbeddingConfigSchema,
|
|
8227
9009
|
ErrorCode,
|
|
9010
|
+
ErrorReporter,
|
|
8228
9011
|
Errors,
|
|
8229
9012
|
GeminiClient,
|
|
8230
9013
|
GraphConfigSchema,
|
|
@@ -8233,8 +9016,10 @@ export {
|
|
|
8233
9016
|
LocalSandbox,
|
|
8234
9017
|
LogLevel,
|
|
8235
9018
|
Logger,
|
|
9019
|
+
METRICS,
|
|
8236
9020
|
MODEL_SPECIFIC_ADDENDUM,
|
|
8237
9021
|
MetaSchema,
|
|
9022
|
+
MetricsCollector,
|
|
8238
9023
|
NegativeContextManager,
|
|
8239
9024
|
OpenAIAdapter,
|
|
8240
9025
|
PluginManager,
|
|
@@ -8244,13 +9029,17 @@ export {
|
|
|
8244
9029
|
RBACManager,
|
|
8245
9030
|
RLMEngine,
|
|
8246
9031
|
RLM_BASE_SYSTEM_PROMPT,
|
|
9032
|
+
SPAN_NAMES,
|
|
8247
9033
|
ScopeManager,
|
|
8248
9034
|
ShadowFileSystem,
|
|
9035
|
+
Span,
|
|
8249
9036
|
StackConfigSchema,
|
|
8250
9037
|
SupportedLanguageSchema,
|
|
8251
9038
|
TeamSync,
|
|
9039
|
+
Telemetry,
|
|
8252
9040
|
TemplateManager,
|
|
8253
9041
|
TokenBudget,
|
|
9042
|
+
Tracer,
|
|
8254
9043
|
TrainingDataCollector,
|
|
8255
9044
|
VectorStore,
|
|
8256
9045
|
Watchdog,
|
|
@@ -8260,8 +9049,10 @@ export {
|
|
|
8260
9049
|
createAIGenerator,
|
|
8261
9050
|
createAnthropicAdapter,
|
|
8262
9051
|
createBlackboard,
|
|
9052
|
+
createConsoleHandler,
|
|
8263
9053
|
createContextAPI,
|
|
8264
9054
|
createDatasetFormatter,
|
|
9055
|
+
createFileHandler,
|
|
8265
9056
|
createGeminiClient,
|
|
8266
9057
|
createInitialUserMessage,
|
|
8267
9058
|
createLogger,
|
|
@@ -8275,6 +9066,7 @@ export {
|
|
|
8275
9066
|
createSandbox,
|
|
8276
9067
|
createSandboxContext,
|
|
8277
9068
|
createScopeManager,
|
|
9069
|
+
createSentryHandler,
|
|
8278
9070
|
createShadowFS,
|
|
8279
9071
|
createSubAgentResultMessage,
|
|
8280
9072
|
createTrainingDataCollector,
|
|
@@ -8300,7 +9092,9 @@ export {
|
|
|
8300
9092
|
getModelPricing,
|
|
8301
9093
|
getParser,
|
|
8302
9094
|
getSupportedLanguages,
|
|
9095
|
+
getTelemetry,
|
|
8303
9096
|
getTreeSitterLanguage,
|
|
9097
|
+
initTelemetry,
|
|
8304
9098
|
isAnthropicAvailable,
|
|
8305
9099
|
isGeminiAvailable,
|
|
8306
9100
|
isInitialized,
|
|
@@ -8319,6 +9113,7 @@ export {
|
|
|
8319
9113
|
saveConfigYaml,
|
|
8320
9114
|
saveContextYaml,
|
|
8321
9115
|
setGlobalLogger,
|
|
9116
|
+
shutdownTelemetry,
|
|
8322
9117
|
splitContextToFiles,
|
|
8323
9118
|
validateCode,
|
|
8324
9119
|
validateLicense
|