* Sandboxed wrapper around run(). When `config.sandbox.enabled` and we're in a * git repo, this runs the whole task on a hidden `qodex/sandbox- ` branch: * the agent experiments freely, and we squash-merge onto the user's branch only * if the task completed (a `final` event, not an error
(
messages: Message[],
sessionId: string,
options: AgentOptions,
)
| 647 | `${providerPromptCfg.override}\n\n` + |
| 648 | `Working directory: ${this.cwd}\n` + |
| 649 | `Git branch: ${gitBranch ?? '(none)'}\n` + |
| 650 | `Available tools (the only ones you can call this turn): ${effectiveTools.join(', ')}\n` + |
| 651 | `If a task needs web data, use \`web_search\` / \`web_fetch\` (if listed above). Do not claim you lack internet access — those tools ARE your internet access.`; |
| 652 | } else { |
| 653 | // Classify the user's intent so the prompt can inject task-shaped reasoning. |
| 654 | const taskClass = this.classifyForPrompt([{ role: 'user', content: userPrompt }]); |
| 655 | // Stack-specialist expertise: detect from the user's words + what's on disk, then |
| 656 | // inject the deep how-an-expert-builds-THIS block(s). Orthogonal to task class. |
| 657 | const stacks = detectStacks(userPrompt, projectSignals); |
| 658 | const stackAddendum = buildStackAddendum(stacks); |
| 659 | if (stacks.length > 0) logger.info('Stack specialist profiles active', { stacks }); |
| 660 | sysPrompt = buildSystemPrompt({ |
| 661 | cwd: this.cwd, |
| 662 | mode, |
| 663 | modelFamily: detectModelFamily(modelId), |
| 664 | modelId: resolvedModelId, |
| 665 | providerName, |
| 666 | projectInfo: { ...projectInfo }, |
| 667 | projectRules: mergedProjectRules, |
| 668 | knowledgeFacts, |
| 669 | directoryTree, |
| 670 | gitBranch, |
| 671 | availableToolNames: effectiveTools, |
| 672 | taskClass, |
| 673 | stackAddendum, |
| 674 | skillsBlock: buildSkillsSystemBlock({ prompt: userPrompt }), |
| 675 | identityBlock: identity.block, |
| 676 | }); |
| 677 | } |
| 678 | |
| 679 | // Provider-specific guidance, appended on top of whatever base prompt was built |
| 680 | // (default, role-override, or provider-override). Additive behavioral steering — |
| 681 | // does NOT replace the read-before-write rule or tool list above it. |
| 682 | if (providerPromptCfg?.append) { |
| 683 | sysPrompt = sysPrompt + |
| 684 | `\n\n# Provider-specific guidance (${providerName})\n${providerPromptCfg.append}`; |
| 685 | } |
| 686 | |
| 687 | // Static/volatile split: injections are routed into two buffers so the prompt-cache |
| 688 | // boundary lands between them. `stableTail` holds session-stable guidance (code style, |
| 689 | // failure lessons) that is byte-identical across turns → folded into the CACHED core. |
| 690 | // `volatileTail` holds genuinely per-turn context (retrieval, dep-graph, episodic recall) |
| 691 | // that changes with the query → kept AFTER the boundary so it never invalidates the core. |
| 692 | let stableTail = ''; |
| 693 | let volatileTail = ''; |
| 694 | |
| 695 | // ── Auto-retrieval pre-pass (best-effort) ── |
| 696 | // Embed the request and inject the most semantically-relevant files so the model |
| 697 | // starts at the right place in a large codebase instead of grepping blind. Only for |
| 698 | // top-level normal turns (sub-agents/vision are already scoped). NEVER blocks: bounded |
| 699 | // by a short timeout and any failure is swallowed to null. |
| 700 | if (mode === 'normal' && !customSysPromptOverride && !isTrivialMessage(userPrompt)) { |
| 701 | const ctxCfg = (this.config as any).context ?? {}; |
| 702 | if (ctxCfg.autoRetrieve !== false) { |
| 703 | try { |
| 704 | const buildInline = ctxCfg.buildIndexIfMissing === true; |
| 705 | const files = await retrieveRelevantFiles(this.cwd, userPrompt, { |
| 706 | embeddingModel: ctxCfg.embeddingModel, |
no test coverage detected