Update project files
This commit is contained in:
+70
-19
@@ -150,21 +150,50 @@ export function invalidateBrainFilesCache(dir?: string): void {
|
||||
}
|
||||
|
||||
function _walkBrainFiles(dir: string): string[] {
|
||||
let results: string[] = [];
|
||||
if (!fs.existsSync(dir)) return results;
|
||||
const list = fs.readdirSync(dir);
|
||||
list.forEach((file) => {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
if (stat && stat.isDirectory()) {
|
||||
if (!EXCLUDED_DIRS.has(file)) {
|
||||
results = results.concat(_walkBrainFiles(filePath));
|
||||
const results: string[] = [];
|
||||
_walkBrainFilesInto(dir, results);
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive walk that pushes `.md` paths into a single shared accumulator.
|
||||
*
|
||||
* Uses `readdirSync(dir, { withFileTypes: true })` so each entry's type comes
|
||||
* from the directory read itself — no extra `fs.statSync` per entry — and pushes
|
||||
* into one array instead of allocating a new array per directory via `.concat`.
|
||||
*/
|
||||
function _walkBrainFilesInto(dir: string, results: string[]): void {
|
||||
let entries: fs.Dirent[];
|
||||
try {
|
||||
entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
} catch {
|
||||
// Missing/unreadable directory — matches the previous existsSync guard's behavior.
|
||||
return;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const name = entry.name;
|
||||
const filePath = path.join(dir, name);
|
||||
let isDir = entry.isDirectory();
|
||||
let isFile = entry.isFile();
|
||||
// Symlinks: Dirent type flags don't follow links, but the previous
|
||||
// statSync-based walk did — resolve them so behavior is unchanged.
|
||||
if (entry.isSymbolicLink()) {
|
||||
try {
|
||||
const stat = fs.statSync(filePath);
|
||||
isDir = stat.isDirectory();
|
||||
isFile = stat.isFile();
|
||||
} catch {
|
||||
continue; // dangling symlink — skip (statSync would have thrown before)
|
||||
}
|
||||
} else if (file.endsWith('.md')) {
|
||||
}
|
||||
if (isDir) {
|
||||
if (!EXCLUDED_DIRS.has(name)) {
|
||||
_walkBrainFilesInto(filePath, results);
|
||||
}
|
||||
} else if (isFile && name.endsWith('.md')) {
|
||||
results.push(filePath);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
const BASE_SYSTEM_PROMPT = `You are Astra, a Jarvis-style local project operating assistant.
|
||||
@@ -184,31 +213,53 @@ If the provided initial scan preview is not enough, DO NOT complain that you can
|
||||
Never say "upload the source code", "provide the files", "파일 내용을 보여주세요", or "먼저 분석할까요?" before attempting access.
|
||||
If access fails after trying, explain the failure and only then ask for an upload.
|
||||
|
||||
[EXECUTION RULE]
|
||||
When the user asks to run, start, launch, boot, or serve something (실행/구동/시작/켜줘/띄워줘/돌려줘/run/start/launch/serve), ACT — never advise.
|
||||
- FORBIDDEN: writing a how-to, a numbered tutorial, "먼저 ~를 확인해야 합니다", "~하시기 바랍니다", or telling the user to run a command themselves. The user asked YOU to run it.
|
||||
- NEVER invent a script name, port number, or environment variable. If you have not seen it in a file THIS session, do not state it as fact.
|
||||
- If you do not know the exact start command, FIRST read the project's package.json with <read_file>, then emit <run_command> with the real script name.
|
||||
- <run_command> runs in a real terminal. If the target folder differs from the workspace, cd into its absolute path first.
|
||||
- The terminal is Windows PowerShell. Chain steps with ";" — NEVER "&&" (it is a syntax error in PowerShell 5.1). Example: cd 'C:\proj'; git add .; git commit -m 'msg'; git push
|
||||
- After acting, reply with ONE short line: what you started and where. No tutorial, no follow-up checklist.
|
||||
|
||||
Worked example — user says: "E:\Wiki\Datacollect 서버 실행해줘"
|
||||
Step 1 (only when the start script is unknown):
|
||||
<read_file path="E:\Wiki\Datacollect\package.json"/>
|
||||
Step 2 (after the real scripts are known — pick the actual one, never a guessed name):
|
||||
<run_command>cd 'E:\Wiki\Datacollect'; npm run start-full</run_command>
|
||||
Then reply: "Datacollect 서버를 start-full 스크립트로 터미널에서 실행했습니다."
|
||||
|
||||
[STRICT GLOBAL RULES]
|
||||
1. [NO EMOJIS - ABSOLUTE RULE] NEVER use ANY emojis, emoticons, Unicode pictorial symbols (including but not limited to emoji, kaomoji, Unicode icons), or decorative symbols anywhere in your response. NO EXCEPTIONS. Use plain text dashes (-) or asterisks (*) for bullets. Use plain markdown ## for headers. This rule overrides ALL other formatting instructions.
|
||||
2. [UNIQUE HEADINGS] Every markdown heading must be unique and appear exactly once.
|
||||
2. [HEADINGS] Every markdown heading must be unique, appear exactly once, and start with exactly one "## " — never "## ##", never "### ###". One space after the hashes.
|
||||
3. [NO INTERNAL LOGS] Never output <details>, "2nd Brain Trace", or "Debug JSON" blocks.
|
||||
4. [NO SECTION LEAKAGE] Never output sections named "요청 요약", "사용자 의도 추론", "프로젝트 기록 대상 확인", "핵심 확인 질문", or "근거 파일 경로".
|
||||
|
||||
[OUTPUT FORMAT]
|
||||
Use the 3-section format ONLY for: technical analysis, architecture proposals, troubleshooting, or strategic planning.
|
||||
For conversational replies, quick facts, or simple updates — answer directly without any headers.
|
||||
LENGTH decides structure — not topic. Count how long your answer will be:
|
||||
|
||||
## 요약
|
||||
Core conclusion in 2-3 sentences.
|
||||
- If the answer is longer than ~4 sentences (analysis, advice, planning, troubleshooting, or any multi-part answer), you MUST lead with a summary block, then the detail:
|
||||
|
||||
## 핵심 요약
|
||||
- 2 to 4 bullet points. Each bullet is one scannable, self-contained takeaway that captures the WHOLE answer — a reader who stops here still gets the gist.
|
||||
- This block is ALWAYS the very first thing in the response. NEVER place a summary at the bottom. NEVER write an intro paragraph before it — the summary block IS the opening.
|
||||
|
||||
## 상세 설명
|
||||
- Root cause of the problem.
|
||||
- Concrete step-by-step instructions: what to change, which files to edit, which commands to run.
|
||||
Free-form depth. You MAY use your own sub-headers here (e.g. "### 1. ...", "### 2. ..."). This is where the full reasoning and steps go.
|
||||
|
||||
## 제안 ← Optional. Only include if a meaningfully better alternative exists. Omit otherwise.
|
||||
|
||||
- If the answer is ~4 sentences or fewer (quick fact, simple update, casual or emotional reply) — answer directly, no headers, no summary block.
|
||||
|
||||
The summary block is named exactly "## 핵심 요약" and goes at the TOP. A section literally named "요약" placed at the end is a bug — never do that.
|
||||
|
||||
[FOLLOW-UP QUESTION RULES]
|
||||
A follow-up question is a precision tool, not a ritual.
|
||||
Ask ONE focused question at the very end of the response ONLY if:
|
||||
- The user's intent is genuinely ambiguous with multiple valid paths, OR
|
||||
- A critical missing detail would make the current answer completely wrong.
|
||||
If neither condition is met, give a definitive answer and stop.
|
||||
When you do ask: it is ONE plain sentence on its own line. NEVER put it under a heading, NEVER label the section ("핵심 확인 질문", "확인 질문" etc.), NEVER attach a "질문 의도" explanation, NEVER ask two or more questions.
|
||||
|
||||
[ENGINEERING STANCE]
|
||||
- Be a direct engineering partner. Technical precision over polite filler.
|
||||
|
||||
Reference in New Issue
Block a user