agent-mp 0.5.39 → 0.5.41
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/commands/repl.js +3 -6
- package/dist/core/engine.js +248 -305
- package/dist/utils/deepseek.d.ts +0 -1
- package/dist/utils/deepseek.js +13 -11
- package/package.json +1 -1
package/dist/commands/repl.js
CHANGED
|
@@ -12,7 +12,7 @@ import { log } from '../utils/logger.js';
|
|
|
12
12
|
import { AgentEngine, ExitError } from '../core/engine.js';
|
|
13
13
|
import { qwenAuthStatus, QWEN_AGENT_HOME, fetchQwenModels, loadApiKeyConfig, saveApiKeyConfig, fetchApiKeyModels, DEFAULT_API_BASE_URL } from '../utils/qwen-auth.js';
|
|
14
14
|
import { loadGeminiApiKey, saveGeminiApiKey, geminiAuthStatus, deleteGeminiApiKey, GEMINI_MODELS, fetchGeminiModels } from '../utils/gemini.js';
|
|
15
|
-
import { loadDeepSeekApiKey, saveDeepSeekApiKey, deleteDeepSeekApiKey,
|
|
15
|
+
import { loadDeepSeekApiKey, saveDeepSeekApiKey, deleteDeepSeekApiKey, fetchDeepSeekModels } from '../utils/deepseek.js';
|
|
16
16
|
import { renderWelcomePanel, renderHelpHint, renderSectionBox, renderMultiSectionBox } from '../ui/theme.js';
|
|
17
17
|
import { FixedInput } from '../ui/input.js';
|
|
18
18
|
import { newSession, saveSession } from '../utils/sessions.js';
|
|
@@ -416,9 +416,8 @@ async function promptDeepseekKeySetup(rl, askFn) {
|
|
|
416
416
|
}
|
|
417
417
|
}
|
|
418
418
|
else {
|
|
419
|
-
console.log(chalk.yellow(' No se pudieron cargar modelos de la API
|
|
420
|
-
|
|
421
|
-
const pick = await askFn(` Modelo [${chosenModel}]: `);
|
|
419
|
+
console.log(chalk.yellow(' No se pudieron cargar modelos de la API.'));
|
|
420
|
+
const pick = await askFn(` Escribí el nombre del modelo [${chosenModel}]: `);
|
|
422
421
|
if (pick.trim())
|
|
423
422
|
chosenModel = pick.trim();
|
|
424
423
|
}
|
|
@@ -804,8 +803,6 @@ async function cmdModels(roleArg, fi, rl) {
|
|
|
804
803
|
else if (isDeepSeekActive || activeProvider === 'deepseek') {
|
|
805
804
|
console.log(chalk.dim(' Fetching DeepSeek models...'));
|
|
806
805
|
models = await fetchDeepSeekModels(deepseekCfg);
|
|
807
|
-
if (!models.length)
|
|
808
|
-
models = DEEPSEEK_MODELS;
|
|
809
806
|
}
|
|
810
807
|
else if (activeProvider === 'qwen') {
|
|
811
808
|
console.log(chalk.dim(' Fetching Qwen models...'));
|
package/dist/core/engine.js
CHANGED
|
@@ -237,8 +237,9 @@ async function walkForKeyFiles(root) {
|
|
|
237
237
|
entry: null,
|
|
238
238
|
controllers: [],
|
|
239
239
|
schemas: [],
|
|
240
|
+
allSourceFiles: [],
|
|
240
241
|
};
|
|
241
|
-
const SOURCE_EXT = /\.(ts|tsx|js|jsx|py|go|java|kt|rs|cs)$/;
|
|
242
|
+
const SOURCE_EXT = /\.(ts|tsx|js|jsx|py|go|java|kt|rs|cs|rb|ex|exs|swift|php|vue|svelte)$/;
|
|
242
243
|
const SKIP_FILE = /\.(test|spec|d)\.[a-z]+$/i;
|
|
243
244
|
const ENTRY_NAMES = new Set([
|
|
244
245
|
'main.ts', 'main.js', 'main.py', 'main.go', 'Main.java',
|
|
@@ -255,8 +256,6 @@ async function walkForKeyFiles(root) {
|
|
|
255
256
|
async function walk(dir, depth) {
|
|
256
257
|
if (depth > 6)
|
|
257
258
|
return;
|
|
258
|
-
if (result.controllers.length >= 5 && result.schemas.length >= 5 && result.entry)
|
|
259
|
-
return;
|
|
260
259
|
let entries;
|
|
261
260
|
try {
|
|
262
261
|
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
@@ -280,6 +279,8 @@ async function walkForKeyFiles(root) {
|
|
|
280
279
|
continue;
|
|
281
280
|
if (SKIP_FILE.test(e.name))
|
|
282
281
|
continue;
|
|
282
|
+
// Collect all source files
|
|
283
|
+
result.allSourceFiles.push(p);
|
|
283
284
|
// entry point detection
|
|
284
285
|
if (!result.entry && (ENTRY_NAMES.has(e.name) || ENTRY_REGEX.test(e.name))) {
|
|
285
286
|
result.entry = p;
|
|
@@ -856,33 +857,66 @@ INSTRUCCIONES GENERALES:
|
|
|
856
857
|
}
|
|
857
858
|
};
|
|
858
859
|
// Role binaries (agent-orch, agent-impl, etc.) require an interactive TTY and can't
|
|
859
|
-
// be spawned as subprocesses. Instead,
|
|
860
|
-
// (
|
|
861
|
-
// the Qwen API directly with those creds. Otherwise skip to fallback.
|
|
860
|
+
// be spawned as subprocesses. Instead, call the appropriate API directly
|
|
861
|
+
// (Qwen via oauth_creds.json, DeepSeek via deepseek_key.json).
|
|
862
862
|
const ROLE_BINARIES = new Set(['agent-orch', 'agent-impl', 'agent-rev', 'agent-explorer']);
|
|
863
|
+
const DEEPSEEK_MODEL_PREFIX = /^deepseek-/;
|
|
863
864
|
const tryRoleBinaryCreds = async (cliName, model) => {
|
|
864
|
-
const
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
865
|
+
const roleDir = path.join(os.homedir(), `.${cliName}`);
|
|
866
|
+
const credsPath = path.join(roleDir, 'oauth_creds.json');
|
|
867
|
+
const deepseekRoleKeyPath = path.join(roleDir, 'deepseek_key.json');
|
|
868
|
+
const deepseekGlobalKeyPath = path.join(os.homedir(), '.agent-mp', 'deepseek_key.json');
|
|
869
|
+
const isDeepSeekModel = DEEPSEEK_MODEL_PREFIX.test(model);
|
|
870
|
+
const hasQwenCreds = await fileExists(credsPath);
|
|
871
|
+
const hasDeepSeekCreds = await fileExists(deepseekRoleKeyPath) || await fileExists(deepseekGlobalKeyPath);
|
|
872
|
+
// Determine primary provider: DeepSeek model with DeepSeek creds -> DeepSeek, else Qwen
|
|
873
|
+
if (isDeepSeekModel && hasDeepSeekCreds) {
|
|
874
|
+
const sp = this._startSpinner(`${cliName} ${model} (deepseek)`);
|
|
875
|
+
const onChunk = (delta) => sp.push(delta);
|
|
876
|
+
try {
|
|
877
|
+
log.info(`${cliName}: calling DeepSeek API (${model})`);
|
|
878
|
+
const result = await callDeepSeekAPI(rolePrompt, model, onChunk);
|
|
879
|
+
sp.stop();
|
|
880
|
+
return result;
|
|
881
|
+
}
|
|
882
|
+
catch (err) {
|
|
883
|
+
sp.stop();
|
|
884
|
+
if (err.message?.startsWith('DEEPSEEK_NOT_CONFIGURED')) {
|
|
885
|
+
log.warn(`${cliName} DeepSeek not configured — using fallback`);
|
|
886
|
+
}
|
|
887
|
+
else if (err.message?.startsWith('DEEPSEEK_QUOTA_EXCEEDED')) {
|
|
888
|
+
log.warn(`${cliName} DeepSeek quota exhausted — using fallback`);
|
|
889
|
+
}
|
|
890
|
+
else if (err.message?.startsWith('DEEPSEEK_NO_BALANCE')) {
|
|
891
|
+
log.warn(`${cliName} DeepSeek balance insufficient — using fallback`);
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
log.warn(`${cliName} DeepSeek API call failed: ${err.message}`);
|
|
895
|
+
}
|
|
896
|
+
return null; // don't try Qwen with a DeepSeek model — let caller fallback handle it
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
// Qwen path (for non-DeepSeek models only)
|
|
900
|
+
if (!hasQwenCreds) {
|
|
868
901
|
const { loadApiKeyConfig } = await import('../utils/qwen-auth.js');
|
|
869
902
|
const apiKeyCfg = await loadApiKeyConfig();
|
|
870
903
|
if (!apiKeyCfg) {
|
|
871
|
-
|
|
904
|
+
if (!isDeepSeekModel) {
|
|
905
|
+
log.warn(`${cliName} has no credentials — run: agent-mp setup api-key or ${cliName} --login`);
|
|
906
|
+
}
|
|
872
907
|
return null;
|
|
873
908
|
}
|
|
874
|
-
// Fall through: callQwenAPIFromCreds will use the API key config
|
|
875
909
|
}
|
|
876
|
-
const
|
|
877
|
-
const
|
|
910
|
+
const sp2 = this._startSpinner(`${cliName} ${model} ${isDeepSeekModel ? '(qwen fallback)' : ''}`);
|
|
911
|
+
const onChunk2 = (delta) => sp2.push(delta);
|
|
878
912
|
try {
|
|
879
913
|
log.info(`${cliName}: calling Qwen API with own credentials (${model})`);
|
|
880
|
-
const result = await callQwenAPIFromCreds(rolePrompt, model, credsPath,
|
|
881
|
-
|
|
914
|
+
const result = await callQwenAPIFromCreds(rolePrompt, model, credsPath, onChunk2);
|
|
915
|
+
sp2.stop();
|
|
882
916
|
return result;
|
|
883
917
|
}
|
|
884
918
|
catch (err) {
|
|
885
|
-
|
|
919
|
+
sp2.stop();
|
|
886
920
|
if (err.message?.startsWith('QWEN_AUTH_EXPIRED')) {
|
|
887
921
|
log.warn(`${cliName} session expired — using fallback`);
|
|
888
922
|
return null;
|
|
@@ -1580,6 +1614,23 @@ INSTRUCCIONES:
|
|
|
1580
1614
|
compSection.push(`### SCHEMA/MODEL: ${rel}\n\`\`\`\n${content}\n\`\`\``);
|
|
1581
1615
|
}
|
|
1582
1616
|
}
|
|
1617
|
+
// Read ALL source files for function-level documentation
|
|
1618
|
+
const MAX_SOURCE_FILE = 2000;
|
|
1619
|
+
const MAX_TOTAL_SOURCE = 20000;
|
|
1620
|
+
let totalSourceRead = 0;
|
|
1621
|
+
const alreadyRead = new Set([found.entry, ...found.controllers, ...found.schemas].filter(Boolean));
|
|
1622
|
+
for (const srcFile of found.allSourceFiles) {
|
|
1623
|
+
if (totalSourceRead >= MAX_TOTAL_SOURCE)
|
|
1624
|
+
break;
|
|
1625
|
+
if (alreadyRead.has(srcFile))
|
|
1626
|
+
continue;
|
|
1627
|
+
const content = await readFileSafe(srcFile, MAX_SOURCE_FILE);
|
|
1628
|
+
if (content) {
|
|
1629
|
+
const rel = path.relative(compDir, srcFile);
|
|
1630
|
+
compSection.push(`### SOURCE: ${rel}\n\`\`\`\n${content}\n\`\`\``);
|
|
1631
|
+
totalSourceRead += content.length;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1583
1634
|
// Only add the component if we read at least the manifest or one source file
|
|
1584
1635
|
if (manifestFound || found.entry || found.controllers.length > 0 || found.schemas.length > 0) {
|
|
1585
1636
|
sections.push(compSection.join('\n\n'));
|
|
@@ -1667,358 +1718,250 @@ INSTRUCCIONES:
|
|
|
1667
1718
|
}
|
|
1668
1719
|
catch { /* ignore */ }
|
|
1669
1720
|
const effectiveTask = task || 'Explorar y documentar todas las aplicaciones y servicios del proyecto';
|
|
1670
|
-
const prompt = `TAREA
|
|
1721
|
+
const prompt = `TAREA: ${effectiveTask}
|
|
1671
1722
|
DIRECTORIO_TRABAJO: ${this.projectDir}
|
|
1672
1723
|
PROYECTO: ${this.config.project}
|
|
1673
|
-
STACK: ${this.config.stack}
|
|
1674
1724
|
|
|
1675
|
-
ESTRUCTURA
|
|
1725
|
+
ESTRUCTURA DEL PROYECTO:
|
|
1676
1726
|
${fsSnapshot}
|
|
1677
1727
|
|
|
1678
|
-
${prefetched ?
|
|
1728
|
+
${prefetched ? `==== ARCHIVOS REALES LEIDOS (tu unica fuente de verdad) ====\n${prefetched}\n` : ''}
|
|
1729
|
+
${existingMainArch ? `==== DOC EXISTENTE: architecture.md (raiz) — preservar y solo actualizar lo que cambio ====\n${existingMainArch.slice(0, 6000)}\n` : ''}
|
|
1730
|
+
${existingComponentDocs ? `==== DOC EXISTENTE por componente ====\n${existingComponentDocs.slice(0, 4000)}\n` : ''}
|
|
1731
|
+
|
|
1732
|
+
==================================================================
|
|
1733
|
+
TU TRABAJO — leelo entero antes de escribir
|
|
1734
|
+
==================================================================
|
|
1735
|
+
|
|
1736
|
+
1. IDENTIFICAR COMPONENTES
|
|
1737
|
+
Un "componente" = cada CARPETA HIJA del DIRECTORIO_TRABAJO que tenga un manifest propio:
|
|
1738
|
+
package.json, pom.xml, build.gradle(.kts), requirements.txt / pyproject.toml,
|
|
1739
|
+
go.mod, Cargo.toml, composer.json, Gemfile, *.csproj, *.sln, mix.exs, Dockerfile.
|
|
1740
|
+
Backend, frontend, worker, batch, mobile — todos cuentan. Si tiene manifest, es componente.
|
|
1679
1741
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1742
|
+
2. PARA CADA COMPONENTE, GENERAR EXACTAMENTE UN ARCHIVO:
|
|
1743
|
+
=== .agent/context/<carpeta-del-componente>/architecture.md ===
|
|
1682
1744
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
Generar documentacion ESCALONADA en 3 niveles, util TANTO para personas funcionales (PM, negocio) como tecnicas (devs).
|
|
1687
|
-
Detallada pero NO excesiva. Concreta, con datos REALES extraidos de los archivos que estan mas arriba. Cero especulaciones.
|
|
1745
|
+
El nombre de carpeta DEBE coincidir con el nombre real del directorio en el proyecto.
|
|
1746
|
+
Si hay 3 carpetas/componentes en la raiz, hay que generar 3 archivos NIVEL 1.
|
|
1747
|
+
No omitas ninguno. Frontends incluidos.
|
|
1688
1748
|
|
|
1689
|
-
|
|
1749
|
+
3. ADEMAS, GENERAR EL DOC RAIZ:
|
|
1750
|
+
=== .agent/context/architecture.md === (NIVEL 0 — vista global)
|
|
1751
|
+
|
|
1752
|
+
4. OPCIONAL — modulos por feature dentro de un componente:
|
|
1753
|
+
=== .agent/context/<componente>/modules/<feature>.md === (NIVEL 2)
|
|
1754
|
+
Solo si el componente tiene features de negocio claras (clients, sales, auth, products...).
|
|
1755
|
+
No crees modulos por capa tecnica (security, db, web). Si no hay features claras, omiti NIVEL 2.
|
|
1756
|
+
|
|
1757
|
+
==================================================================
|
|
1690
1758
|
REGLA DE ORO — PROHIBIDO INVENTAR
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
NO devuelvas
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
- BIEN: modulos llamados "clients", "sales", "products", "auth", "orders" — eso es hablar de features reales
|
|
1716
|
-
- Para identificar los modulos, MIRA los CONTROLLER/ROUTER pre-leidos: el nombre del modulo = lo que maneja ese controller
|
|
1717
|
-
* ClientController o clients.controller → modulo "clients"
|
|
1718
|
-
* SaleController o sale.routes → modulo "sales"
|
|
1719
|
-
* AuthController o auth.handler → modulo "auth"
|
|
1720
|
-
- "Archivos clave" en cada modulo DEBE listar los archivos FUENTE REALES que leiste, NO solo el manifest.
|
|
1721
|
-
Ejemplo correcto:
|
|
1722
|
-
| Archivo (ruta relativa al componente) | Rol |
|
|
1723
|
-
| controller/ClientController.java | Endpoints REST /clients |
|
|
1724
|
-
| domain/Client.java | Entidad mapeada a tabla CLIENTS |
|
|
1725
|
-
| repository/ClientRepository.java | Acceso a base de datos |
|
|
1726
|
-
| src/clients/clients.controller.ts | Endpoints /clients |
|
|
1727
|
-
| src/clients/client.schema.ts | Modelo de datos Client |
|
|
1728
|
-
|
|
1729
|
-
NO inventes datos. Si un componente no tiene una de esas piezas en los archivos leidos, simplemente omiti esa seccion en su documentacion.
|
|
1730
|
-
|
|
1731
|
-
================================================================
|
|
1732
|
-
LENGUAJE DUAL (regla critica)
|
|
1733
|
-
================================================================
|
|
1734
|
-
Cada seccion abre con UNA linea en lenguaje simple (que entienda un PM/negocio), DESPUES viene el detalle tecnico.
|
|
1735
|
-
- MAL: "El microservicio orquesta la persistencia mediante un repositorio."
|
|
1736
|
-
- BIEN: "Guarda la informacion del usuario en la base. Internamente usa un repositorio que abstrae la conexion a MongoDB."
|
|
1737
|
-
|
|
1738
|
-
================================================================
|
|
1739
|
-
ESTRUCTURA DE LOS 3 NIVELES
|
|
1740
|
-
================================================================
|
|
1741
|
-
|
|
1742
|
-
────────────────────────────────────────────────────────────────
|
|
1743
|
-
────────────────────────────────────────────────────────────────
|
|
1744
|
-
NIVEL 0 — architecture.md (raiz de .agent/context/)
|
|
1745
|
-
Objetivo: 80-150 lineas. Panorama global real, no generico.
|
|
1746
|
-
────────────────────────────────────────────────────────────────
|
|
1747
|
-
|
|
1748
|
-
# [Nombre del proyecto] — Arquitectura Global (NIVEL 0)
|
|
1759
|
+
==================================================================
|
|
1760
|
+
- Si un dato (puerto, version, endpoint, env var, ruta, clase) no aparece en los ARCHIVOS REALES → OMITILO.
|
|
1761
|
+
- NO uses "inferido", "probablemente", "asumido", "(quizas)", "parece ser".
|
|
1762
|
+
- Mejor doc corta y veraz que larga llena de suposiciones.
|
|
1763
|
+
- NO devuelvas "tool_call", "function_call" ni invocaciones — devolves MARKDOWN, nada mas.
|
|
1764
|
+
|
|
1765
|
+
==================================================================
|
|
1766
|
+
PLANTILLAS — usa lo que aplique al stack real, omite lo que no
|
|
1767
|
+
==================================================================
|
|
1768
|
+
|
|
1769
|
+
────── NIVEL 0 (.agent/context/architecture.md, 80-180 lineas) ──────
|
|
1770
|
+
|
|
1771
|
+
REGLA CRITICA PARA NIVEL 0 — UPDATE INCREMENTAL, NO REESCRIBIR:
|
|
1772
|
+
Si arriba aparece "DOC EXISTENTE: architecture.md (raiz)", USALA COMO BASE.
|
|
1773
|
+
- Mantene su estructura, sus secciones y su redaccion tal cual.
|
|
1774
|
+
- Cambia UNICAMENTE las celdas/lineas donde el dato real (puerto, version, endpoint, dependencia) cambio.
|
|
1775
|
+
- Si un componente seguia listado en la doc previa pero su carpeta YA NO EXISTE en el filesystem actual:
|
|
1776
|
+
NO LO BORRES. Conservalo en su fila y agrega el sufijo " — (archivado, fuera del workspace actual)".
|
|
1777
|
+
Si tiene seccion propia (flujos, relaciones), preservala igual y marca el componente como archivado.
|
|
1778
|
+
- Si hay un componente NUEVO (carpeta presente ahora que antes no estaba), agregalo como fila/seccion nueva.
|
|
1779
|
+
- No reescribas overview/diagrama/flujos a menos que el cambio real lo requiera.
|
|
1780
|
+
- Si NO hay doc previa, generala con la plantilla de abajo.
|
|
1781
|
+
|
|
1782
|
+
# ${this.config.project} — Arquitectura Global
|
|
1749
1783
|
|
|
1750
1784
|
> Lectura escalonada:
|
|
1751
|
-
> NIVEL 0: este archivo
|
|
1752
|
-
> NIVEL 1: .agent/context
|
|
1753
|
-
> NIVEL 2: .agent/context
|
|
1754
|
-
|
|
1755
|
-
## 1.
|
|
1756
|
-
2-4 lineas.
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
| Origen | Destino | Tipo | Proposito |
|
|
1785
|
+
> NIVEL 0: este archivo (vista global)
|
|
1786
|
+
> NIVEL 1: .agent/context/<componente>/architecture.md
|
|
1787
|
+
> NIVEL 2: .agent/context/<componente>/modules/<feature>.md
|
|
1788
|
+
|
|
1789
|
+
## 1. Que es el sistema
|
|
1790
|
+
2-4 lineas. Para quien sirve, que problema resuelve. Si hay multiples componentes, contrastalos.
|
|
1791
|
+
|
|
1792
|
+
## 2. Componentes
|
|
1793
|
+
| Componente | Estado | Tipo (api / web / worker / mobile) | Stack + version | Puerto | Rol |
|
|
1794
|
+
|---|---|---|---|---|---|
|
|
1795
|
+
(Estado: "activo" si la carpeta existe ahora; "archivado" si estaba en la doc previa pero ya no esta en el filesystem.)
|
|
1796
|
+
(Datos REALES del manifest. Componentes archivados conservan sus datos previos.)
|
|
1797
|
+
|
|
1798
|
+
## 3. Como se conectan
|
|
1799
|
+
| Origen | Destino | Tipo (HTTP, DB, mensaje) | Detalle |
|
|
1767
1800
|
|---|---|---|---|
|
|
1768
|
-
(
|
|
1801
|
+
(URLs/hosts reales de .env / config. Si una relacion involucra un componente archivado, mantenerla y marcarla con "(archivado)".)
|
|
1769
1802
|
|
|
1770
|
-
## 4. Diagrama
|
|
1771
|
-
|
|
1772
|
-
Incluir endpoints clave inline en los componentes cuando se conocen.
|
|
1803
|
+
## 4. Diagrama
|
|
1804
|
+
Box-drawing y flechas. Mostrar puertos REALES y endpoints clave si se conocen.
|
|
1773
1805
|
\`\`\`text
|
|
1774
|
-
|
|
1775
|
-
│
|
|
1776
|
-
|
|
1777
|
-
│
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
│ SQL Server │ │ Auth Service│
|
|
1783
|
-
│ :31434 │ │ :8000 │
|
|
1784
|
-
└──────────────┘ └──────────────┘
|
|
1806
|
+
┌──────────────┐ HTTP ┌──────────────┐
|
|
1807
|
+
│ frontend :3000│──────────>│ api :8080 │
|
|
1808
|
+
└──────────────┘ └──────┬───────┘
|
|
1809
|
+
│ JDBC
|
|
1810
|
+
▼
|
|
1811
|
+
┌──────────┐
|
|
1812
|
+
│ DB :5432 │
|
|
1813
|
+
└──────────┘
|
|
1785
1814
|
\`\`\`
|
|
1786
1815
|
|
|
1787
|
-
## 5. Flujos end-to-end
|
|
1788
|
-
|
|
1789
|
-
- **"Nombre del flujo":** Actor → POST /endpoint (componente-a) → valida JWT con auth-service → escribe en SQL Server → responde 201.
|
|
1816
|
+
## 5. Flujos end-to-end (2-5)
|
|
1817
|
+
- **<nombre>:** Actor → endpoint/componente → valida X → escribe Y → responde Z.
|
|
1790
1818
|
|
|
1791
|
-
## 6. Prerequisitos
|
|
1792
|
-
|
|
1819
|
+
## 6. Prerequisitos
|
|
1820
|
+
Lo concreto: acceso a hosts externos, herramientas requeridas, secrets esperados. Sin frases genericas.
|
|
1793
1821
|
|
|
1794
|
-
## 7. Comandos
|
|
1822
|
+
## 7. Comandos
|
|
1795
1823
|
| Comando | Descripcion | Directorio |
|
|
1796
1824
|
|---|---|---|
|
|
1797
|
-
(
|
|
1825
|
+
(scripts reales: package.json scripts, Makefile targets, run.sh, mvnw, gradlew, etc.)
|
|
1826
|
+
|
|
1798
1827
|
|
|
1799
|
-
|
|
1800
|
-
NIVEL 1 — [componente]/architecture.md
|
|
1801
|
-
Objetivo: 120-250 lineas. Un archivo por cada componente no trivial.
|
|
1802
|
-
────────────────────────────────────────────────────────────────
|
|
1828
|
+
────── NIVEL 1 (.agent/context/<componente>/architecture.md, 150-400 lineas) ──────
|
|
1803
1829
|
|
|
1804
|
-
#
|
|
1830
|
+
# <componente> — Arquitectura
|
|
1805
1831
|
|
|
1806
1832
|
## Que hace
|
|
1807
|
-
Parrafo 1:
|
|
1808
|
-
Parrafo 2 (si
|
|
1833
|
+
Parrafo 1: rol funcional + quien lo consume (en lenguaje de negocio).
|
|
1834
|
+
Parrafo 2 (si aplica): que lo diferencia de los otros componentes hermanos.
|
|
1809
1835
|
|
|
1810
1836
|
## Casos de uso principales
|
|
1811
|
-
|
|
1812
|
-
| Caso de uso | Actor | Descripcion |
|
|
1837
|
+
| Caso de uso | Quien lo dispara | Detalle |
|
|
1813
1838
|
|---|---|---|
|
|
1814
|
-
| Ingesta de ventas | Proceso batch BAT | POST /api/sales — upsert bulk de ventas finales |
|
|
1815
|
-
| Consulta de productos | Portal Nexus | GET /api/products?eanCode=XXX |
|
|
1816
1839
|
|
|
1817
|
-
## Stack
|
|
1840
|
+
## Stack
|
|
1818
1841
|
| Item | Valor |
|
|
1819
1842
|
|---|---|
|
|
1820
|
-
| Lenguaje |
|
|
1821
|
-
| Framework |
|
|
1822
|
-
|
|
|
1823
|
-
| Seguridad | Spring Security 6 + JJWT |
|
|
1824
|
-
(versiones REALES del manifest. Si hay librerias clave como POI, MapStruct, HikariCP: incluirlas)
|
|
1843
|
+
| Lenguaje | (real, version del manifest) |
|
|
1844
|
+
| Framework | (real) |
|
|
1845
|
+
| Librerias clave | (las relevantes con version) |
|
|
1825
1846
|
|
|
1826
|
-
##
|
|
1847
|
+
## URLs y puertos (si aplica)
|
|
1827
1848
|
| Recurso | URL |
|
|
1828
1849
|
|---|---|
|
|
1829
|
-
|
|
|
1830
|
-
| Swagger /
|
|
1831
|
-
| Perfil activo | development (application-development.properties) |
|
|
1850
|
+
| Base | http://localhost:<puerto-real> |
|
|
1851
|
+
| Docs / Swagger / Storybook | (si existe) |
|
|
1832
1852
|
|
|
1833
|
-
## Estructura
|
|
1834
|
-
Arbol con
|
|
1853
|
+
## Estructura
|
|
1854
|
+
Arbol con DIRECTORIOS y archivos REALES leidos, anotados con → que rol cumple cada uno.
|
|
1835
1855
|
\`\`\`text
|
|
1836
|
-
|
|
1837
|
-
├──
|
|
1838
|
-
│ ├── ClientController → CRUD /api/clients
|
|
1839
|
-
│ ├── SaleController → POST /api/sales, /api/sales/interim-sales
|
|
1840
|
-
│ └── ExportController → GET /api/export/combos (genera .xlsx)
|
|
1841
|
-
├── service/ → interfaces de logica de negocio
|
|
1842
|
-
│ └── impl/ → implementaciones (@Transactional aqui)
|
|
1843
|
-
├── repository/ → Spring Data JPA Repositories
|
|
1844
|
-
├── domain/ → Entidades JPA (@Entity)
|
|
1845
|
-
│ ├── Client, InterimClient → clientes finales y en staging
|
|
1846
|
-
│ ├── Sale, InterimSale → ventas finales y en staging
|
|
1847
|
-
│ └── compositekeys/ → @IdClass para PKs compuestas
|
|
1848
|
-
├── dto/ → contratos de API (Request/Response DTOs)
|
|
1849
|
-
├── mapper/ → MapStruct: Entity ↔ DTO
|
|
1850
|
-
├── security/ → filtros JWT, validacion, handler 401
|
|
1851
|
-
└── configuration/ → CORS, Swagger, SecurityConfig
|
|
1856
|
+
src/
|
|
1857
|
+
├── ... → ...
|
|
1852
1858
|
\`\`\`
|
|
1853
|
-
(Adaptar a la estructura real del proyecto: puede ser src/, app/, pkg/, etc.)
|
|
1854
1859
|
|
|
1855
|
-
##
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
{
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1860
|
+
## Flujo interno y funciones
|
|
1861
|
+
|
|
1862
|
+
REGLAS:
|
|
1863
|
+
- Lee cada archivo fuente del componente (no solo entry/controller, TODOS los .ts/.js/.py/.go/.java/.rs/.rb/.ex/.cs que haya).
|
|
1864
|
+
- Por cada archivo, lista sus funciones exportadas y las internas importantes.
|
|
1865
|
+
- NO escribas el codigo completo — solo descripcion resumida de que hace.
|
|
1866
|
+
- Para cada funcion, indica con que se conecta (mismo archivo, otro modulo, API externa, BD).
|
|
1867
|
+
- Inclui un ejemplo concreto de datos de entrada y salida.
|
|
1868
|
+
|
|
1869
|
+
### <ruta/archivo.ext>
|
|
1870
|
+
| Funcion | Que hace | Recibe (ejemplo) | Devuelve (ejemplo) | Conecta con |
|
|
1871
|
+
|---------|----------|-------------------|---------------------|-------------|
|
|
1872
|
+
| nombreFunc | 1-linea que hace | {campo: valor, ...} | {campo: valor, ...} | modulo.func(), this.otra(), API externa |
|
|
1873
|
+
|
|
1874
|
+
#### Conecta con — leyenda
|
|
1875
|
+
| Notacion | Significado |
|
|
1876
|
+
|---|---|
|
|
1877
|
+
| \`this.func()\` | Mismo archivo |
|
|
1878
|
+
| \`Modulo.func()\` | Otro archivo del componente |
|
|
1879
|
+
| \`@comp/Otro.func()\` | Otro componente del proyecto |
|
|
1880
|
+
| \`HTTP POST /api/x\` | Llamada HTTP externa |
|
|
1881
|
+
| \`DB: tabla.columna\` | Base de datos |
|
|
1882
|
+
| \`COLA: nombre\` | Mensajeria / eventos |
|
|
1883
|
+
|
|
1884
|
+
### Grafo de dependencias (obligatorio)
|
|
1885
|
+
Diagrama ASCII que muestre como se llaman las funciones entre si.
|
|
1886
|
+
Usa nombres reales de funciones, no de archivos.
|
|
1887
|
+
\`\`\`text
|
|
1888
|
+
controlador.createUser(req)
|
|
1889
|
+
│
|
|
1890
|
+
├──> UserService.validate(data) ── mismo archivo
|
|
1891
|
+
│ └──> UserModel.findByEmail(e) ── DB
|
|
1892
|
+
│
|
|
1893
|
+
├──> UserModel.create(user) ── DB: users.insert
|
|
1894
|
+
│
|
|
1895
|
+
└──> EmailService.sendWelcome(email) ── @notification/EmailService.send()
|
|
1873
1896
|
\`\`\`
|
|
1874
|
-
Si no hay wrapper, omitir esta seccion.
|
|
1875
1897
|
|
|
1876
|
-
##
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
| api-web | Controladores, DTOs, validacion, exportacion | modules/web-api.md |
|
|
1882
|
-
(Agrupar por responsabilidad tecnica real, no inventar modulos)
|
|
1898
|
+
## Endpoints / Rutas / Pantallas
|
|
1899
|
+
- Backend (api): tabla con metodo, ruta, auth, proposito.
|
|
1900
|
+
- Frontend (web): tabla con ruta de pagina, proposito, datos que consume.
|
|
1901
|
+
- Worker / batch: tabla con job, trigger, proposito.
|
|
1902
|
+
Solo lo leido en archivos reales.
|
|
1883
1903
|
|
|
1884
|
-
##
|
|
1885
|
-
|
|
|
1904
|
+
## Configuracion clave
|
|
1905
|
+
| Variable / Propiedad | Valor real | Proposito |
|
|
1886
1906
|
|---|---|---|
|
|
1887
|
-
|
|
1888
|
-
| spring.datasource.url | jdbc:sqlserver://... | Conexion SQL Server |
|
|
1889
|
-
| auth.url | http://57.151.96.13:8000/v1/validate | Servicio externo de validacion JWT |
|
|
1890
|
-
(Valores REALES del archivo de config/env leido. Si no se leyo el archivo, omitir la tabla)
|
|
1907
|
+
(de .env / application*.properties / config files leidos)
|
|
1891
1908
|
|
|
1892
1909
|
## Como levantar
|
|
1893
|
-
Comando principal primero. Luego paso a paso si existe.
|
|
1894
1910
|
\`\`\`bash
|
|
1895
|
-
|
|
1896
|
-
\`\`\`
|
|
1897
|
-
O paso a paso:
|
|
1898
|
-
\`\`\`bash
|
|
1899
|
-
source ./scripts/env.sh
|
|
1900
|
-
npm install && npm run dev
|
|
1911
|
+
# comando real del manifest / scripts
|
|
1901
1912
|
\`\`\`
|
|
1902
1913
|
|
|
1903
|
-
##
|
|
1904
|
-
Frameworks
|
|
1905
|
-
\`\`\`bash
|
|
1906
|
-
npm test # todos los tests
|
|
1907
|
-
npm test -- --watch # modo watch
|
|
1908
|
-
\`\`\`
|
|
1914
|
+
## Tests (si los hay)
|
|
1915
|
+
Frameworks + comando para correr.
|
|
1909
1916
|
|
|
1910
|
-
────────────────────────────────────────────────────────────────
|
|
1911
|
-
NIVEL 2 — [componente]/modules/[modulo].md
|
|
1912
|
-
Objetivo: 50-120 lineas. Un archivo por modulo significativo.
|
|
1913
|
-
────────────────────────────────────────────────────────────────
|
|
1914
1917
|
|
|
1915
|
-
|
|
1918
|
+
────── NIVEL 2 (.agent/context/<componente>/modules/<feature>.md, 40-100 lineas) ──────
|
|
1919
|
+
Solo si el componente tiene features de negocio claras (no crees modulos por capa tecnica).
|
|
1916
1920
|
|
|
1917
|
-
|
|
1918
|
-
1-2 lineas: "Protege todos los endpoints /api/**. Cada request debe llevar un token JWT valido."
|
|
1921
|
+
# <feature> — <componente>
|
|
1919
1922
|
|
|
1920
|
-
##
|
|
1921
|
-
1-2 lineas: como esta implementado. ej. "Filtro OncePerRequestFilter que extrae el JWT del header Authorization, lo valida contra el servicio externo auth.url, y si es valido establece el SecurityContext."
|
|
1923
|
+
## Que hace (negocio, 1-2 lineas)
|
|
1922
1924
|
|
|
1923
|
-
##
|
|
1924
|
-
Para modulos de seguridad, acceso a datos, o cualquiera con logica de decision/secuencia:
|
|
1925
|
-
mostrar el flujo con ASCII art y nombres REALES de clases/metodos.
|
|
1926
|
-
\`\`\`text
|
|
1927
|
-
HTTP Request
|
|
1928
|
-
│
|
|
1929
|
-
▼
|
|
1930
|
-
AuthFilter (OncePerRequestFilter)
|
|
1931
|
-
│
|
|
1932
|
-
├── X-User-Source == "Azure"?
|
|
1933
|
-
│ ▼ SI
|
|
1934
|
-
│ AzureHeaderValidator → construye usuario virtual desde headers
|
|
1935
|
-
│
|
|
1936
|
-
└── NO
|
|
1937
|
-
▼
|
|
1938
|
-
JwtValidator → POST http://auth-service/validate → carga usuario de BD
|
|
1939
|
-
│
|
|
1940
|
-
▼
|
|
1941
|
-
SecurityContextHolder.setAuthentication(...)
|
|
1942
|
-
│
|
|
1943
|
-
▼
|
|
1944
|
-
@PreAuthorize("hasAnyAuthority('ROLE_A','ROLE_B')") en el controller
|
|
1945
|
-
\`\`\`
|
|
1925
|
+
## Como esta implementado (tecnico, 1-2 lineas)
|
|
1946
1926
|
|
|
1947
|
-
##
|
|
1948
|
-
|
|
1927
|
+
## Flujo principal
|
|
1928
|
+
Diagrama ASCII si hay logica de decision, con nombres REALES de clases/funciones.
|
|
1929
|
+
|
|
1930
|
+
## Entidades / modelos (si aplica)
|
|
1949
1931
|
| Entidad | Proposito | Notas |
|
|
1950
1932
|
|---|---|---|
|
|
1951
|
-
| Client | Clientes finales | Clave compuesta: ClientId |
|
|
1952
|
-
| InterimClient | Clientes en staging | Tabla intermedia antes de procesar |
|
|
1953
|
-
|
|
1954
|
-
## Reglas del modulo
|
|
1955
|
-
- Rutas protegidas: /api/** → autenticacion obligatoria
|
|
1956
|
-
- Rutas publicas: OPTIONS /**, /swagger-ui/**, /*
|
|
1957
|
-
- Sin sesion: STATELESS — sin cookies
|
|
1958
|
-
- ddl-auto=validate → el schema nunca se auto-modifica
|
|
1959
1933
|
|
|
1960
1934
|
## Archivos clave
|
|
1961
|
-
|
|
1962
|
-
| Archivo | Rol |
|
|
1935
|
+
| Archivo (ruta relativa al componente) | Rol |
|
|
1963
1936
|
|---|---|
|
|
1964
|
-
| security/AuthFilter.java | Filtro principal — intercepta y valida cada request |
|
|
1965
|
-
| security/JwtValidator.java | Extrae username del JWT, verifica firma y expiracion |
|
|
1966
|
-
| configuration/SecurityConfig.java | Define SecurityFilterChain, rutas publicas/protegidas |
|
|
1967
|
-
| application-development.properties | auth.url, security.token.secret, security.token.expiration |
|
|
1968
|
-
|
|
1969
|
-
## Dependencias
|
|
1970
|
-
- Librerias clave con version si se conoce: io.jsonwebtoken:jjwt:0.9.1, spring-boot-starter-security
|
|
1971
|
-
- Cross-component si corresponde: "llama a http://auth-service:8000/v1/validate para validar tokens"
|
|
1972
|
-
|
|
1973
|
-
================================================================
|
|
1974
|
-
CALIBRACION DE DETALLE
|
|
1975
|
-
================================================================
|
|
1976
|
-
- NIVEL 0: 80-150 lineas
|
|
1977
|
-
- NIVEL 1: 120-250 lineas por componente
|
|
1978
|
-
- NIVEL 2: 50-120 lineas por modulo
|
|
1979
|
-
- Si te queda corto → incluir mas endpoints reales, mas clases en el arbol, mas config values
|
|
1980
|
-
- Si te queda largo → estas repitiendo entre niveles o agregando relleno; recorta
|
|
1981
|
-
|
|
1982
|
-
================================================================
|
|
1983
|
-
QUE NO HACER
|
|
1984
|
-
================================================================
|
|
1985
|
-
- NO usar "Inferido", "Probablemente", "(asumido)", "(quizas)", "parece"
|
|
1986
|
-
- NO repetir lo mismo entre niveles sin agregar valor (cada nivel zoomea mas)
|
|
1987
|
-
- NO dejar tablas vacias ni con placeholders tipo "..." o "ver manifest"
|
|
1988
|
-
- NO escribir overview que podria aplicar a cualquier proyecto (tiene que ser especifico de ESTE proyecto)
|
|
1989
|
-
- NO documentar componentes triviales (scripts sueltos, configs simples) con carpeta propia — mencionalos en NIVEL 0 y listo
|
|
1990
|
-
- NO inventar endpoints, env vars, puertos, hosts, clases o schemas que no leiste en los archivos reales
|
|
1991
|
-
|
|
1992
|
-
================================================================
|
|
1993
|
-
FORMATO DE SALIDA — OBLIGATORIO
|
|
1994
|
-
================================================================
|
|
1995
|
-
Devolve UNICAMENTE bloques de archivos separados por marcadores ===. Nada de explicaciones extra fuera de los bloques.
|
|
1996
1937
|
|
|
1997
|
-
IMPORTANTE: TODAS las rutas son RELATIVAS al directorio del proyecto.
|
|
1998
1938
|
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
=== .agent/context/nexus-core-api/modules/clients.md ===
|
|
1939
|
+
==================================================================
|
|
1940
|
+
FORMATO DE SALIDA — OBLIGATORIO
|
|
1941
|
+
==================================================================
|
|
1942
|
+
Devolve UNICAMENTE bloques separados por marcadores ===. Sin texto extra fuera de los bloques.
|
|
1943
|
+
TODAS las rutas son RELATIVAS al directorio del proyecto.
|
|
2005
1944
|
|
|
2006
1945
|
=== .agent/context/architecture.md ===
|
|
2007
|
-
[
|
|
1946
|
+
[NIVEL 0]
|
|
1947
|
+
|
|
1948
|
+
=== .agent/context/<componente-A>/architecture.md ===
|
|
1949
|
+
[NIVEL 1 del componente A]
|
|
1950
|
+
|
|
1951
|
+
=== .agent/context/<componente-B>/architecture.md ===
|
|
1952
|
+
[NIVEL 1 del componente B]
|
|
2008
1953
|
|
|
2009
|
-
|
|
2010
|
-
[contenido NIVEL 1]
|
|
1954
|
+
(... un bloque NIVEL 1 por cada componente identificado en paso 1)
|
|
2011
1955
|
|
|
2012
|
-
=== .agent/context
|
|
2013
|
-
[
|
|
1956
|
+
=== .agent/context/<componente-A>/modules/<feature>.md ===
|
|
1957
|
+
[NIVEL 2 — opcional]
|
|
2014
1958
|
|
|
2015
|
-
REGLAS
|
|
2016
|
-
-
|
|
2017
|
-
-
|
|
2018
|
-
-
|
|
2019
|
-
-
|
|
2020
|
-
-
|
|
2021
|
-
- Si existe documentacion previa, ACTUALIZALA preservando lo que sigue siendo valido y agregando lo nuevo`;
|
|
1959
|
+
REGLAS FINALES:
|
|
1960
|
+
- Un archivo NIVEL 1 por cada carpeta-componente que EXISTE HOY en el filesystem (no saltes ninguna, incluye frontends).
|
|
1961
|
+
- NO regeneres NIVEL 1 de componentes archivados (carpetas que ya no existen): no los incluyas en tu output. La doc previa de esos componentes queda intacta en disco.
|
|
1962
|
+
- NIVEL 0: update incremental. Si la doc previa lista componentes archivados, conservalos marcados como tal — no los borres.
|
|
1963
|
+
- NO escribir bajo .agent/docs/.
|
|
1964
|
+
- Los nombres de carpeta en los marcadores DEBEN coincidir con los nombres reales del proyecto (los activos).`;
|
|
2022
1965
|
const res = await this.runWithFallback('explorer', prompt, 'Exploracion');
|
|
2023
1966
|
const text = extractCliText(res);
|
|
2024
1967
|
// Always overwrite the single last-run report so we have a debug trail
|
package/dist/utils/deepseek.d.ts
CHANGED
|
@@ -11,4 +11,3 @@ export declare function deepseekAuthStatus(): Promise<{
|
|
|
11
11
|
}>;
|
|
12
12
|
export declare function callDeepSeekAPI(prompt: string, model?: string, onData?: (chunk: string) => void): Promise<string>;
|
|
13
13
|
export declare function fetchDeepSeekModels(cfg?: DeepSeekKeyConfig | null): Promise<string[]>;
|
|
14
|
-
export declare const DEEPSEEK_MODELS: string[];
|
package/dist/utils/deepseek.js
CHANGED
|
@@ -35,6 +35,7 @@ export async function callDeepSeekAPI(prompt, model = 'deepseek-chat', onData) {
|
|
|
35
35
|
throw new Error('DEEPSEEK_NOT_CONFIGURED: Run /login y elegí DeepSeek');
|
|
36
36
|
}
|
|
37
37
|
const useModel = (model && model !== 'deepseek-model') ? model : cfg.model;
|
|
38
|
+
const isV4 = useModel.startsWith('deepseek-v4');
|
|
38
39
|
const client = new OpenAI({
|
|
39
40
|
apiKey: cfg.api_key,
|
|
40
41
|
baseURL: DEEPSEEK_BASE_URL,
|
|
@@ -43,21 +44,26 @@ export async function callDeepSeekAPI(prompt, model = 'deepseek-chat', onData) {
|
|
|
43
44
|
let lastErr;
|
|
44
45
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
45
46
|
try {
|
|
47
|
+
const baseParams = {
|
|
48
|
+
model: useModel,
|
|
49
|
+
messages: [{ role: 'user', content: prompt }],
|
|
50
|
+
};
|
|
51
|
+
if (isV4) {
|
|
52
|
+
baseParams.reasoning_effort = 'high';
|
|
53
|
+
baseParams.extra_body = { thinking: { type: 'enabled' } };
|
|
54
|
+
}
|
|
46
55
|
if (!onData) {
|
|
47
|
-
const completion = await client.chat.completions.create(
|
|
48
|
-
model: useModel,
|
|
49
|
-
messages: [{ role: 'user', content: prompt }],
|
|
50
|
-
});
|
|
56
|
+
const completion = await client.chat.completions.create(baseParams);
|
|
51
57
|
return completion.choices[0]?.message?.content ?? '';
|
|
52
58
|
}
|
|
53
59
|
let fullText = '';
|
|
54
60
|
const stream = await client.chat.completions.create({
|
|
55
|
-
|
|
56
|
-
messages: [{ role: 'user', content: prompt }],
|
|
61
|
+
...baseParams,
|
|
57
62
|
stream: true,
|
|
63
|
+
stream_options: { include_usage: true },
|
|
58
64
|
});
|
|
59
65
|
for await (const chunk of stream) {
|
|
60
|
-
const delta = chunk.choices[0]?.delta?.content ?? '';
|
|
66
|
+
const delta = chunk.choices?.[0]?.delta?.content ?? '';
|
|
61
67
|
if (delta) {
|
|
62
68
|
fullText += delta;
|
|
63
69
|
onData(delta);
|
|
@@ -101,7 +107,3 @@ export async function fetchDeepSeekModels(cfg) {
|
|
|
101
107
|
return [];
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
|
-
export const DEEPSEEK_MODELS = [
|
|
105
|
-
'deepseek-chat',
|
|
106
|
-
'deepseek-reasoner',
|
|
107
|
-
];
|