(taskType, messages)
| 1923 | // loop. A stable system prompt lets llama.cpp reuse its KV cache across turns. |
| 1924 | // Set SMALLCODE_CACHE_SPLIT=false to revert to the old behaviour. |
| 1925 | function buildCompactSystemPrompt(taskType, messages) { |
| 1926 | const cacheSplit = process.env.SMALLCODE_CACHE_SPLIT !== 'false'; // default: true |
| 1927 | const os = process.platform === 'win32' ? 'Windows' : process.platform === 'darwin' ? 'macOS' : 'Linux'; |
| 1928 | const osHint = process.platform === 'win32' ? '\nUse "dir" not "ls", "type" not "cat". No bash-only commands.' : ''; |
| 1929 | |
| 1930 | // Bootstrap detection (Feature 11): compact project summary at the top so |
| 1931 | // the model knows its runtime, build/test commands, and entry point without |
| 1932 | // burning tool calls on discovery. |
| 1933 | let bootstrapLine = ''; |
| 1934 | try { |
| 1935 | if (_bootstrapDetector) { |
| 1936 | const raw = _bootstrapDetector.formatForPrompt(); |
| 1937 | // Prefix as a workspace hint so the model treats it as tool context, |
| 1938 | // not as a project description to regurgitate when users ask questions. |
| 1939 | // Without this framing models answer "tell me about the project" from |
| 1940 | // the bootstrap summary instead of reading README.md. |
| 1941 | if (raw) bootstrapLine = raw.replace('\n\nProject:', '\n\nWorkspace context:'); |
| 1942 | } |
| 1943 | } catch {} |
| 1944 | |
| 1945 | let prompt = `You are SmallCode, a coding agent. Working directory: ${process.cwd()} |
| 1946 | OS: ${os}${osHint}${bootstrapLine} |
| 1947 | |
| 1948 | Rules: Use patch for edits (not full rewrites). Prefer compound tools. Be concise. ACT immediately — do not ask for confirmation unless the task is genuinely ambiguous. If asked to read a file, read it. If asked to create something, create it. If asked about the project, read README.md or relevant files — do not answer from the workspace context line above. |
| 1949 | |
| 1950 | CRITICAL — large file rule: write_file calls are limited to 60 lines / ~8KB. llama.cpp's JSON parser crashes on larger tool calls. For any file over 60 lines: (1) write_file with just the skeleton (imports + empty stubs), then (2) use multiple patch calls to fill in each function/section. Never put more than 60 lines in a single write_file content field.`; |
| 1951 | |
| 1952 | // Only add tool-use instructions for tasks that need tools |
| 1953 | if (taskType !== 'explanation') { |
| 1954 | prompt += `\nUse graph_search/explain_symbol for "how does X work" questions. Use list_projects for workspace overview.`; |
| 1955 | } |
| 1956 | |
| 1957 | // Only add BoneScript for backend tasks |
| 1958 | if (taskType === 'backend') { |
| 1959 | prompt += `\n\nFor Node.js backends: write a .bone file → bone_check → bone_compile. Don't hand-write routes.`; |
| 1960 | } |
| 1961 | |
| 1962 | // Web research tools — only advertise when web browsing is enabled. Small |
| 1963 | // models trust this prose over the raw `tools` array and otherwise refuse |
| 1964 | // research tasks ("my tools are for code files only") even though the web |
| 1965 | // tools are available (issue #58). |
| 1966 | if (taskType !== 'explanation' && String(process.env.SMALLCODE_WEB_BROWSE).toLowerCase() === 'true') { |
| 1967 | prompt += `\n\nWEB RESEARCH — you have live internet access: web_search (query → results with URLs) and web_fetch (URL → page text). Use them for research / look-up / current-info tasks; report a short summary with source URL(s). Do NOT write scripts to fetch the web.`; |
| 1968 | } |
| 1969 | |
| 1970 | if (cacheSplit) { |
| 1971 | // Dynamic context goes into a separate [CONTEXT] user message — see |
| 1972 | // buildDynamicContext(). Plan + plugins stay here (system role = authoritative). |
| 1973 | prompt += getPluginPrompts() + getActivePlanContext() + getTestRunnerContext(); |
| 1974 | return prompt; |
| 1975 | } |
| 1976 | |
| 1977 | // Legacy behavior: everything in the system prompt |
| 1978 | prompt += getMemoryContext(messages) + getSkillContext(messages) + getPluginPrompts() + getKnowledgeContext(messages) + getRagContext(messages) + getActivePlanContext() + getTestRunnerContext(); |
| 1979 | |
| 1980 | return prompt; |
| 1981 | } |
| 1982 |
no test coverage detected