shark-ai 0.4.6 → 0.4.10
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 +156 -146
- package/dist/bin/shark.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/shark.js
CHANGED
|
@@ -1717,46 +1717,93 @@ function getAgentId2(overrideId) {
|
|
|
1717
1717
|
}
|
|
1718
1718
|
async function interactiveSpecificationAgent(options = {}) {
|
|
1719
1719
|
FileLogger.init();
|
|
1720
|
-
tui.intro("\u{1F3D7}\uFE0F Specification Agent");
|
|
1720
|
+
tui.intro("\u{1F3D7}\uFE0F Specification Agent (Template-Based)");
|
|
1721
1721
|
const projectRoot = process.cwd();
|
|
1722
|
+
const sharkRcDir = path6.resolve(projectRoot, "_sharkrc");
|
|
1723
|
+
if (!fs5.existsSync(sharkRcDir)) fs5.mkdirSync(sharkRcDir, { recursive: true });
|
|
1724
|
+
const outputFile = path6.resolve(sharkRcDir, "tech-spec.md");
|
|
1725
|
+
if (!fs5.existsSync(outputFile)) {
|
|
1726
|
+
let initialContent = `# Technical Specification: {{PROJECT_NAME}}
|
|
1727
|
+
|
|
1728
|
+
## 1. Technology Stack
|
|
1729
|
+
[TO BE ANALYZED]
|
|
1730
|
+
- Language: [e.g. TypeScript]
|
|
1731
|
+
- Framework: [e.g. Node.js / React]
|
|
1732
|
+
- Database: [e.g. SQLite / PostgreSQL]
|
|
1733
|
+
- Key Libraries: [Top 5 dependencies]
|
|
1734
|
+
|
|
1735
|
+
## 2. Architecture Overview
|
|
1736
|
+
[TO BE ANALYZED]
|
|
1737
|
+
[Brief description of architectural pattern]
|
|
1738
|
+
|
|
1739
|
+
## 3. Data Model
|
|
1740
|
+
[TO BE ANALYZED]
|
|
1741
|
+
[Schema/ERD definitions]
|
|
1742
|
+
|
|
1743
|
+
## 4. API / Interface Contracts
|
|
1744
|
+
[TO BE ANALYZED]
|
|
1745
|
+
[Main endpoints or CLI commands]
|
|
1746
|
+
|
|
1747
|
+
## 5. Implementation Steps
|
|
1748
|
+
[TO BE FILLED - MUST BE CHECKBOXES]
|
|
1749
|
+
`;
|
|
1750
|
+
const projectName = path6.basename(projectRoot);
|
|
1751
|
+
initialContent = initialContent.replace(/{{PROJECT_NAME}}/g, projectName);
|
|
1752
|
+
const BOM = "\uFEFF";
|
|
1753
|
+
fs5.writeFileSync(outputFile, BOM + initialContent, { encoding: "utf-8" });
|
|
1754
|
+
tui.log.success(`\u2705 Created: ${colors.bold("_sharkrc/tech-spec.md")}`);
|
|
1755
|
+
} else {
|
|
1756
|
+
tui.log.info(`\u{1F4C4} Using existing ${colors.bold("_sharkrc/tech-spec.md")}`);
|
|
1757
|
+
}
|
|
1722
1758
|
let contextContent = "";
|
|
1723
1759
|
const contextPath = path6.resolve(projectRoot, "_sharkrc", "project-context.md");
|
|
1724
1760
|
if (fs5.existsSync(contextPath)) {
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
tui.log.info(`\u{1F4D8} Context loaded from: ${colors.dim(path6.relative(projectRoot, contextPath))}`);
|
|
1728
|
-
} catch (e) {
|
|
1729
|
-
tui.log.warning(`Failed to read context file: ${e}`);
|
|
1730
|
-
}
|
|
1761
|
+
contextContent = fs5.readFileSync(contextPath, "utf-8");
|
|
1762
|
+
tui.log.info(`\u{1F4D8} Context loaded.`);
|
|
1731
1763
|
}
|
|
1732
1764
|
let briefingContent = "";
|
|
1733
1765
|
if (options.briefingPath && fs5.existsSync(options.briefingPath)) {
|
|
1734
1766
|
briefingContent = fs5.readFileSync(options.briefingPath, "utf-8");
|
|
1735
1767
|
tui.log.info(`\u{1F4C4} Briefing loaded from: ${colors.dim(options.briefingPath)}`);
|
|
1736
1768
|
} else {
|
|
1737
|
-
const
|
|
1738
|
-
if (fs5.existsSync(
|
|
1739
|
-
briefingContent = fs5.readFileSync(
|
|
1740
|
-
tui.log.info(`\u{1F4C4}
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1769
|
+
const standardBriefing = path6.resolve(projectRoot, "_sharkrc", "briefing.md");
|
|
1770
|
+
if (fs5.existsSync(standardBriefing)) {
|
|
1771
|
+
briefingContent = fs5.readFileSync(standardBriefing, "utf-8");
|
|
1772
|
+
tui.log.info(`\u{1F4C4} Briefing loaded.`);
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
let initialPrompt = `
|
|
1776
|
+
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\`.
|
|
1778
|
+
|
|
1779
|
+
\u26A0\uFE0F WORKFLOW OBRIGAT\xD3RIO \u2013 SIGA ESSA SEQU\xCANCIA ESTRITAMENTE. N\xC3O PULE ETAPAS.
|
|
1780
|
+
|
|
1781
|
+
**FASE 1 \u2013 ENTENDA A TAREFA (COMECE AQUI):**
|
|
1782
|
+
- 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.
|
|
1754
1802
|
`;
|
|
1755
|
-
}
|
|
1756
1803
|
if (briefingContent) {
|
|
1757
1804
|
initialPrompt += `
|
|
1758
|
-
|
|
1759
|
-
|
|
1805
|
+
\u2139\uFE0F Um documento de briefing foi encontrado. Ele define parcialmente a tarefa para a Fase 1.
|
|
1806
|
+
Confirme seu entendimento com o usu\xE1rio via \`talk_with_user\` antes de prosseguir para a Fase 2.
|
|
1760
1807
|
|
|
1761
1808
|
--- BRIEFING ---
|
|
1762
1809
|
${briefingContent}
|
|
@@ -1764,48 +1811,44 @@ ${briefingContent}
|
|
|
1764
1811
|
`;
|
|
1765
1812
|
} else {
|
|
1766
1813
|
initialPrompt += `
|
|
1767
|
-
|
|
1768
|
-
|
|
1814
|
+
\u2139\uFE0F Nenhum documento de briefing foi encontrado. Inicie a Fase 1 imediatamente: use \`talk_with_user\` para perguntar ao usu\xE1rio o que precisa ser especificado.
|
|
1815
|
+
`;
|
|
1816
|
+
}
|
|
1817
|
+
if (options.initialContext) {
|
|
1818
|
+
initialPrompt += `
|
|
1819
|
+
--- CONTEXTO DE EXECU\xC7\xC3O ANTERIOR (HANDOVER/FEEDBACK) ---
|
|
1820
|
+
${options.initialContext}
|
|
1821
|
+
-----------------------------------------------------
|
|
1769
1822
|
`;
|
|
1770
1823
|
}
|
|
1771
1824
|
if (contextContent) {
|
|
1772
1825
|
initialPrompt += `
|
|
1773
|
-
|
|
1826
|
+
\u2139\uFE0F O contexto do projeto est\xE1 dispon\xEDvel para refer\xEAncia. Use-o na Fase 2 para se alinhar com os padr\xF5es de arquitetura existentes, mas N\xC3O o use para preencher as se\xE7\xF5es de forma gen\xE9rica.
|
|
1774
1827
|
|
|
1775
1828
|
--- PROJECT CONTEXT ---
|
|
1776
1829
|
${contextContent}
|
|
1777
1830
|
-----------------------
|
|
1778
1831
|
`;
|
|
1779
1832
|
}
|
|
1780
|
-
initialPrompt
|
|
1781
|
-
|
|
1782
|
-
Seu objetivo final \xE9 gerar o arquivo 'tech-spec.md'.
|
|
1783
|
-
|
|
1784
|
-
\u26A0\uFE0F ATEN\xC7\xC3O: WORKFLOW DE AN\xC1LISE
|
|
1785
|
-
1. **Entenda**: Alinhe o objetivo com o usu\xE1rio.
|
|
1786
|
-
2. **Explore**: Use 'list_files' e 'read_file' para encontrar os arquivos RELEVANTES para a tarefa.
|
|
1787
|
-
3. **Especifique**: Gere o 'tech-spec.md' citando nomes de arquivos REAIS que voc\xEA leu.
|
|
1788
|
-
|
|
1789
|
-
\u26A0\uFE0F REGRA DE FORMATA\xC7\xC3O (CRITICA):
|
|
1790
|
-
Na se\xE7\xE3o 'Implementation Steps', voc\xEA DEVE usar CHECKBOXES markdown ( - [ ] ) e N\xC3O listas numeradas.
|
|
1791
|
-
O agente de desenvolvimento S\xD3 reconhece checkboxes.
|
|
1792
|
-
|
|
1793
|
-
Exemplo CORRETO:
|
|
1794
|
-
- [ ] Criar arquivo X
|
|
1795
|
-
- [ ] Atualizar fun\xE7\xE3o Y
|
|
1796
|
-
|
|
1797
|
-
Exemplo ERRADO (N\xC3O FA\xC7A):
|
|
1798
|
-
1. Criar arquivo X
|
|
1799
|
-
2. Atualizar fun\xE7\xE3o Y
|
|
1800
|
-
`;
|
|
1801
|
-
await runSpecLoop(initialPrompt.trim(), options.agentId);
|
|
1833
|
+
await runSpecLoop(initialPrompt.trim(), outputFile, options.agentId);
|
|
1802
1834
|
}
|
|
1803
|
-
async function runSpecLoop(initialMessage, overrideAgentId) {
|
|
1835
|
+
async function runSpecLoop(initialMessage, targetPath, overrideAgentId) {
|
|
1804
1836
|
let nextPrompt = initialMessage;
|
|
1805
1837
|
let keepGoing = true;
|
|
1806
|
-
|
|
1838
|
+
let stepCount = 0;
|
|
1839
|
+
const MAX_STEPS = 30;
|
|
1840
|
+
while (keepGoing && stepCount < MAX_STEPS) {
|
|
1841
|
+
stepCount++;
|
|
1807
1842
|
const spinner = tui.spinner();
|
|
1808
|
-
spinner.start(
|
|
1843
|
+
spinner.start(`\u{1F3D7}\uFE0F Spec Agent working (Step ${stepCount}/${MAX_STEPS})...`);
|
|
1844
|
+
let pendingSections = [];
|
|
1845
|
+
if (fs5.existsSync(targetPath)) {
|
|
1846
|
+
const content = fs5.readFileSync(targetPath, "utf-8");
|
|
1847
|
+
if (content.includes("[TO BE ANALYZED]")) pendingSections.push("Analysis Sections (Stack, Arch, Data, API)");
|
|
1848
|
+
if (content.includes("[TO BE FILLED")) pendingSections.push("Implementation Steps");
|
|
1849
|
+
}
|
|
1850
|
+
if (pendingSections.length === 0 && stepCount > 1) {
|
|
1851
|
+
}
|
|
1809
1852
|
let responseText = "";
|
|
1810
1853
|
let lastResponse = null;
|
|
1811
1854
|
try {
|
|
@@ -1816,10 +1859,10 @@ async function runSpecLoop(initialMessage, overrideAgentId) {
|
|
|
1816
1859
|
if (lastResponse && lastResponse.actions) {
|
|
1817
1860
|
let executionResults = "";
|
|
1818
1861
|
let waitingForUser = false;
|
|
1862
|
+
let specUpdated = false;
|
|
1819
1863
|
if (lastResponse.message && lastResponse.message.includes("SPEC_UPDATED:")) {
|
|
1820
1864
|
const updateSummary = lastResponse.message.split("SPEC_UPDATED:")[1].trim();
|
|
1821
|
-
tui.log.success(`\u2705 Spec
|
|
1822
|
-
tui.log.info("\u{1F4CB} Returning to orchestration loop...");
|
|
1865
|
+
tui.log.success(`\u2705 Spec Finalized: ${updateSummary}`);
|
|
1823
1866
|
return;
|
|
1824
1867
|
}
|
|
1825
1868
|
for (const action of lastResponse.actions) {
|
|
@@ -1848,97 +1891,78 @@ ${result}
|
|
|
1848
1891
|
${result}
|
|
1849
1892
|
|
|
1850
1893
|
`;
|
|
1851
|
-
} else if (["create_file", "modify_file"
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1894
|
+
} else if (["create_file", "modify_file"].includes(action.type)) {
|
|
1895
|
+
let actionPath = path6.resolve(action.path || "");
|
|
1896
|
+
const resolvedTargetPath = path6.resolve(targetPath);
|
|
1897
|
+
let isTarget = actionPath === resolvedTargetPath;
|
|
1898
|
+
if (!isTarget && path6.basename(actionPath) === "tech-spec.md") {
|
|
1899
|
+
tui.log.warning(`Redirecting ${action.type} from ${action.path} to ${path6.relative(process.cwd(), targetPath)}`);
|
|
1900
|
+
action.path = targetPath;
|
|
1901
|
+
actionPath = resolvedTargetPath;
|
|
1902
|
+
isTarget = true;
|
|
1857
1903
|
}
|
|
1858
|
-
|
|
1859
|
-
message: `
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
});
|
|
1863
|
-
if (confirm) {
|
|
1864
|
-
if (action.path) {
|
|
1865
|
-
try {
|
|
1866
|
-
if (action.type === "create_file") {
|
|
1867
|
-
const BOM = "\uFEFF";
|
|
1868
|
-
const contentToWrite = action.content || "";
|
|
1869
|
-
const finalContent = contentToWrite.startsWith(BOM) ? contentToWrite : BOM + contentToWrite;
|
|
1870
|
-
const dir = path6.dirname(action.path);
|
|
1871
|
-
if (!fs5.existsSync(dir)) fs5.mkdirSync(dir, { recursive: true });
|
|
1872
|
-
fs5.writeFileSync(action.path, finalContent, { encoding: "utf-8" });
|
|
1873
|
-
tui.log.success(`\u2705 Created: ${action.path}`);
|
|
1874
|
-
executionResults += `[Action create_file(${action.path})]: Success
|
|
1875
|
-
|
|
1904
|
+
if (!isTarget && action.type === "create_file") {
|
|
1905
|
+
const confirm = await tui.confirm({ message: `Agent wants to create ${action.path}. Allow?` });
|
|
1906
|
+
if (!confirm) {
|
|
1907
|
+
executionResults += `[Action create_file]: User denied.
|
|
1876
1908
|
`;
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1909
|
+
continue;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
try {
|
|
1913
|
+
if (action.type === "create_file") {
|
|
1914
|
+
const BOM = "\uFEFF";
|
|
1915
|
+
fs5.writeFileSync(action.path, BOM + (action.content || ""), "utf-8");
|
|
1916
|
+
tui.log.success(`\u2705 Created: ${action.path}`);
|
|
1917
|
+
executionResults += `[Action create_file]: Success.
|
|
1882
1918
|
`;
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1919
|
+
} else if (action.type === "modify_file") {
|
|
1920
|
+
if (action.target_content) {
|
|
1921
|
+
const success = startSmartReplace(action.path, action.content || "", action.target_content, tui);
|
|
1922
|
+
if (success) {
|
|
1923
|
+
executionResults += `[Action modify_file]: Success.
|
|
1887
1924
|
`;
|
|
1888
|
-
|
|
1889
|
-
} else
|
|
1890
|
-
|
|
1891
|
-
tui.log.success(`\u2705 Deleted: ${action.path}`);
|
|
1892
|
-
executionResults += `[Action delete_file(${action.path})]: Success
|
|
1893
|
-
|
|
1925
|
+
specUpdated = true;
|
|
1926
|
+
} else {
|
|
1927
|
+
executionResults += `[Action modify_file]: Failed. Target content not found.
|
|
1894
1928
|
`;
|
|
1895
1929
|
}
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
executionResults += `[Action ${action.type}(${action.path})]: Error: ${e.message}
|
|
1899
|
-
|
|
1930
|
+
} else {
|
|
1931
|
+
executionResults += `[Action modify_file]: Failed. 'target_content' is required.
|
|
1900
1932
|
`;
|
|
1901
1933
|
}
|
|
1902
1934
|
}
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
executionResults += `[Action ${action.type}]: User Denied
|
|
1906
|
-
|
|
1935
|
+
} catch (e) {
|
|
1936
|
+
executionResults += `[Action ${action.type}]: Error: ${e.message}
|
|
1907
1937
|
`;
|
|
1908
1938
|
}
|
|
1909
1939
|
}
|
|
1910
1940
|
}
|
|
1911
|
-
if (
|
|
1912
|
-
|
|
1913
|
-
const userReply = await tui.text({
|
|
1914
|
-
message: "Your answer",
|
|
1915
|
-
placeholder: "Type your answer..."
|
|
1916
|
-
});
|
|
1917
|
-
if (tui.isCancel(userReply)) {
|
|
1918
|
-
keepGoing = false;
|
|
1919
|
-
return;
|
|
1920
|
-
}
|
|
1921
|
-
nextPrompt = `${executionResults}
|
|
1922
|
-
|
|
1923
|
-
User Reply: ${userReply}`;
|
|
1924
|
-
} else {
|
|
1925
|
-
nextPrompt = executionResults;
|
|
1926
|
-
FileLogger.log("SYSTEM", "Auto-replying with Tool Results", { length: executionResults.length });
|
|
1927
|
-
tui.log.info(colors.dim("Processing tool results..."));
|
|
1928
|
-
}
|
|
1929
|
-
} else if (waitingForUser) {
|
|
1930
|
-
const userReply = await tui.text({
|
|
1931
|
-
message: "Your answer",
|
|
1932
|
-
placeholder: "Type your answer..."
|
|
1933
|
-
});
|
|
1941
|
+
if (waitingForUser) {
|
|
1942
|
+
const userReply = await tui.text({ message: "Your answer", placeholder: "Type your answer..." });
|
|
1934
1943
|
if (tui.isCancel(userReply)) {
|
|
1935
1944
|
keepGoing = false;
|
|
1936
1945
|
return;
|
|
1937
1946
|
}
|
|
1938
|
-
nextPrompt =
|
|
1947
|
+
nextPrompt = `${executionResults}
|
|
1948
|
+
|
|
1949
|
+
User Reply: ${userReply}`;
|
|
1950
|
+
} else if (executionResults) {
|
|
1951
|
+
const content = fs5.existsSync(targetPath) ? fs5.readFileSync(targetPath, "utf-8") : "";
|
|
1952
|
+
let systemMsg = "Execu\xE7\xE3o da ferramenta conclu\xEDda.";
|
|
1953
|
+
if (specUpdated) {
|
|
1954
|
+
if (content.includes("[TO BE")) {
|
|
1955
|
+
systemMsg += "\n[System]: Se\xE7\xE3o atualizada. Por favor, continue harmonizando e preenchendo os placeholders '[TO BE ...]' restantes.";
|
|
1956
|
+
} else {
|
|
1957
|
+
systemMsg += "\n[System]: O arquivo parece completo! Se estiver satisfeito, retorne 'SPEC_UPDATED: Complete'.";
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
nextPrompt = `${executionResults}
|
|
1961
|
+
|
|
1962
|
+
${systemMsg}`;
|
|
1939
1963
|
} else {
|
|
1940
1964
|
if (lastResponse.message) {
|
|
1941
|
-
tui.log.info(colors.primary("\u{1F916} Architect:"));
|
|
1965
|
+
tui.log.info(colors.primary("\u{1F916} Architect (Message only):"));
|
|
1942
1966
|
console.log(lastResponse.message);
|
|
1943
1967
|
const userReply = await tui.text({ message: "Your answer:" });
|
|
1944
1968
|
if (tui.isCancel(userReply)) {
|
|
@@ -1947,12 +1971,11 @@ User Reply: ${userReply}`;
|
|
|
1947
1971
|
}
|
|
1948
1972
|
nextPrompt = userReply;
|
|
1949
1973
|
} else {
|
|
1950
|
-
tui.log.warning("No actions taken.");
|
|
1951
1974
|
keepGoing = false;
|
|
1952
1975
|
}
|
|
1953
1976
|
}
|
|
1954
1977
|
} else {
|
|
1955
|
-
tui.log.warning("No actions received
|
|
1978
|
+
tui.log.warning("No actions received.");
|
|
1956
1979
|
keepGoing = false;
|
|
1957
1980
|
}
|
|
1958
1981
|
} catch (error) {
|
|
@@ -1978,12 +2001,7 @@ async function callSpecAgentApi(prompt, onChunk, agentId) {
|
|
|
1978
2001
|
const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${effectiveAgentId}/chat`;
|
|
1979
2002
|
let fullMsg = "";
|
|
1980
2003
|
let raw = {};
|
|
1981
|
-
FileLogger.log("AGENT", "Calling Agent API", {
|
|
1982
|
-
agentId: effectiveAgentId,
|
|
1983
|
-
conversationId,
|
|
1984
|
-
prompt: prompt.substring(0, 500)
|
|
1985
|
-
// Log summary of prompt
|
|
1986
|
-
});
|
|
2004
|
+
FileLogger.log("AGENT", "Calling Agent API", { agentId: effectiveAgentId, conversationId });
|
|
1987
2005
|
await sseClient.streamAgentResponse(url, payload, { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }, {
|
|
1988
2006
|
onChunk: (c) => {
|
|
1989
2007
|
fullMsg += c;
|
|
@@ -1991,15 +2009,7 @@ async function callSpecAgentApi(prompt, onChunk, agentId) {
|
|
|
1991
2009
|
},
|
|
1992
2010
|
onComplete: (msg, metadata) => {
|
|
1993
2011
|
const returnedId = metadata?.conversation_id;
|
|
1994
|
-
|
|
1995
|
-
conversationId,
|
|
1996
|
-
returnedId,
|
|
1997
|
-
messageLength: msg?.length
|
|
1998
|
-
});
|
|
1999
|
-
raw = {
|
|
2000
|
-
message: msg || fullMsg,
|
|
2001
|
-
conversation_id: returnedId || conversationId
|
|
2002
|
-
};
|
|
2012
|
+
raw = { message: msg || fullMsg, conversation_id: returnedId || conversationId };
|
|
2003
2013
|
},
|
|
2004
2014
|
onError: (e) => {
|
|
2005
2015
|
throw e;
|