orquesta-cli 0.2.91 → 0.2.92
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/core/project-context.js +58 -24
- package/package.json +1 -1
|
@@ -1,51 +1,85 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { logger } from '../utils/logger.js';
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const PER_FILE_MAX_BYTES = 32_000;
|
|
5
|
+
const TOTAL_MAX_BYTES = 48_000;
|
|
6
|
+
const CANDIDATE_FILES = [
|
|
6
7
|
'CLAUDE.md',
|
|
7
8
|
'.claude/CLAUDE.md',
|
|
9
|
+
'AGENTS.md',
|
|
8
10
|
'AGENT.md',
|
|
9
11
|
'agent.md',
|
|
12
|
+
'GEMINI.md',
|
|
13
|
+
'QWEN.md',
|
|
14
|
+
'KIRO.md',
|
|
15
|
+
];
|
|
16
|
+
const CANDIDATE_DIRS = [
|
|
17
|
+
'.kiro/steering',
|
|
10
18
|
];
|
|
11
19
|
let cachedContext;
|
|
12
|
-
function
|
|
13
|
-
|
|
20
|
+
function capFile(content) {
|
|
21
|
+
if (Buffer.byteLength(content, 'utf-8') > PER_FILE_MAX_BYTES) {
|
|
22
|
+
return content.slice(0, PER_FILE_MAX_BYTES) + '\n\n[...truncated for context window]';
|
|
23
|
+
}
|
|
24
|
+
return content;
|
|
25
|
+
}
|
|
26
|
+
function collectContextFiles(cwd) {
|
|
27
|
+
const out = [];
|
|
28
|
+
const seen = new Set();
|
|
29
|
+
const tryAdd = (rel) => {
|
|
14
30
|
const abs = path.join(cwd, rel);
|
|
15
31
|
try {
|
|
16
32
|
const stat = fs.statSync(abs);
|
|
17
33
|
if (!stat.isFile())
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
return;
|
|
35
|
+
const content = capFile(fs.readFileSync(abs, 'utf-8'));
|
|
36
|
+
const key = content.trim();
|
|
37
|
+
if (!key || seen.has(key))
|
|
38
|
+
return;
|
|
39
|
+
seen.add(key);
|
|
40
|
+
out.push({ path: rel, content });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
for (const rel of CANDIDATE_FILES)
|
|
46
|
+
tryAdd(rel);
|
|
47
|
+
for (const dir of CANDIDATE_DIRS) {
|
|
48
|
+
try {
|
|
49
|
+
const entries = fs.readdirSync(path.join(cwd, dir)).filter(f => f.toLowerCase().endsWith('.md')).sort();
|
|
50
|
+
for (const f of entries)
|
|
51
|
+
tryAdd(path.join(dir, f));
|
|
24
52
|
}
|
|
25
53
|
catch {
|
|
26
|
-
continue;
|
|
27
54
|
}
|
|
28
55
|
}
|
|
29
|
-
return
|
|
56
|
+
return out;
|
|
30
57
|
}
|
|
31
58
|
export function getProjectContext(cwd = process.cwd()) {
|
|
32
59
|
if (cachedContext !== undefined)
|
|
33
60
|
return cachedContext ?? '';
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
61
|
+
const files = collectContextFiles(cwd);
|
|
62
|
+
if (files.length === 0) {
|
|
36
63
|
cachedContext = null;
|
|
37
|
-
logger.debug('No CLAUDE.md /
|
|
64
|
+
logger.debug('No agent-instruction files (CLAUDE.md / AGENTS.md / …) found in cwd', { cwd });
|
|
38
65
|
return '';
|
|
39
66
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
''
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
const sections = ['', '## PROJECT CONTEXT'];
|
|
68
|
+
let total = 0;
|
|
69
|
+
const used = [];
|
|
70
|
+
for (const f of files) {
|
|
71
|
+
const block = `\n### From ${f.path} (authoritative project conventions)\n\n${f.content}\n`;
|
|
72
|
+
if (total + Buffer.byteLength(block, 'utf-8') > TOTAL_MAX_BYTES) {
|
|
73
|
+
logger.debug(`Skipping ${f.path}: merged project context would exceed ${TOTAL_MAX_BYTES} bytes`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
total += Buffer.byteLength(block, 'utf-8');
|
|
77
|
+
sections.push(block);
|
|
78
|
+
used.push(f.path);
|
|
79
|
+
}
|
|
80
|
+
sections.push('');
|
|
81
|
+
logger.info(`Loaded project context from ${used.length} file(s): ${used.join(', ')} (${total} bytes)`);
|
|
82
|
+
cachedContext = sections.join('\n');
|
|
49
83
|
return cachedContext;
|
|
50
84
|
}
|
|
51
85
|
export function invalidateProjectContext() {
|