shark-ai 0.2.0 → 0.2.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
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager,
4
+ FileLogger,
4
5
  colors,
5
6
  configCommand,
6
7
  loginCommand,
7
8
  tokenStorage,
8
9
  tui
9
- } from "../chunk-4UPBRJYA.js";
10
+ } from "../chunk-R3MIUNVD.js";
10
11
 
11
12
  // src/core/error/crash-handler.ts
12
13
  import fs from "fs";
@@ -267,41 +268,6 @@ var initCommand = new Command("init").description("Initialize a new Shark projec
267
268
  // src/core/api/stackspot-client.ts
268
269
  var STACKSPOT_AGENT_API_BASE = "https://genai-inference-app.stackspot.com";
269
270
 
270
- // src/core/debug/file-logger.ts
271
- import fs3 from "fs";
272
- import path3 from "path";
273
- var FileLogger = class {
274
- static logPath = path3.resolve(process.cwd(), "shark-debug.log");
275
- static enabled = true;
276
- // Enabled by default for this debugging session
277
- static init() {
278
- try {
279
- fs3.writeFileSync(this.logPath, `--- Shark CLI Debug Log Started at ${(/* @__PURE__ */ new Date()).toISOString()} ---
280
- `);
281
- } catch (e) {
282
- console.error("Failed to initialize debug log:", e);
283
- }
284
- }
285
- static log(category, message, data) {
286
- if (!this.enabled) return;
287
- try {
288
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
289
- let logEntry = `[${timestamp}] [${category.toUpperCase()}] ${message}
290
- `;
291
- if (data !== void 0) {
292
- if (typeof data === "object") {
293
- logEntry += JSON.stringify(data, null, 2) + "\n";
294
- } else {
295
- logEntry += String(data) + "\n";
296
- }
297
- }
298
- logEntry += "-".repeat(40) + "\n";
299
- fs3.appendFileSync(this.logPath, logEntry);
300
- } catch (e) {
301
- }
302
- }
303
- };
304
-
305
271
  // src/core/api/sse-client.ts
306
272
  var SSEClient = class {
307
273
  /**
@@ -760,17 +726,17 @@ async function interactiveBusinessAnalyst() {
760
726
  }
761
727
 
762
728
  // src/core/agents/specification-agent.ts
763
- import fs5 from "fs";
729
+ import fs4 from "fs";
764
730
 
765
731
  // src/core/agents/agent-tools.ts
766
- import fs4 from "fs";
767
- import path4 from "path";
732
+ import fs3 from "fs";
733
+ import path3 from "path";
768
734
  import fg from "fast-glob";
769
735
  function handleListFiles(dirPath) {
770
736
  try {
771
- const fullPath = path4.resolve(process.cwd(), dirPath);
772
- if (!fs4.existsSync(fullPath)) return `Error: Directory ${dirPath} does not exist.`;
773
- const items = fs4.readdirSync(fullPath, { withFileTypes: true });
737
+ const fullPath = path3.resolve(process.cwd(), dirPath);
738
+ if (!fs3.existsSync(fullPath)) return `Error: Directory ${dirPath} does not exist.`;
739
+ const items = fs3.readdirSync(fullPath, { withFileTypes: true });
774
740
  return items.map((item) => {
775
741
  return `${item.isDirectory() ? "[DIR]" : "[FILE]"} ${item.name}`;
776
742
  }).join("\n");
@@ -780,11 +746,11 @@ function handleListFiles(dirPath) {
780
746
  }
781
747
  function handleReadFile(filePath) {
782
748
  try {
783
- const fullPath = path4.resolve(process.cwd(), filePath);
784
- if (!fs4.existsSync(fullPath)) return `Error: File ${filePath} does not exist.`;
785
- const stats = fs4.statSync(fullPath);
749
+ const fullPath = path3.resolve(process.cwd(), filePath);
750
+ if (!fs3.existsSync(fullPath)) return `Error: File ${filePath} does not exist.`;
751
+ const stats = fs3.statSync(fullPath);
786
752
  if (stats.size > 100 * 1024) return `Error: File too large to read (${stats.size} bytes). Limit is 100KB.`;
787
- return fs4.readFileSync(fullPath, "utf-8");
753
+ return fs3.readFileSync(fullPath, "utf-8");
788
754
  } catch (e) {
789
755
  return `Error reading file: ${e.message}`;
790
756
  }
@@ -799,11 +765,11 @@ function handleSearchFile(pattern) {
799
765
  }
800
766
  }
801
767
  function startSmartReplace(filePath, newContent, targetContent, tui2) {
802
- if (!fs4.existsSync(filePath)) {
768
+ if (!fs3.existsSync(filePath)) {
803
769
  tui2.log.error(`\u274C File not found for modification: ${filePath}`);
804
770
  return false;
805
771
  }
806
- const currentFileContent = fs4.readFileSync(filePath, "utf-8");
772
+ const currentFileContent = fs3.readFileSync(filePath, "utf-8");
807
773
  if (!currentFileContent.includes(targetContent)) {
808
774
  tui2.log.error(`\u274C Target content not found in ${filePath}. Modification aborted.`);
809
775
  console.log(colors.dim("--- Target Content Expected ---"));
@@ -816,7 +782,7 @@ function startSmartReplace(filePath, newContent, targetContent, tui2) {
816
782
  return false;
817
783
  }
818
784
  const updatedContent = currentFileContent.replace(targetContent, newContent);
819
- fs4.writeFileSync(filePath, updatedContent);
785
+ fs3.writeFileSync(filePath, updatedContent);
820
786
  tui2.log.success(`\u2705 Smart Replace Applied: ${filePath}`);
821
787
  return true;
822
788
  }
@@ -877,21 +843,21 @@ async function interactiveSpecificationAgent(options = {}) {
877
843
  let briefingContent = "";
878
844
  let briefingPath = options.briefingPath;
879
845
  if (!briefingPath) {
880
- const files = fs5.readdirSync(process.cwd());
846
+ const files = fs4.readdirSync(process.cwd());
881
847
  const defaultBriefing = files.find((f) => f.endsWith("_briefing.md"));
882
848
  briefingPath = await tui.text({
883
849
  message: "Path to Briefing file (Leave empty to skip)",
884
850
  initialValue: defaultBriefing || "",
885
851
  placeholder: "e.g., todo-list_briefing.md",
886
852
  validate: (val) => {
887
- if (val && !fs5.existsSync(val)) return "File not found";
853
+ if (val && !fs4.existsSync(val)) return "File not found";
888
854
  }
889
855
  });
890
856
  }
891
857
  if (tui.isCancel(briefingPath)) return;
892
858
  if (briefingPath) {
893
859
  try {
894
- briefingContent = fs5.readFileSync(briefingPath, "utf-8");
860
+ briefingContent = fs4.readFileSync(briefingPath, "utf-8");
895
861
  tui.log.info(`Loaded briefing: ${colors.bold(briefingPath)}`);
896
862
  } catch (e) {
897
863
  tui.log.error(`Failed to read briefing: ${e}`);
@@ -980,7 +946,7 @@ ${result}
980
946
  if (action.path) {
981
947
  try {
982
948
  if (action.type === "create_file") {
983
- fs5.writeFileSync(action.path, action.content || "");
949
+ fs4.writeFileSync(action.path, action.content || "");
984
950
  tui.log.success(`\u2705 Created: ${action.path}`);
985
951
  executionResults += `[Action create_file(${action.path})]: Success
986
952
 
@@ -992,14 +958,14 @@ ${result}
992
958
 
993
959
  `;
994
960
  } else {
995
- fs5.writeFileSync(action.path, action.content || "");
961
+ fs4.writeFileSync(action.path, action.content || "");
996
962
  tui.log.success(`\u2705 Overwritten: ${action.path}`);
997
963
  executionResults += `[Action modify_file(${action.path})]: Success (Overwrite)
998
964
 
999
965
  `;
1000
966
  }
1001
967
  } else if (action.type === "delete_file") {
1002
- fs5.unlinkSync(action.path);
968
+ fs4.unlinkSync(action.path);
1003
969
  tui.log.success(`\u2705 Deleted: ${action.path}`);
1004
970
  executionResults += `[Action delete_file(${action.path})]: Success
1005
971
 
@@ -1119,8 +1085,8 @@ async function callSpecAgentApi(prompt, onChunk, agentId) {
1119
1085
  import { Command as Command2 } from "commander";
1120
1086
 
1121
1087
  // src/core/agents/scan-agent.ts
1122
- import fs6 from "fs";
1123
- import path5 from "path";
1088
+ import fs5 from "fs";
1089
+ import path4 from "path";
1124
1090
  var AGENT_TYPE3 = "scan_agent";
1125
1091
  var AGENT_ID3 = process.env.STACKSPOT_SCAN_AGENT_ID || "01KEQ9AHWB550J2244YBH3QATN";
1126
1092
  async function interactiveScanAgent(options = {}) {
@@ -1131,29 +1097,29 @@ async function interactiveScanAgent(options = {}) {
1131
1097
  const projectRoot = process.cwd();
1132
1098
  let outputFile;
1133
1099
  if (options.output) {
1134
- outputFile = path5.resolve(process.cwd(), options.output);
1100
+ outputFile = path4.resolve(process.cwd(), options.output);
1135
1101
  } else {
1136
- const outputDir = path5.resolve(projectRoot, "_sharkrc");
1137
- if (!fs6.existsSync(outputDir)) {
1138
- const stat = fs6.existsSync(outputDir) ? fs6.statSync(outputDir) : null;
1102
+ const outputDir = path4.resolve(projectRoot, "_sharkrc");
1103
+ if (!fs5.existsSync(outputDir)) {
1104
+ const stat = fs5.existsSync(outputDir) ? fs5.statSync(outputDir) : null;
1139
1105
  if (stat && stat.isFile()) {
1140
1106
  tui.log.warning(`Warning: '_sharkrc' exists as a file. Using '_bmad/project-context' instead to avoid overwrite.`);
1141
- const fallbackDir = path5.resolve(projectRoot, "_bmad/project-context");
1142
- if (!fs6.existsSync(fallbackDir)) fs6.mkdirSync(fallbackDir, { recursive: true });
1143
- outputFile = path5.join(fallbackDir, "project-context.md");
1107
+ const fallbackDir = path4.resolve(projectRoot, "_bmad/project-context");
1108
+ if (!fs5.existsSync(fallbackDir)) fs5.mkdirSync(fallbackDir, { recursive: true });
1109
+ outputFile = path4.join(fallbackDir, "project-context.md");
1144
1110
  } else {
1145
- fs6.mkdirSync(outputDir, { recursive: true });
1146
- outputFile = path5.join(outputDir, "project-context.md");
1111
+ fs5.mkdirSync(outputDir, { recursive: true });
1112
+ outputFile = path4.join(outputDir, "project-context.md");
1147
1113
  }
1148
1114
  } else {
1149
- fs6.mkdirSync(outputDir, { recursive: true });
1150
- outputFile = path5.join(outputDir, "project-context.md");
1115
+ fs5.mkdirSync(outputDir, { recursive: true });
1116
+ outputFile = path4.join(outputDir, "project-context.md");
1151
1117
  }
1152
1118
  }
1153
1119
  tui.log.info(`Scanning project at: ${colors.bold(projectRoot)}`);
1154
1120
  tui.log.info(`Output targeted at: ${colors.bold(outputFile)}`);
1155
1121
  tui.log.info(`Language: ${colors.bold(language)}`);
1156
- const configFileRelative = path5.relative(projectRoot, outputFile);
1122
+ const configFileRelative = path4.relative(projectRoot, outputFile);
1157
1123
  const superPrompt = `
1158
1124
  You are the **Scan Agent**, an expert software architect and analyst.
1159
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.
@@ -1247,22 +1213,22 @@ ${result}
1247
1213
 
1248
1214
  `;
1249
1215
  } else if (action.type === "create_file" || action.type === "modify_file") {
1250
- const resolvedActionPath = path5.resolve(action.path || "");
1251
- const resolvedTargetPath = path5.resolve(targetPath);
1216
+ const resolvedActionPath = path4.resolve(action.path || "");
1217
+ const resolvedTargetPath = path4.resolve(targetPath);
1252
1218
  let isTarget = resolvedActionPath === resolvedTargetPath;
1253
- if (!isTarget && path5.basename(action.path || "") === "project-context.md") {
1254
- tui.log.warning(`Agent targeted '${action.path}' but we enforce '${path5.relative(process.cwd(), targetPath)}'. Redirecting write.`);
1219
+ 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.`);
1255
1221
  isTarget = true;
1256
1222
  action.path = targetPath;
1257
1223
  }
1258
1224
  if (isTarget) {
1259
1225
  const finalPath = targetPath;
1260
1226
  if (action.type === "create_file") {
1261
- fs6.writeFileSync(finalPath, action.content || "");
1227
+ fs5.writeFileSync(finalPath, action.content || "");
1262
1228
  tui.log.success(`\u2705 Generated Context: ${finalPath}`);
1263
1229
  fileCreated = true;
1264
1230
  } else {
1265
- fs6.writeFileSync(finalPath, action.content || "");
1231
+ fs5.writeFileSync(finalPath, action.content || "");
1266
1232
  tui.log.success(`\u2705 Updated Context: ${finalPath}`);
1267
1233
  fileCreated = true;
1268
1234
  }
@@ -1356,8 +1322,8 @@ var scanCommand = new Command2("scan").description("Analyze the project and gene
1356
1322
  import { Command as Command3 } from "commander";
1357
1323
 
1358
1324
  // src/core/agents/developer-agent.ts
1359
- import fs7 from "fs";
1360
- import path6 from "path";
1325
+ import fs6 from "fs";
1326
+ import path5 from "path";
1361
1327
  var AGENT_TYPE4 = "developer_agent";
1362
1328
  var AGENT_ID4 = process.env.STACKSPOT_DEV_AGENT_ID || "01KEQCGJ65YENRA4QBXVN1YFFX";
1363
1329
  async function interactiveDeveloperAgent(options = {}) {
@@ -1369,12 +1335,12 @@ async function interactiveDeveloperAgent(options = {}) {
1369
1335
  }
1370
1336
  const projectRoot = process.cwd();
1371
1337
  let contextContent = "";
1372
- const defaultContextPath = path6.resolve(projectRoot, "_sharkrc", "project-context.md");
1373
- const specificContextPath = options.context ? path6.resolve(projectRoot, options.context) : defaultContextPath;
1374
- if (fs7.existsSync(specificContextPath)) {
1338
+ const defaultContextPath = path5.resolve(projectRoot, "_sharkrc", "project-context.md");
1339
+ const specificContextPath = options.context ? path5.resolve(projectRoot, options.context) : defaultContextPath;
1340
+ if (fs6.existsSync(specificContextPath)) {
1375
1341
  try {
1376
- contextContent = fs7.readFileSync(specificContextPath, "utf-8");
1377
- tui.log.info(`\u{1F4D8} Context loaded from: ${colors.dim(path6.relative(projectRoot, specificContextPath))}`);
1342
+ contextContent = fs6.readFileSync(specificContextPath, "utf-8");
1343
+ tui.log.info(`\u{1F4D8} Context loaded from: ${colors.dim(path5.relative(projectRoot, specificContextPath))}`);
1378
1344
  } catch (e) {
1379
1345
  tui.log.warning(`Failed to read context file: ${e}`);
1380
1346
  }
@@ -1466,11 +1432,11 @@ ${result}
1466
1432
  });
1467
1433
  if (confirm) {
1468
1434
  if (filePath) {
1469
- const targetPath = path6.resolve(projectRoot, filePath);
1470
- const dir = path6.dirname(targetPath);
1471
- if (!fs7.existsSync(dir)) fs7.mkdirSync(dir, { recursive: true });
1435
+ const targetPath = path5.resolve(projectRoot, filePath);
1436
+ const dir = path5.dirname(targetPath);
1437
+ if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
1472
1438
  if (isCreate) {
1473
- fs7.writeFileSync(targetPath, action.content || "");
1439
+ fs6.writeFileSync(targetPath, action.content || "");
1474
1440
  tui.log.success(`\u2705 Created: ${filePath}`);
1475
1441
  executionResults += `[Action create_file(${filePath})]: Success
1476
1442
 
@@ -1540,6 +1506,7 @@ User Reply: ${userReply}`;
1540
1506
  } catch (e) {
1541
1507
  spinner.stop("Error");
1542
1508
  tui.log.error(e.message);
1509
+ FileLogger.log("DEV_AGENT", "Main Loop Error", e);
1543
1510
  keepGoing = false;
1544
1511
  }
1545
1512
  }
@@ -1593,8 +1560,8 @@ var devCommand = new Command3("dev").description("Starts the Shark Developer Age
1593
1560
  import { Command as Command4 } from "commander";
1594
1561
 
1595
1562
  // src/core/agents/qa-agent.ts
1596
- import fs8 from "fs";
1597
- import path7 from "path";
1563
+ import fs7 from "fs";
1564
+ import path6 from "path";
1598
1565
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
1599
1566
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1600
1567
  var AGENT_TYPE5 = "qa_agent";
@@ -1658,9 +1625,9 @@ async function runQAAgent(options) {
1658
1625
  }
1659
1626
  let projectContext = "";
1660
1627
  try {
1661
- const contextPath = path7.join(process.cwd(), "_sharkrc", "project-context.md");
1662
- if (fs8.existsSync(contextPath)) {
1663
- projectContext = fs8.readFileSync(contextPath, "utf-8");
1628
+ const contextPath = path6.join(process.cwd(), "_sharkrc", "project-context.md");
1629
+ if (fs7.existsSync(contextPath)) {
1630
+ projectContext = fs7.readFileSync(contextPath, "utf-8");
1664
1631
  tui.log.info(`\u{1F4D8} Context loaded from: _sharkrc/project-context.md`);
1665
1632
  }
1666
1633
  } catch (e) {
@@ -1769,8 +1736,8 @@ ${projectContext}
1769
1736
  break;
1770
1737
  case "create_file":
1771
1738
  if (action.path && action.content) {
1772
- const fullPath = path7.resolve(process.cwd(), action.path);
1773
- fs8.writeFileSync(fullPath, action.content);
1739
+ const fullPath = path6.resolve(process.cwd(), action.path);
1740
+ fs7.writeFileSync(fullPath, action.content);
1774
1741
  tui.log.success(`File created: ${action.path}`);
1775
1742
  result = "File created successfully.";
1776
1743
  }