shark-ai 0.2.1 → 0.3.1

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
@@ -5,9 +5,10 @@ import {
5
5
  colors,
6
6
  configCommand,
7
7
  loginCommand,
8
+ t,
8
9
  tokenStorage,
9
10
  tui
10
- } from "../chunk-R3MIUNVD.js";
11
+ } from "../chunk-JQAVZJTG.js";
11
12
 
12
13
  // src/core/error/crash-handler.ts
13
14
  import fs from "fs";
@@ -594,7 +595,12 @@ async function getActiveRealm() {
594
595
 
595
596
  // src/core/agents/business-analyst-agent.ts
596
597
  var AGENT_TYPE = "business_analyst";
597
- var AGENT_ID = process.env.STACKSPOT_BA_AGENT_ID || "01KEJ95G304TNNAKGH5XNEEBVD";
598
+ function getAgentId(overrideId) {
599
+ if (overrideId) return overrideId;
600
+ const config = ConfigManager.getInstance().getConfig();
601
+ if (config.agents?.ba) return config.agents.ba;
602
+ return process.env.STACKSPOT_BA_AGENT_ID || "01KEJ95G304TNNAKGH5XNEEBVD";
603
+ }
598
604
  async function runBusinessAnalystAgent(prompt, options = {}) {
599
605
  const { agentId, onChunk, onComplete } = options;
600
606
  const realm = await getActiveRealm();
@@ -612,8 +618,8 @@ async function runBusinessAnalystAgent(prompt, options = {}) {
612
618
  deep_search_ks: false,
613
619
  conversation_id: existingConversationId
614
620
  };
615
- const finalAgentId = agentId || AGENT_ID;
616
- const agentUrl = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalAgentId}/chat`;
621
+ const effectiveAgentId = getAgentId(options.agentId);
622
+ const agentUrl = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${effectiveAgentId}/chat`;
617
623
  const headers = {
618
624
  "Authorization": `Bearer ${token}`,
619
625
  "Content-Type": "application/json"
@@ -689,7 +695,7 @@ async function interactiveBusinessAnalyst() {
689
695
  if (response.actions && response.actions.length > 0) {
690
696
  for (const action of response.actions) {
691
697
  if (action.type === "talk_with_user") {
692
- tui.log.info(colors.green("\u{1F916} BA Agent:"));
698
+ tui.log.info(colors.success("\u{1F916} BA Agent:"));
693
699
  console.log(action.content);
694
700
  } else {
695
701
  tui.log.warning(`
@@ -712,9 +718,6 @@ async function interactiveBusinessAnalyst() {
712
718
  }
713
719
  }
714
720
  }
715
- if (response.tokens) {
716
- tui.log.info(`Tokens used: ${response.tokens.output || 0}`);
717
- }
718
721
  }
719
722
  });
720
723
  tui.outro("Session complete");
@@ -836,7 +839,12 @@ ${stdout}`);
836
839
 
837
840
  // src/core/agents/specification-agent.ts
838
841
  var AGENT_TYPE2 = "specification_agent";
839
- var AGENT_ID2 = process.env.STACKSPOT_SPEC_AGENT_ID || "01KEPXTX37FTB4N672TZST4SGP";
842
+ function getAgentId2(overrideId) {
843
+ if (overrideId) return overrideId;
844
+ const config = ConfigManager.getInstance().getConfig();
845
+ if (config.agents?.spec) return config.agents.spec;
846
+ return process.env.STACKSPOT_SPEC_AGENT_ID || "01KEPXTX37FTB4N672TZST4SGP";
847
+ }
840
848
  async function interactiveSpecificationAgent(options = {}) {
841
849
  FileLogger.init();
842
850
  tui.intro("\u{1F3D7}\uFE0F Specification Agent");
@@ -1043,12 +1051,12 @@ async function callSpecAgentApi(prompt, onChunk, agentId) {
1043
1051
  use_conversation: true,
1044
1052
  conversation_id: conversationId
1045
1053
  };
1046
- const finalId = agentId || AGENT_ID2;
1047
- const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${finalId}/chat`;
1054
+ const effectiveAgentId = getAgentId2(agentId);
1055
+ const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${effectiveAgentId}/chat`;
1048
1056
  let fullMsg = "";
1049
1057
  let raw = {};
1050
1058
  FileLogger.log("AGENT", "Calling Agent API", {
1051
- agentId: finalId,
1059
+ agentId: effectiveAgentId,
1052
1060
  conversationId,
1053
1061
  prompt: prompt.substring(0, 500)
1054
1062
  // Log summary of prompt
@@ -1088,12 +1096,16 @@ import { Command as Command2 } from "commander";
1088
1096
  import fs5 from "fs";
1089
1097
  import path4 from "path";
1090
1098
  var AGENT_TYPE3 = "scan_agent";
1091
- var AGENT_ID3 = process.env.STACKSPOT_SCAN_AGENT_ID || "01KEQ9AHWB550J2244YBH3QATN";
1099
+ function getAgentId3() {
1100
+ const config = ConfigManager.getInstance().getConfig();
1101
+ if (config.agents?.scan) return config.agents.scan;
1102
+ return process.env.STACKSPOT_SCAN_AGENT_ID || "01KEQ9AHWB550J2244YBH3QATN";
1103
+ }
1092
1104
  async function interactiveScanAgent(options = {}) {
1093
1105
  FileLogger.init();
1094
- tui.intro("\u{1F575}\uFE0F\u200D\u2642\uFE0F Scan Agent");
1095
1106
  const config = ConfigManager.getInstance().getConfig();
1096
1107
  const language = config.language || "English";
1108
+ tui.intro(t("commands.scan.intro"));
1097
1109
  const projectRoot = process.cwd();
1098
1110
  let outputFile;
1099
1111
  if (options.output) {
@@ -1116,58 +1128,295 @@ async function interactiveScanAgent(options = {}) {
1116
1128
  outputFile = path4.join(outputDir, "project-context.md");
1117
1129
  }
1118
1130
  }
1119
- tui.log.info(`Scanning project at: ${colors.bold(projectRoot)}`);
1120
- tui.log.info(`Output targeted at: ${colors.bold(outputFile)}`);
1121
- tui.log.info(`Language: ${colors.bold(language)}`);
1131
+ tui.log.info(`${t("commands.scan.scanningProject")} ${colors.bold(projectRoot)}`);
1132
+ tui.log.info(`${t("commands.scan.outputTarget")} ${colors.bold(outputFile)}`);
1133
+ tui.log.info(`${t("commands.scan.language")} ${colors.bold(language)}`);
1122
1134
  const configFileRelative = path4.relative(projectRoot, outputFile);
1135
+ const initialTemplate = `# Project Context
1136
+
1137
+ ## Overview
1138
+ [TO BE ANALYZED]
1139
+
1140
+ ## Tech Stack
1141
+ [TO BE ANALYZED]
1142
+
1143
+ ## Architecture
1144
+ [TO BE ANALYZED]
1145
+
1146
+ ## Directory Structure
1147
+ [TO BE ANALYZED]
1148
+
1149
+ ## Key Components
1150
+ [TO BE ANALYZED]
1151
+
1152
+ ## API / Interfaces
1153
+ [TO BE ANALYZED]
1154
+
1155
+ ## Data Layer
1156
+ [TO BE ANALYZED]
1157
+
1158
+ ## Configuration & Environment
1159
+ [TO BE ANALYZED]
1160
+
1161
+ ## Build & Development
1162
+ [TO BE ANALYZED]
1163
+
1164
+ ## Key Patterns & Conventions
1165
+ [TO BE ANALYZED]
1166
+ `;
1167
+ if (!fs5.existsSync(outputFile)) {
1168
+ fs5.writeFileSync(outputFile, initialTemplate, { encoding: "utf-8" });
1169
+ tui.log.success(`${t("commands.scan.templateCreated")} ${outputFile}`);
1170
+ } else {
1171
+ tui.log.info(t("commands.scan.fileExists"));
1172
+ }
1123
1173
  const superPrompt = `
1124
1174
  You are the **Scan Agent**, an expert software architect and analyst.
1125
- Your mission is to explore this project's codebase and generate a comprehensive context file that will be used by other AI agents (specifically a Developer Agent) to understand how to work on this project.
1175
+ Your mission is to explore this project's codebase THOROUGHLY and generate a COMPREHENSIVE context file that will be used by other AI agents (specifically a Developer Agent) to understand how to work on this project.
1126
1176
 
1127
- **Goal**: Create a markdown file at: \`${configFileRelative}\`.
1177
+ **IMPORTANT**: The file \`${configFileRelative}\` has already been created with a template structure. Your job is to FILL IN each section by analyzing the project.
1128
1178
 
1129
1179
  **LANGUAGE INSTRUCTION**:
1130
- You MUST write the content of the \`project-context.md\` file in **${language}**.
1131
- Also, strictly interact with tools using the appropriate payload.
1132
-
1133
- **Instructions**:
1134
- 1. **Analyze Structure**: Use \`list_files\` to understand the root directory and key subdirectories (src, tools, config, etc.).
1135
- 2. **Identify Tech Stack**: Use \`read_file\` or \`search_file\` on key manifests (package.json, pom.xml, go.mod, Dockerfile, etc.) to determine languages, frameworks, and versions.
1136
- 3. **Map Architecture**: Infer the architectural pattern (Monolith? Microservices? Clean Architecture?) based on folder structure and key files.
1137
- 4. **Document Key Paths**: Identify where source code, tests, and configs live.
1138
-
1139
- **Output Format** (Markdown):
1140
- The final action MUST be \`create_file\` (or \`modify_file\`) for the target file with the following structure:
1180
+ You MUST write the content in **${language}**.
1181
+
1182
+ **CRITICAL STRATEGY - INCREMENTAL UPDATES**:
1183
+ DO NOT try to rewrite the entire file at once! Instead:
1184
+
1185
+ 1. **Explore** the project using \`list_files\`, \`read_file\`, \`search_file\`
1186
+ 2. **Update** specific sections incrementally using \`modify_file\`
1187
+ 3. **Benefit**: Build a MUCH MORE DETAILED document without context size limitations
1188
+
1189
+ **WORKFLOW - FILL EACH SECTION:**
1190
+
1191
+ **Step 1 - Analyze Tech Stack:**
1192
+ - \`list_files\` root directory to see project structure
1193
+ - \`read_file\` package.json (or pom.xml, go.mod, requirements.txt, etc.)
1194
+ - \`modify_file\` to replace:
1195
+ - \`target_content\`: "## Tech Stack\\n[TO BE ANALYZED]"
1196
+ - \`content\`: Detailed tech stack with versions, dependencies, and their purposes
1197
+
1198
+ **Step 2 - Analyze Directory Structure:**
1199
+ - \`list_files\` on ALL key directories (src, tests, config, docs, etc.)
1200
+ - Map the complete directory tree
1201
+ - \`modify_file\` to replace:
1202
+ - \`target_content\`: "## Directory Structure\\n[TO BE ANALYZED]"
1203
+ - \`content\`: Visual directory tree with purpose of each folder
1204
+
1205
+ **Step 3 - Analyze Architecture:**
1206
+ - \`read_file\` entry points (main.ts, index.js, app.py, etc.)
1207
+ - \`read_file\` 5-10 source files to understand code patterns and organization
1208
+ - Identify architectural pattern (Clean Arch, MVC, Microservices, etc.)
1209
+ - \`modify_file\` to replace:
1210
+ - \`target_content\`: "## Architecture\\n[TO BE ANALYZED]"
1211
+ - \`content\`: Comprehensive architectural description with patterns and module organization
1212
+
1213
+ **Step 4 - Document Components:**
1214
+ - Identify ALL major modules/components by reading source files
1215
+ - For each component: location, purpose, key files
1216
+ - \`modify_file\` to replace:
1217
+ - \`target_content\`: "## Key Components\\n[TO BE ANALYZED]"
1218
+ - \`content\`: Detailed list of components with their purposes
1219
+
1220
+ **Step 5 - Document APIs (if applicable):**
1221
+ - Search for route definitions, controllers, API endpoints
1222
+ - Document base URL, main endpoints, request/response patterns
1223
+ - \`modify_file\` to replace:
1224
+ - \`target_content\`: "## API / Interfaces\\n[TO BE ANALYZED]"
1225
+ - \`content\`: API documentation (or "Not applicable" if no API)
1226
+
1227
+ **Step 6 - Document Data Layer (if applicable):**
1228
+ - Search for database configs, ORM setup, model definitions
1229
+ - Document database type, ORM tool, key entities/tables
1230
+ - \`modify_file\` to replace:
1231
+ - \`target_content\`: "## Data Layer\\n[TO BE ANALYZED]"
1232
+ - \`content\`: Data layer details (or "Not applicable" if no database)
1233
+
1234
+ **Step 7 - Configuration & Environment:**
1235
+ - Read config files (.env.example, config/, etc.)
1236
+ - Identify environment variables and their purposes
1237
+ - \`modify_file\` to replace:
1238
+ - \`target_content\`: "## Configuration & Environment\\n[TO BE ANALYZED]"
1239
+ - \`content\`: List of env vars and config files
1240
+
1241
+ **Step 8 - Build & Development:**
1242
+ - Read package.json scripts, Makefile, build configs
1243
+ - Document dev, build, test, lint commands
1244
+ - \`modify_file\` to replace:
1245
+ - \`target_content\`: "## Build & Development\\n[TO BE ANALYZED]"
1246
+ - \`content\`: Commands for development workflow
1247
+
1248
+ **Step 9 - Patterns & Conventions:**
1249
+ - Based on files read, document naming conventions, code organization
1250
+ - Note error handling, logging strategies
1251
+ - \`modify_file\` to replace:
1252
+ - \`target_content\`: "## Key Patterns & Conventions\\n[TO BE ANALYZED]"
1253
+ - \`content\`: Observed patterns and conventions
1254
+
1255
+ **Step 10 - Overview (LAST):**
1256
+ - Synthesize all findings into a comprehensive overview
1257
+ - \`modify_file\` to replace:
1258
+ - \`target_content\`: "## Overview\\n[TO BE ANALYZED]"
1259
+ - \`content\`: Detailed project description with purpose and main functionality
1260
+
1261
+ **HOW TO USE modify_file:**
1262
+ \`\`\`json
1263
+ {
1264
+ "actions": [{
1265
+ "type": "modify_file",
1266
+ "path": "${configFileRelative}",
1267
+ "target_content": "## Tech Stack\\n[TO BE ANALYZED]",
1268
+ "content": "## Tech Stack\\n- **Language**: TypeScript 5.3\\n- **Runtime**: Node.js 20.x\\n..."
1269
+ }]
1270
+ }
1271
+ \`\`\`
1141
1272
 
1273
+ \`\`\`markdown
1142
1274
  # Project Context
1143
1275
 
1144
1276
  ## Overview
1145
- [Brief description of what this project seems to be]
1277
+ [TO BE ANALYZED]
1146
1278
 
1147
1279
  ## Tech Stack
1148
- - **Language**: [e.g. TypeScript]
1149
- - **Framework**: [e.g. React, Express, NestJS]
1150
- - **Build Tool**: [e.g. Vite, Webpack]
1151
- - **Database**: [e.g. PostgreSQL, Prisma] (if detected)
1280
+ [TO BE ANALYZED]
1152
1281
 
1153
1282
  ## Architecture
1154
- [Description of the folder structure and architectural patterns detected]
1283
+ [TO BE ANALYZED]
1155
1284
 
1156
- ## Key Locations
1157
- - **Source**: [path/to/src]
1158
- - **Tests**: [path/to/tests]
1159
- - **Config**: [path/to/config]
1285
+ ## Directory Structure
1286
+ [TO BE ANALYZED]
1160
1287
 
1161
- ## Commands
1162
- [List of discovered npm scripts or makefile commands for dev, build, test]
1288
+ ## Key Components
1289
+ [TO BE ANALYZED]
1163
1290
 
1164
- ---
1291
+ ## API / Interfaces
1292
+ [TO BE ANALYZED]
1293
+
1294
+ ## Data Layer
1295
+ [TO BE ANALYZED]
1296
+
1297
+ ## Configuration & Environment
1298
+ [TO BE ANALYZED]
1299
+
1300
+ ## Build & Development
1301
+ [TO BE ANALYZED]
1302
+
1303
+ ## Key Patterns & Conventions
1304
+ [TO BE ANALYZED]
1305
+ \`\`\`
1306
+
1307
+ **Step 2 - Explore and Update Incrementally:**
1308
+ After creating the template, perform these analyses and UPDATE each section:
1309
+
1310
+ **2.1 - Analyze Tech Stack:**
1311
+ - \`list_files\` root directory
1312
+ - \`read_file\` package.json (or equivalent manifest)
1313
+ - \`modify_file\` to replace "## Tech Stack\\n[TO BE ANALYZED]" with detailed findings
1314
+
1315
+ **2.2 - Analyze Directory Structure:**
1316
+ - \`list_files\` on key directories (src, tests, config, etc.)
1317
+ - \`modify_file\` to replace "## Directory Structure\\n[TO BE ANALYZED]" with complete structure
1318
+
1319
+ **2.3 - Analyze Architecture:**
1320
+ - \`read_file\` entry points (main.ts, index.js, etc.)
1321
+ - \`read_file\` 5-10 source files to understand patterns
1322
+ - \`modify_file\` to replace "## Architecture\\n[TO BE ANALYZED]" with architectural insights
1165
1323
 
1166
- **Rules**:
1167
- - Do NOT guess. If you are unsure, check the file.
1168
- - Be concise.
1169
- - Focus on FACTS that a Developer Agent needs to know to write code correcty.
1170
- - Start by listing the root directory.
1324
+ **2.4 - Document Components:**
1325
+ - Identify major modules/components
1326
+ - \`modify_file\` to replace "## Key Components\\n[TO BE ANALYZED]" with component details
1327
+
1328
+ **2.5 - Document APIs (if applicable):**
1329
+ - Search for route definitions, controllers, API endpoints
1330
+ - \`modify_file\` to replace "## API / Interfaces\\n[TO BE ANALYZED]"
1331
+
1332
+ **2.6 - Document Data Layer (if applicable):**
1333
+ - Search for database configs, ORM, models
1334
+ - \`modify_file\` to replace "## Data Layer\\n[TO BE ANALYZED]"
1335
+
1336
+ **2.7 - Final Touches:**
1337
+ - Update remaining sections (Config, Build, Patterns)
1338
+ - Ensure Overview is comprehensive
1339
+
1340
+ **HOW TO USE modify_file:**
1341
+ \`\`\`json
1342
+ {
1343
+ "actions": [{
1344
+ "type": "modify_file",
1345
+ "path": "${configFileRelative}",
1346
+ "target_content": "## Tech Stack\\n[TO BE ANALYZED]",
1347
+ "content": "## Tech Stack\\n- **Language**: TypeScript 5.3\\n- **Runtime**: Node.js 20.x\\n- **Framework**: Express 4.18\\n..."
1348
+ }]
1349
+ }
1350
+ \`\`\`
1351
+
1352
+ **SECTION TEMPLATES (For your updates):**
1353
+
1354
+ **Tech Stack:**
1355
+ \`\`\`markdown
1356
+ ## Tech Stack
1357
+ - **Language**: [name + version]
1358
+ - **Runtime**: [name + version]
1359
+ - **Framework**: [name + version]
1360
+ - **Build Tool**: [name]
1361
+ - **Testing**: [framework]
1362
+ - **Key Dependencies**:
1363
+ - [dep-name]: [purpose]
1364
+ - [dep-name]: [purpose]
1365
+ \`\`\`
1366
+
1367
+ **Architecture:**
1368
+ \`\`\`markdown
1369
+ ## Architecture
1370
+ [Comprehensive description]
1371
+ - **Pattern**: [Clean Arch, MVC, etc.]
1372
+ - **Module Organization**: [how modules are structured]
1373
+ - **Layer Separation**: [controllers, services, repos]
1374
+ - **Configuration**: [how config is managed]
1375
+ \`\`\`
1376
+
1377
+ **Directory Structure:**
1378
+ \`\`\`markdown
1379
+ ## Directory Structure
1380
+ \\\`\\\`\\\`
1381
+ /src
1382
+ /core - [Purpose]
1383
+ /commands - [Purpose]
1384
+ /ui - [Purpose]
1385
+ /tests - [Purpose]
1386
+ /docs - [Purpose]
1387
+ \\\`\\\`\\\`
1388
+ \`\`\`
1389
+
1390
+ **Key Components:**
1391
+ \`\`\`markdown
1392
+ ## Key Components
1393
+
1394
+ ### [Component Name 1]
1395
+ - **Location**: \\\`path/to/component\\\`
1396
+ - **Purpose**: [What it does]
1397
+ - **Key Files**: [Important files]
1398
+
1399
+ ### [Component Name 2]
1400
+ - **Location**: \\\`path/to/component\\\`
1401
+ - **Purpose**: [What it does]
1402
+ - **Key Files**: [Important files]
1403
+ \`\`\`
1404
+
1405
+ **DEPTH REQUIREMENT**:
1406
+ - Read MULTIPLE files (5-10 minimum) to understand patterns
1407
+ - Identify ALL major modules/components
1408
+ - Document API routes, database schemas if applicable
1409
+ - Note design patterns and architectural decisions
1410
+ - List important dependencies with their purposes
1411
+
1412
+ **RULES**:
1413
+ - Create template FIRST (step 1)
1414
+ - Update sections INCREMENTALLY (steps 2-7)
1415
+ - Do NOT wait to write everything at the end
1416
+ - Use \`modify_file\` to replace "[TO BE ANALYZED]" sections
1417
+ - Be DETAILED and COMPREHENSIVE
1418
+ - Take your time - you have up to 30 steps
1419
+ - Verify facts with \`read_file\` or \`search_file\` before documenting
1171
1420
  `.trim();
1172
1421
  await runScanLoop(superPrompt, outputFile);
1173
1422
  }
@@ -1175,38 +1424,39 @@ async function runScanLoop(initialPrompt, targetPath) {
1175
1424
  let nextPrompt = initialPrompt;
1176
1425
  let keepGoing = true;
1177
1426
  let stepCount = 0;
1178
- const MAX_STEPS = 15;
1427
+ const MAX_STEPS = 30;
1179
1428
  while (keepGoing && stepCount < MAX_STEPS) {
1180
1429
  stepCount++;
1181
1430
  const spinner = tui.spinner();
1182
- spinner.start(`\u{1F575}\uFE0F\u200D\u2642\uFE0F Scan Agent analyzing (Step ${stepCount}/${MAX_STEPS})...`);
1431
+ const msg = t("commands.scan.analyzing").replace("{step}", stepCount.toString());
1432
+ spinner.start(msg);
1183
1433
  let responseText = "";
1184
1434
  let lastResponse = null;
1185
1435
  try {
1186
1436
  lastResponse = await callScanAgentApi(nextPrompt, (chunk) => {
1187
1437
  responseText += chunk;
1188
1438
  });
1189
- spinner.stop("Step complete");
1190
- if (lastResponse && lastResponse.actions) {
1439
+ spinner.stop(t("commands.scan.stepComplete"));
1440
+ if (lastResponse && lastResponse.actions && lastResponse.actions.length > 0) {
1191
1441
  let executionResults = "";
1192
1442
  let fileCreated = false;
1193
1443
  for (const action of lastResponse.actions) {
1194
1444
  if (action.type === "list_files") {
1195
- tui.log.info(`\u{1F4C2} Scanning dir: ${colors.bold(action.path || ".")}`);
1445
+ tui.log.info(t("commands.scan.scanningDir").replace("{0}", colors.bold(action.path || ".")));
1196
1446
  const result = handleListFiles(action.path || ".");
1197
1447
  executionResults += `[Action list_files(${action.path}) Result]:
1198
1448
  ${result}
1199
1449
 
1200
1450
  `;
1201
1451
  } else if (action.type === "read_file") {
1202
- tui.log.info(`\u{1F4D6} Reading file: ${colors.bold(action.path || "")}`);
1452
+ tui.log.info(t("commands.scan.readingFile").replace("{0}", colors.bold(action.path || "")));
1203
1453
  const result = handleReadFile(action.path || "");
1204
1454
  executionResults += `[Action read_file(${action.path}) Result]:
1205
1455
  ${result}
1206
1456
 
1207
1457
  `;
1208
1458
  } else if (action.type === "search_file") {
1209
- tui.log.info(`\u{1F50D} Searching: ${colors.bold(action.path || "")}`);
1459
+ tui.log.info(t("commands.scan.searching").replace("{0}", colors.bold(action.path || "")));
1210
1460
  const result = handleSearchFile(action.path || "");
1211
1461
  executionResults += `[Action search_file(${action.path}) Result]:
1212
1462
  ${result}
@@ -1217,7 +1467,7 @@ ${result}
1217
1467
  const resolvedTargetPath = path4.resolve(targetPath);
1218
1468
  let isTarget = resolvedActionPath === resolvedTargetPath;
1219
1469
  if (!isTarget && path4.basename(action.path || "") === "project-context.md") {
1220
- tui.log.warning(`Agent targeted '${action.path}' but we enforce '${path4.relative(process.cwd(), targetPath)}'. Redirecting write.`);
1470
+ tui.log.warning(t("commands.scan.targetRedirect").replace("{0}", action.path || "").replace("{1}", path4.relative(process.cwd(), targetPath)));
1221
1471
  isTarget = true;
1222
1472
  action.path = targetPath;
1223
1473
  }
@@ -1225,44 +1475,75 @@ ${result}
1225
1475
  const finalPath = targetPath;
1226
1476
  if (action.type === "create_file") {
1227
1477
  fs5.writeFileSync(finalPath, action.content || "");
1228
- tui.log.success(`\u2705 Generated Context: ${finalPath}`);
1478
+ tui.log.success(t("commands.scan.generated").replace("{0}", finalPath));
1229
1479
  fileCreated = true;
1230
1480
  } else {
1231
- fs5.writeFileSync(finalPath, action.content || "");
1232
- tui.log.success(`\u2705 Updated Context: ${finalPath}`);
1233
- fileCreated = true;
1481
+ if (fs5.existsSync(finalPath)) {
1482
+ const currentContent = fs5.readFileSync(finalPath, "utf-8");
1483
+ if (action.target_content && currentContent.includes(action.target_content)) {
1484
+ const newContent = currentContent.replace(action.target_content, action.content || "");
1485
+ fs5.writeFileSync(finalPath, newContent, { encoding: "utf-8" });
1486
+ tui.log.success(t("commands.scan.updated").replace("{0}", finalPath));
1487
+ fileCreated = true;
1488
+ } else {
1489
+ tui.log.warning(t("commands.scan.error") + ": " + t("commands.scan.contentNotFound"));
1490
+ executionResults += `[Action ${action.type}]: Failed. Target content not found in file.
1491
+ `;
1492
+ fileCreated = false;
1493
+ }
1494
+ } else {
1495
+ tui.log.warning(t("commands.scan.error") + ": " + t("commands.scan.notFound"));
1496
+ }
1234
1497
  }
1235
1498
  executionResults += `[Action ${action.type}]: Success. Task Completed.
1236
1499
  `;
1237
1500
  } else {
1238
- tui.log.warning(`Agent wants to write to unexpected file: ${action.path}`);
1239
- executionResults += `[Action ${action.type}]: Skipped (Scan Agent only writes context file)
1501
+ tui.log.warning(t("commands.scan.error"));
1502
+ executionResults += `[Action ${action.type}]: ${t("commands.scan.skipped")}
1240
1503
  `;
1241
1504
  }
1242
1505
  } else if (action.type === "talk_with_user") {
1243
- tui.log.info(colors.primary("\u{1F916} Scan Agent asks:"));
1506
+ tui.log.info(colors.primary(t("commands.scan.agentAsks")));
1244
1507
  console.log(action.content);
1245
- const reply = await tui.text({ message: "Agent needs input:", placeholder: "Reply..." });
1508
+ const reply = await tui.text({ message: t("commands.scan.agentInput"), placeholder: t("commands.scan.replyPlaceholder") });
1246
1509
  executionResults += `[User Reply]: ${reply}
1247
1510
  `;
1248
1511
  }
1249
1512
  }
1250
1513
  if (fileCreated) {
1251
- tui.log.success("\u2728 Scan completed successfully!");
1252
- keepGoing = false;
1514
+ const currentContent = fs5.readFileSync(targetPath, "utf-8");
1515
+ const pendingSections = [];
1516
+ const lines = currentContent.split("\n");
1517
+ let currentSection = "";
1518
+ for (const line of lines) {
1519
+ if (line.startsWith("## ")) {
1520
+ currentSection = line.substring(3).trim();
1521
+ }
1522
+ if (line.includes("[TO BE ANALYZED]")) {
1523
+ if (currentSection && !pendingSections.includes(currentSection)) {
1524
+ pendingSections.push(currentSection);
1525
+ }
1526
+ }
1527
+ }
1528
+ const pendingMsg = pendingSections.length > 0 ? `
1529
+
1530
+ [System Helper]: ${t("commands.scan.pendingSections").replace("{0}", pendingSections.join(", "))}` : `
1531
+
1532
+ [System Helper]: ${t("commands.scan.allPopulated")}`;
1533
+ nextPrompt = `${executionResults}
1534
+
1535
+ [System]: File updated successfully.${pendingMsg} Please continue with the next step of the analysis and focus on the pending sections.`;
1536
+ FileLogger.log("SCAN", "Section updated, continuing loop", { step: stepCount, pending: pendingSections.length });
1253
1537
  } else {
1254
1538
  nextPrompt = executionResults;
1255
1539
  FileLogger.log("SCAN", "Auto-replying with results", { length: executionResults.length });
1256
1540
  }
1257
1541
  } else {
1258
- if (stepCount > 1) {
1259
- tui.log.warning("Scan Agent stopped without actions.");
1260
- keepGoing = false;
1261
- } else {
1262
- }
1542
+ tui.log.success(t("commands.scan.completed"));
1543
+ keepGoing = false;
1263
1544
  }
1264
1545
  } catch (error) {
1265
- spinner.stop("Error");
1546
+ spinner.stop(t("common.error"));
1266
1547
  tui.log.error(error.message);
1267
1548
  keepGoing = false;
1268
1549
  }
@@ -1281,7 +1562,7 @@ async function callScanAgentApi(prompt, onChunk) {
1281
1562
  use_conversation: true,
1282
1563
  conversation_id: conversationId
1283
1564
  };
1284
- const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID3}/chat`;
1565
+ const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${getAgentId3()}/chat`;
1285
1566
  let fullMsg = "";
1286
1567
  let raw = {};
1287
1568
  FileLogger.log("SCAN", "Calling API", { promptLength: prompt.length });
@@ -1325,11 +1606,18 @@ import { Command as Command3 } from "commander";
1325
1606
  import fs6 from "fs";
1326
1607
  import path5 from "path";
1327
1608
  var AGENT_TYPE4 = "developer_agent";
1328
- var AGENT_ID4 = process.env.STACKSPOT_DEV_AGENT_ID || "01KEQCGJ65YENRA4QBXVN1YFFX";
1609
+ function getAgentId4(overrideId) {
1610
+ if (overrideId) return overrideId;
1611
+ const config = ConfigManager.getInstance().getConfig();
1612
+ if (config.agents?.dev) return config.agents.dev;
1613
+ if (process.env.STACKSPOT_DEV_AGENT_ID) return process.env.STACKSPOT_DEV_AGENT_ID;
1614
+ return "01KEQCGJ65YENRA4QBXVN1YFFX";
1615
+ }
1329
1616
  async function interactiveDeveloperAgent(options = {}) {
1330
1617
  FileLogger.init();
1331
1618
  tui.intro("\u{1F988} Shark Dev Agent");
1332
- if (AGENT_ID4 === "PENDING_CONFIGURATION") {
1619
+ const agentId = getAgentId4();
1620
+ if (agentId === "PENDING_CONFIGURATION") {
1333
1621
  tui.log.error("\u274C STACKSPOT_DEV_AGENT_ID not configured in .env");
1334
1622
  return;
1335
1623
  }
@@ -1525,7 +1813,7 @@ async function callDevAgentApi(prompt, onChunk) {
1525
1813
  stackspot_knowledge: false
1526
1814
  // Dev Agent focuses on project context
1527
1815
  };
1528
- const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${AGENT_ID4}/chat`;
1816
+ const url = `${STACKSPOT_AGENT_API_BASE}/v1/agent/${getAgentId4()}/chat`;
1529
1817
  let fullMsg = "";
1530
1818
  let raw = {};
1531
1819
  await sseClient.streamAgentResponse(url, payload, { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }, {
@@ -1565,7 +1853,11 @@ import path6 from "path";
1565
1853
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1566
1854
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1567
1855
  var AGENT_TYPE5 = "qa_agent";
1568
- var AGENT_ID5 = process.env.STACKSPOT_QA_AGENT_ID || "01KEQFJZ3Q3JER11NH22HEZX9X";
1856
+ function getAgentId5() {
1857
+ const config = ConfigManager.getInstance().getConfig();
1858
+ if (config.agents?.qa) return config.agents.qa;
1859
+ return process.env.STACKSPOT_QA_AGENT_ID || "01KEQFJZ3Q3JER11NH22HEZX9X";
1860
+ }
1569
1861
  var ChromeDevToolsClient = class {
1570
1862
  client = null;
1571
1863
  transport = null;
@@ -1609,7 +1901,8 @@ var ChromeDevToolsClient = class {
1609
1901
  };
1610
1902
  var mcpClient = new ChromeDevToolsClient();
1611
1903
  async function runQAAgent(options) {
1612
- if (!AGENT_ID5) {
1904
+ const agentId = getAgentId5();
1905
+ if (!agentId) {
1613
1906
  tui.log.error("\u274C STACKSPOT_QA_AGENT_ID not configured.");
1614
1907
  tui.log.info("Please run: set STACKSPOT_QA_AGENT_ID=<your-id>");
1615
1908
  return;
@@ -1655,7 +1948,7 @@ ${projectContext}
1655
1948
  try {
1656
1949
  const existingConversationId = await conversationManager.getConversationId(AGENT_TYPE5);
1657
1950
  await sseClient.streamAgentResponse(
1658
- `https://genai-inference-app.stackspot.com/v1/agent/${AGENT_ID5}/chat`,
1951
+ `https://genai-inference-app.stackspot.com/v1/agent/${getAgentId5()}/chat`,
1659
1952
  {
1660
1953
  user_prompt: userMessage,
1661
1954
  streaming: true,