sharkbait 1.0.24 → 1.0.25

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.
Files changed (2) hide show
  1. package/dist/cli.js +181 -46
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -614,6 +614,8 @@ import { resolve, relative } from "path";
614
614
  var ALLOWED_COMMAND_PREFIXES = [
615
615
  "git",
616
616
  "gh",
617
+ "bd",
618
+ "dolt",
617
619
  "bun",
618
620
  "npm",
619
621
  "npx",
@@ -1404,10 +1406,24 @@ function getBdPath() {
1404
1406
  return "bd";
1405
1407
  }
1406
1408
  var BD_PATH = getBdPath();
1407
- function isBeadsInitialized(cwd) {
1409
+ function hasBeadsDir(cwd) {
1408
1410
  const dir = cwd || process.cwd();
1409
1411
  return existsSync3(join3(dir, ".beads"));
1410
1412
  }
1413
+ async function isBeadsFunctional() {
1414
+ if (!hasBeadsDir()) {
1415
+ return { functional: false, error: "No .beads directory found" };
1416
+ }
1417
+ try {
1418
+ const result = await exec([BD_PATH, "list", "--json"], { cwd: process.cwd() });
1419
+ if (result.exitCode === 0) {
1420
+ return { functional: true };
1421
+ }
1422
+ return { functional: false, error: result.stderr || "bd list failed" };
1423
+ } catch (err) {
1424
+ return { functional: false, error: err instanceof Error ? err.message : String(err) };
1425
+ }
1426
+ }
1411
1427
  async function isBdInstalled() {
1412
1428
  try {
1413
1429
  const result = await exec([BD_PATH, "--version"]);
@@ -1416,6 +1432,14 @@ async function isBdInstalled() {
1416
1432
  return false;
1417
1433
  }
1418
1434
  }
1435
+ function bdSupportsNoDb() {
1436
+ try {
1437
+ const help = execSync(`${BD_PATH} init --help 2>&1`, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
1438
+ return help.includes("--no-db");
1439
+ } catch {
1440
+ return false;
1441
+ }
1442
+ }
1419
1443
  var beadsTools = [
1420
1444
  {
1421
1445
  name: "beads_install",
@@ -1479,7 +1503,7 @@ var beadsTools = [
1479
1503
  },
1480
1504
  {
1481
1505
  name: "beads_status",
1482
- description: "Check if Beads (bd CLI) is installed and initialized in the current directory. ALWAYS call this before using other beads tools. If not installed, use the beads_install tool (never run_command).",
1506
+ description: "Check if Beads (bd CLI) is installed and functional in the current directory. ALWAYS call this before using other beads tools. If not installed, use the beads_install tool (never run_command). If beads is not functional, do NOT keep retrying — proceed with the user's task and inform them beads is unavailable.",
1483
1507
  parameters: {
1484
1508
  type: "object",
1485
1509
  properties: {},
@@ -1487,19 +1511,41 @@ var beadsTools = [
1487
1511
  },
1488
1512
  async execute() {
1489
1513
  const installed = await isBdInstalled();
1490
- const initialized = isBeadsInitialized();
1514
+ const dirExists = hasBeadsDir();
1515
+ if (!installed) {
1516
+ return {
1517
+ installed: false,
1518
+ initialized: false,
1519
+ ready: false,
1520
+ message: "Beads (bd) is not installed. Use the beads_install tool to install it.",
1521
+ bdPath: BD_PATH,
1522
+ proceedWithoutBeads: true
1523
+ };
1524
+ }
1525
+ if (!dirExists) {
1526
+ return {
1527
+ installed: true,
1528
+ initialized: false,
1529
+ ready: false,
1530
+ message: "Beads is installed but not initialized here. Use beads_init to initialize.",
1531
+ bdPath: BD_PATH
1532
+ };
1533
+ }
1534
+ const { functional, error } = await isBeadsFunctional();
1491
1535
  return {
1492
- installed,
1493
- initialized,
1494
- ready: installed && initialized,
1495
- message: !installed ? "Beads (bd) is not installed. Use the beads_install tool to install it." : !initialized ? "Beads is installed but not initialized here. Use beads_init to initialize." : "Beads is ready to use.",
1496
- bdPath: BD_PATH
1536
+ installed: true,
1537
+ initialized: dirExists,
1538
+ functional,
1539
+ ready: functional,
1540
+ message: functional ? "Beads is ready to use." : `Beads directory exists but is not functional: ${error}. Try beads_init to reinitialize, or proceed without beads.`,
1541
+ bdPath: BD_PATH,
1542
+ proceedWithoutBeads: !functional
1497
1543
  };
1498
1544
  }
1499
1545
  },
1500
1546
  {
1501
1547
  name: "beads_init",
1502
- description: "Initialize a Beads database in the current directory. Required before creating tasks.",
1548
+ description: "Initialize a Beads database in the current directory. Required before creating tasks. If beads was previously initialized but is broken, this will attempt to reinitialize. If initialization fails, proceed with the user's task without beads.",
1503
1549
  parameters: {
1504
1550
  type: "object",
1505
1551
  properties: {
@@ -1511,28 +1557,65 @@ var beadsTools = [
1511
1557
  required: []
1512
1558
  },
1513
1559
  async execute({ noDb }) {
1514
- if (isBeadsInitialized()) {
1560
+ if (!await isBdInstalled()) {
1515
1561
  return {
1516
- success: true,
1517
- message: "Beads is already initialized in this directory.",
1518
- alreadyInitialized: true
1562
+ success: false,
1563
+ message: "Beads (bd) is not installed. Use the beads_install tool to install it.",
1564
+ installed: false,
1565
+ proceedWithoutBeads: true
1519
1566
  };
1520
1567
  }
1521
- if (!await isBdInstalled()) {
1568
+ if (hasBeadsDir()) {
1569
+ const { functional } = await isBeadsFunctional();
1570
+ if (functional) {
1571
+ return {
1572
+ success: true,
1573
+ message: "Beads is already initialized and functional in this directory.",
1574
+ alreadyInitialized: true
1575
+ };
1576
+ }
1577
+ if (bdSupportsNoDb()) {
1578
+ try {
1579
+ const result = await exec([BD_PATH, "init", "--no-db"], { cwd: process.cwd() });
1580
+ if (result.exitCode === 0) {
1581
+ return {
1582
+ success: true,
1583
+ message: "Beads reinitialized in no-db mode (dolt was not reachable).",
1584
+ output: result.stdout.trim(),
1585
+ mode: "no-db"
1586
+ };
1587
+ }
1588
+ } catch {}
1589
+ }
1522
1590
  return {
1523
1591
  success: false,
1524
- message: "Beads (bd) is not installed. Use the beads_install tool to install it.",
1525
- installed: false
1592
+ message: "Beads directory exists but is not functional (dolt may not be running). Could not reinitialize. Proceed with the task without beads and inform the user.",
1593
+ proceedWithoutBeads: true
1526
1594
  };
1527
1595
  }
1528
1596
  const args = [BD_PATH, "init"];
1529
- if (noDb) {
1597
+ if (noDb && bdSupportsNoDb()) {
1530
1598
  args.push("--no-db");
1531
1599
  }
1532
1600
  try {
1533
1601
  const result = await exec(args, { cwd: process.cwd() });
1534
1602
  if (result.exitCode !== 0) {
1535
- throw new Error(result.stderr || result.stdout || "Failed to initialize beads");
1603
+ if (!noDb && bdSupportsNoDb()) {
1604
+ const fallback = await exec([BD_PATH, "init", "--no-db"], { cwd: process.cwd() });
1605
+ if (fallback.exitCode === 0) {
1606
+ return {
1607
+ success: true,
1608
+ message: "Beads initialized in no-db mode (dolt not available, using JSONL).",
1609
+ output: fallback.stdout.trim(),
1610
+ mode: "no-db"
1611
+ };
1612
+ }
1613
+ }
1614
+ return {
1615
+ success: false,
1616
+ message: `Failed to initialize beads: ${result.stderr || result.stdout}. Proceed with the task without beads.`,
1617
+ proceedWithoutBeads: true
1618
+ };
1536
1619
  }
1537
1620
  return {
1538
1621
  success: true,
@@ -1542,7 +1625,8 @@ var beadsTools = [
1542
1625
  } catch (error) {
1543
1626
  return {
1544
1627
  success: false,
1545
- message: `Failed to initialize beads: ${error}`
1628
+ message: `Failed to initialize beads: ${error}. Proceed with the task without beads.`,
1629
+ proceedWithoutBeads: true
1546
1630
  };
1547
1631
  }
1548
1632
  }
@@ -1559,17 +1643,17 @@ var beadsTools = [
1559
1643
  try {
1560
1644
  const result = await exec([BD_PATH, "ready", "--json"]);
1561
1645
  if (result.exitCode !== 0) {
1562
- throw new Error("Failed to get ready tasks");
1646
+ return { tasks: [], message: "Beads not functional. Proceed without beads.", proceedWithoutBeads: true };
1563
1647
  }
1564
1648
  return JSON.parse(result.stdout);
1565
- } catch (error) {
1566
- return { tasks: [], message: "Beads (bd) not available" };
1649
+ } catch {
1650
+ return { tasks: [], message: "Beads (bd) not available. Proceed without beads.", proceedWithoutBeads: true };
1567
1651
  }
1568
1652
  }
1569
1653
  },
1570
1654
  {
1571
1655
  name: "beads_create",
1572
- description: "Create a new task. Requires beads to be initialized first (use beads_status to check, beads_init to initialize).",
1656
+ description: "Create a new task. Requires beads to be initialized first (use beads_status to check, beads_init to initialize). If this fails, do NOT retry — proceed with the user's task without beads and inform them.",
1573
1657
  parameters: {
1574
1658
  type: "object",
1575
1659
  properties: {
@@ -1580,11 +1664,11 @@ var beadsTools = [
1580
1664
  required: ["title"]
1581
1665
  },
1582
1666
  async execute({ title, priority, parent }) {
1583
- if (!isBeadsInitialized()) {
1667
+ if (!hasBeadsDir()) {
1584
1668
  return {
1585
1669
  success: false,
1586
- error: "Beads is not initialized in this directory. Use beads_init first.",
1587
- hint: "Call beads_init to set up beads in this repository."
1670
+ error: "Beads is not initialized in this directory. Use beads_init first, or proceed without beads.",
1671
+ proceedWithoutBeads: true
1588
1672
  };
1589
1673
  }
1590
1674
  const args = [BD_PATH, "create", title];
@@ -1598,19 +1682,21 @@ var beadsTools = [
1598
1682
  try {
1599
1683
  const result = await exec(args, { cwd: process.cwd() });
1600
1684
  if (result.exitCode !== 0) {
1601
- if (result.stderr.includes("no beads database found")) {
1602
- return {
1603
- success: false,
1604
- error: "Beads database not found. Use beads_init to initialize.",
1605
- hint: "Run beads_init first, then retry creating the task."
1606
- };
1607
- }
1608
- throw new Error(result.stderr || "Failed to create task");
1685
+ const errorText = result.stderr || result.stdout || "Unknown error";
1686
+ return {
1687
+ success: false,
1688
+ error: `Failed to create beads task: ${errorText}. Proceed with the user's task without beads — do NOT retry.`,
1689
+ proceedWithoutBeads: true
1690
+ };
1609
1691
  }
1610
1692
  const jsonStart = result.stdout.indexOf("{");
1611
1693
  const jsonEnd = result.stdout.lastIndexOf("}");
1612
1694
  if (jsonStart === -1 || jsonEnd === -1) {
1613
- throw new Error(`No JSON in output: ${result.stdout}`);
1695
+ return {
1696
+ success: false,
1697
+ error: `No JSON in beads output: ${result.stdout}. Proceed without beads.`,
1698
+ proceedWithoutBeads: true
1699
+ };
1614
1700
  }
1615
1701
  const jsonStr = result.stdout.substring(jsonStart, jsonEnd + 1);
1616
1702
  const parsed = JSON.parse(jsonStr);
@@ -1618,7 +1704,8 @@ var beadsTools = [
1618
1704
  } catch (error) {
1619
1705
  return {
1620
1706
  success: false,
1621
- error: `Failed to create task: ${error}`
1707
+ error: `Failed to create beads task: ${error}. Proceed with the user's task without beads — do NOT retry.`,
1708
+ proceedWithoutBeads: true
1622
1709
  };
1623
1710
  }
1624
1711
  }
@@ -1637,11 +1724,11 @@ var beadsTools = [
1637
1724
  try {
1638
1725
  const result = await exec([BD_PATH, "show", id, "--json"]);
1639
1726
  if (result.exitCode !== 0) {
1640
- throw new Error(`Task not found: ${id}`);
1727
+ return { error: `Task not found: ${id}`, proceedWithoutBeads: true };
1641
1728
  }
1642
1729
  return JSON.parse(result.stdout);
1643
1730
  } catch (error) {
1644
- throw new Error(`Failed to get task: ${error}`);
1731
+ return { error: `Failed to get task: ${error}`, proceedWithoutBeads: true };
1645
1732
  }
1646
1733
  }
1647
1734
  },
@@ -1661,11 +1748,11 @@ var beadsTools = [
1661
1748
  try {
1662
1749
  const result = await exec([BD_PATH, "close", id, "-m", msg]);
1663
1750
  if (result.exitCode !== 0) {
1664
- throw new Error(`Failed to complete task: ${id}`);
1751
+ return { success: false, error: `Failed to complete task: ${id}`, proceedWithoutBeads: true };
1665
1752
  }
1666
1753
  return { success: true, id, message: msg };
1667
1754
  } catch (error) {
1668
- throw new Error(`Failed to complete task: ${error}`);
1755
+ return { success: false, error: `Failed to complete task: ${error}`, proceedWithoutBeads: true };
1669
1756
  }
1670
1757
  }
1671
1758
  },
@@ -1684,11 +1771,11 @@ var beadsTools = [
1684
1771
  try {
1685
1772
  const result = await exec([BD_PATH, "dep", "add", childId, parentId]);
1686
1773
  if (result.exitCode !== 0) {
1687
- throw new Error("Failed to add dependency");
1774
+ return { success: false, error: "Failed to add dependency", proceedWithoutBeads: true };
1688
1775
  }
1689
1776
  return { success: true, childId, parentId };
1690
1777
  } catch (error) {
1691
- throw new Error(`Failed to add dependency: ${error}`);
1778
+ return { success: false, error: `Failed to add dependency: ${error}`, proceedWithoutBeads: true };
1692
1779
  }
1693
1780
  }
1694
1781
  },
@@ -1720,7 +1807,7 @@ var beadsTools = [
1720
1807
  }
1721
1808
  return JSON.parse(result.stdout);
1722
1809
  } catch {
1723
- return { tasks: [], message: "Beads (bd) not available" };
1810
+ return { tasks: [], message: "Beads (bd) not available. Proceed without beads.", proceedWithoutBeads: true };
1724
1811
  }
1725
1812
  }
1726
1813
  }
@@ -3283,6 +3370,17 @@ var STALL_THRESHOLD2 = 3;
3283
3370
  var MAX_REPLANS2 = 2;
3284
3371
  var MAX_ITERATIONS = 50;
3285
3372
  var MAX_MESSAGES = 200;
3373
+ var BEADS_FAIL_LIMIT = 2;
3374
+ var BEADS_TOOL_NAMES = new Set([
3375
+ "beads_status",
3376
+ "beads_init",
3377
+ "beads_create",
3378
+ "beads_ready",
3379
+ "beads_show",
3380
+ "beads_done",
3381
+ "beads_list",
3382
+ "beads_add_dependency"
3383
+ ]);
3286
3384
 
3287
3385
  class AgentLoop {
3288
3386
  llm;
@@ -3324,6 +3422,8 @@ class AgentLoop {
3324
3422
  };
3325
3423
  let iteration = 0;
3326
3424
  let summaryRequested = false;
3425
+ let beadsFailCount = 0;
3426
+ let beadsAbandoned = false;
3327
3427
  while (iteration < MAX_ITERATIONS) {
3328
3428
  iteration++;
3329
3429
  log.debug(`Agent loop iteration ${iteration}`);
@@ -3423,6 +3523,12 @@ Revise your approach based on what we've learned.`
3423
3523
  tool_call_id: call.id,
3424
3524
  content: JSON.stringify(result)
3425
3525
  });
3526
+ if (BEADS_TOOL_NAMES.has(call.function.name)) {
3527
+ const resultObj = result;
3528
+ if (resultObj && (resultObj["proceedWithoutBeads"] || resultObj["success"] === false)) {
3529
+ beadsFailCount++;
3530
+ }
3531
+ }
3426
3532
  progressLedger.stepHistory.push({
3427
3533
  step: progressLedger.currentStep++,
3428
3534
  action: call.function.name,
@@ -3440,6 +3546,9 @@ Revise your approach based on what we've learned.`
3440
3546
  tool_call_id: call.id,
3441
3547
  content: JSON.stringify({ error: errorMsg })
3442
3548
  });
3549
+ if (BEADS_TOOL_NAMES.has(call.function.name)) {
3550
+ beadsFailCount++;
3551
+ }
3443
3552
  progressLedger.stepHistory.push({
3444
3553
  step: progressLedger.currentStep++,
3445
3554
  action: call.function.name,
@@ -3450,6 +3559,14 @@ Revise your approach based on what we've learned.`
3450
3559
  progressLedger.stallCount++;
3451
3560
  }
3452
3561
  }
3562
+ if (beadsFailCount >= BEADS_FAIL_LIMIT && !beadsAbandoned) {
3563
+ beadsAbandoned = true;
3564
+ this.messages.push({
3565
+ role: "system",
3566
+ content: "[SYSTEM] Beads has failed multiple times. STOP using ALL beads tools immediately. Proceed with the user's actual task WITHOUT beads. Do NOT call any beads_ tools again. Inform the user that beads is unavailable."
3567
+ });
3568
+ log.debug("Beads circuit breaker triggered — injected stop message");
3569
+ }
3453
3570
  this.boundMessages();
3454
3571
  if (progressLedger.stallCount >= STALL_THRESHOLD2) {
3455
3572
  if (taskLedger.replanCount >= MAX_REPLANS2) {
@@ -3485,10 +3602,19 @@ BEADS ARE YOUR MEMORY SYSTEM:
3485
3602
  - Use beads_create at the START of any coding task
3486
3603
  - Use beads_done when you've completed the work
3487
3604
 
3605
+ CRITICAL — BEADS FAILURE POLICY:
3606
+ If ANY beads tool fails or returns proceedWithoutBeads:
3607
+ - Do NOT retry the same beads operation more than ONCE
3608
+ - Do NOT try to troubleshoot, fix, or debug beads problems
3609
+ - Do NOT install dolt, restart services, or run bd commands via run_command
3610
+ - IMMEDIATELY proceed with the user's actual task
3611
+ - Inform the user beads is unavailable — their task will proceed without tracking
3612
+ - The user's task is ALWAYS more important than beads
3613
+
3488
3614
  Guidelines:
3489
3615
  1. Always read files before editing
3490
3616
  2. Make precise, minimal edits
3491
- 3. Create a Bead for EVERY code task
3617
+ 3. Create a Bead for EVERY code task (but proceed without it if beads fails)
3492
3618
  4. Ask for confirmation before destructive operations
3493
3619
  5. Explain your reasoning clearly
3494
3620
 
@@ -3784,6 +3910,15 @@ Platform: ${process.platform}
3784
3910
  **Beads (Task Tracking) Installation:**
3785
3911
  When the user asks to install Beads, use the \`beads_install\` tool. NEVER use run_command/shell to install beads.
3786
3912
  To check status, use \`beads_status\`. To initialize in a project, use \`beads_init\`.
3913
+
3914
+ **CRITICAL — Beads Failure Policy:**
3915
+ If ANY beads tool fails (beads_status, beads_init, beads_create, beads_done, etc.):
3916
+ - Do NOT retry the same beads operation more than ONCE
3917
+ - Do NOT try to troubleshoot or fix beads (e.g., installing dolt, restarting services, running bd commands via run_command)
3918
+ - IMMEDIATELY proceed with the user's actual task
3919
+ - Inform the user that beads is unavailable and their task will proceed without task tracking
3920
+ - The user's task is ALWAYS more important than beads working
3921
+ If a beads tool returns \`proceedWithoutBeads: true\`, that is your signal to stop all beads operations and focus on the task.
3787
3922
  `;
3788
3923
  var ORCHESTRATOR_PROMPT = `${BASE_PROMPT}
3789
3924
 
@@ -8887,7 +9022,7 @@ ${event.consolidated}`,
8887
9022
  }
8888
9023
 
8889
9024
  // src/version.ts
8890
- var VERSION = "1.0.24";
9025
+ var VERSION = "1.0.25";
8891
9026
 
8892
9027
  // src/agent/start-chat.ts
8893
9028
  async function startChat(options = {}) {
@@ -10171,7 +10306,7 @@ ${"━".repeat(60)}`);
10171
10306
  }
10172
10307
 
10173
10308
  // src/version.ts
10174
- var VERSION2 = "1.0.24";
10309
+ var VERSION2 = "1.0.25";
10175
10310
 
10176
10311
  // src/ui/logo.tsx
10177
10312
  import { Box as Box14, Text as Text14 } from "ink";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sharkbait",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "description": "AI-powered coding assistant for the command line. Uses OpenAI Responses API (not Chat). Autonomous agents, parallel code reviews, 36 tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",