apex-dev 3.4.0 → 3.6.0

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.
Files changed (2) hide show
  1. package/dist/index.js +387 -26
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31679,6 +31679,8 @@ var require_config = __commonJS((exports, module2) => {
31679
31679
  var THINKER_MODEL = "z-ai/glm4.7";
31680
31680
  var COMMANDER_MODEL = "nvidia/llama-3.3-nemotron-70b-instruct";
31681
31681
  var CONTEXT_PRUNER_MODEL = "nvidia/llama-3.3-nemotron-70b-instruct";
31682
+ var RESEARCHER_MODEL = "nvidia/llama-3.3-nemotron-70b-instruct";
31683
+ var GENERAL_AGENT_MODEL = "z-ai/glm4.7";
31682
31684
  var MAX_TOOL_ITERATIONS = 50;
31683
31685
  var MAX_OUTPUT_LEN = 12000;
31684
31686
  var TOOL_TIMEOUT = 60000;
@@ -31777,6 +31779,30 @@ Output JSON only, no markdown fences:
31777
31779
  "reason": "Brief explanation of why this is the best",
31778
31780
  "improvements": "Any good ideas from other implementations to incorporate"
31779
31781
  }`;
31782
+ var RESEARCHER_WEB_SYSTEM_PROMPT = `You are a web research specialist embedded in a coding assistant. You receive web search results and synthesize them into a clear, accurate answer.
31783
+
31784
+ Rules:
31785
+ 1. Extract the most relevant information from results. Cite sources with URLs.
31786
+ 2. Be specific and actionable \u2014 code examples and exact details over generic advice.
31787
+ 3. If results don't contain the answer, say so clearly and share what you know from training data.
31788
+ 4. Prefer recent/authoritative sources. Note when information may be outdated.
31789
+ 5. Keep answers concise but thorough \u2014 developers are your audience.`;
31790
+ var RESEARCHER_DOCS_SYSTEM_PROMPT = `You are a documentation research specialist embedded in a coding assistant. You receive documentation search results and synthesize them into a precise, practical answer.
31791
+
31792
+ Rules:
31793
+ 1. Extract exact API signatures, parameter types, return values, and defaults.
31794
+ 2. Include code examples that can be used directly \u2014 prefer showing code over describing it.
31795
+ 3. Note version-specific behavior when relevant.
31796
+ 4. Highlight common pitfalls, gotchas, and deprecation warnings.
31797
+ 5. If the docs don't cover the question, say so and provide your best guidance from training data.`;
31798
+ var GENERAL_AGENT_SYSTEM_PROMPT = `You are a general-purpose coding agent. You receive file contents and conversation context, then produce a thorough, actionable response.
31799
+
31800
+ Your strengths:
31801
+ 1. Deep analysis \u2014 read and reason about complex codebases, trace call chains, identify patterns.
31802
+ 2. Problem solving \u2014 identify root causes, suggest fixes, plan multi-step implementations.
31803
+ 3. Code generation \u2014 write complete, working code that matches existing project conventions.
31804
+
31805
+ Be direct and comprehensive. Provide actual solutions, not descriptions of what to do. If you identify issues or risks, flag them clearly with severity.`;
31780
31806
  var nvidiaClient = new OpenAI({
31781
31807
  apiKey: process.env.NVIDIA_API_KEY || "",
31782
31808
  baseURL: "https://integrate.api.nvidia.com/v1"
@@ -31821,6 +31847,8 @@ Output JSON only, no markdown fences:
31821
31847
  THINKER_MODEL,
31822
31848
  COMMANDER_MODEL,
31823
31849
  CONTEXT_PRUNER_MODEL,
31850
+ RESEARCHER_MODEL,
31851
+ GENERAL_AGENT_MODEL,
31824
31852
  MAX_TOOL_ITERATIONS,
31825
31853
  MAX_OUTPUT_LEN,
31826
31854
  TOOL_TIMEOUT,
@@ -31832,6 +31860,9 @@ Output JSON only, no markdown fences:
31832
31860
  COMMANDER_SYSTEM_PROMPT,
31833
31861
  CONTEXT_PRUNER_SYSTEM_PROMPT,
31834
31862
  SELECTOR_SYSTEM_PROMPT,
31863
+ RESEARCHER_WEB_SYSTEM_PROMPT,
31864
+ RESEARCHER_DOCS_SYSTEM_PROMPT,
31865
+ GENERAL_AGENT_SYSTEM_PROMPT,
31835
31866
  nvidiaClient,
31836
31867
  session,
31837
31868
  truncateOutput,
@@ -31879,15 +31910,16 @@ Scripts: ${Object.keys(pkg.scripts).join(", ")}`;
31879
31910
 
31880
31911
  # Core Mandates
31881
31912
 
31882
- - **Tone:** Professional, direct, and concise. Suitable for a CLI environment.
31883
31913
  - **Understand first, act second:** Always gather context and read relevant files BEFORE editing. Use sub-agents (FilePickerMax, Grep, Read) to verify assumptions before implementing.
31884
31914
  - **Quality over speed:** Prioritize correctness over appearing productive. Fewer, well-informed sub-agent calls are better than many rushed ones.
31915
+ - **Tone:** Professional, direct, and concise. Suitable for a CLI environment.
31885
31916
  - **Validate assumptions:** Use FilePickerMax and Read to verify assumptions about libraries, APIs, and project structure before implementing.
31886
31917
  - **Proactiveness:** Fulfill the user's request thoroughly, including reasonable, directly implied follow-up actions.
31887
31918
  - **Confirm ambiguity:** Do not take significant actions beyond the clear scope of the request without confirming. If asked *how* to do something, explain first, don't just do it.
31888
31919
  - **Do what the user asks:** If the user asks you to do something, even running a risky command, do it.
31889
31920
  - **If a tool fails, try again or try a different tool.** Don't give up after one attempt.
31890
31921
  - **Act on errors.** If the user pastes an error or stack trace, locate the source, identify root cause, and fix it. Never punt back with "try checking X."
31922
+ - **Use <think></think> tags for moderate reasoning.** Call the Thinker sub-agent for anything more complex.
31891
31923
 
31892
31924
  # Output Style
31893
31925
  - Default to short answers (\u22644 lines) unless the user asks for detail.
@@ -31896,7 +31928,6 @@ Scripts: ${Object.keys(pkg.scripts).join(", ")}`;
31896
31928
  - No emojis unless the user uses them first.
31897
31929
  - For casual conversation, greetings, or quick questions, respond naturally without tools.
31898
31930
  - NEVER say "I don't have any tool to call" \u2014 just respond with what you know.
31899
- - Use <think></think> tags for moderate reasoning. Call the Thinker sub-agent for anything more complex.
31900
31931
 
31901
31932
  # Code Editing Mandates
31902
31933
 
@@ -31918,45 +31949,77 @@ Scripts: ${Object.keys(pkg.scripts).join(", ")}`;
31918
31949
 
31919
31950
  You have specialized sub-agents available as tools. **Your strong default should be to delegate to sub-agents** for anything beyond trivially simple operations. Sub-agents are specialists \u2014 they produce better, more thorough results than you chaining basic tools manually.
31920
31951
 
31921
- **Available sub-agents:**
31922
- - **FilePickerMax** \u2014 Scans the full codebase to find files relevant to a prompt. Use instead of manually chaining Glob/Grep/ListDir. Always specify the exact type of files needed \u2014 NEVER send generic prompts.
31952
+ ## Available Sub-Agents
31953
+
31954
+ **Context Gathering:**
31955
+ - **FilePickerMax** \u2014 Scans the full codebase to find files relevant to a prompt. Use instead of manually chaining Glob/Grep/ListDir. Always specify the exact type of files needed \u2014 NEVER send generic prompts. Spawn 2-5 of these in parallel for different aspects of the codebase.
31956
+ - **ResearcherWeb** \u2014 Searches the web and synthesizes results with an LLM. Use when you need up-to-date information, best practices, or answers that may not be in your training data. Falls back to LLM knowledge if web search is unavailable.
31957
+ - **ResearcherDocs** \u2014 Searches technical documentation for a library/framework and synthesizes a precise answer. Use when you need to verify API signatures, find usage patterns, or check library behavior.
31958
+
31959
+ **Reasoning & Planning:**
31923
31960
  - **Thinker** \u2014 Deep reasoning and planning. Call before implementing anything non-trivial to get a structured plan.
31924
- - **ThinkerBestOfN** \u2014 Multiple parallel reasoning passes, selects the best. Use for critical decisions.
31961
+ - **ThinkerBestOfN** \u2014 Multiple parallel reasoning passes, selects the best. Use for critical decisions that benefit from diverse perspectives.
31962
+ - **GeneralAgent** \u2014 Independent agent that reads specified files and solves problems. More powerful than Thinker because it receives actual file contents. Use when you need deep independent analysis, complex reasoning with full file context, or a second opinion.
31963
+
31964
+ **Implementation:**
31965
+ - **EditorMultiPrompt** \u2014 Tries multiple implementation strategies in parallel, selects the best, and **auto-applies the changes**. Use for important code changes where you want to explore multiple approaches.
31925
31966
  - **Commander** \u2014 Terminal command specialist. Plans and executes shell commands for a goal. Use instead of calling Bash directly for multi-step operations.
31926
- - **EditorMultiPrompt** \u2014 Tries multiple implementation strategies in parallel, selects the best.
31927
- - **CodeReview** \u2014 Reviews code changes for bugs, security, edge cases. Runs automatically after edits.
31928
- - **CodeReviewMulti** \u2014 Multiple reviewers analyze from different perspectives.
31967
+
31968
+ **Review & Maintenance:**
31969
+ - **CodeReview** / **CodeReviewMulti** \u2014 Reviews code changes for bugs, security, edge cases. CodeReviewMulti runs automatically after edits.
31929
31970
  - **ContextPruner** \u2014 Summarizes conversation history to free context space.
31930
31971
 
31931
- **How to orchestrate (use your judgment):**
31932
- 1. Spawn context-gathering sub-agents first (FilePickerMax, Read) to understand the codebase before making edits.
31933
- 2. For complex problems, call Thinker to reason and plan before implementing.
31934
- 3. Call Commander for shell operations (builds, tests, installs, git) instead of Bash directly.
31935
- 4. After implementing changes, validate by running tests/builds/lints via Commander.
31936
- 5. A code reviewer runs automatically after edits (skipped in lite mode, multi-perspective in max mode).
31937
- 6. If a sub-agent fails, fall back to doing the work yourself with basic tools (Read, Edit, Bash, Grep, etc.).
31938
- 7. Bundle independent sub-agent calls in the same turn for parallel execution.
31972
+ ## How to Orchestrate (use your judgment)
31939
31973
 
31940
- **When to skip sub-agents and act directly:**
31974
+ **Phase 1 \u2014 Context Gathering:**
31975
+ - Spawn multiple FilePickerMax in parallel for different aspects of the codebase (e.g. one for "entry points and routing", one for "authentication files", one for "test files").
31976
+ - Use Read to read all relevant files. For complex tasks, read 12-20 files to build a thorough understanding.
31977
+ - Use ResearcherWeb/ResearcherDocs when you need external information about libraries or APIs.
31978
+ - Bundle independent context-gathering calls in the same turn for parallel execution.
31979
+
31980
+ **Phase 2 \u2014 Planning:**
31981
+ - For tasks requiring 3+ steps, use TodoList to write out a step-by-step plan.
31982
+ - Call Thinker (or ThinkerBestOfN for critical decisions) to reason about the approach.
31983
+ - Call GeneralAgent when you need independent deep analysis with file context.
31984
+
31985
+ **Phase 3 \u2014 Implementation:**
31986
+ - Use EditorMultiPrompt for non-trivial code changes \u2014 it tries multiple strategies and auto-applies the best result.
31987
+ - For trivially simple edits on already-read files, use Edit or Patch directly.
31988
+ - Use Write only for creating new files.
31989
+
31990
+ **Phase 4 \u2014 Validation:**
31991
+ - After code changes, run the most relevant checks: tests, lint, typecheck, or build.
31992
+ - Use Commander for multi-step validation. Use Bash for single commands.
31993
+ - If checks fail, fix and re-run. If blocked, clearly state what's failing.
31994
+
31995
+ **Phase 5 \u2014 Review:**
31996
+ - CodeReviewMulti runs automatically after edits \u2014 don't duplicate its work.
31997
+ - If the review finds issues, fix them and re-validate.
31998
+
31999
+ ## When to Skip Sub-Agents and Act Directly
31941
32000
  - Reading a single known file path (just use Read)
31942
32001
  - A single targeted grep for a known pattern (just use Grep)
31943
32002
  - A quick one-line bash command (just use Bash)
31944
32003
  - Answering a question from memory/context (just respond)
31945
32004
  - Trivially simple edits where the file is already read and understood
31946
32005
 
32006
+ ## Parallel Execution Rules
32007
+ - Bundle independent tool calls in the same turn \u2014 this is critical for speed.
32008
+ - Spawn multiple FilePickerMax simultaneously for different aspects of the codebase.
32009
+ - Run independent Read calls in parallel.
32010
+ - **Don't spawn dependent agents in parallel** \u2014 e.g. don't spawn EditorMultiPrompt at the same time as FilePickerMax, since editing depends on context.
32011
+ - After implementation, run tests AND typechecks in parallel.
32012
+
31947
32013
  # Tool Usage (basic tools)
31948
- - Use Read to understand files before modifying them.
32014
+ - Use Read to understand files before modifying them. NEVER modify a file you haven't read.
31949
32015
  - Use Edit for surgical changes to existing files (preferred over Write).
31950
32016
  - Use Patch for multiple edits to the same file.
31951
32017
  - Use Write only for creating new files.
31952
32018
  - Use Bash for simple, single commands. Use Commander for multi-step operations.
31953
32019
  - Use Grep/Glob/ListDir for quick, targeted lookups. Use FilePickerMax for broad codebase discovery.
32020
+ - Use TodoList to track multi-step plans.
31954
32021
  - Don't ask for permission to use tools \u2014 just use them.
31955
32022
 
31956
- # Validation
31957
- - After code changes, run the most relevant checks: tests, lint, typecheck, or build. Prefer Commander or scripts from package.json.
31958
- - If checks fail, fix and re-run. If blocked, clearly state what's failing and why.
31959
-
31960
32023
  # Environment
31961
32024
  Working directory: ${PROJECT_ROOT}
31962
32025
  OS: ${process.platform}
@@ -32297,6 +32360,59 @@ var require_tools = __commonJS((exports, module2) => {
32297
32360
  required: []
32298
32361
  }
32299
32362
  }
32363
+ },
32364
+ {
32365
+ type: "function",
32366
+ function: {
32367
+ name: "ResearcherWeb",
32368
+ description: "Search the web and synthesize results into a clear answer using an LLM. Use when you need up-to-date information, best practices, or answers that may not be in your training data. Falls back to LLM knowledge if web search is unavailable.",
32369
+ parameters: {
32370
+ type: "object",
32371
+ properties: {
32372
+ prompt: { type: "string", description: "The question to research. Be specific for better results." },
32373
+ domains: {
32374
+ type: "array",
32375
+ description: 'Optional list of domains to restrict search to (e.g. ["stackoverflow.com", "github.com"]).',
32376
+ items: { type: "string" }
32377
+ }
32378
+ },
32379
+ required: ["prompt"]
32380
+ }
32381
+ }
32382
+ },
32383
+ {
32384
+ type: "function",
32385
+ function: {
32386
+ name: "ResearcherDocs",
32387
+ description: "Search technical documentation for a library or framework and synthesize a precise answer with API details and code examples. Use when you need to verify API signatures, find usage patterns, or check library behavior.",
32388
+ parameters: {
32389
+ type: "object",
32390
+ properties: {
32391
+ prompt: { type: "string", description: "The documentation question. Include the library/framework name and version if relevant." },
32392
+ library: { type: "string", description: 'The library or framework name (e.g. "React", "Express", "Prisma").' }
32393
+ },
32394
+ required: ["prompt"]
32395
+ }
32396
+ }
32397
+ },
32398
+ {
32399
+ type: "function",
32400
+ function: {
32401
+ name: "GeneralAgent",
32402
+ description: "Spawn an independent general-purpose agent that reads specified files and solves a problem. Use when you need deep independent analysis, complex reasoning with full file context, or a second opinion. More powerful than Thinker because it receives actual file contents.",
32403
+ parameters: {
32404
+ type: "object",
32405
+ properties: {
32406
+ prompt: { type: "string", description: "The problem to solve. Be specific about what analysis or output you need." },
32407
+ filePaths: {
32408
+ type: "array",
32409
+ description: "File paths to read and provide as context. The agent will analyze these files to solve the problem.",
32410
+ items: { type: "string" }
32411
+ }
32412
+ },
32413
+ required: ["prompt"]
32414
+ }
32415
+ }
32300
32416
  }
32301
32417
  ];
32302
32418
  module2.exports = { toolDefs };
@@ -32322,6 +32438,11 @@ var require_toolExecutors = __commonJS((exports, module2) => {
32322
32438
  CONTEXT_PRUNER_MODEL,
32323
32439
  CONTEXT_PRUNER_SYSTEM_PROMPT,
32324
32440
  SELECTOR_SYSTEM_PROMPT,
32441
+ RESEARCHER_MODEL,
32442
+ GENERAL_AGENT_MODEL,
32443
+ RESEARCHER_WEB_SYSTEM_PROMPT,
32444
+ RESEARCHER_DOCS_SYSTEM_PROMPT,
32445
+ GENERAL_AGENT_SYSTEM_PROMPT,
32325
32446
  NVIDIA_MODEL,
32326
32447
  nvidiaClient,
32327
32448
  session,
@@ -32361,6 +32482,35 @@ var require_toolExecutors = __commonJS((exports, module2) => {
32361
32482
  }
32362
32483
  }
32363
32484
  }
32485
+ function parseEditorOps(text) {
32486
+ const ops = [];
32487
+ const editRe = /---\s*EDIT:\s*(.+?)\s*---[\s\S]*?OLD:\s*\n```[^\n]*\n([\s\S]*?)\n```[\s\S]*?NEW:\s*\n```[^\n]*\n([\s\S]*?)\n```/g;
32488
+ let m2;
32489
+ while ((m2 = editRe.exec(text)) !== null) {
32490
+ ops.push({ type: "edit", path: m2[1].trim(), old_str: m2[2], new_str: m2[3] });
32491
+ }
32492
+ const createRe = /---\s*CREATE:\s*(.+?)\s*---\s*\n```[^\n]*\n([\s\S]*?)\n```/g;
32493
+ while ((m2 = createRe.exec(text)) !== null) {
32494
+ const p = m2[1].trim();
32495
+ if (!ops.some((o) => o.path === p && o.type === "edit")) {
32496
+ ops.push({ type: "create", path: p, content: m2[2] });
32497
+ }
32498
+ }
32499
+ return ops;
32500
+ }
32501
+ async function applyEditorOps(ops, executeFn) {
32502
+ const results = [];
32503
+ for (const op of ops) {
32504
+ if (op.type === "edit") {
32505
+ const r = await executeFn("Edit", { path: op.path, old_str: op.old_str, new_str: op.new_str });
32506
+ results.push(r.startsWith("Error") ? `\u2717 Edit ${op.path}: ${r}` : `\u2713 Edit ${op.path}`);
32507
+ } else if (op.type === "create") {
32508
+ const r = await executeFn("Write", { path: op.path, content: op.content });
32509
+ results.push(r.startsWith("Error") ? `\u2717 Create ${op.path}: ${r}` : `\u2713 Create ${op.path}`);
32510
+ }
32511
+ }
32512
+ return results;
32513
+ }
32364
32514
  async function executeTool(name, args, onStream) {
32365
32515
  try {
32366
32516
  switch (name) {
@@ -33049,17 +33199,37 @@ Reason: ${reason}`;
33049
33199
  if (improvements)
33050
33200
  result += `
33051
33201
  Improvements to consider: ${improvements}`;
33052
- result += `
33202
+ const ops = parseEditorOps(winning.result);
33203
+ if (ops.length > 0) {
33204
+ if (onStream)
33205
+ onStream(truncateOutput(result + `
33206
+
33207
+ Applying ${ops.length} change(s)...`));
33208
+ const applyResults = await applyEditorOps(ops, executeTool);
33209
+ result += `
33210
+
33211
+ --- Applied Changes ---
33212
+ ${applyResults.join(`
33213
+ `)}`;
33214
+ } else {
33215
+ result += `
33053
33216
 
33054
33217
  ${winning.result}`;
33218
+ }
33055
33219
  if (onStream)
33056
33220
  onStream(truncateOutput(result));
33057
33221
  return truncateOutput(result);
33058
33222
  } catch (apiErr) {
33059
- const result = `${header}Selector failed, using Implementation A:
33223
+ const fallbackOps = parseEditorOps(implementations[0].result);
33224
+ if (fallbackOps.length > 0) {
33225
+ const applyResults = await applyEditorOps(fallbackOps, executeTool);
33226
+ return truncateOutput(`${header}Selector failed, applied Implementation A:
33227
+ ${applyResults.join(`
33228
+ `)}`);
33229
+ }
33230
+ return truncateOutput(`${header}Selector failed, using Implementation A:
33060
33231
 
33061
- ${implementations[0].result}`;
33062
- return truncateOutput(result);
33232
+ ${implementations[0].result}`);
33063
33233
  }
33064
33234
  }
33065
33235
  case "CodeReviewMulti": {
@@ -33242,6 +33412,187 @@ ${summary}`;
33242
33412
  return `Error: Context pruning failed \u2014 ${apiErr.message}`;
33243
33413
  }
33244
33414
  }
33415
+ case "ResearcherWeb": {
33416
+ const header = `Web Research (${RESEARCHER_MODEL})
33417
+ ${"\u2500".repeat(40)}
33418
+ `;
33419
+ if (onStream)
33420
+ onStream(header + "Searching the web...");
33421
+ let searchResults = "";
33422
+ const searchArgs = { query: args.prompt, num_results: 5 };
33423
+ if (args.domains && args.domains.length)
33424
+ searchArgs.include_domains = args.domains;
33425
+ try {
33426
+ searchResults = await executeTool("WebSearch", searchArgs);
33427
+ } catch {
33428
+ searchResults = "(Web search unavailable \u2014 answering from knowledge)";
33429
+ }
33430
+ if (searchResults.startsWith("Error")) {
33431
+ searchResults = `(Web search failed: ${searchResults.slice(0, 200)})
33432
+
33433
+ Please answer from your training data.`;
33434
+ }
33435
+ try {
33436
+ const streamCb = onStream ? (text) => onStream(truncateOutput(header + text)) : null;
33437
+ const result = await streamCompletion({
33438
+ model: RESEARCHER_MODEL,
33439
+ messages: [
33440
+ { role: "system", content: RESEARCHER_WEB_SYSTEM_PROMPT },
33441
+ { role: "user", content: `# Question
33442
+ ${args.prompt}
33443
+
33444
+ # Web Search Results
33445
+ ${searchResults}` }
33446
+ ],
33447
+ max_tokens: 4096,
33448
+ temperature: 0.3
33449
+ }, streamCb) || "(No response from researcher)";
33450
+ return truncateOutput(header + result);
33451
+ } catch (apiErr) {
33452
+ return `Error: ResearcherWeb failed \u2014 ${apiErr.message}`;
33453
+ }
33454
+ }
33455
+ case "ResearcherDocs": {
33456
+ const header = `Docs Research (${RESEARCHER_MODEL})
33457
+ ${"\u2500".repeat(40)}
33458
+ `;
33459
+ if (onStream)
33460
+ onStream(header + "Searching documentation...");
33461
+ const docDomains = [
33462
+ "developer.mozilla.org",
33463
+ "react.dev",
33464
+ "nodejs.org",
33465
+ "docs.python.org",
33466
+ "doc.rust-lang.org",
33467
+ "pkg.go.dev",
33468
+ "learn.microsoft.com",
33469
+ "typescriptlang.org",
33470
+ "expressjs.com",
33471
+ "nextjs.org",
33472
+ "vuejs.org",
33473
+ "angular.io",
33474
+ "svelte.dev",
33475
+ "docs.rs",
33476
+ "rubydoc.info",
33477
+ "docs.oracle.com",
33478
+ "npmjs.com"
33479
+ ];
33480
+ const query = args.library ? `${args.library} ${args.prompt}` : args.prompt;
33481
+ let searchResults = "";
33482
+ try {
33483
+ searchResults = await executeTool("WebSearch", {
33484
+ query: `${query} documentation`,
33485
+ num_results: 8,
33486
+ include_domains: docDomains
33487
+ });
33488
+ } catch {
33489
+ searchResults = "";
33490
+ }
33491
+ if (!searchResults || searchResults === "No results found.") {
33492
+ try {
33493
+ searchResults = await executeTool("WebSearch", {
33494
+ query: `${query} documentation API reference`,
33495
+ num_results: 5
33496
+ });
33497
+ } catch {
33498
+ searchResults = "(Documentation search unavailable \u2014 answering from knowledge)";
33499
+ }
33500
+ }
33501
+ if (!searchResults || searchResults.startsWith("Error")) {
33502
+ searchResults = "(No documentation results found \u2014 answering from knowledge)";
33503
+ }
33504
+ try {
33505
+ const streamCb = onStream ? (text) => onStream(truncateOutput(header + text)) : null;
33506
+ const result = await streamCompletion({
33507
+ model: RESEARCHER_MODEL,
33508
+ messages: [
33509
+ { role: "system", content: RESEARCHER_DOCS_SYSTEM_PROMPT },
33510
+ {
33511
+ role: "user",
33512
+ content: `# Question
33513
+ ${args.prompt}${args.library ? `
33514
+ Library: ${args.library}` : ""}
33515
+
33516
+ # Documentation Search Results
33517
+ ${searchResults}`
33518
+ }
33519
+ ],
33520
+ max_tokens: 4096,
33521
+ temperature: 0.2
33522
+ }, streamCb) || "(No response from researcher)";
33523
+ return truncateOutput(header + result);
33524
+ } catch (apiErr) {
33525
+ return `Error: ResearcherDocs failed \u2014 ${apiErr.message}`;
33526
+ }
33527
+ }
33528
+ case "GeneralAgent": {
33529
+ const header = `General Agent (${GENERAL_AGENT_MODEL})
33530
+ ${"\u2500".repeat(40)}
33531
+ `;
33532
+ if (onStream)
33533
+ onStream(header + "Reading files and analyzing...");
33534
+ const MAX_TOTAL_CHARS = 50000;
33535
+ let totalChars = 0;
33536
+ const fileContents = [];
33537
+ for (const fp of args.filePaths || []) {
33538
+ const absPath = resolvePath(fp);
33539
+ const stat = fs2.statSync(absPath, { throwIfNoEntry: false });
33540
+ if (!stat || stat.isDirectory()) {
33541
+ fileContents.push(`--- ${fp} ---
33542
+ [Not found or is a directory]`);
33543
+ continue;
33544
+ }
33545
+ if (stat.size > 256 * 1024) {
33546
+ fileContents.push(`--- ${fp} ---
33547
+ [File too large: ${(stat.size / 1024).toFixed(0)}KB \u2014 skipped]`);
33548
+ continue;
33549
+ }
33550
+ const content = fs2.readFileSync(absPath, "utf-8");
33551
+ if (totalChars + content.length > MAX_TOTAL_CHARS) {
33552
+ const remaining = MAX_TOTAL_CHARS - totalChars;
33553
+ if (remaining > 500) {
33554
+ fileContents.push(`--- ${fp} ---
33555
+ ${content.slice(0, remaining)}
33556
+ [Truncated \u2014 context limit reached]`);
33557
+ }
33558
+ totalChars = MAX_TOTAL_CHARS;
33559
+ break;
33560
+ }
33561
+ fileContents.push(`--- ${fp} ---
33562
+ ${content}`);
33563
+ totalChars += content.length;
33564
+ }
33565
+ const historyCtx = session.conversationHistory.slice(-8).map((m2) => `[${m2.role}]: ${(m2.content || "").slice(0, 400)}`).join(`
33566
+ `);
33567
+ const userContent = [
33568
+ `# Task
33569
+ ${args.prompt}`,
33570
+ fileContents.length > 0 ? `
33571
+ # Files (${fileContents.length})
33572
+ ${fileContents.join(`
33573
+
33574
+ `)}` : "",
33575
+ historyCtx ? `
33576
+ # Recent conversation
33577
+ ${historyCtx}` : ""
33578
+ ].filter(Boolean).join(`
33579
+ `);
33580
+ try {
33581
+ const streamCb = onStream ? (text) => onStream(truncateOutput(header + text)) : null;
33582
+ const result = await streamCompletion({
33583
+ model: GENERAL_AGENT_MODEL,
33584
+ messages: [
33585
+ { role: "system", content: GENERAL_AGENT_SYSTEM_PROMPT },
33586
+ { role: "user", content: userContent }
33587
+ ],
33588
+ max_tokens: 4096,
33589
+ temperature: 0.4
33590
+ }, streamCb) || "(No response from agent)";
33591
+ return truncateOutput(header + result);
33592
+ } catch (apiErr) {
33593
+ return `Error: GeneralAgent failed \u2014 ${apiErr.message}`;
33594
+ }
33595
+ }
33245
33596
  default:
33246
33597
  return `Unknown tool: ${name}`;
33247
33598
  }
@@ -33298,6 +33649,16 @@ var require_utils3 = __commonJS((exports, module2) => {
33298
33649
  return args.prompt ? args.prompt.slice(0, 40) : "running commands";
33299
33650
  case "ContextPruner":
33300
33651
  return "pruning context";
33652
+ case "ResearcherWeb":
33653
+ return args.prompt ? args.prompt.slice(0, 40) : "web research";
33654
+ case "ResearcherDocs":
33655
+ return args.prompt ? `${args.library ? args.library + ": " : ""}${args.prompt.slice(0, 30)}` : "docs research";
33656
+ case "GeneralAgent":
33657
+ return args.prompt ? args.prompt.slice(0, 40) : "analyzing";
33658
+ case "WebSearch":
33659
+ return args.query ? args.query.slice(0, 40) : "searching";
33660
+ case "TodoList":
33661
+ return args.action || "";
33301
33662
  default:
33302
33663
  return JSON.stringify(args).slice(0, 60);
33303
33664
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apex-dev",
3
- "version": "3.4.0",
3
+ "version": "3.6.0",
4
4
  "description": "Apex AI - a friendly agentic coding assistant for the terminal",
5
5
  "main": "dist/index.js",
6
6
  "bin": {