@versatly/workgraph 1.1.0 → 1.3.0

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.
@@ -3,13 +3,16 @@ import {
3
3
  allClaims,
4
4
  append,
5
5
  checkpoint,
6
+ claim,
6
7
  create,
7
8
  createRun,
8
9
  createThread,
10
+ done,
9
11
  historyOf,
10
12
  keywordSearch,
11
13
  list,
12
14
  listReadyThreads,
15
+ listReadyThreadsInSpace,
13
16
  listRuns,
14
17
  listTypes,
15
18
  loadPolicyRegistry,
@@ -23,7 +26,7 @@ import {
23
26
  saveRegistry,
24
27
  stop,
25
28
  update
26
- } from "./chunk-OTSECVE5.js";
29
+ } from "./chunk-BJVBE7F4.js";
27
30
 
28
31
  // src/workspace.ts
29
32
  var workspace_exports = {};
@@ -300,7 +303,7 @@ function renderCommandCenter(input) {
300
303
  const claimsSection = [
301
304
  "## Active Claims",
302
305
  "",
303
- ...input.claims.length > 0 ? input.claims.map((claim) => `- ${claim.owner} -> \`${claim.target}\``) : ["- None"],
306
+ ...input.claims.length > 0 ? input.claims.map((claim2) => `- ${claim2.owner} -> \`${claim2.target}\``) : ["- None"],
304
307
  ""
305
308
  ];
306
309
  const blockedSection = [
@@ -360,8 +363,7 @@ function writeSkill(workspacePath, title, body, actor, options = {}) {
360
363
  owner: options.owner ?? actor,
361
364
  version: options.version ?? "0.1.0",
362
365
  status,
363
- distribution: options.distribution ?? "tailscale-shared-vault",
364
- tailscale_path: options.tailscalePath,
366
+ distribution: options.distribution ?? "shared-vault",
365
367
  reviewers: options.reviewers ?? [],
366
368
  depends_on: options.dependsOn ?? [],
367
369
  tags: options.tags ?? []
@@ -376,8 +378,7 @@ function writeSkill(workspacePath, title, body, actor, options = {}) {
376
378
  owner: options.owner ?? existing.fields.owner ?? actor,
377
379
  version: options.version ?? existing.fields.version ?? "0.1.0",
378
380
  status,
379
- distribution: options.distribution ?? existing.fields.distribution ?? "tailscale-shared-vault",
380
- tailscale_path: options.tailscalePath ?? existing.fields.tailscale_path,
381
+ distribution: options.distribution ?? existing.fields.distribution ?? "shared-vault",
381
382
  reviewers: options.reviewers ?? existing.fields.reviewers ?? [],
382
383
  depends_on: options.dependsOn ?? existing.fields.depends_on ?? [],
383
384
  tags: options.tags ?? existing.fields.tags ?? []
@@ -1610,6 +1611,311 @@ function supportedIntegrationList() {
1610
1611
  return Object.keys(INTEGRATIONS).sort().join(", ");
1611
1612
  }
1612
1613
 
1614
+ // src/swarm.ts
1615
+ var swarm_exports = {};
1616
+ __export(swarm_exports, {
1617
+ createPlanTemplate: () => createPlanTemplate,
1618
+ deployPlan: () => deployPlan,
1619
+ getSwarmStatus: () => getSwarmStatus,
1620
+ synthesize: () => synthesize,
1621
+ validatePlan: () => validatePlan,
1622
+ workerClaim: () => workerClaim,
1623
+ workerComplete: () => workerComplete,
1624
+ workerLoop: () => workerLoop
1625
+ });
1626
+ import * as fs7 from "fs";
1627
+ import * as path7 from "path";
1628
+ function createPlanTemplate(goal) {
1629
+ return {
1630
+ goal,
1631
+ tasks: [],
1632
+ phases: [],
1633
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1634
+ estimatedTotalMinutes: 0
1635
+ };
1636
+ }
1637
+ function validatePlan(plan) {
1638
+ const errors = [];
1639
+ if (!plan.goal.title) errors.push("Goal title is required");
1640
+ if (plan.tasks.length === 0) errors.push("Plan has no tasks");
1641
+ if (plan.tasks.length > (plan.goal.maxTasks ?? 1e3)) {
1642
+ errors.push(`Plan has ${plan.tasks.length} tasks, exceeds max ${plan.goal.maxTasks ?? 1e3}`);
1643
+ }
1644
+ const taskTitles = new Set(plan.tasks.map((t) => t.title));
1645
+ for (const task of plan.tasks) {
1646
+ for (const dep of task.dependsOn ?? []) {
1647
+ if (!taskTitles.has(dep)) {
1648
+ errors.push(`Task "${task.title}" depends on unknown task "${dep}"`);
1649
+ }
1650
+ }
1651
+ }
1652
+ const visited = /* @__PURE__ */ new Set();
1653
+ const stack = /* @__PURE__ */ new Set();
1654
+ const depMap = /* @__PURE__ */ new Map();
1655
+ for (const task of plan.tasks) {
1656
+ depMap.set(task.title, task.dependsOn ?? []);
1657
+ }
1658
+ function hasCycle(node) {
1659
+ if (stack.has(node)) return true;
1660
+ if (visited.has(node)) return false;
1661
+ visited.add(node);
1662
+ stack.add(node);
1663
+ for (const dep of depMap.get(node) ?? []) {
1664
+ if (hasCycle(dep)) return true;
1665
+ }
1666
+ stack.delete(node);
1667
+ return false;
1668
+ }
1669
+ for (const task of plan.tasks) {
1670
+ visited.clear();
1671
+ stack.clear();
1672
+ if (hasCycle(task.title)) {
1673
+ errors.push(`Circular dependency detected involving "${task.title}"`);
1674
+ break;
1675
+ }
1676
+ }
1677
+ for (const phase of plan.phases) {
1678
+ for (const idx of phase.taskIndices) {
1679
+ if (idx < 0 || idx >= plan.tasks.length) {
1680
+ errors.push(`Phase "${phase.name}" references invalid task index ${idx}`);
1681
+ }
1682
+ }
1683
+ }
1684
+ return { valid: errors.length === 0, errors };
1685
+ }
1686
+ function deployPlan(workspacePath, plan, actor) {
1687
+ const validation = validatePlan(plan);
1688
+ if (!validation.valid) {
1689
+ throw new Error(`Invalid plan: ${validation.errors.join("; ")}`);
1690
+ }
1691
+ const spaceSlug = slugify(`swarm-${plan.goal.title}`);
1692
+ const spacePath = path7.join("spaces", `${spaceSlug}.md`);
1693
+ const spaceFullPath = path7.join(workspacePath, spacePath);
1694
+ if (!fs7.existsSync(spaceFullPath)) {
1695
+ const spaceDir = path7.join(workspacePath, "spaces");
1696
+ fs7.mkdirSync(spaceDir, { recursive: true });
1697
+ const spaceFrontmatter = [
1698
+ "---",
1699
+ `title: "Swarm: ${plan.goal.title}"`,
1700
+ `status: active`,
1701
+ `created: '${(/* @__PURE__ */ new Date()).toISOString()}'`,
1702
+ `updated: '${(/* @__PURE__ */ new Date()).toISOString()}'`,
1703
+ "---",
1704
+ "",
1705
+ `# Swarm Space: ${plan.goal.title}`,
1706
+ "",
1707
+ plan.goal.description,
1708
+ "",
1709
+ `Total tasks: ${plan.tasks.length}`
1710
+ ].join("\n");
1711
+ fs7.writeFileSync(spaceFullPath, spaceFrontmatter);
1712
+ }
1713
+ const threadPaths = [];
1714
+ const slugMap = /* @__PURE__ */ new Map();
1715
+ for (const task of plan.tasks) {
1716
+ const taskSlug = slugify(task.title);
1717
+ slugMap.set(task.title, taskSlug);
1718
+ }
1719
+ for (const task of plan.tasks) {
1720
+ const taskSlug = slugMap.get(task.title);
1721
+ let body = `# ${task.title}
1722
+
1723
+ ${task.description}
1724
+ `;
1725
+ if (task.dependsOn && task.dependsOn.length > 0) {
1726
+ body += `
1727
+ ## Dependencies
1728
+ `;
1729
+ for (const dep of task.dependsOn) {
1730
+ const depSlug = slugMap.get(dep);
1731
+ if (depSlug) {
1732
+ body += `- [[${depSlug}]]
1733
+ `;
1734
+ }
1735
+ }
1736
+ }
1737
+ body += `
1738
+ ## Output
1739
+
1740
+ _Agent writes result here._
1741
+ `;
1742
+ if (task.tags && task.tags.length > 0) {
1743
+ body += `
1744
+ Tags: ${task.tags.join(", ")}
1745
+ `;
1746
+ }
1747
+ const created = createThread(workspacePath, task.title, body, actor, {
1748
+ priority: task.priority,
1749
+ space: `spaces/${spaceSlug}`
1750
+ });
1751
+ threadPaths.push(created.path);
1752
+ }
1753
+ const deployment = {
1754
+ planPath: path7.join(".workgraph", `swarm-${spaceSlug}.json`),
1755
+ workspacePath,
1756
+ threadPaths,
1757
+ spaceSlug,
1758
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1759
+ status: "deployed"
1760
+ };
1761
+ const manifestPath = path7.join(workspacePath, deployment.planPath);
1762
+ fs7.mkdirSync(path7.dirname(manifestPath), { recursive: true });
1763
+ fs7.writeFileSync(manifestPath, JSON.stringify({ plan, deployment }, null, 2));
1764
+ append(workspacePath, actor, "create", deployment.planPath, "swarm");
1765
+ return deployment;
1766
+ }
1767
+ function getSwarmStatus(workspacePath, spaceSlug) {
1768
+ const manifestPath = path7.join(workspacePath, ".workgraph", `swarm-${spaceSlug}.json`);
1769
+ if (!fs7.existsSync(manifestPath)) {
1770
+ throw new Error(`No swarm deployment found for space "${spaceSlug}"`);
1771
+ }
1772
+ const manifest = JSON.parse(fs7.readFileSync(manifestPath, "utf-8"));
1773
+ const deployment = manifest.deployment;
1774
+ const threads = [];
1775
+ let claimed = 0;
1776
+ let done2 = 0;
1777
+ let blocked = 0;
1778
+ let open = 0;
1779
+ for (const threadPath of deployment.threadPaths) {
1780
+ const t = read(workspacePath, threadPath);
1781
+ if (!t) continue;
1782
+ const status = String(t.fields.status ?? "open");
1783
+ const threadInfo = {
1784
+ path: threadPath,
1785
+ title: String(t.fields.title ?? ""),
1786
+ status,
1787
+ owner: t.fields.owner ? String(t.fields.owner) : void 0,
1788
+ priority: String(t.fields.priority ?? "medium")
1789
+ };
1790
+ threads.push(threadInfo);
1791
+ if (status === "done") done2++;
1792
+ else if (status === "active") claimed++;
1793
+ else if (status === "blocked") blocked++;
1794
+ else open++;
1795
+ }
1796
+ const total = deployment.threadPaths.length;
1797
+ const readyToClaim = open;
1798
+ const percentComplete = total > 0 ? Math.round(done2 / total * 100) : 0;
1799
+ if (done2 === total) deployment.status = "done";
1800
+ else if (claimed > 0 || done2 > 0) deployment.status = "running";
1801
+ return {
1802
+ deployment,
1803
+ total,
1804
+ claimed,
1805
+ done: done2,
1806
+ blocked,
1807
+ open,
1808
+ readyToClaim,
1809
+ percentComplete,
1810
+ threads
1811
+ };
1812
+ }
1813
+ function workerClaim(workspacePath, spaceSlug, agent) {
1814
+ const ready = listReadyThreadsInSpace(workspacePath, `spaces/${spaceSlug}`);
1815
+ if (ready.length === 0) return null;
1816
+ const priorityOrder = {
1817
+ critical: 0,
1818
+ high: 1,
1819
+ medium: 2,
1820
+ low: 3
1821
+ };
1822
+ ready.sort((a, b) => {
1823
+ const aPri = priorityOrder[String(a.fields.priority)] ?? 2;
1824
+ const bPri = priorityOrder[String(b.fields.priority)] ?? 2;
1825
+ return aPri - bPri;
1826
+ });
1827
+ const target = ready[0];
1828
+ return claim(workspacePath, target.path, agent);
1829
+ }
1830
+ function workerComplete(workspacePath, threadPath, agent, result) {
1831
+ const t = read(workspacePath, threadPath);
1832
+ if (!t) throw new Error(`Thread not found: ${threadPath}`);
1833
+ const currentBody = t.body ?? "";
1834
+ const updatedBody = currentBody.replace(
1835
+ "_Agent writes result here._",
1836
+ result
1837
+ );
1838
+ return done(workspacePath, threadPath, agent, updatedBody);
1839
+ }
1840
+ async function workerLoop(workspacePath, spaceSlug, agent, workFn, options) {
1841
+ let completed = 0;
1842
+ let errors = 0;
1843
+ const maxTasks = options?.maxTasks ?? Infinity;
1844
+ const delayMs = options?.delayMs ?? 1e3;
1845
+ while (completed + errors < maxTasks) {
1846
+ const claimed = workerClaim(workspacePath, spaceSlug, agent);
1847
+ if (!claimed) break;
1848
+ try {
1849
+ const result = await workFn(claimed);
1850
+ workerComplete(workspacePath, claimed.path, agent, result);
1851
+ completed++;
1852
+ } catch (err) {
1853
+ errors++;
1854
+ const errorMsg = err instanceof Error ? err.message : String(err);
1855
+ try {
1856
+ update(workspacePath, claimed.path, {
1857
+ status: "blocked"
1858
+ }, `Error: ${errorMsg}`, agent);
1859
+ } catch {
1860
+ }
1861
+ }
1862
+ if (delayMs > 0) {
1863
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
1864
+ }
1865
+ }
1866
+ return { completed, errors };
1867
+ }
1868
+ function synthesize(workspacePath, spaceSlug) {
1869
+ const status = getSwarmStatus(workspacePath, spaceSlug);
1870
+ const sections = [];
1871
+ const manifestPath = path7.join(workspacePath, ".workgraph", `swarm-${spaceSlug}.json`);
1872
+ const manifest = JSON.parse(fs7.readFileSync(manifestPath, "utf-8"));
1873
+ const plan = manifest.plan;
1874
+ sections.push(`# ${plan.goal.title}
1875
+ `);
1876
+ sections.push(`${plan.goal.description}
1877
+ `);
1878
+ sections.push(`---
1879
+ `);
1880
+ for (const threadInfo of status.threads) {
1881
+ const t = read(workspacePath, threadInfo.path);
1882
+ if (!t) continue;
1883
+ if (threadInfo.status !== "done") {
1884
+ sections.push(`## [PENDING] ${threadInfo.title}
1885
+
1886
+ _Not yet completed._
1887
+ `);
1888
+ continue;
1889
+ }
1890
+ const body = t.body ?? "";
1891
+ const result = body.replace(/^#\s+.*\n/, "").trim();
1892
+ if (result && result !== "_Agent writes result here._") {
1893
+ sections.push(`## ${threadInfo.title}
1894
+
1895
+ ${result}
1896
+ `);
1897
+ } else {
1898
+ sections.push(`## ${threadInfo.title}
1899
+
1900
+ _Completed but no output found._
1901
+ `);
1902
+ }
1903
+ }
1904
+ sections.push(`
1905
+ ---
1906
+ `);
1907
+ sections.push(`*Generated from swarm "${plan.goal.title}" \u2014 ${status.done}/${status.total} tasks completed.*
1908
+ `);
1909
+ return {
1910
+ markdown: sections.join("\n"),
1911
+ completedCount: status.done,
1912
+ totalCount: status.total
1913
+ };
1914
+ }
1915
+ function slugify(text) {
1916
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").substring(0, 80);
1917
+ }
1918
+
1613
1919
  // src/diagnostics/index.ts
1614
1920
  var diagnostics_exports = {};
1615
1921
  __export(diagnostics_exports, {
@@ -1625,8 +1931,8 @@ __export(diagnostics_exports, {
1625
1931
  });
1626
1932
 
1627
1933
  // src/diagnostics/doctor.ts
1628
- import fs7 from "fs";
1629
- import path8 from "path";
1934
+ import fs8 from "fs";
1935
+ import path9 from "path";
1630
1936
  import YAML2 from "yaml";
1631
1937
 
1632
1938
  // src/diagnostics/format.ts
@@ -1690,7 +1996,7 @@ function inferPrimitiveTypeFromPath(targetPath) {
1690
1996
  }
1691
1997
 
1692
1998
  // src/diagnostics/primitives.ts
1693
- import path7 from "path";
1999
+ import path8 from "path";
1694
2000
  function loadPrimitiveInventory(workspacePath) {
1695
2001
  const registry = loadRegistry(workspacePath);
1696
2002
  const allPrimitives = queryPrimitives(workspacePath);
@@ -1708,7 +2014,7 @@ function loadPrimitiveInventory(workspacePath) {
1708
2014
  const requiredFields = Object.entries(typeDef?.fields ?? {}).filter(([, fieldDef]) => fieldDef.required === true).map(([fieldName]) => fieldName);
1709
2015
  const presentCount = requiredFields.filter((fieldName) => hasRequiredValue(instance.fields[fieldName])).length;
1710
2016
  const frontmatterCompleteness = requiredFields.length === 0 ? 1 : presentCount / requiredFields.length;
1711
- const slug = path7.basename(instance.path, ".md");
2017
+ const slug = path8.basename(instance.path, ".md");
1712
2018
  return {
1713
2019
  ...instance,
1714
2020
  slug,
@@ -2050,8 +2356,8 @@ function collectStaleRuns(workspacePath, staleAfterMs, now) {
2050
2356
  }
2051
2357
  function collectPrimitiveRegistryReferenceIssues(workspacePath, inventory) {
2052
2358
  const issues = [];
2053
- const manifestPath = path8.join(workspacePath, ".workgraph", "primitive-registry.yaml");
2054
- if (!fs7.existsSync(manifestPath)) {
2359
+ const manifestPath = path9.join(workspacePath, ".workgraph", "primitive-registry.yaml");
2360
+ if (!fs8.existsSync(manifestPath)) {
2055
2361
  issues.push({
2056
2362
  code: "broken-primitive-registry-reference",
2057
2363
  severity: "error",
@@ -2062,7 +2368,7 @@ function collectPrimitiveRegistryReferenceIssues(workspacePath, inventory) {
2062
2368
  }
2063
2369
  let parsed;
2064
2370
  try {
2065
- parsed = YAML2.parse(fs7.readFileSync(manifestPath, "utf-8"));
2371
+ parsed = YAML2.parse(fs8.readFileSync(manifestPath, "utf-8"));
2066
2372
  } catch (error) {
2067
2373
  issues.push({
2068
2374
  code: "broken-primitive-registry-reference",
@@ -2114,7 +2420,7 @@ function collectPrimitiveRegistryReferenceIssues(workspacePath, inventory) {
2114
2420
  path: ".workgraph/primitive-registry.yaml"
2115
2421
  });
2116
2422
  }
2117
- if (!fs7.existsSync(path8.join(workspacePath, directory))) {
2423
+ if (!fs8.existsSync(path9.join(workspacePath, directory))) {
2118
2424
  issues.push({
2119
2425
  code: "broken-primitive-registry-reference",
2120
2426
  severity: "error",
@@ -2149,8 +2455,8 @@ function collectPrimitiveRegistryReferenceIssues(workspacePath, inventory) {
2149
2455
  function collectEmptyPrimitiveDirectoryIssues(workspacePath, inventory) {
2150
2456
  const issues = [];
2151
2457
  for (const typeDef of inventory.typeDefs.values()) {
2152
- const directoryPath = path8.join(workspacePath, typeDef.directory);
2153
- if (!fs7.existsSync(directoryPath)) continue;
2458
+ const directoryPath = path9.join(workspacePath, typeDef.directory);
2459
+ if (!fs8.existsSync(directoryPath)) continue;
2154
2460
  const markdownCount = listMarkdownFilesRecursive(directoryPath).length;
2155
2461
  if (markdownCount > 0) continue;
2156
2462
  issues.push({
@@ -2179,10 +2485,10 @@ function removeOrphanLinks(workspacePath, orphanLinks) {
2179
2485
  }
2180
2486
  let removedLinks = 0;
2181
2487
  for (const [sourcePath, tokenSet] of tokensBySource.entries()) {
2182
- const absPath = path8.join(workspacePath, sourcePath);
2183
- if (!fs7.existsSync(absPath)) continue;
2488
+ const absPath = path9.join(workspacePath, sourcePath);
2489
+ if (!fs8.existsSync(absPath)) continue;
2184
2490
  try {
2185
- const raw = fs7.readFileSync(absPath, "utf-8");
2491
+ const raw = fs8.readFileSync(absPath, "utf-8");
2186
2492
  let fileRemoved = 0;
2187
2493
  const updated = raw.replace(/\[\[([^[\]]+)\]\]/g, (token) => {
2188
2494
  if (!tokenSet.has(token)) return token;
@@ -2190,7 +2496,7 @@ function removeOrphanLinks(workspacePath, orphanLinks) {
2190
2496
  return "";
2191
2497
  });
2192
2498
  if (fileRemoved === 0) continue;
2193
- fs7.writeFileSync(absPath, updated, "utf-8");
2499
+ fs8.writeFileSync(absPath, updated, "utf-8");
2194
2500
  removedLinks += fileRemoved;
2195
2501
  filesUpdated.push(sourcePath);
2196
2502
  } catch (error) {
@@ -2255,10 +2561,10 @@ function cancelStaleRuns(workspacePath, staleRuns, actor) {
2255
2561
  return { cancelled, errors };
2256
2562
  }
2257
2563
  function readDispatchRunsSnapshot(workspacePath) {
2258
- const runsPath = path8.join(workspacePath, ".workgraph", "dispatch-runs.json");
2259
- if (!fs7.existsSync(runsPath)) return [];
2564
+ const runsPath = path9.join(workspacePath, ".workgraph", "dispatch-runs.json");
2565
+ if (!fs8.existsSync(runsPath)) return [];
2260
2566
  try {
2261
- const parsed = JSON.parse(fs7.readFileSync(runsPath, "utf-8"));
2567
+ const parsed = JSON.parse(fs8.readFileSync(runsPath, "utf-8"));
2262
2568
  return Array.isArray(parsed.runs) ? parsed.runs : [];
2263
2569
  } catch {
2264
2570
  return [];
@@ -2269,9 +2575,9 @@ function listMarkdownFilesRecursive(rootDirectory) {
2269
2575
  const stack = [rootDirectory];
2270
2576
  while (stack.length > 0) {
2271
2577
  const current = stack.pop();
2272
- const entries = fs7.readdirSync(current, { withFileTypes: true });
2578
+ const entries = fs8.readdirSync(current, { withFileTypes: true });
2273
2579
  for (const entry of entries) {
2274
- const absPath = path8.join(current, entry.name);
2580
+ const absPath = path9.join(current, entry.name);
2275
2581
  if (entry.isDirectory()) {
2276
2582
  stack.push(absPath);
2277
2583
  continue;
@@ -2415,7 +2721,7 @@ function toNullableString(value) {
2415
2721
  }
2416
2722
 
2417
2723
  // src/diagnostics/viz.ts
2418
- import path9 from "path";
2724
+ import path10 from "path";
2419
2725
  var TYPE_COLORS = ["cyan", "magenta", "yellow", "green", "blue", "red"];
2420
2726
  function visualizeVaultGraph(workspacePath, options = {}) {
2421
2727
  const inventory = loadPrimitiveInventory(workspacePath);
@@ -2555,7 +2861,7 @@ function resolveFocusPath(focusInput, inventory) {
2555
2861
  const directCandidate = normalized.endsWith(".md") ? normalized : `${normalized}.md`;
2556
2862
  if (inventory.byPath.has(normalized)) return normalized;
2557
2863
  if (inventory.byPath.has(directCandidate)) return directCandidate;
2558
- const slug = path9.basename(normalized, ".md");
2864
+ const slug = path10.basename(normalized, ".md");
2559
2865
  const candidates = inventory.slugToPaths.get(slug) ?? [];
2560
2866
  if (candidates.length === 1) return candidates[0];
2561
2867
  if (candidates.length > 1) {
@@ -2863,8 +3169,8 @@ __export(autonomy_daemon_exports, {
2863
3169
  startAutonomyDaemon: () => startAutonomyDaemon,
2864
3170
  stopAutonomyDaemon: () => stopAutonomyDaemon
2865
3171
  });
2866
- import fs8 from "fs";
2867
- import path10 from "path";
3172
+ import fs9 from "fs";
3173
+ import path11 from "path";
2868
3174
  import { spawn } from "child_process";
2869
3175
  var DAEMON_DIR = ".workgraph/daemon";
2870
3176
  var AUTONOMY_PID_FILE = "autonomy.pid";
@@ -2873,29 +3179,29 @@ var AUTONOMY_LOG_FILE = "autonomy.log";
2873
3179
  var AUTONOMY_META_FILE = "autonomy-process.json";
2874
3180
  function startAutonomyDaemon(workspacePath, input) {
2875
3181
  const daemonDir = ensureDaemonDir(workspacePath);
2876
- const pidPath = path10.join(daemonDir, AUTONOMY_PID_FILE);
2877
- const heartbeatPath = input.heartbeatPath ? resolvePathWithinWorkspace4(workspacePath, input.heartbeatPath) : path10.join(daemonDir, AUTONOMY_HEARTBEAT_FILE);
2878
- const logPath = input.logPath ? resolvePathWithinWorkspace4(workspacePath, input.logPath) : path10.join(daemonDir, AUTONOMY_LOG_FILE);
2879
- const metaPath = path10.join(daemonDir, AUTONOMY_META_FILE);
3182
+ const pidPath = path11.join(daemonDir, AUTONOMY_PID_FILE);
3183
+ const heartbeatPath = input.heartbeatPath ? resolvePathWithinWorkspace4(workspacePath, input.heartbeatPath) : path11.join(daemonDir, AUTONOMY_HEARTBEAT_FILE);
3184
+ const logPath = input.logPath ? resolvePathWithinWorkspace4(workspacePath, input.logPath) : path11.join(daemonDir, AUTONOMY_LOG_FILE);
3185
+ const metaPath = path11.join(daemonDir, AUTONOMY_META_FILE);
2880
3186
  const existing = readAutonomyDaemonStatus(workspacePath, { cleanupStalePidFile: true });
2881
3187
  if (existing.running) {
2882
3188
  throw new Error(`Autonomy daemon already running (pid=${existing.pid}). Stop it before starting a new one.`);
2883
3189
  }
2884
- const logFd = fs8.openSync(logPath, "a");
3190
+ const logFd = fs9.openSync(logPath, "a");
2885
3191
  const args = buildAutonomyDaemonArgs(workspacePath, input, heartbeatPath);
2886
3192
  const child = spawn(process.execPath, args, {
2887
3193
  detached: true,
2888
3194
  stdio: ["ignore", logFd, logFd],
2889
3195
  env: process.env
2890
3196
  });
2891
- fs8.closeSync(logFd);
3197
+ fs9.closeSync(logFd);
2892
3198
  child.unref();
2893
3199
  if (!child.pid) {
2894
3200
  throw new Error("Failed to start autonomy daemon: missing child process pid.");
2895
3201
  }
2896
- fs8.writeFileSync(pidPath, `${child.pid}
3202
+ fs9.writeFileSync(pidPath, `${child.pid}
2897
3203
  `, "utf-8");
2898
- fs8.writeFileSync(metaPath, JSON.stringify({
3204
+ fs9.writeFileSync(metaPath, JSON.stringify({
2899
3205
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2900
3206
  pid: child.pid,
2901
3207
  args,
@@ -2929,9 +3235,9 @@ async function stopAutonomyDaemon(workspacePath, input = {}) {
2929
3235
  await waitForProcessExit(pid, 1500);
2930
3236
  stopped = !isProcessAlive(pid);
2931
3237
  }
2932
- const pidPath = path10.join(ensureDaemonDir(workspacePath), AUTONOMY_PID_FILE);
2933
- if (stopped && fs8.existsSync(pidPath)) {
2934
- fs8.rmSync(pidPath, { force: true });
3238
+ const pidPath = path11.join(ensureDaemonDir(workspacePath), AUTONOMY_PID_FILE);
3239
+ if (stopped && fs9.existsSync(pidPath)) {
3240
+ fs9.rmSync(pidPath, { force: true });
2935
3241
  }
2936
3242
  return {
2937
3243
  stopped,
@@ -2942,14 +3248,14 @@ async function stopAutonomyDaemon(workspacePath, input = {}) {
2942
3248
  }
2943
3249
  function readAutonomyDaemonStatus(workspacePath, options = {}) {
2944
3250
  const daemonDir = ensureDaemonDir(workspacePath);
2945
- const pidPath = path10.join(daemonDir, AUTONOMY_PID_FILE);
2946
- const meta = readDaemonMeta(path10.join(daemonDir, AUTONOMY_META_FILE));
2947
- const logPath = meta?.logPath ? String(meta.logPath) : path10.join(daemonDir, AUTONOMY_LOG_FILE);
2948
- const heartbeatPath = meta?.heartbeatPath ? String(meta.heartbeatPath) : path10.join(daemonDir, AUTONOMY_HEARTBEAT_FILE);
3251
+ const pidPath = path11.join(daemonDir, AUTONOMY_PID_FILE);
3252
+ const meta = readDaemonMeta(path11.join(daemonDir, AUTONOMY_META_FILE));
3253
+ const logPath = meta?.logPath ? String(meta.logPath) : path11.join(daemonDir, AUTONOMY_LOG_FILE);
3254
+ const heartbeatPath = meta?.heartbeatPath ? String(meta.heartbeatPath) : path11.join(daemonDir, AUTONOMY_HEARTBEAT_FILE);
2949
3255
  const pid = readPid(pidPath);
2950
3256
  const running = pid ? isProcessAlive(pid) : false;
2951
- if (!running && pid && options.cleanupStalePidFile !== false && fs8.existsSync(pidPath)) {
2952
- fs8.rmSync(pidPath, { force: true });
3257
+ if (!running && pid && options.cleanupStalePidFile !== false && fs9.existsSync(pidPath)) {
3258
+ fs9.rmSync(pidPath, { force: true });
2953
3259
  }
2954
3260
  return {
2955
3261
  running,
@@ -2962,7 +3268,7 @@ function readAutonomyDaemonStatus(workspacePath, options = {}) {
2962
3268
  }
2963
3269
  function buildAutonomyDaemonArgs(workspacePath, input, heartbeatPath) {
2964
3270
  const args = [
2965
- path10.resolve(input.cliEntrypointPath),
3271
+ path11.resolve(input.cliEntrypointPath),
2966
3272
  "autonomy",
2967
3273
  "run",
2968
3274
  "-w",
@@ -3020,22 +3326,22 @@ function waitForProcessExit(pid, timeoutMs) {
3020
3326
  });
3021
3327
  }
3022
3328
  function ensureDaemonDir(workspacePath) {
3023
- const daemonDir = path10.join(workspacePath, DAEMON_DIR);
3024
- if (!fs8.existsSync(daemonDir)) fs8.mkdirSync(daemonDir, { recursive: true });
3329
+ const daemonDir = path11.join(workspacePath, DAEMON_DIR);
3330
+ if (!fs9.existsSync(daemonDir)) fs9.mkdirSync(daemonDir, { recursive: true });
3025
3331
  return daemonDir;
3026
3332
  }
3027
3333
  function readPid(pidPath) {
3028
- if (!fs8.existsSync(pidPath)) return void 0;
3029
- const raw = fs8.readFileSync(pidPath, "utf-8").trim();
3334
+ if (!fs9.existsSync(pidPath)) return void 0;
3335
+ const raw = fs9.readFileSync(pidPath, "utf-8").trim();
3030
3336
  if (!raw) return void 0;
3031
3337
  const parsed = Number(raw);
3032
3338
  if (!Number.isInteger(parsed) || parsed <= 0) return void 0;
3033
3339
  return parsed;
3034
3340
  }
3035
3341
  function readHeartbeat(heartbeatPath) {
3036
- if (!fs8.existsSync(heartbeatPath)) return void 0;
3342
+ if (!fs9.existsSync(heartbeatPath)) return void 0;
3037
3343
  try {
3038
- const parsed = JSON.parse(fs8.readFileSync(heartbeatPath, "utf-8"));
3344
+ const parsed = JSON.parse(fs9.readFileSync(heartbeatPath, "utf-8"));
3039
3345
  if (!parsed || typeof parsed !== "object") return void 0;
3040
3346
  return parsed;
3041
3347
  } catch {
@@ -3043,9 +3349,9 @@ function readHeartbeat(heartbeatPath) {
3043
3349
  }
3044
3350
  }
3045
3351
  function readDaemonMeta(metaPath) {
3046
- if (!fs8.existsSync(metaPath)) return void 0;
3352
+ if (!fs9.existsSync(metaPath)) return void 0;
3047
3353
  try {
3048
- const parsed = JSON.parse(fs8.readFileSync(metaPath, "utf-8"));
3354
+ const parsed = JSON.parse(fs9.readFileSync(metaPath, "utf-8"));
3049
3355
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
3050
3356
  return parsed;
3051
3357
  } catch {
@@ -3063,9 +3369,9 @@ function isProcessAlive(pid) {
3063
3369
  }
3064
3370
  function isZombieProcess(pid) {
3065
3371
  const statPath = `/proc/${pid}/stat`;
3066
- if (!fs8.existsSync(statPath)) return false;
3372
+ if (!fs9.existsSync(statPath)) return false;
3067
3373
  try {
3068
- const stat = fs8.readFileSync(statPath, "utf-8");
3374
+ const stat = fs9.readFileSync(statPath, "utf-8");
3069
3375
  const closingIdx = stat.indexOf(")");
3070
3376
  if (closingIdx === -1 || closingIdx + 2 >= stat.length) return false;
3071
3377
  const state = stat.slice(closingIdx + 2, closingIdx + 3);
@@ -3075,9 +3381,9 @@ function isZombieProcess(pid) {
3075
3381
  }
3076
3382
  }
3077
3383
  function resolvePathWithinWorkspace4(workspacePath, filePath) {
3078
- const base = path10.resolve(workspacePath);
3079
- const resolved = path10.resolve(base, filePath);
3080
- if (!resolved.startsWith(base + path10.sep) && resolved !== base) {
3384
+ const base = path11.resolve(workspacePath);
3385
+ const resolved = path11.resolve(base, filePath);
3386
+ if (!resolved.startsWith(base + path11.sep) && resolved !== base) {
3081
3387
  throw new Error(`Invalid path outside workspace: ${filePath}`);
3082
3388
  }
3083
3389
  return resolved;
@@ -3102,6 +3408,7 @@ export {
3102
3408
  fetchSkillMarkdownFromUrl,
3103
3409
  clawdapus_exports,
3104
3410
  integration_exports,
3411
+ swarm_exports,
3105
3412
  diagnostics_exports,
3106
3413
  autonomy_daemon_exports
3107
3414
  };