agendex-cli 0.8.3 → 0.8.4

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 +103 -70
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
2
  var __create = Object.create;
4
3
  var __getProtoOf = Object.getPrototypeOf;
5
4
  var __defProp = Object.defineProperty;
@@ -45,7 +44,6 @@ var __export = (target, all) => {
45
44
  });
46
45
  };
47
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
48
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
49
47
 
50
48
  // ../../node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
51
49
  var require_picocolors = __commonJS((exports, module) => {
@@ -1478,66 +1476,101 @@ var continueIdeAdapter = {
1478
1476
  };
1479
1477
 
1480
1478
  // ../shared/src/adapters/cursor.ts
1481
- import { existsSync } from "node:fs";
1482
- import { stat as stat4 } from "node:fs/promises";
1479
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
1480
+ import { readFile as readFile4, stat as stat4 } from "node:fs/promises";
1483
1481
  import { homedir as homedir4 } from "node:os";
1484
- import { join as join4 } from "node:path";
1485
- function quoteIdentifier(name) {
1486
- return `"${name.replaceAll('"', '""')}"`;
1482
+ import { basename as basename3, join as join4 } from "node:path";
1483
+ var cursorProjectsDir = join4(homedir4(), ".cursor", "projects");
1484
+ function discoverCursorPlanDirs() {
1485
+ if (!existsSync(cursorProjectsDir))
1486
+ return [];
1487
+ const dirs = [];
1488
+ let entries;
1489
+ try {
1490
+ entries = readdirSync(cursorProjectsDir);
1491
+ } catch {
1492
+ return [];
1493
+ }
1494
+ for (const entry of entries) {
1495
+ const trustedFile = join4(cursorProjectsDir, entry, ".workspace-trusted");
1496
+ if (!existsSync(trustedFile))
1497
+ continue;
1498
+ try {
1499
+ const raw = JSON.parse(readFileSync(trustedFile, "utf-8"));
1500
+ if (!raw.workspacePath)
1501
+ continue;
1502
+ const plansDir2 = join4(raw.workspacePath, ".cursor", "plans");
1503
+ if (existsSync(plansDir2)) {
1504
+ dirs.push(plansDir2);
1505
+ }
1506
+ } catch {}
1507
+ }
1508
+ return dirs;
1509
+ }
1510
+ function extractTitle3(content, filename) {
1511
+ const match = content.match(/^#\s+(.+)/m);
1512
+ if (match?.[1])
1513
+ return match[1].replace(/^Plan:\s*/i, "").trim();
1514
+ return basename3(filename, ".plan.md").split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
1515
+ }
1516
+ function stripFrontmatter(raw) {
1517
+ const text = raw.replace(/^<!--\s*[\w-]+\s*-->\s*\n?/, "");
1518
+ const fmMatch = text.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
1519
+ if (!fmMatch)
1520
+ return { body: text.trim(), metadata: {} };
1521
+ const metadata = {};
1522
+ const fmBody = fmMatch[1] ?? "";
1523
+ const todoIdMatches = fmBody.match(/^\s+-\s+id:\s/gm);
1524
+ if (todoIdMatches) {
1525
+ metadata.todoCount = todoIdMatches.length;
1526
+ }
1527
+ const projectMatch = fmBody.match(/^isProject:\s*(.+)$/m);
1528
+ if (projectMatch?.[1]) {
1529
+ metadata.isProject = projectMatch[1].trim() === "true";
1530
+ }
1531
+ const body = text.slice(fmMatch[0].length).trim();
1532
+ return { body, metadata };
1533
+ }
1534
+ function workspaceFromPlanPath(filePath) {
1535
+ const normalized = filePath.replaceAll("\\", "/");
1536
+ const idx = normalized.indexOf("/.cursor/plans/");
1537
+ if (idx === -1)
1538
+ return;
1539
+ return filePath.slice(0, idx);
1487
1540
  }
1488
1541
  var cursorAdapter = {
1489
1542
  agent: "cursor",
1490
1543
  writable: false,
1491
1544
  getSearchPaths() {
1492
- return [join4(homedir4(), ".cursor", "ai-tracking")];
1545
+ return discoverCursorPlanDirs();
1493
1546
  },
1494
1547
  getWatchPaths() {
1495
- return [join4(homedir4(), ".cursor", "ai-tracking")];
1548
+ return discoverCursorPlanDirs();
1496
1549
  },
1497
1550
  matches(filePath) {
1498
- return filePath.endsWith(".db");
1551
+ return filePath.endsWith(".plan.md");
1499
1552
  },
1500
1553
  async parse(filePath) {
1501
- if (!existsSync(filePath))
1502
- return [];
1503
- let db = null;
1504
1554
  try {
1505
- const { default: SqliteDatabase } = await import("better-sqlite3");
1506
- db = new SqliteDatabase(filePath, { fileMustExist: true, readonly: true });
1507
- const tables = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all();
1508
- const plans = [];
1555
+ const raw = await readFile4(filePath, "utf-8");
1509
1556
  const stats = await stat4(filePath);
1510
- for (const table of tables) {
1511
- try {
1512
- const rows = db.prepare(`SELECT * FROM ${quoteIdentifier(table.name)} LIMIT 50`).all();
1513
- if (rows.length === 0)
1514
- continue;
1515
- const content = rows.map((row) => {
1516
- return Object.entries(row).map(([k, v]) => `**${k}**: ${String(v)}`).join(`
1517
- `);
1518
- }).join(`
1519
-
1520
- ---
1521
-
1522
- `);
1523
- plans.push({
1524
- id: hashPath(`${filePath}:${table.name}`),
1525
- agent: "cursor",
1526
- title: `Cursor: ${table.name}`,
1527
- content,
1528
- filePath,
1529
- format: "sqlite",
1530
- createdAt: stats.birthtime,
1531
- updatedAt: stats.mtime,
1532
- metadata: { table: table.name }
1533
- });
1534
- } catch {}
1535
- }
1536
- return plans;
1557
+ const { body, metadata } = stripFrontmatter(raw);
1558
+ return [
1559
+ {
1560
+ id: hashPath(filePath),
1561
+ agent: "cursor",
1562
+ title: extractTitle3(body, filePath),
1563
+ content: body,
1564
+ filePath,
1565
+ format: "md",
1566
+ createdAt: stats.birthtime,
1567
+ updatedAt: stats.mtime,
1568
+ workspace: workspaceFromPlanPath(filePath),
1569
+ metadata
1570
+ }
1571
+ ];
1537
1572
  } catch {
1538
1573
  return [];
1539
- } finally {
1540
- db?.close();
1541
1574
  }
1542
1575
  },
1543
1576
  async write() {
@@ -1546,10 +1579,10 @@ var cursorAdapter = {
1546
1579
  };
1547
1580
 
1548
1581
  // ../shared/src/adapters/oh-my-opencode.ts
1549
- import { existsSync as existsSync2, readdirSync, readFileSync } from "node:fs";
1550
- import { readdir, readFile as readFile4, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
1582
+ import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
1583
+ import { readdir, readFile as readFile5, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
1551
1584
  import { homedir as homedir5 } from "node:os";
1552
- import { basename as basename3, join as join5 } from "node:path";
1585
+ import { basename as basename4, join as join5 } from "node:path";
1553
1586
  var dataHome = process.env.XDG_DATA_HOME || join5(homedir5(), ".local", "share");
1554
1587
  var opencodeSessionDir = join5(dataHome, "opencode", "storage", "session");
1555
1588
  var cwdPlansDir = join5(process.cwd(), ".sisyphus", "plans");
@@ -1569,13 +1602,13 @@ function isSessionFile(filePath) {
1569
1602
  const root = normalizePath(opencodeSessionDir);
1570
1603
  return normalized.startsWith(`${root}/`) && normalized.endsWith(".json");
1571
1604
  }
1572
- function extractTitle3(content, filePath) {
1605
+ function extractTitle4(content, filePath) {
1573
1606
  const heading = content.match(/^\s{0,3}#{1,6}\s+(.+?)\s*$/m)?.[1];
1574
1607
  if (heading)
1575
1608
  return heading.replace(/^Plan:\s*/i, "").trim();
1576
- return basename3(filePath, ".md").split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
1609
+ return basename4(filePath, ".md").split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
1577
1610
  }
1578
- function workspaceFromPlanPath(filePath) {
1611
+ function workspaceFromPlanPath2(filePath) {
1579
1612
  const normalized = normalizePath(filePath);
1580
1613
  const lower = normalized.toLowerCase();
1581
1614
  const markerIndex = lower.lastIndexOf(PLAN_PATH_MARKER);
@@ -1602,14 +1635,14 @@ function discoverPlanDirectories() {
1602
1635
  if (!existsSync2(opencodeSessionDir))
1603
1636
  return Array.from(dirs);
1604
1637
  try {
1605
- const projectDirs = readdirSync(opencodeSessionDir, { withFileTypes: true });
1638
+ const projectDirs = readdirSync2(opencodeSessionDir, { withFileTypes: true });
1606
1639
  for (const projectDir of projectDirs) {
1607
1640
  if (!projectDir.isDirectory())
1608
1641
  continue;
1609
1642
  const projectPath = join5(opencodeSessionDir, projectDir.name);
1610
1643
  let sessionFiles = [];
1611
1644
  try {
1612
- sessionFiles = readdirSync(projectPath);
1645
+ sessionFiles = readdirSync2(projectPath);
1613
1646
  } catch {
1614
1647
  continue;
1615
1648
  }
@@ -1617,7 +1650,7 @@ function discoverPlanDirectories() {
1617
1650
  if (!file.endsWith(".json"))
1618
1651
  continue;
1619
1652
  try {
1620
- const raw = readFileSync(join5(projectPath, file), "utf-8");
1653
+ const raw = readFileSync2(join5(projectPath, file), "utf-8");
1621
1654
  const session = parseSessionMeta(raw);
1622
1655
  if (!session?.directory)
1623
1656
  continue;
@@ -1632,13 +1665,13 @@ function discoverPlanDirectories() {
1632
1665
  }
1633
1666
  async function parsePlanFile(filePath, workspace, metadata = {}) {
1634
1667
  try {
1635
- const content = await readFile4(filePath, "utf-8");
1668
+ const content = await readFile5(filePath, "utf-8");
1636
1669
  const stats = await stat5(filePath);
1637
1670
  return [
1638
1671
  {
1639
1672
  id: hashPath(filePath),
1640
1673
  agent: "oh-my-opencode",
1641
- title: extractTitle3(content, filePath),
1674
+ title: extractTitle4(content, filePath),
1642
1675
  content,
1643
1676
  filePath,
1644
1677
  format: "md",
@@ -1654,7 +1687,7 @@ async function parsePlanFile(filePath, workspace, metadata = {}) {
1654
1687
  }
1655
1688
  async function parseSessionFile(filePath) {
1656
1689
  try {
1657
- const raw = await readFile4(filePath, "utf-8");
1690
+ const raw = await readFile5(filePath, "utf-8");
1658
1691
  const session = parseSessionMeta(raw);
1659
1692
  if (!session?.directory)
1660
1693
  return [];
@@ -1694,7 +1727,7 @@ var ohMyOpencodeAdapter = {
1694
1727
  },
1695
1728
  async parse(filePath) {
1696
1729
  if (isPlanMarkdown(filePath)) {
1697
- return parsePlanFile(filePath, workspaceFromPlanPath(filePath), {
1730
+ return parsePlanFile(filePath, workspaceFromPlanPath2(filePath), {
1698
1731
  source: "plan-file"
1699
1732
  });
1700
1733
  }
@@ -2163,7 +2196,7 @@ function getActiveAdapters() {
2163
2196
  var activeAdapters = resolveAdapters(getDefaultAdapterIds());
2164
2197
  // ../shared/src/config.ts
2165
2198
  import { randomBytes } from "node:crypto";
2166
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
2199
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "node:fs";
2167
2200
  import { homedir as homedir7 } from "node:os";
2168
2201
  import { join as join7 } from "node:path";
2169
2202
 
@@ -2230,7 +2263,7 @@ function readStoredConfig() {
2230
2263
  if (!existsSync3(configPath))
2231
2264
  return null;
2232
2265
  try {
2233
- const raw = JSON.parse(readFileSync2(configPath, "utf-8"));
2266
+ const raw = JSON.parse(readFileSync3(configPath, "utf-8"));
2234
2267
  if (!raw || typeof raw !== "object")
2235
2268
  return null;
2236
2269
  return raw;
@@ -2352,8 +2385,8 @@ async function loadOrInitConfig(options = {}) {
2352
2385
  var CLI_DAEMON_HEARTBEAT_INTERVAL_MS = 30000;
2353
2386
  var CLI_DAEMON_STALE_AFTER_MS = CLI_DAEMON_HEARTBEAT_INTERVAL_MS * 3;
2354
2387
  // ../shared/src/services/plan-service.ts
2355
- import { existsSync as existsSync4, readdirSync as readdirSync2, statSync } from "node:fs";
2356
- import { lstat, mkdir, readdir as readdir2, readFile as readFile5, stat as stat6, writeFile as writeFile3 } from "node:fs/promises";
2388
+ import { existsSync as existsSync4, readdirSync as readdirSync3, statSync } from "node:fs";
2389
+ import { lstat, mkdir, readdir as readdir2, readFile as readFile6, stat as stat6, writeFile as writeFile3 } from "node:fs/promises";
2357
2390
  import { homedir as homedir8 } from "node:os";
2358
2391
  import { join as join8, resolve as resolve2, sep as sep2 } from "node:path";
2359
2392
  var USER_PLANS_DIR = join8(homedir8(), ".agendex", "plans");
@@ -2408,7 +2441,7 @@ function discoverProjectPlanDirs() {
2408
2441
  }
2409
2442
  let names;
2410
2443
  try {
2411
- names = readdirSync2(dir);
2444
+ names = readdirSync3(dir);
2412
2445
  } catch {
2413
2446
  return;
2414
2447
  }
@@ -2470,7 +2503,7 @@ async function scanUserPlans() {
2470
2503
  if (!file.endsWith(".md"))
2471
2504
  continue;
2472
2505
  try {
2473
- const content = await readFile5(file, "utf-8");
2506
+ const content = await readFile6(file, "utf-8");
2474
2507
  const stats = await stat6(file);
2475
2508
  let agent = "unknown";
2476
2509
  const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
@@ -2620,7 +2653,7 @@ import { request as httpsRequest } from "node:https";
2620
2653
  import { hostname as osHostname } from "node:os";
2621
2654
 
2622
2655
  // src/pid.ts
2623
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
2656
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
2624
2657
  import { homedir as homedir9, hostname } from "node:os";
2625
2658
  import { dirname, join as join10 } from "node:path";
2626
2659
  var pidPath = join10(homedir9(), ".agendex", "daemon.pid");
@@ -2636,7 +2669,7 @@ function writePid() {
2636
2669
  function readPidInfo() {
2637
2670
  if (!existsSync6(pidPath))
2638
2671
  return null;
2639
- const raw = readFileSync3(pidPath, "utf-8").trim();
2672
+ const raw = readFileSync4(pidPath, "utf-8").trim();
2640
2673
  const asNumber = Number(raw);
2641
2674
  if (Number.isFinite(asNumber) && asNumber > 0 && !raw.startsWith("{")) {
2642
2675
  return { pid: asNumber };
@@ -3249,13 +3282,13 @@ async function syncAll() {
3249
3282
  }
3250
3283
 
3251
3284
  // src/version.ts
3252
- import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
3285
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
3253
3286
  import { tmpdir } from "node:os";
3254
3287
  import { join as join11 } from "node:path";
3255
3288
  // package.json
3256
3289
  var package_default = {
3257
3290
  name: "agendex-cli",
3258
- version: "0.8.3",
3291
+ version: "0.8.4",
3259
3292
  description: "Agendex CLI for login, sync, and daemon workflows",
3260
3293
  homepage: "https://github.com/Tyru5/Agendex#readme",
3261
3294
  repository: {
@@ -3306,7 +3339,7 @@ function readCache(current) {
3306
3339
  try {
3307
3340
  if (!existsSync7(CACHE_FILE))
3308
3341
  return null;
3309
- const { result, ts } = JSON.parse(readFileSync4(CACHE_FILE, "utf8"));
3342
+ const { result, ts } = JSON.parse(readFileSync5(CACHE_FILE, "utf8"));
3310
3343
  if (Date.now() - ts > CACHE_TTL_MS)
3311
3344
  return null;
3312
3345
  return normalizeResult(result, current);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agendex-cli",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Agendex CLI for login, sync, and daemon workflows",
5
5
  "homepage": "https://github.com/Tyru5/Agendex#readme",
6
6
  "repository": {