shark-ai 0.4.14 → 0.4.16

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/bin/shark.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  t,
10
10
  tokenStorage,
11
11
  tui
12
- } from "../chunk-WVBOO6LE.js";
12
+ } from "../chunk-H6S7DYRG.js";
13
13
 
14
14
  // src/core/error/crash-handler.ts
15
15
  import fs from "fs";
@@ -422,6 +422,7 @@ var AgentActionSchema = z2.object({
422
422
  "modify_file",
423
423
  "list_files",
424
424
  "search_file",
425
+ "search_code",
425
426
  "read_file",
426
427
  "delete_file",
427
428
  "list_structure",
@@ -429,6 +430,7 @@ var AgentActionSchema = z2.object({
429
430
  "search_ast",
430
431
  "run_command",
431
432
  "talk_with_user",
433
+ "use_mcp_tool",
432
434
  "ast_list_structure",
433
435
  "ast_get_method",
434
436
  "ast_add_method",
@@ -457,6 +459,9 @@ var AgentActionSchema = z2.object({
457
459
  tool_name: z2.string().nullable().optional(),
458
460
  tool_args: z2.string().nullable().optional(),
459
461
  // JSON string argument
462
+ // search_code fields
463
+ query: z2.string().nullable().optional(),
464
+ is_regex: z2.boolean().nullable().optional(),
460
465
  // AST-Grep fields
461
466
  pattern: z2.string().nullable().optional(),
462
467
  fix: z2.string().nullable().optional(),
@@ -704,6 +709,12 @@ function getAgentId(overrideId) {
704
709
  if (config.agents?.ba) return config.agents.ba;
705
710
  return process.env.STACKSPOT_BA_AGENT_ID || "01KEJ95G304TNNAKGH5XNEEBVD";
706
711
  }
712
+ function getAgentVersion(overrideVersion) {
713
+ if (overrideVersion) return overrideVersion;
714
+ const config = ConfigManager.getInstance().getConfig();
715
+ if (config.agentVersions?.ba) return config.agentVersions.ba;
716
+ return process.env.STACKSPOT_BA_AGENT_VERSION;
717
+ }
707
718
  async function runBusinessAnalystAgent(prompt, options = {}) {
708
719
  const { agentId, onChunk, onComplete } = options;
709
720
  const realm = await getActiveRealm();
@@ -721,6 +732,10 @@ async function runBusinessAnalystAgent(prompt, options = {}) {
721
732
  deep_search_ks: false,
722
733
  conversation_id: existingConversationId
723
734
  };
735
+ const agentVersion = getAgentVersion();
736
+ if (agentVersion) {
737
+ requestPayload.agent_version_number = agentVersion;
738
+ }
724
739
  const effectiveAgentId = getAgentId(options.agentId);
725
740
  const agentUrl = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${effectiveAgentId}/chat`;
726
741
  const headers = {
@@ -1349,6 +1364,49 @@ function handleSearchFile(pattern) {
1349
1364
  return `Error searching files: ${e.message}`;
1350
1365
  }
1351
1366
  }
1367
+ function handleSearchCode(globPattern, query, isRegex = false) {
1368
+ const MAX_MATCHES = 50;
1369
+ const MAX_FILE_SIZE_BYTES = 500 * 1024;
1370
+ try {
1371
+ const files = fg.sync(globPattern, { dot: true, absolute: false });
1372
+ if (files.length === 0) return `No files found matching pattern: "${globPattern}"`;
1373
+ let searchRegex;
1374
+ try {
1375
+ searchRegex = isRegex ? new RegExp(query, "gi") : new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
1376
+ } catch {
1377
+ return `Error: Invalid regex pattern: "${query}"`;
1378
+ }
1379
+ const results = [];
1380
+ let totalMatches = 0;
1381
+ for (const filePath of files) {
1382
+ if (totalMatches >= MAX_MATCHES) break;
1383
+ try {
1384
+ const fullPath = path5.resolve(process.cwd(), filePath);
1385
+ const stats = fs4.statSync(fullPath);
1386
+ if (stats.size > MAX_FILE_SIZE_BYTES) continue;
1387
+ const content = fs4.readFileSync(fullPath, "utf-8");
1388
+ const lines = content.split("\n");
1389
+ for (let i = 0; i < lines.length; i++) {
1390
+ if (totalMatches >= MAX_MATCHES) break;
1391
+ searchRegex.lastIndex = 0;
1392
+ if (searchRegex.test(lines[i])) {
1393
+ results.push(`${filePath}:${i + 1}: ${lines[i].trim()}`);
1394
+ totalMatches++;
1395
+ }
1396
+ }
1397
+ } catch {
1398
+ }
1399
+ }
1400
+ if (results.length === 0) {
1401
+ return `No matches found for "${query}" in files matching "${globPattern}"`;
1402
+ }
1403
+ const limited = totalMatches >= MAX_MATCHES ? ` (limited to ${MAX_MATCHES})` : "";
1404
+ return `Found ${totalMatches} match(es) for "${query}" in "${globPattern}"${limited}:
1405
+ ${results.join("\n")}`;
1406
+ } catch (e) {
1407
+ return `Error searching code: ${e.message}`;
1408
+ }
1409
+ }
1352
1410
  function startSmartReplace(filePath, newContent, targetContent, tui2) {
1353
1411
  if (!fs4.existsSync(filePath)) {
1354
1412
  tui2.log.error(`\u274C File not found for modification: ${filePath}`);
@@ -1715,6 +1773,12 @@ function getAgentId2(overrideId) {
1715
1773
  if (config.agents?.spec) return config.agents.spec;
1716
1774
  return process.env.STACKSPOT_SPEC_AGENT_ID || "01KEPXTX37FTB4N672TZST4SGP";
1717
1775
  }
1776
+ function getAgentVersion2(overrideVersion) {
1777
+ if (overrideVersion) return overrideVersion;
1778
+ const config = ConfigManager.getInstance().getConfig();
1779
+ if (config.agentVersions?.spec) return config.agentVersions.spec;
1780
+ return process.env.STACKSPOT_SPEC_AGENT_VERSION;
1781
+ }
1718
1782
  async function interactiveSpecificationAgent(options = {}) {
1719
1783
  FileLogger.init();
1720
1784
  tui.intro("\u{1F3D7}\uFE0F Specification Agent (Template-Based)");
@@ -1726,22 +1790,22 @@ async function interactiveSpecificationAgent(options = {}) {
1726
1790
  let initialContent = `# Technical Specification: {{PROJECT_NAME}}
1727
1791
 
1728
1792
  ## 1. Technology Stack
1729
- [TO BE ANALYZED]
1793
+ [TO BE ANALYZED - STACK]
1730
1794
  - Language: [e.g. TypeScript]
1731
1795
  - Framework: [e.g. Node.js / React]
1732
1796
  - Database: [e.g. SQLite / PostgreSQL]
1733
1797
  - Key Libraries: [Top 5 dependencies]
1734
1798
 
1735
1799
  ## 2. Architecture Overview
1736
- [TO BE ANALYZED]
1800
+ [TO BE ANALYZED - ARCHITECTURE]
1737
1801
  [Brief description of architectural pattern]
1738
1802
 
1739
1803
  ## 3. Data Model
1740
- [TO BE ANALYZED]
1804
+ [TO BE ANALYZED - DATA MODEL]
1741
1805
  [Schema/ERD definitions]
1742
1806
 
1743
1807
  ## 4. API / Interface Contracts
1744
- [TO BE ANALYZED]
1808
+ [TO BE ANALYZED - API]
1745
1809
  [Main endpoints or CLI commands]
1746
1810
 
1747
1811
  ## 5. Implementation Steps
@@ -1774,31 +1838,17 @@ async function interactiveSpecificationAgent(options = {}) {
1774
1838
  }
1775
1839
  let initialPrompt = `
1776
1840
  Voc\xEA \xE9 o **Shark Spec**, um Arquiteto de Software S\xEAnior e Tech Lead.
1777
- Seu objetivo \xE9 produzir uma especifica\xE7\xE3o t\xE9cnica precisa e espec\xEDfica para a tarefa no arquivo \`_sharkrc/tech-spec.md\`.
1841
+ Seu objetivo final \xE9 produzir uma especifica\xE7\xE3o t\xE9cnica precisa para a tarefa no arquivo \`_sharkrc/tech-spec.md\`.
1778
1842
 
1779
- \u26A0\uFE0F WORKFLOW OBRIGAT\xD3RIO \u2013 SIGA ESSA SEQU\xCANCIA ESTRITAMENTE. N\xC3O PULE ETAPAS.
1843
+ \u26A0\uFE0F O SEU WORKFLOW \xC9 GUIADO POR FASES.
1844
+ N\xC3O TENTE ADIANTAR O TRABALHO (ex: investigar c\xF3digo ou preencher template agora).
1780
1845
 
1781
- **FASE 1 \u2013 ENTENDA A TAREFA (COMECE AQUI):**
1846
+ **VOC\xCA EST\xC1 NA FASE 1: ENTENDIMENTO DA TAREFA**
1782
1847
  - Use \`talk_with_user\` para perguntar ao usu\xE1rio qual tarefa espec\xEDfica, funcionalidade ou bug ele precisa especificar.
1783
- - N\xC3O explore o c\xF3digo ou leia arquivos ainda.
1784
- - Confirme o escopo e os limites com o usu\xE1rio antes de prosseguir.
1785
-
1786
- **FASE 2 \u2013 INVESTIGUE (FOCADO APENAS NA TAREFA):**
1787
- - Use \`list_files\` e \`read_file\` APENAS em arquivos diretamente relevantes para a tarefa confirmada.
1788
- - N\xC3O leia o projeto de forma gen\xE9rica.
1789
- - REGRA DE LEITURA PR\xC9VIA: Voc\xEA N\xC3O PODE adicionar uma tarefa referenciando um arquivo que voc\xEA n\xE3o leu nesta sess\xE3o (exce\xE7\xE3o: novos arquivos a serem criados).
1790
-
1791
- **FASE 3 \u2013 PREENCHA O TEMPLATE:**
1792
- - Use \`modify_file\` em \`_sharkrc/tech-spec.md\` para substituir os placeholders com conte\xFAdo real e espec\xEDfico da tarefa.
1793
- - As Se\xE7\xF5es 1-4 (Stack, Arquitetura, Modelo de Dados, API) devem descrever o contexto da TAREFA, n\xE3o do projeto como um todo.
1794
- - Passos de Implementa\xE7\xE3o: APENAS checkboxes markdown: \`- [ ] [Verbo de A\xE7\xE3o] [O Que] em [Caminho Relativo]\`. SEM listas numeradas, SEM subn\xEDveis.
1795
- - Quando todos os placeholders acabarem e voc\xEA estiver satisfeito, retorne: \`SPEC_UPDATED: Complete\`.
1796
-
1797
- **REGRAS CR\xCDTICAS:**
1798
- - NUNCA preencha a Technology Stack ou Architecture com informa\xE7\xF5es gen\xE9ricas do projeto. Essas se\xE7\xF5es devem refletir o que a tarefa ir\xE1 usar ou alterar.
1799
- - Use \`talk_with_user\` sempre que os requisitos forem amb\xEDguos.
1800
- - N\xC3O tente escrever todas as se\xE7\xF5es de uma vez. Trabalhe de forma incremental, uma se\xE7\xE3o por vez.
1801
- - IMPORTANTE: Toda a sua comunica\xE7\xE3o e a especifica\xE7\xE3o gerada DEVEM ser em Portugu\xEAs.
1848
+ - Confirme o escopo e os limites com o usu\xE1rio.
1849
+ - Se o escopo estiver perfeitamente claro e confirmado (com o usu\xE1rio), emita "PHASE_COMPLETED" no campo "summary" do JSON para avan\xE7ar.
1850
+
1851
+ IMPORTANTE: Toda a sua comunica\xE7\xE3o DEVE ser em Portugu\xEAs.
1802
1852
  `;
1803
1853
  if (briefingContent) {
1804
1854
  initialPrompt += `
@@ -1836,6 +1886,7 @@ async function runSpecLoop(initialMessage, targetPath, overrideAgentId) {
1836
1886
  let nextPrompt = initialMessage;
1837
1887
  let keepGoing = true;
1838
1888
  let stepCount = 0;
1889
+ let currentPhase = 1;
1839
1890
  const MAX_STEPS = 30;
1840
1891
  while (keepGoing && stepCount < MAX_STEPS) {
1841
1892
  stepCount++;
@@ -1860,23 +1911,6 @@ async function runSpecLoop(initialMessage, targetPath, overrideAgentId) {
1860
1911
  let executionResults = "";
1861
1912
  let waitingForUser = false;
1862
1913
  let specUpdated = false;
1863
- if (lastResponse.message && lastResponse.message.includes("SPEC_UPDATED:")) {
1864
- const content = fs5.existsSync(targetPath) ? fs5.readFileSync(targetPath, "utf-8") : "";
1865
- if (content.includes("[TO BE")) {
1866
- const pendingMatches = [...content.matchAll(/## ([^\n]+)[\s\S]*?\[TO BE/g)].map((m) => m[1]);
1867
- let missing = pendingMatches.length > 0 ? pendingMatches.join(", ") : "algumas se\xE7\xF5es";
1868
- tui.log.warning(`O agente tentou concluir prematuramente, mas h\xE1 placeholders pendentes. For\xE7ando retorno...`);
1869
- nextPrompt = `[System Error]: A valida\xE7\xE3o falhou e o bloqueio autom\xE1tico foi acionado.
1870
- Voc\xEA tentou concluir a tarefa, mas o arquivo AINDA possui placeholders '[TO BE ANALYZED]' ou '[TO BE FILLED]'.
1871
- As seguintes se\xE7\xF5es ainda cont\xEAm estes placeholders: ${missing}.
1872
- Voc\xEA \xE9 OBRIGADO a usar a action \`modify_file\` para preencher o conte\xFAdo de cada uma dessas se\xE7\xF5es. Use o placeholder exato no campo \`target_content\`. N\xC3O repita a conclus\xE3o da tarefa at\xE9 corrigir todas as pend\xEAncias.`;
1873
- continue;
1874
- } else {
1875
- const updateSummary = lastResponse.message.split("SPEC_UPDATED:")[1].trim();
1876
- tui.log.success(`\u2705 Spec Finalized: ${updateSummary}`);
1877
- return;
1878
- }
1879
- }
1880
1914
  for (const action of lastResponse.actions) {
1881
1915
  if (action.type === "talk_with_user") {
1882
1916
  tui.log.info(colors.primary("\u{1F916} Architect:"));
@@ -1902,6 +1936,16 @@ ${result}
1902
1936
  executionResults += `[Action search_file(${action.path}) Result]:
1903
1937
  ${result}
1904
1938
 
1939
+ `;
1940
+ } else if (action.type === "search_code") {
1941
+ const glob = action.path || "src/**/*";
1942
+ const query = action.query || "";
1943
+ const isRegex = action.is_regex === true;
1944
+ tui.log.info(`\u{1F50E} Search code: ${colors.dim(`"${query}" in ${glob}`)}`);
1945
+ const result = handleSearchCode(glob, query, isRegex);
1946
+ executionResults += `[Action search_code("${query}" in "${glob}") Result]:
1947
+ ${result}
1948
+
1905
1949
  `;
1906
1950
  } else if (["create_file", "modify_file"].includes(action.type)) {
1907
1951
  let actionPath = path6.resolve(action.path || "");
@@ -1936,7 +1980,7 @@ ${result}
1936
1980
  `;
1937
1981
  specUpdated = true;
1938
1982
  } else {
1939
- executionResults += `[Action modify_file]: Failed. Target content not found.
1983
+ executionResults += `[Action modify_file]: Failed. Target content not found or ambiguous.
1940
1984
  `;
1941
1985
  }
1942
1986
  } else {
@@ -1950,6 +1994,62 @@ ${result}
1950
1994
  }
1951
1995
  }
1952
1996
  }
1997
+ if (lastResponse.message && lastResponse.message.includes("PHASE_COMPLETED")) {
1998
+ const extraContext = executionResults ? `
1999
+
2000
+ Resultados das \xFAltimas a\xE7\xF5es executadas antes da conclus\xE3o:
2001
+ ${executionResults}` : "";
2002
+ if (currentPhase === 1) {
2003
+ currentPhase = 2;
2004
+ tui.log.success(`\u2705 Fase 1 Conclu\xEDda. Iniciando Fase 2 (Investiga\xE7\xE3o).`);
2005
+ nextPrompt = `[System Message]
2006
+ Voc\xEA completou a FASE 1 com sucesso.
2007
+
2008
+ **VOC\xCA AGORA EST\xC1 NA FASE 2: INVESTIGA\xC7\xC3O**
2009
+ - Use \`search_code\` e \`list_files\` para explorar os arquivos relevantes \xE0 tarefa.
2010
+ - Prefira \`search_code\` em vez de \`read_file\` para buscar c\xF3digo sem inflar o contexto.
2011
+ - N\xC3O leia o projeto inteiro de forma gen\xE9rica.
2012
+ - REGRA DE OURO (READ-FIRST): Voc\xEA N\xC3O PODE referenciar um arquivo na especifica\xE7\xE3o t\xE9cnica que n\xE3o tenha investigado nesta fase.
2013
+ - Quando achar que possui toda a clareza t\xE9cnica sobre onde e o que deve ser feito no c\xF3digo, emita "PHASE_COMPLETED" no summary.${extraContext}`;
2014
+ continue;
2015
+ } else if (currentPhase === 2) {
2016
+ currentPhase = 3;
2017
+ tui.log.success(`\u2705 Fase 2 Conclu\xEDda. Iniciando Fase 3 (Preenchimento).`);
2018
+ nextPrompt = `[System Message]
2019
+ Voc\xEA completou a FASE 2 com sucesso.
2020
+
2021
+ **VOC\xCA AGORA EST\xC1 NA FASE 3: PREENCHIMENTO DO TEMPLATE**
2022
+ - Use \`modify_file\` no arquivo \`${targetPath}\` para substituir os placeholders pelo conte\xFAdo real levantado na fase de investiga\xE7\xE3o.
2023
+ - As se\xE7\xF5es 1-4 devem descrever o contexto da TAREFA, e n\xE3o o projeto como um todo.
2024
+ - Passos de Implementa\xE7\xE3o (Implementation Steps): APENAS checkboxes markdown: \`- [ ] [Verbo de A\xE7\xE3o] [O Que] em [Caminho Relativo]\`.
2025
+ - Quando TODOS os placeholders ([TO BE ANALYZED...] ou [TO BE FILLED]) forem substitu\xEDdos e o trabalho conclu\xEDdo, emita "SPEC_UPDATED: Complete" no summary para finalizar.${extraContext}`;
2026
+ continue;
2027
+ }
2028
+ }
2029
+ if (lastResponse.message && lastResponse.message.includes("SPEC_UPDATED:")) {
2030
+ if (currentPhase < 3) {
2031
+ tui.log.warning(`O agente tentou finalizar prematuramente. For\xE7ando retorno para a fase atual...`);
2032
+ nextPrompt = `[System Error]: Voc\xEA tentou finalizar a especifica\xE7\xE3o prematuramente emitindo SPEC_UPDATED, mas ainda est\xE1 na Fase ${currentPhase}. Voc\xEA s\xF3 pode finalizar quando estiver na Fase 3.
2033
+
2034
+ Continue seu trabalho na Fase ${currentPhase} ou emita "PHASE_COMPLETED" se terminou esta etapa atual.`;
2035
+ continue;
2036
+ }
2037
+ const content = fs5.existsSync(targetPath) ? fs5.readFileSync(targetPath, "utf-8") : "";
2038
+ if (content.includes("[TO BE")) {
2039
+ const pendingMatches = [...content.matchAll(/## ([^\n]+)[\s\S]*?\[TO BE/g)].map((m) => m[1]);
2040
+ let missing = pendingMatches.length > 0 ? pendingMatches.join(", ") : "algumas se\xE7\xF5es";
2041
+ tui.log.warning(`O agente tentou concluir prematuramente, mas h\xE1 placeholders pendentes. For\xE7ando retorno...`);
2042
+ nextPrompt = `[System Error]: A valida\xE7\xE3o falhou e o bloqueio autom\xE1tico foi acionado.
2043
+ Voc\xEA tentou concluir a tarefa, mas o arquivo AINDA possui placeholders '[TO BE ANALYZED...]' ou '[TO BE FILLED]'.
2044
+ As seguintes se\xE7\xF5es ainda cont\xEAm estes placeholders: ${missing}.
2045
+ Voc\xEA \xE9 OBRIGADO a usar a action \`modify_file\` para preencher o conte\xFAdo de cada uma dessas se\xE7\xF5es. Use o placeholder exato no campo \`target_content\`. N\xC3O repita a conclus\xE3o da tarefa at\xE9 corrigir todas as pend\xEAncias.`;
2046
+ continue;
2047
+ } else {
2048
+ const updateSummary = lastResponse.message.split("SPEC_UPDATED:")[1].trim();
2049
+ tui.log.success(`\u2705 Spec Finalized: ${updateSummary}`);
2050
+ return;
2051
+ }
2052
+ }
1953
2053
  if (waitingForUser) {
1954
2054
  const userReply = await tui.text({ message: "Your answer", placeholder: "Type your answer..." });
1955
2055
  if (tui.isCancel(userReply)) {
@@ -1972,6 +2072,8 @@ Por favor, envie uma nova action \`modify_file\` focada em uma destas se\xE7\xF5
1972
2072
  } else {
1973
2073
  systemMsg += "\n[System]: O arquivo parece completo! Se estiver satisfeito e possuir TODAS as implementa\xE7\xF5es descritas, retorne 'SPEC_UPDATED: Complete'.";
1974
2074
  }
2075
+ } else {
2076
+ systemMsg += "\n[System]: A modifica\xE7\xE3o do arquivo falhou. Verifique se o `target_content` que voc\xEA usou existe EXATAMENTE como no arquivo e se ele \xE9 \xDANICO na hora de usar a action `modify_file`.";
1975
2077
  }
1976
2078
  nextPrompt = `${executionResults}
1977
2079
 
@@ -2013,6 +2115,10 @@ async function callSpecAgentApi(prompt, onChunk, agentId) {
2013
2115
  use_conversation: true,
2014
2116
  conversation_id: conversationId
2015
2117
  };
2118
+ const agentVersion = getAgentVersion2();
2119
+ if (agentVersion) {
2120
+ payload.agent_version_number = agentVersion;
2121
+ }
2016
2122
  const effectiveAgentId = getAgentId2(agentId);
2017
2123
  const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${effectiveAgentId}/chat`;
2018
2124
  let fullMsg = "";
@@ -2050,6 +2156,11 @@ function getAgentId3() {
2050
2156
  if (config.agents?.scan) return config.agents.scan;
2051
2157
  return process.env.STACKSPOT_SCAN_AGENT_ID || "01KEQ9AHWB550J2244YBH3QATN";
2052
2158
  }
2159
+ function getAgentVersion3() {
2160
+ const config = ConfigManager.getInstance().getConfig();
2161
+ if (config.agentVersions?.scan) return config.agentVersions.scan;
2162
+ return process.env.STACKSPOT_SCAN_AGENT_VERSION;
2163
+ }
2053
2164
  async function interactiveScanAgent(options = {}) {
2054
2165
  FileLogger.init();
2055
2166
  const config = ConfigManager.getInstance().getConfig();
@@ -2515,6 +2626,10 @@ async function callScanAgentApi(prompt, onChunk) {
2515
2626
  use_conversation: true,
2516
2627
  conversation_id: conversationId
2517
2628
  };
2629
+ const agentVersion = getAgentVersion3();
2630
+ if (agentVersion) {
2631
+ payload.agent_version_number = agentVersion;
2632
+ }
2518
2633
  const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${getAgentId3()}/chat`;
2519
2634
  let fullMsg = "";
2520
2635
  let raw = {};
@@ -2577,6 +2692,13 @@ function getAgentId4(overrideId) {
2577
2692
  if (process.env.STACKSPOT_DEV_AGENT_ID) return process.env.STACKSPOT_DEV_AGENT_ID;
2578
2693
  return "01KEQCGJ65YENRA4QBXVN1YFFX";
2579
2694
  }
2695
+ function getAgentVersion4(overrideVersion) {
2696
+ if (overrideVersion) return overrideVersion;
2697
+ const config = ConfigManager.getInstance().getConfig();
2698
+ if (config.agentVersions?.dev) return config.agentVersions.dev;
2699
+ if (process.env.STACKSPOT_DEV_AGENT_VERSION) return process.env.STACKSPOT_DEV_AGENT_VERSION;
2700
+ return void 0;
2701
+ }
2580
2702
  async function interactiveDeveloperAgent(options = {}) {
2581
2703
  FileLogger.init();
2582
2704
  const agentId = getAgentId4();
@@ -2886,6 +3008,10 @@ async function callDevAgentApi(prompt, onChunk, conversationKey = AGENT_TYPE4) {
2886
3008
  conversation_id: conversationId,
2887
3009
  stackspot_knowledge: false
2888
3010
  };
3011
+ const agentVersion = getAgentVersion4();
3012
+ if (agentVersion) {
3013
+ payload.agent_version_number = agentVersion;
3014
+ }
2889
3015
  const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${getAgentId4()}/chat`;
2890
3016
  let fullMsg = "";
2891
3017
  let raw = {};
@@ -3168,6 +3294,11 @@ function getAgentId5() {
3168
3294
  if (config.agents?.qa) return config.agents.qa;
3169
3295
  return process.env.STACKSPOT_QA_AGENT_ID || "01KEQFJZ3Q3JER11NH22HEZX9X";
3170
3296
  }
3297
+ function getAgentVersion5() {
3298
+ const config = ConfigManager.getInstance().getConfig();
3299
+ if (config.agentVersions?.qa) return config.agentVersions.qa;
3300
+ return process.env.STACKSPOT_QA_AGENT_VERSION;
3301
+ }
3171
3302
  var ChromeDevToolsClient = class {
3172
3303
  client = null;
3173
3304
  transport = null;
@@ -3263,7 +3394,8 @@ ${projectContext}
3263
3394
  user_prompt: userMessage,
3264
3395
  streaming: true,
3265
3396
  use_conversation: true,
3266
- conversation_id: existingConversationId
3397
+ conversation_id: existingConversationId,
3398
+ ...getAgentVersion5() ? { agent_version_number: getAgentVersion5() } : {}
3267
3399
  },
3268
3400
  {
3269
3401
  "Authorization": `Bearer ${token}`
@@ -3295,11 +3427,12 @@ ${projectContext}
3295
3427
  keepRunning = false;
3296
3428
  break;
3297
3429
  }
3298
- if (!agentResponse) continue;
3299
- if (agentResponse.summary) {
3300
- tui.log.info(colors.primary(`\u{1F4CB} Plan: ${agentResponse.summary}`));
3430
+ const currentResponse = agentResponse;
3431
+ if (!currentResponse) continue;
3432
+ if (currentResponse.summary) {
3433
+ tui.log.info(colors.primary(`\u{1F4CB} Plan: ${currentResponse.summary}`));
3301
3434
  }
3302
- if (agentResponse.actions.length === 0) {
3435
+ if (currentResponse.actions.length === 0) {
3303
3436
  const reply = await tui.text({
3304
3437
  message: "\u{1F916} Shark QA:",
3305
3438
  placeholder: "Your reply..."
@@ -3311,7 +3444,7 @@ ${projectContext}
3311
3444
  }
3312
3445
  continue;
3313
3446
  }
3314
- for (const action of agentResponse.actions) {
3447
+ for (const action of currentResponse.actions) {
3315
3448
  tui.log.info(colors.dim(`Executing: ${action.type}`));
3316
3449
  let result = "";
3317
3450
  try {