@contextgraph/agent 0.4.25 → 0.4.26

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/index.js CHANGED
@@ -42,6 +42,7 @@ async function startCallbackServer() {
42
42
  if (url.pathname === "/callback") {
43
43
  const token = url.searchParams.get("token");
44
44
  const userId = url.searchParams.get("userId");
45
+ const email = url.searchParams.get("email");
45
46
  if (!token) {
46
47
  res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
47
48
  res.end(getErrorPage("Missing token parameter"));
@@ -53,7 +54,7 @@ async function startCallbackServer() {
53
54
  return;
54
55
  }
55
56
  if (callbackResolve) {
56
- callbackResolve({ token, userId });
57
+ callbackResolve({ token, userId, ...email ? { email } : {} });
57
58
  }
58
59
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
59
60
  res.end(getSuccessPage());
@@ -542,6 +543,7 @@ async function authenticateAgent(options = {}) {
542
543
  await saveCredentials({
543
544
  clerkToken: result.token,
544
545
  userId: result.userId,
546
+ ...result.email ? { email: result.email } : {},
545
547
  expiresAt,
546
548
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
547
549
  });
@@ -550,7 +552,8 @@ async function authenticateAgent(options = {}) {
550
552
  success: true,
551
553
  credentials: {
552
554
  token: result.token,
553
- userId: result.userId
555
+ userId: result.userId,
556
+ email: result.email
554
557
  }
555
558
  };
556
559
  } catch (error) {
@@ -1377,6 +1380,7 @@ async function fetchSkillsLibrary(options) {
1377
1380
  }
1378
1381
 
1379
1382
  // src/workspace-prep.ts
1383
+ import chalk from "chalk";
1380
1384
  var API_BASE_URL2 = "https://www.contextgraph.dev";
1381
1385
  async function fetchGitHubCredentials(authToken) {
1382
1386
  const response = await fetchWithRetry(`${API_BASE_URL2}/api/cli/credentials`, {
@@ -1441,15 +1445,15 @@ async function prepareWorkspace(repoUrl, options) {
1441
1445
  try {
1442
1446
  await rm(workspacePath, { recursive: true, force: true });
1443
1447
  } catch (error) {
1444
- console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);
1448
+ console.error(chalk.yellow(`Warning: Failed to cleanup workspace at ${workspacePath}:`), error);
1445
1449
  }
1446
1450
  };
1447
1451
  try {
1448
1452
  const cloneUrl = buildAuthenticatedUrl(repoUrl, credentials.githubToken, credentials.gitCredentialsUsername);
1449
- console.log(`\u{1F4C2} Cloning ${repoUrl}`);
1450
- console.log(` \u2192 ${workspacePath}`);
1453
+ console.log(`Cloning ${chalk.cyan(repoUrl)}`);
1454
+ console.log(chalk.dim(` ${workspacePath}`));
1451
1455
  await runGitCommand(["clone", cloneUrl, workspacePath]);
1452
- console.log(`\u2705 Repository cloned`);
1456
+ console.log(chalk.green("Repository cloned"));
1453
1457
  if (credentials.githubUsername) {
1454
1458
  await runGitCommand(["config", "user.name", credentials.githubUsername], workspacePath);
1455
1459
  }
@@ -1464,10 +1468,10 @@ async function prepareWorkspace(repoUrl, options) {
1464
1468
  );
1465
1469
  const branchExists = stdout.trim().length > 0;
1466
1470
  if (branchExists) {
1467
- console.log(`\u{1F33F} Checking out branch: ${branch}`);
1471
+ console.log(`Checking out branch: ${chalk.cyan(branch)}`);
1468
1472
  await runGitCommand(["checkout", branch], workspacePath);
1469
1473
  } else {
1470
- console.log(`\u{1F331} Creating new branch: ${branch}`);
1474
+ console.log(`Creating new branch: ${chalk.cyan(branch)}`);
1471
1475
  await runGitCommand(["checkout", "-b", branch], workspacePath);
1472
1476
  }
1473
1477
  }
@@ -1475,17 +1479,17 @@ async function prepareWorkspace(repoUrl, options) {
1475
1479
  const startingCommit = commitHash.trim();
1476
1480
  console.log("");
1477
1481
  if (skipSkills) {
1478
- console.log("\u{1F4DA} Skipping skill injection (--no-skills flag)");
1482
+ console.log(chalk.dim("Skipping skill injection (--no-skills flag)"));
1479
1483
  } else {
1480
1484
  try {
1481
1485
  const librarySkills = await fetchSkillsLibrary({ authToken, runId });
1482
1486
  if (librarySkills.length > 0) {
1483
1487
  await injectSkills(workspacePath, librarySkills);
1484
1488
  } else {
1485
- console.log("\u{1F4DA} No skills to inject (empty library)");
1489
+ console.log(chalk.dim("No skills to inject (empty library)"));
1486
1490
  }
1487
1491
  } catch (skillError) {
1488
- console.warn("\u26A0\uFE0F Skill injection failed (agent will continue):", skillError);
1492
+ console.warn(chalk.yellow("Skill injection failed (agent will continue):"), skillError);
1489
1493
  }
1490
1494
  }
1491
1495
  return { path: workspacePath, startingCommit, cleanup };
@@ -1527,7 +1531,9 @@ var package_default = {
1527
1531
  },
1528
1532
  dependencies: {
1529
1533
  "@anthropic-ai/claude-agent-sdk": "^0.1.50",
1534
+ chalk: "^5.6.2",
1530
1535
  commander: "^11.0.0",
1536
+ listr2: "^9.0.5",
1531
1537
  open: "^10.0.0"
1532
1538
  },
1533
1539
  devDependencies: {
@@ -1654,21 +1660,22 @@ var ApiClient = class {
1654
1660
  };
1655
1661
 
1656
1662
  // src/workspace-setup.ts
1663
+ import chalk2 from "chalk";
1657
1664
  var API_BASE_URL3 = "https://www.contextgraph.dev";
1658
1665
  async function setupWorkspaceForAction(actionId, options) {
1659
1666
  const { authToken, phase, startingCommit: startingCommitOverride, skipSkills } = options;
1660
1667
  let actionDetail = options.actionDetail;
1661
1668
  if (!actionDetail) {
1662
1669
  const apiClient2 = new ApiClient();
1663
- console.log(`Fetching action details for ${actionId}...`);
1670
+ console.log(chalk2.dim(`Fetching action details for ${actionId}...`));
1664
1671
  actionDetail = await apiClient2.getActionDetail(actionId);
1665
1672
  }
1666
1673
  const logTransport = new LogTransportService(API_BASE_URL3, authToken);
1667
- console.log(`[Log Streaming] Creating run for ${phase} phase...`);
1674
+ console.log(chalk2.dim(`[Log Streaming] Creating run for ${phase} phase...`));
1668
1675
  const runId = await logTransport.createRun(actionId, phase, {
1669
1676
  startingCommit: startingCommitOverride
1670
1677
  });
1671
- console.log(`[Log Streaming] Run created: ${runId}`);
1678
+ console.log(chalk2.dim(`[Log Streaming] Run created: ${runId}`));
1672
1679
  const repoUrl = actionDetail.resolved_repository_url || actionDetail.repository_url;
1673
1680
  const branch = actionDetail.resolved_branch || actionDetail.branch;
1674
1681
  let workspacePath;
@@ -1685,14 +1692,14 @@ async function setupWorkspaceForAction(actionId, options) {
1685
1692
  cleanup = workspace.cleanup;
1686
1693
  startingCommit = workspace.startingCommit;
1687
1694
  } else {
1688
- console.log(`\u{1F4C2} No repository configured - creating blank workspace`);
1695
+ console.log(chalk2.dim("No repository configured - creating blank workspace"));
1689
1696
  workspacePath = await mkdtemp2(join3(tmpdir2(), "cg-workspace-"));
1690
- console.log(` \u2192 ${workspacePath}`);
1697
+ console.log(chalk2.dim(` ${workspacePath}`));
1691
1698
  cleanup = async () => {
1692
1699
  try {
1693
1700
  await rm2(workspacePath, { recursive: true, force: true });
1694
1701
  } catch (error) {
1695
- console.error(`Warning: Failed to cleanup workspace at ${workspacePath}:`, error);
1702
+ console.error(chalk2.yellow(`Warning: Failed to cleanup workspace at ${workspacePath}:`), error);
1696
1703
  }
1697
1704
  };
1698
1705
  }
@@ -1706,15 +1713,16 @@ async function setupWorkspaceForAction(actionId, options) {
1706
1713
  }
1707
1714
 
1708
1715
  // src/workflows/prepare.ts
1716
+ import chalk3 from "chalk";
1709
1717
  var API_BASE_URL4 = "https://www.contextgraph.dev";
1710
1718
  async function runPrepare(actionId, options) {
1711
1719
  const credentials = await loadCredentials();
1712
1720
  if (!credentials) {
1713
- console.error("\u274C Not authenticated. Run authentication first.");
1721
+ console.error(chalk3.red("Not authenticated."), "Run authentication first.");
1714
1722
  process.exit(1);
1715
1723
  }
1716
1724
  if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {
1717
- console.error("\u274C Token expired. Re-authenticate to continue.");
1725
+ console.error(chalk3.red("Token expired."), "Re-authenticate to continue.");
1718
1726
  process.exit(1);
1719
1727
  }
1720
1728
  let runId = options?.runId;
@@ -1736,12 +1744,12 @@ async function runPrepare(actionId, options) {
1736
1744
  runId = setup.runId;
1737
1745
  logTransport = setup.logTransport;
1738
1746
  } else {
1739
- console.log(`[Log Streaming] Using pre-created run: ${runId}`);
1747
+ console.log(chalk3.dim(`[Log Streaming] Using pre-created run: ${runId}`));
1740
1748
  workspacePath = options?.cwd || process.cwd();
1741
1749
  logTransport = new LogTransportService(API_BASE_URL4, credentials.clerkToken, runId);
1742
1750
  }
1743
- console.log(`Fetching preparation instructions for action ${actionId}...
1744
- `);
1751
+ console.log(chalk3.dim(`Fetching preparation instructions for action ${actionId}...
1752
+ `));
1745
1753
  const response = await fetchWithRetry(
1746
1754
  `${API_BASE_URL4}/api/prompts/prepare`,
1747
1755
  {
@@ -1762,7 +1770,7 @@ ${errorText}`);
1762
1770
  await logTransport.updateRunState("preparing");
1763
1771
  heartbeatManager = new HeartbeatManager(API_BASE_URL4, credentials.clerkToken, runId);
1764
1772
  heartbeatManager.start();
1765
- console.log("[Log Streaming] Heartbeat started");
1773
+ console.log(chalk3.dim("[Log Streaming] Heartbeat started"));
1766
1774
  logBuffer = new LogBuffer(logTransport);
1767
1775
  logBuffer.start();
1768
1776
  console.log("Spawning Claude for preparation...\n");
@@ -1781,14 +1789,13 @@ ${errorText}`);
1781
1789
  cost: claudeResult.cost,
1782
1790
  usage: claudeResult.usage
1783
1791
  });
1784
- console.log("\n\u2705 Preparation complete");
1792
+ console.log("\n" + chalk3.green("Preparation complete"));
1785
1793
  } else {
1786
1794
  await logTransport.finishRun("error", {
1787
1795
  exitCode: claudeResult.exitCode,
1788
1796
  errorMessage: `Claude preparation failed with exit code ${claudeResult.exitCode}`
1789
1797
  });
1790
- console.error(`
1791
- \u274C Claude preparation failed with exit code ${claudeResult.exitCode}`);
1798
+ console.error("\n" + chalk3.red(`Claude preparation failed with exit code ${claudeResult.exitCode}`));
1792
1799
  process.exit(1);
1793
1800
  }
1794
1801
  } catch (error) {
@@ -1798,18 +1805,18 @@ ${errorText}`);
1798
1805
  errorMessage: error instanceof Error ? error.message : String(error)
1799
1806
  });
1800
1807
  } catch (stateError) {
1801
- console.error("[Log Streaming] Failed to update run state:", stateError);
1808
+ console.error(chalk3.dim("[Log Streaming] Failed to update run state:"), stateError);
1802
1809
  }
1803
1810
  }
1804
1811
  throw error;
1805
1812
  } finally {
1806
1813
  if (heartbeatManager) {
1807
1814
  heartbeatManager.stop();
1808
- console.log("[Log Streaming] Heartbeat stopped");
1815
+ console.log(chalk3.dim("[Log Streaming] Heartbeat stopped"));
1809
1816
  }
1810
1817
  if (logBuffer) {
1811
1818
  await logBuffer.stop();
1812
- console.log("[Log Streaming] Logs flushed");
1819
+ console.log(chalk3.dim("[Log Streaming] Logs flushed"));
1813
1820
  }
1814
1821
  if (cleanup) {
1815
1822
  await cleanup();
@@ -1818,15 +1825,16 @@ ${errorText}`);
1818
1825
  }
1819
1826
 
1820
1827
  // src/workflows/execute.ts
1828
+ import chalk4 from "chalk";
1821
1829
  var API_BASE_URL5 = "https://www.contextgraph.dev";
1822
1830
  async function runExecute(actionId, options) {
1823
1831
  const credentials = await loadCredentials();
1824
1832
  if (!credentials) {
1825
- console.error("\u274C Not authenticated. Run authentication first.");
1833
+ console.error(chalk4.red("Not authenticated."), "Run authentication first.");
1826
1834
  process.exit(1);
1827
1835
  }
1828
1836
  if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {
1829
- console.error("\u274C Token expired. Re-authenticate to continue.");
1837
+ console.error(chalk4.red("Token expired."), "Re-authenticate to continue.");
1830
1838
  process.exit(1);
1831
1839
  }
1832
1840
  let runId = options?.runId;
@@ -1848,12 +1856,12 @@ async function runExecute(actionId, options) {
1848
1856
  runId = setup.runId;
1849
1857
  logTransport = setup.logTransport;
1850
1858
  } else {
1851
- console.log(`[Log Streaming] Using pre-created run: ${runId}`);
1859
+ console.log(chalk4.dim(`[Log Streaming] Using pre-created run: ${runId}`));
1852
1860
  workspacePath = options?.cwd || process.cwd();
1853
1861
  logTransport = new LogTransportService(API_BASE_URL5, credentials.clerkToken, runId);
1854
1862
  }
1855
- console.log(`Fetching execution instructions for action ${actionId}...
1856
- `);
1863
+ console.log(chalk4.dim(`Fetching execution instructions for action ${actionId}...
1864
+ `));
1857
1865
  const response = await fetchWithRetry(
1858
1866
  `${API_BASE_URL5}/api/prompts/execute`,
1859
1867
  {
@@ -1874,7 +1882,7 @@ ${errorText}`);
1874
1882
  await logTransport.updateRunState("executing");
1875
1883
  heartbeatManager = new HeartbeatManager(API_BASE_URL5, credentials.clerkToken, runId);
1876
1884
  heartbeatManager.start();
1877
- console.log("[Log Streaming] Heartbeat started");
1885
+ console.log(chalk4.dim("[Log Streaming] Heartbeat started"));
1878
1886
  logBuffer = new LogBuffer(logTransport);
1879
1887
  logBuffer.start();
1880
1888
  console.log("Spawning Claude for execution...\n");
@@ -1893,7 +1901,7 @@ ${errorText}`);
1893
1901
  cost: claudeResult.cost,
1894
1902
  usage: claudeResult.usage
1895
1903
  });
1896
- console.log("\n\u2705 Execution complete");
1904
+ console.log("\n" + chalk4.green("Execution complete"));
1897
1905
  } else {
1898
1906
  await logTransport.finishRun("error", {
1899
1907
  exitCode: claudeResult.exitCode,
@@ -1908,18 +1916,18 @@ ${errorText}`);
1908
1916
  errorMessage: error instanceof Error ? error.message : String(error)
1909
1917
  });
1910
1918
  } catch (stateError) {
1911
- console.error("[Log Streaming] Failed to update run state:", stateError);
1919
+ console.error(chalk4.dim("[Log Streaming] Failed to update run state:"), stateError);
1912
1920
  }
1913
1921
  }
1914
1922
  throw error;
1915
1923
  } finally {
1916
1924
  if (heartbeatManager) {
1917
1925
  heartbeatManager.stop();
1918
- console.log("[Log Streaming] Heartbeat stopped");
1926
+ console.log(chalk4.dim("[Log Streaming] Heartbeat stopped"));
1919
1927
  }
1920
1928
  if (logBuffer) {
1921
1929
  await logBuffer.stop();
1922
- console.log("[Log Streaming] Logs flushed");
1930
+ console.log(chalk4.dim("[Log Streaming] Logs flushed"));
1923
1931
  }
1924
1932
  if (cleanup) {
1925
1933
  await cleanup();
@@ -1932,6 +1940,7 @@ import { randomUUID } from "crypto";
1932
1940
  import { readFileSync } from "fs";
1933
1941
  import { fileURLToPath } from "url";
1934
1942
  import { dirname, join as join4 } from "path";
1943
+ import chalk5 from "chalk";
1935
1944
  var __filename2 = fileURLToPath(import.meta.url);
1936
1945
  var __dirname2 = dirname(__filename2);
1937
1946
  var packageJson = JSON.parse(
@@ -1967,34 +1976,34 @@ function formatDuration(ms) {
1967
1976
  function printStatus() {
1968
1977
  const uptime = formatDuration(Date.now() - stats.startTime);
1969
1978
  const total = stats.prepared + stats.executed;
1970
- console.log(`Status: ${total} actions (${stats.prepared} prepared, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`);
1979
+ console.log(chalk5.dim(`Status: ${total} actions (${stats.prepared} prepared, ${stats.executed} executed, ${stats.errors} errors) | Uptime: ${uptime}`));
1971
1980
  }
1972
1981
  async function cleanupAndExit() {
1973
1982
  if (currentClaim && apiClient) {
1974
1983
  try {
1975
- console.log(`
1976
- \u{1F9F9} Releasing claim on action ${currentClaim.actionId}...`);
1984
+ console.log(chalk5.dim(`
1985
+ Releasing claim on action ${currentClaim.actionId}...`));
1977
1986
  await apiClient.releaseClaim({
1978
1987
  action_id: currentClaim.actionId,
1979
1988
  worker_id: currentClaim.workerId,
1980
1989
  claim_id: currentClaim.claimId
1981
1990
  });
1982
- console.log("\u2705 Claim released successfully");
1991
+ console.log(chalk5.dim("Claim released successfully"));
1983
1992
  } catch (error) {
1984
- console.error("\u26A0\uFE0F Failed to release claim:", error.message);
1993
+ console.error(chalk5.yellow("Failed to release claim:"), error.message);
1985
1994
  }
1986
1995
  }
1987
- console.log("\u{1F44B} Shutdown complete");
1996
+ console.log("Shutdown complete");
1988
1997
  process.exit(0);
1989
1998
  }
1990
1999
  function setupSignalHandlers() {
1991
2000
  process.on("SIGINT", async () => {
1992
- console.log("\n\n\u26A0\uFE0F Received SIGINT (Ctrl+C). Shutting down gracefully...");
2001
+ console.log(chalk5.yellow("\n\nReceived SIGINT (Ctrl+C). Shutting down gracefully..."));
1993
2002
  running = false;
1994
2003
  await cleanupAndExit();
1995
2004
  });
1996
2005
  process.on("SIGTERM", async () => {
1997
- console.log("\n\n\u26A0\uFE0F Received SIGTERM. Shutting down gracefully...");
2006
+ console.log(chalk5.yellow("\n\nReceived SIGTERM. Shutting down gracefully..."));
1998
2007
  running = false;
1999
2008
  await cleanupAndExit();
2000
2009
  });
@@ -2011,25 +2020,23 @@ async function runLocalAgent(options) {
2011
2020
  setupSignalHandlers();
2012
2021
  const credentials = await loadCredentials();
2013
2022
  if (!credentials) {
2014
- console.error("\u274C Not authenticated.");
2015
- console.error(" Set CONTEXTGRAPH_API_TOKEN environment variable or run `contextgraph-agent auth`");
2023
+ console.error(chalk5.red("Not authenticated."));
2024
+ console.error(` Set CONTEXTGRAPH_API_TOKEN environment variable or run ${chalk5.cyan("contextgraph-agent auth")}`);
2016
2025
  process.exit(1);
2017
2026
  }
2018
2027
  if (isExpired(credentials) || isTokenExpired(credentials.clerkToken)) {
2019
- console.error("\u274C Token expired. Run `contextgraph-agent auth` to re-authenticate.");
2028
+ console.error(chalk5.red("Token expired."), `Run ${chalk5.cyan("contextgraph-agent auth")} to re-authenticate.`);
2020
2029
  process.exit(1);
2021
2030
  }
2022
2031
  const usingApiToken = !!process.env.CONTEXTGRAPH_API_TOKEN;
2023
2032
  if (usingApiToken) {
2024
- console.log("\u{1F510} Authenticated via CONTEXTGRAPH_API_TOKEN");
2033
+ console.log(chalk5.dim("Authenticated via CONTEXTGRAPH_API_TOKEN"));
2025
2034
  }
2026
2035
  const workerId = randomUUID();
2027
- console.log(`\u{1F916} ContextGraph Agent v${packageJson.version}`);
2028
- console.log(`\u{1F477} Worker ID: ${workerId}`);
2029
- console.log(`\u{1F504} Starting continuous worker loop...
2030
- `);
2031
- console.log(`\u{1F4A1} Press Ctrl+C to gracefully shutdown and release any claimed work
2032
- `);
2036
+ console.log(`${chalk5.bold("ContextGraph Agent")} ${chalk5.dim(`v${packageJson.version}`)}`);
2037
+ console.log(chalk5.dim(`Worker ID: ${workerId}`));
2038
+ console.log("Starting continuous worker loop...\n");
2039
+ console.log(chalk5.dim("Press Ctrl+C to gracefully shutdown and release any claimed work\n"));
2033
2040
  let currentPollInterval = INITIAL_POLL_INTERVAL;
2034
2041
  let lastStatusTime = Date.now();
2035
2042
  let consecutiveApiErrors = 0;
@@ -2045,20 +2052,20 @@ async function runLocalAgent(options) {
2045
2052
  if (isRetryableError(err)) {
2046
2053
  consecutiveApiErrors++;
2047
2054
  if (consecutiveApiErrors === OUTAGE_WARNING_THRESHOLD) {
2048
- console.warn(`
2049
- \u26A0\uFE0F API appears to be experiencing an outage.`);
2050
- console.warn(` Will continue retrying indefinitely (every ${MAX_RETRY_DELAY / 1e3}s max).`);
2051
- console.warn(` Press Ctrl+C to stop.
2052
- `);
2055
+ console.warn(chalk5.yellow(`
2056
+ API appears to be experiencing an outage.`));
2057
+ console.warn(chalk5.yellow(` Will continue retrying indefinitely (every ${MAX_RETRY_DELAY / 1e3}s max).`));
2058
+ console.warn(chalk5.yellow(` Press Ctrl+C to stop.
2059
+ `));
2053
2060
  }
2054
2061
  if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {
2055
- console.warn(`\u26A0\uFE0F API error (attempt ${consecutiveApiErrors}): ${err.message}`);
2062
+ console.warn(chalk5.yellow(`API error (attempt ${consecutiveApiErrors}):`), err.message);
2056
2063
  } else if (consecutiveApiErrors % 10 === 0) {
2057
- console.warn(`\u26A0\uFE0F Still retrying... (attempt ${consecutiveApiErrors}, last error: ${err.message})`);
2064
+ console.warn(chalk5.yellow(`Still retrying... (attempt ${consecutiveApiErrors}, last error: ${err.message})`));
2058
2065
  }
2059
2066
  const delaySeconds = Math.round(apiRetryDelay / 1e3);
2060
2067
  if (consecutiveApiErrors < OUTAGE_WARNING_THRESHOLD) {
2061
- console.warn(` Retrying in ${delaySeconds}s...`);
2068
+ console.warn(chalk5.dim(` Retrying in ${delaySeconds}s...`));
2062
2069
  }
2063
2070
  await sleep(apiRetryDelay);
2064
2071
  apiRetryDelay = Math.min(apiRetryDelay * 2, MAX_RETRY_DELAY);
@@ -2089,7 +2096,7 @@ async function runLocalAgent(options) {
2089
2096
  } else if (!actionDetail.done) {
2090
2097
  phase = "execute";
2091
2098
  } else {
2092
- console.log(`\u23ED\uFE0F Skipping action "${actionDetail.title}" - already completed`);
2099
+ console.log(chalk5.dim(`Skipping action "${actionDetail.title}" - already completed`));
2093
2100
  if (currentClaim && apiClient) {
2094
2101
  try {
2095
2102
  await apiClient.releaseClaim({
@@ -2098,13 +2105,13 @@ async function runLocalAgent(options) {
2098
2105
  claim_id: currentClaim.claimId
2099
2106
  });
2100
2107
  } catch (releaseError) {
2101
- console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
2108
+ console.error(chalk5.yellow("Failed to release claim:"), releaseError.message);
2102
2109
  }
2103
2110
  }
2104
2111
  currentClaim = null;
2105
2112
  continue;
2106
2113
  }
2107
- console.log(`Working: ${actionDetail.title}`);
2114
+ console.log(`${chalk5.bold("Working:")} ${chalk5.cyan(actionDetail.title)}`);
2108
2115
  let workspacePath;
2109
2116
  let cleanup;
2110
2117
  let startingCommit;
@@ -2132,7 +2139,7 @@ async function runLocalAgent(options) {
2132
2139
  claim_id: currentClaim.claimId
2133
2140
  });
2134
2141
  } catch (releaseError) {
2135
- console.error("\u26A0\uFE0F Failed to release claim after preparation:", releaseError.message);
2142
+ console.error(chalk5.yellow("Failed to release claim after preparation:"), releaseError.message);
2136
2143
  }
2137
2144
  }
2138
2145
  currentClaim = null;
@@ -2141,10 +2148,10 @@ async function runLocalAgent(options) {
2141
2148
  try {
2142
2149
  await runExecute(actionDetail.id, { cwd: workspacePath, startingCommit, model: options?.forceModel, runId });
2143
2150
  stats.executed++;
2144
- console.log(`Completed: ${actionDetail.title}`);
2151
+ console.log(`${chalk5.bold.green("Completed:")} ${chalk5.cyan(actionDetail.title)}`);
2145
2152
  } catch (executeError) {
2146
2153
  stats.errors++;
2147
- console.error(`Error: ${executeError.message}. Continuing...`);
2154
+ console.error(chalk5.red("Error:"), `${executeError.message}. Continuing...`);
2148
2155
  } finally {
2149
2156
  if (currentClaim && apiClient) {
2150
2157
  try {
@@ -2154,25 +2161,25 @@ async function runLocalAgent(options) {
2154
2161
  claim_id: currentClaim.claimId
2155
2162
  });
2156
2163
  } catch (releaseError) {
2157
- console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
2164
+ console.error(chalk5.yellow("Failed to release claim:"), releaseError.message);
2158
2165
  }
2159
2166
  }
2160
2167
  currentClaim = null;
2161
2168
  }
2162
2169
  } catch (workspaceError) {
2163
2170
  stats.errors++;
2164
- console.error(`Error preparing workspace: ${workspaceError.message}. Continuing...`);
2171
+ console.error(chalk5.red("Error preparing workspace:"), `${workspaceError.message}. Continuing...`);
2165
2172
  if (currentClaim && apiClient) {
2166
2173
  try {
2167
- console.log(`\u{1F9F9} Releasing claim due to workspace error...`);
2174
+ console.log(chalk5.dim("Releasing claim due to workspace error..."));
2168
2175
  await apiClient.releaseClaim({
2169
2176
  action_id: currentClaim.actionId,
2170
2177
  worker_id: currentClaim.workerId,
2171
2178
  claim_id: currentClaim.claimId
2172
2179
  });
2173
- console.log("\u2705 Claim released");
2180
+ console.log(chalk5.dim("Claim released"));
2174
2181
  } catch (releaseError) {
2175
- console.error("\u26A0\uFE0F Failed to release claim:", releaseError.message);
2182
+ console.error(chalk5.yellow("Failed to release claim:"), releaseError.message);
2176
2183
  }
2177
2184
  }
2178
2185
  currentClaim = null;
@@ -2184,6 +2191,10 @@ async function runLocalAgent(options) {
2184
2191
  }
2185
2192
  }
2186
2193
 
2194
+ // src/workflows/setup.ts
2195
+ import chalk6 from "chalk";
2196
+ import { Listr } from "listr2";
2197
+
2187
2198
  // src/plugin-setup.ts
2188
2199
  import { spawn as spawn2 } from "child_process";
2189
2200
  var MARKETPLACE_SOURCE = "contextgraph/claude-code-plugin";
@@ -2252,81 +2263,131 @@ async function ensurePluginInstalled() {
2252
2263
 
2253
2264
  // src/workflows/setup.ts
2254
2265
  async function runSetup() {
2255
- console.log("\nWelcome to ContextGraph!\n");
2256
- console.log("This setup wizard will help you get started with ContextGraph.\n");
2257
- console.log("Step 1: Checking authentication...\n");
2258
- let needsAuth = false;
2259
- const existingCredentials = await loadCredentials();
2260
- if (!existingCredentials) {
2261
- console.log(" Not authenticated yet.");
2262
- needsAuth = true;
2263
- } else if (isExpired(existingCredentials) || isTokenExpired(existingCredentials.clerkToken)) {
2264
- console.log(" Your credentials have expired.");
2265
- needsAuth = true;
2266
- } else {
2267
- console.log(" Already authenticated");
2268
- console.log(` User ID: ${existingCredentials.userId}
2266
+ console.log(`
2267
+ ${chalk6.bold("Welcome to ContextGraph!")}`);
2268
+ console.log("This setup wizard will help you get started.\n");
2269
+ const tasks = new Listr(
2270
+ [
2271
+ {
2272
+ title: "Checking authentication",
2273
+ task: async (ctx2, task) => {
2274
+ const creds = await loadCredentials();
2275
+ if (!creds) {
2276
+ ctx2.needsAuth = true;
2277
+ } else if (isExpired(creds) || isTokenExpired(creds.clerkToken)) {
2278
+ ctx2.needsAuth = true;
2279
+ } else {
2280
+ ctx2.needsAuth = false;
2281
+ ctx2.userId = creds.userId;
2282
+ ctx2.displayName = creds.email ?? creds.userId;
2283
+ task.title = `Checking authentication \u2014 logged in as ${chalk6.cyan(ctx2.displayName)}`;
2284
+ }
2285
+ }
2286
+ },
2287
+ {
2288
+ title: "Authenticating with ContextGraph",
2289
+ skip: (ctx2) => !ctx2.needsAuth ? "Already authenticated" : false,
2290
+ task: async (ctx2, task) => {
2291
+ task.output = "Waiting for browser...";
2292
+ const result = await authenticateAgent();
2293
+ if (!result.success) {
2294
+ throw new Error("Authentication failed: " + result.error);
2295
+ }
2296
+ ctx2.userId = result.credentials.userId;
2297
+ ctx2.displayName = result.credentials.email ?? result.credentials.userId;
2298
+ task.title = `Authenticated as ${chalk6.cyan(ctx2.displayName)}`;
2299
+ },
2300
+ options: { bottomBar: Infinity }
2301
+ },
2302
+ {
2303
+ title: "Checking for Claude Code",
2304
+ task: async (ctx2, task) => {
2305
+ ctx2.hasClaudeCode = await isClaudeCodeAvailable();
2306
+ task.title = ctx2.hasClaudeCode ? "Checking for Claude Code \u2014 detected" : "Checking for Claude Code \u2014 not found";
2307
+ }
2308
+ },
2309
+ {
2310
+ title: "Installing ContextGraph plugin",
2311
+ skip: (ctx2) => !ctx2.hasClaudeCode ? "Claude Code not detected" : false,
2312
+ task: async (ctx2, task) => {
2313
+ try {
2314
+ if (await isPluginInstalled()) {
2315
+ ctx2.pluginInstalled = true;
2316
+ task.title = "ContextGraph plugin already installed";
2317
+ } else {
2318
+ await ensurePluginInstalled();
2319
+ ctx2.pluginInstalled = true;
2320
+ task.title = "ContextGraph plugin installed";
2321
+ }
2322
+ } catch {
2323
+ ctx2.pluginInstalled = false;
2324
+ task.skip("Could not install automatically \u2014 see manual instructions below");
2325
+ }
2326
+ }
2327
+ }
2328
+ ],
2329
+ {
2330
+ ctx: { needsAuth: false, userId: null, displayName: null, hasClaudeCode: false, pluginInstalled: false },
2331
+ rendererOptions: { collapseErrors: false }
2332
+ }
2333
+ );
2334
+ const ctx = await tasks.run();
2335
+ console.log("");
2336
+ if (ctx.hasClaudeCode) {
2337
+ if (!ctx.pluginInstalled) {
2338
+ console.log(chalk6.yellow("Plugin could not be installed automatically."));
2339
+ console.log("You can install it manually with:\n");
2340
+ console.log(` ${chalk6.dim("$")} claude plugin marketplace add contextgraph/claude-code-plugin`);
2341
+ console.log(` ${chalk6.dim("$")} claude plugin install contextgraph
2269
2342
  `);
2270
- }
2271
- if (needsAuth) {
2272
- console.log("Step 2: Authenticating with ContextGraph...\n");
2273
- const result = await authenticateAgent();
2274
- if (!result.success) {
2275
- throw new Error("Authentication failed: " + result.error);
2276
2343
  }
2277
- console.log("\n Authentication successful!");
2278
- console.log(` User ID: ${result.credentials.userId}
2344
+ console.log(chalk6.bold.green("Setup complete!") + " You're ready to go.\n");
2345
+ console.log(`There are three ways to work with ContextGraph:
2279
2346
  `);
2347
+ console.log(chalk6.bold("1. Run the ContextGraph agent"));
2348
+ console.log(" Wraps Claude Code and automatically prepares and executes");
2349
+ console.log(" actions for you in your codebase.\n");
2350
+ console.log(` ${chalk6.cyan("npx @contextgraph/agent run")}
2351
+ `);
2352
+ console.log(chalk6.bold("2. Use ContextGraph directly via Claude Code"));
2353
+ console.log(" Open Claude Code (or restart if already running) and interact");
2354
+ console.log(" with your action graph through the MCP tools.\n");
2355
+ console.log(chalk6.dim(" Examples:"));
2356
+ console.log(chalk6.dim(' "Create an action plan for implementing user auth"'));
2357
+ console.log(chalk6.dim(' "Show me my action tree"'));
2358
+ console.log(chalk6.dim(' "What should I work on next?"'));
2359
+ console.log(chalk6.dim(' "Capture this discussion as an action with sub-tasks"'));
2360
+ console.log("");
2361
+ console.log(chalk6.bold("3. Integrate the MCP server into other platforms"));
2362
+ console.log(" Add the ContextGraph MCP server to any compatible tool.\n");
2363
+ console.log(` MCP Server URL: ${chalk6.cyan("https://mcp.contextgraph.dev")}
2364
+ `);
2365
+ console.log(chalk6.dim(" Works with: Cursor, Claude.ai, ChatGPT, Codex CLI, Windsurf,"));
2366
+ console.log(chalk6.dim(" and any other MCP-compatible client."));
2367
+ console.log("");
2368
+ console.log(` Web dashboard: ${chalk6.cyan("https://contextgraph.dev")}`);
2280
2369
  } else {
2281
- console.log("Step 2: Already authenticated, skipping.\n");
2282
- }
2283
- console.log("Step 3: Checking for Claude Code...\n");
2284
- const hasClaudeCode = await isClaudeCodeAvailable();
2285
- if (hasClaudeCode) {
2286
- console.log(" Claude Code detected!\n");
2287
- console.log("Step 4: Installing ContextGraph plugin...\n");
2288
- try {
2289
- if (await isPluginInstalled()) {
2290
- console.log(" ContextGraph plugin is already installed.\n");
2291
- } else {
2292
- await ensurePluginInstalled();
2293
- console.log("");
2294
- }
2295
- } catch (error) {
2296
- console.error(" Could not install plugin automatically.");
2297
- console.error(" You can install it manually with:");
2298
- console.error(" claude plugin marketplace add contextgraph/claude-code-plugin");
2299
- console.error(" claude plugin install contextgraph\n");
2300
- }
2301
- console.log("Setup complete! You're ready to go.\n");
2302
- console.log("Next steps:\n");
2303
- console.log(" 1. Open Claude Code (or restart if already running)");
2304
- console.log(" 2. Ask Claude to help you plan \u2014 it has access to your action graph\n");
2305
- console.log(" Examples:");
2306
- console.log(' "Create an action plan for implementing user auth"');
2307
- console.log(' "Show me my action tree"');
2308
- console.log(' "What should I work on next?"\n');
2309
- console.log(" Run the autonomous agent: npx @contextgraph/agent run");
2310
- console.log(" Web dashboard: https://contextgraph.dev");
2311
- } else {
2312
- console.log(" Claude Code not detected.\n");
2313
2370
  console.log("You have a few options:\n");
2314
- console.log("Option 1: Install Claude Code");
2315
- console.log(" Visit: https://claude.ai/download");
2316
- console.log(" Then run this setup again: npx @contextgraph/agent@latest setup\n");
2317
- console.log("Option 2: Use ContextGraph MCP server with other editors");
2371
+ console.log(chalk6.bold("Option 1: Install Claude Code"));
2372
+ console.log(` Visit: ${chalk6.cyan("https://claude.ai/download")}`);
2373
+ console.log(` Then run this setup again: ${chalk6.cyan("npx @contextgraph/agent@latest setup")}
2374
+ `);
2375
+ console.log(chalk6.bold("Option 2: Use ContextGraph MCP server with other editors"));
2318
2376
  console.log(" ContextGraph works with any MCP-compatible editor!\n");
2319
2377
  console.log(" To add the ContextGraph MCP server to your editor:");
2320
- console.log(" - Cursor: See https://docs.cursor.com/advanced/mcp");
2321
- console.log(" - Windsurf: See https://docs.windsurf.ai/mcp");
2322
- console.log(" - Other: See https://modelcontextprotocol.io/clients\n");
2378
+ console.log(` - Cursor: See ${chalk6.cyan("https://docs.cursor.com/advanced/mcp")}`);
2379
+ console.log(` - Windsurf: See ${chalk6.cyan("https://docs.windsurf.ai/mcp")}`);
2380
+ console.log(` - Other: See ${chalk6.cyan("https://modelcontextprotocol.io/clients")}
2381
+ `);
2323
2382
  console.log(" MCP Server URL:");
2324
- console.log(" https://mcp.contextgraph.dev\n");
2325
- console.log("Option 3: Use the agent CLI directly");
2326
- console.log(" Run autonomous agent: npx @contextgraph/agent run");
2327
- console.log(" Execute specific action: npx @contextgraph/agent execute <action-id>");
2328
- console.log(" Prepare an action: npx @contextgraph/agent prepare <action-id>\n");
2329
- console.log("Authentication complete! Visit https://contextgraph.dev to get started!");
2383
+ console.log(` ${chalk6.cyan("https://mcp.contextgraph.dev")}
2384
+ `);
2385
+ console.log(chalk6.bold("Option 3: Use the agent CLI directly"));
2386
+ console.log(` Run autonomous agent: ${chalk6.cyan("npx @contextgraph/agent run")}`);
2387
+ console.log(` Execute specific action: ${chalk6.cyan("npx @contextgraph/agent execute <action-id>")}`);
2388
+ console.log(` Prepare an action: ${chalk6.cyan("npx @contextgraph/agent prepare <action-id>")}
2389
+ `);
2390
+ console.log(`Authentication complete! Visit ${chalk6.cyan("https://contextgraph.dev")} to get started!`);
2330
2391
  }
2331
2392
  console.log("");
2332
2393
  }