@mclawnet/agent 0.6.24 → 0.6.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=projects-handler.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects-handler.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/projects-handler.test.ts"],"names":[],"mappings":""}
@@ -3,8 +3,8 @@ import {
3
3
  } from "./chunk-PJ5M6Q36.js";
4
4
 
5
5
  // src/start.ts
6
- import { homedir as homedir3 } from "os";
7
- import { join as join4 } from "path";
6
+ import { homedir as homedir4 } from "os";
7
+ import { join as join5 } from "path";
8
8
 
9
9
  // src/hub-connection.ts
10
10
  import { hostname as osHostname } from "os";
@@ -246,10 +246,177 @@ async function handleLoadSessionHistory(workDir, claudeSessionId, opts) {
246
246
  };
247
247
  }
248
248
 
249
+ // src/projects-handler.ts
250
+ import { homedir as homedir2 } from "os";
251
+ import { join as join2 } from "path";
252
+ import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
253
+ import { TaskStore, projectRoot } from "@mclawnet/task";
254
+ import {
255
+ listAllProjectSummaries,
256
+ loadProjectSummary,
257
+ loadSwarmSummaries,
258
+ resolveWorkDir,
259
+ loadSwarmSnapshot,
260
+ InboxStore,
261
+ listProjectFiles,
262
+ readProjectFile,
263
+ writeProjectFile,
264
+ ProjectFilesError
265
+ } from "@mclawnet/swarm";
266
+ function getHome() {
267
+ return process.env.CLAWNET_HOME ?? homedir2();
268
+ }
269
+ async function handleProjectsList() {
270
+ return { projects: listAllProjectSummaries(getHome()) };
271
+ }
272
+ async function handleProjectsGet(encodedCwd) {
273
+ const home = getHome();
274
+ const summary = loadProjectSummary(home, encodedCwd);
275
+ if (!summary) return { project: null };
276
+ const swarms = loadSwarmSummaries(home, summary.workDir);
277
+ return { project: { ...summary, swarms } };
278
+ }
279
+ async function handleProjectsTasks(encodedCwd, filters = {}) {
280
+ const home = getHome();
281
+ const workDir = resolveWorkDir(home, encodedCwd);
282
+ if (!workDir) return { tasks: [] };
283
+ const store = new TaskStore({ workDir, home });
284
+ let tasks = store.list();
285
+ if (filters.status) tasks = tasks.filter((t) => t.status === filters.status);
286
+ if (filters.swarmId) tasks = tasks.filter((t) => t.swarmId === filters.swarmId);
287
+ if (filters.owner) tasks = tasks.filter((t) => t.owner === filters.owner);
288
+ return { tasks };
289
+ }
290
+ async function handleProjectsTask(encodedCwd, taskId) {
291
+ const home = getHome();
292
+ const workDir = resolveWorkDir(home, encodedCwd);
293
+ if (!workDir) return { task: null };
294
+ const task = new TaskStore({ workDir, home }).tryGet(taskId);
295
+ return { task: task ?? null };
296
+ }
297
+ async function handleProjectsSwarms(encodedCwd) {
298
+ const home = getHome();
299
+ const workDir = resolveWorkDir(home, encodedCwd);
300
+ if (!workDir) return { swarms: [] };
301
+ return { swarms: loadSwarmSummaries(home, workDir) };
302
+ }
303
+ async function handleProjectsSwarm(encodedCwd, swarmId) {
304
+ const home = getHome();
305
+ const workDir = resolveWorkDir(home, encodedCwd);
306
+ if (!workDir) return { snapshot: null, tasks: [] };
307
+ const snapshot = loadSwarmSnapshot(workDir, swarmId);
308
+ if (!snapshot) return { snapshot: null, tasks: [] };
309
+ const tasks = new TaskStore({ workDir, home }).listBySwarm(swarmId);
310
+ return { snapshot, tasks };
311
+ }
312
+ async function handleProjectsInboxes(encodedCwd, swarmId) {
313
+ const home = getHome();
314
+ const workDir = resolveWorkDir(home, encodedCwd);
315
+ if (!workDir) return { projectFound: false, inboxes: [] };
316
+ const dir = join2(projectRoot(workDir, home), "swarms", swarmId, "inboxes");
317
+ if (!existsSync2(dir)) return { projectFound: true, inboxes: [] };
318
+ const store = new InboxStore(workDir, swarmId, home);
319
+ let entries;
320
+ try {
321
+ entries = readdirSync2(dir).filter((f) => f.endsWith(".json"));
322
+ } catch (err) {
323
+ return {
324
+ projectFound: true,
325
+ inboxes: [],
326
+ error: err instanceof Error ? err.message : String(err)
327
+ };
328
+ }
329
+ const inboxes = await Promise.all(
330
+ entries.map(async (file) => {
331
+ const instanceId = file.slice(0, -".json".length);
332
+ const all = await store.readAll(instanceId);
333
+ return {
334
+ instanceId,
335
+ messageCount: all.length,
336
+ unreadCount: all.filter((m) => !m.delivered).length
337
+ };
338
+ })
339
+ );
340
+ return { projectFound: true, inboxes };
341
+ }
342
+ async function handleProjectsInbox(encodedCwd, swarmId, instanceId) {
343
+ const home = getHome();
344
+ const workDir = resolveWorkDir(home, encodedCwd);
345
+ if (!workDir) return { projectFound: false, messages: null, error: null };
346
+ try {
347
+ const messages = await new InboxStore(workDir, swarmId, home).readAll(instanceId);
348
+ return { projectFound: true, messages, error: null };
349
+ } catch (err) {
350
+ return {
351
+ projectFound: true,
352
+ messages: null,
353
+ error: err instanceof Error ? err.message : String(err)
354
+ };
355
+ }
356
+ }
357
+ async function handleProjectsSwarmSessionId(encodedCwd, swarmId) {
358
+ const home = getHome();
359
+ const workDir = resolveWorkDir(home, encodedCwd);
360
+ if (!workDir) return { projectFound: false, swarmFound: false, hubSessionId: null };
361
+ const snap = loadSwarmSnapshot(workDir, swarmId);
362
+ if (!snap) return { projectFound: true, swarmFound: false, hubSessionId: null };
363
+ return { projectFound: true, swarmFound: true, hubSessionId: snap.hubSessionId ?? null };
364
+ }
365
+ async function handleProjectsFilesList(encodedCwd) {
366
+ const home = getHome();
367
+ const workDir = resolveWorkDir(home, encodedCwd);
368
+ if (!workDir) return { projectFound: false, files: [] };
369
+ return { projectFound: true, files: listProjectFiles(workDir) };
370
+ }
371
+ async function handleProjectsFileRead(encodedCwd, relPath) {
372
+ const home = getHome();
373
+ const workDir = resolveWorkDir(home, encodedCwd);
374
+ if (!workDir) return { projectFound: false, file: null, error: null };
375
+ try {
376
+ const file = readProjectFile(workDir, relPath);
377
+ return { projectFound: true, file, error: null };
378
+ } catch (err) {
379
+ if (err instanceof ProjectFilesError) {
380
+ return {
381
+ projectFound: true,
382
+ file: null,
383
+ error: { status: err.status, message: err.message, details: err.details }
384
+ };
385
+ }
386
+ return {
387
+ projectFound: true,
388
+ file: null,
389
+ error: { status: 500, message: err instanceof Error ? err.message : String(err) }
390
+ };
391
+ }
392
+ }
393
+ async function handleProjectsFileWrite(encodedCwd, relPath, content, ifMatchEtag) {
394
+ const home = getHome();
395
+ const workDir = resolveWorkDir(home, encodedCwd);
396
+ if (!workDir) return { projectFound: false, file: null, error: null };
397
+ try {
398
+ const file = writeProjectFile(workDir, relPath, content, { ifMatchEtag });
399
+ return { projectFound: true, file, error: null };
400
+ } catch (err) {
401
+ if (err instanceof ProjectFilesError) {
402
+ return {
403
+ projectFound: true,
404
+ file: null,
405
+ error: { status: err.status, message: err.message, details: err.details }
406
+ };
407
+ }
408
+ return {
409
+ projectFound: true,
410
+ file: null,
411
+ error: { status: 500, message: err instanceof Error ? err.message : String(err) }
412
+ };
413
+ }
414
+ }
415
+
249
416
  // src/swarm-control-dispatch.ts
250
417
  import { randomUUID } from "crypto";
251
418
  import { createLogger } from "@mclawnet/logger";
252
- import { InboxStore } from "@mclawnet/swarm";
419
+ import { InboxStore as InboxStore2 } from "@mclawnet/swarm";
253
420
  var log = createLogger({ module: "agent/swarm-control" });
254
421
  async function handleSwarmControl(coord, msg, opts) {
255
422
  if (!msg || msg.type !== "swarm_spawn" && msg.type !== "swarm_resume") {
@@ -280,7 +447,7 @@ async function handleSwarmControl(coord, msg, opts) {
280
447
  const queen = coord.findQueenInstance?.(swarmId);
281
448
  if (swarm && swarm.workDir && queen) {
282
449
  try {
283
- const store = new InboxStore(swarm.workDir, swarmId, opts.home);
450
+ const store = new InboxStore2(swarm.workDir, swarmId, opts.home);
284
451
  await store.append(queen.instanceId, {
285
452
  id: randomUUID(),
286
453
  from: "user",
@@ -509,6 +676,132 @@ var HubConnection = class {
509
676
  });
510
677
  return true;
511
678
  }
679
+ if (msg.type === "projects.list") {
680
+ log2.info("projects.list");
681
+ handleProjectsList().then((r) => this.send({ type: "projects.list_result", requestId: msg.requestId, ...r })).catch((err) => {
682
+ log2.error({ err }, "projects.list failed");
683
+ this.send({ type: "projects.list_result", requestId: msg.requestId, projects: [] });
684
+ });
685
+ return true;
686
+ }
687
+ if (msg.type === "projects.get") {
688
+ log2.info({ encodedCwd: msg.encodedCwd }, "projects.get");
689
+ handleProjectsGet(msg.encodedCwd).then((r) => this.send({ type: "projects.get_result", requestId: msg.requestId, ...r })).catch((err) => {
690
+ log2.error({ err, encodedCwd: msg.encodedCwd }, "projects.get failed");
691
+ this.send({ type: "projects.get_result", requestId: msg.requestId, project: null });
692
+ });
693
+ return true;
694
+ }
695
+ if (msg.type === "projects.tasks") {
696
+ log2.info({ encodedCwd: msg.encodedCwd, status: msg.status, swarmId: msg.swarmId, owner: msg.owner }, "projects.tasks");
697
+ handleProjectsTasks(msg.encodedCwd, { status: msg.status, swarmId: msg.swarmId, owner: msg.owner }).then((r) => this.send({ type: "projects.tasks_result", requestId: msg.requestId, ...r })).catch((err) => {
698
+ log2.error({ err, encodedCwd: msg.encodedCwd, status: msg.status, swarmId: msg.swarmId, owner: msg.owner }, "projects.tasks failed");
699
+ this.send({ type: "projects.tasks_result", requestId: msg.requestId, tasks: [] });
700
+ });
701
+ return true;
702
+ }
703
+ if (msg.type === "projects.task") {
704
+ log2.info({ encodedCwd: msg.encodedCwd, taskId: msg.taskId }, "projects.task");
705
+ handleProjectsTask(msg.encodedCwd, msg.taskId).then((r) => this.send({ type: "projects.task_result", requestId: msg.requestId, ...r })).catch((err) => {
706
+ log2.error({ err, encodedCwd: msg.encodedCwd, taskId: msg.taskId }, "projects.task failed");
707
+ this.send({ type: "projects.task_result", requestId: msg.requestId, task: null });
708
+ });
709
+ return true;
710
+ }
711
+ if (msg.type === "projects.swarms") {
712
+ log2.info({ encodedCwd: msg.encodedCwd }, "projects.swarms");
713
+ handleProjectsSwarms(msg.encodedCwd).then((r) => this.send({ type: "projects.swarms_result", requestId: msg.requestId, ...r })).catch((err) => {
714
+ log2.error({ err, encodedCwd: msg.encodedCwd }, "projects.swarms failed");
715
+ this.send({ type: "projects.swarms_result", requestId: msg.requestId, swarms: [] });
716
+ });
717
+ return true;
718
+ }
719
+ if (msg.type === "projects.swarm") {
720
+ log2.info({ encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.swarm");
721
+ handleProjectsSwarm(msg.encodedCwd, msg.swarmId).then((r) => this.send({ type: "projects.swarm_result", requestId: msg.requestId, ...r })).catch((err) => {
722
+ log2.error({ err, encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.swarm failed");
723
+ this.send({ type: "projects.swarm_result", requestId: msg.requestId, snapshot: null, tasks: [] });
724
+ });
725
+ return true;
726
+ }
727
+ if (msg.type === "projects.inboxes") {
728
+ log2.info({ encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.inboxes");
729
+ handleProjectsInboxes(msg.encodedCwd, msg.swarmId).then((r) => this.send({ type: "projects.inboxes_result", requestId: msg.requestId, ...r })).catch((err) => {
730
+ log2.error({ err, encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.inboxes failed");
731
+ this.send({
732
+ type: "projects.inboxes_result",
733
+ requestId: msg.requestId,
734
+ projectFound: true,
735
+ inboxes: [],
736
+ error: err instanceof Error ? err.message : String(err)
737
+ });
738
+ });
739
+ return true;
740
+ }
741
+ if (msg.type === "projects.inbox") {
742
+ log2.info({ encodedCwd: msg.encodedCwd, swarmId: msg.swarmId, instanceId: msg.instanceId }, "projects.inbox");
743
+ handleProjectsInbox(msg.encodedCwd, msg.swarmId, msg.instanceId).then((r) => this.send({ type: "projects.inbox_result", requestId: msg.requestId, ...r })).catch((err) => {
744
+ log2.error({ err, encodedCwd: msg.encodedCwd, swarmId: msg.swarmId, instanceId: msg.instanceId }, "projects.inbox failed");
745
+ this.send({
746
+ type: "projects.inbox_result",
747
+ requestId: msg.requestId,
748
+ projectFound: false,
749
+ messages: null,
750
+ error: "agent error"
751
+ });
752
+ });
753
+ return true;
754
+ }
755
+ if (msg.type === "projects.swarm_session_id") {
756
+ log2.info({ encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.swarm_session_id");
757
+ handleProjectsSwarmSessionId(msg.encodedCwd, msg.swarmId).then((r) => this.send({ type: "projects.swarm_session_id_result", requestId: msg.requestId, ...r })).catch((err) => {
758
+ log2.error({ err, encodedCwd: msg.encodedCwd, swarmId: msg.swarmId }, "projects.swarm_session_id failed");
759
+ this.send({
760
+ type: "projects.swarm_session_id_result",
761
+ requestId: msg.requestId,
762
+ projectFound: false,
763
+ swarmFound: false,
764
+ hubSessionId: null
765
+ });
766
+ });
767
+ return true;
768
+ }
769
+ if (msg.type === "projects.files_list") {
770
+ log2.info({ encodedCwd: msg.encodedCwd }, "projects.files_list");
771
+ handleProjectsFilesList(msg.encodedCwd).then((r) => this.send({ type: "projects.files_list_result", requestId: msg.requestId, ...r })).catch((err) => {
772
+ log2.error({ err, encodedCwd: msg.encodedCwd }, "projects.files_list failed");
773
+ this.send({ type: "projects.files_list_result", requestId: msg.requestId, projectFound: false, files: [] });
774
+ });
775
+ return true;
776
+ }
777
+ if (msg.type === "projects.file_read") {
778
+ log2.info({ encodedCwd: msg.encodedCwd, relPath: msg.relPath }, "projects.file_read");
779
+ handleProjectsFileRead(msg.encodedCwd, msg.relPath).then((r) => this.send({ type: "projects.file_read_result", requestId: msg.requestId, ...r })).catch((err) => {
780
+ log2.error({ err, encodedCwd: msg.encodedCwd, relPath: msg.relPath }, "projects.file_read failed");
781
+ this.send({
782
+ type: "projects.file_read_result",
783
+ requestId: msg.requestId,
784
+ projectFound: false,
785
+ file: null,
786
+ error: { status: 500, message: "agent error" }
787
+ });
788
+ });
789
+ return true;
790
+ }
791
+ if (msg.type === "projects.file_write") {
792
+ log2.info({ encodedCwd: msg.encodedCwd, relPath: msg.relPath, hasIfMatch: !!msg.ifMatchEtag }, "projects.file_write");
793
+ handleProjectsFileWrite(msg.encodedCwd, msg.relPath, msg.content, msg.ifMatchEtag).then((r) => this.send({ type: "projects.file_write_result", requestId: msg.requestId, ...r })).catch((err) => {
794
+ log2.error({ err, encodedCwd: msg.encodedCwd, relPath: msg.relPath }, "projects.file_write failed");
795
+ this.send({
796
+ type: "projects.file_write_result",
797
+ requestId: msg.requestId,
798
+ projectFound: false,
799
+ file: null,
800
+ error: { status: 500, message: "agent error" }
801
+ });
802
+ });
803
+ return true;
804
+ }
512
805
  if (msg.type === "list_roles") {
513
806
  log2.info("list_roles");
514
807
  const roleNames = listRoles();
@@ -1286,18 +1579,18 @@ import { buildMemorySection } from "@mclawnet/memory";
1286
1579
  import { MAX_TOKENS_LADDER, clampLadderIndex } from "@mclawnet/shared";
1287
1580
 
1288
1581
  // src/skill-loader.ts
1289
- import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
1582
+ import { existsSync as existsSync3, mkdirSync, readdirSync as readdirSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
1290
1583
  import { createHash } from "crypto";
1291
- import { join as join2, dirname } from "path";
1292
- import { homedir as homedir2 } from "os";
1584
+ import { join as join3, dirname } from "path";
1585
+ import { homedir as homedir3 } from "os";
1293
1586
  import { createRequire } from "module";
1294
1587
  import { fileURLToPath } from "url";
1295
1588
  import { createLogger as createLogger4 } from "@mclawnet/logger";
1296
1589
  import { ManifestManager, mergeSkillSections } from "@mclawnet/skill-manager";
1297
1590
  var log4 = createLogger4({ module: "agent/skill-loader" });
1298
- var CLAWNET_DIR = join2(homedir2(), ".clawnet");
1299
- var SKILLS_DIR = join2(CLAWNET_DIR, ".claude", "skills");
1300
- var MCP_CONFIG_PATH = join2(CLAWNET_DIR, "mcp.json");
1591
+ var CLAWNET_DIR = join3(homedir3(), ".clawnet");
1592
+ var SKILLS_DIR = join3(CLAWNET_DIR, ".claude", "skills");
1593
+ var MCP_CONFIG_PATH = join3(CLAWNET_DIR, "mcp.json");
1301
1594
  async function initSkills() {
1302
1595
  ensureSkillsDir();
1303
1596
  syncBuiltinSkills(CLAWNET_DIR, defaultBuiltinSourceDir());
@@ -1306,7 +1599,7 @@ async function initSkills() {
1306
1599
  }
1307
1600
  function defaultBuiltinSourceDir() {
1308
1601
  const thisFile = fileURLToPath(import.meta.url);
1309
- return join2(dirname(thisFile), "..", "skills");
1602
+ return join3(dirname(thisFile), "..", "skills");
1310
1603
  }
1311
1604
  function sha256(s) {
1312
1605
  return createHash("sha256").update(s).digest("hex");
@@ -1316,26 +1609,26 @@ function readBuiltinVersion(content) {
1316
1609
  return match ? match[1].trim().replace(/^["']|["']$/g, "") : "1.0.0";
1317
1610
  }
1318
1611
  function syncBuiltinSkills(rootDir, srcDir) {
1319
- const skillsDir = join2(rootDir, ".claude", "skills");
1320
- if (!existsSync2(skillsDir)) mkdirSync(skillsDir, { recursive: true });
1321
- if (!existsSync2(srcDir)) {
1612
+ const skillsDir = join3(rootDir, ".claude", "skills");
1613
+ if (!existsSync3(skillsDir)) mkdirSync(skillsDir, { recursive: true });
1614
+ if (!existsSync3(srcDir)) {
1322
1615
  log4.debug({ srcDir }, "no built-in skills directory found, skipping");
1323
1616
  return;
1324
1617
  }
1325
1618
  const manifest = new ManifestManager(rootDir);
1326
1619
  let entries;
1327
1620
  try {
1328
- entries = readdirSync2(srcDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1621
+ entries = readdirSync3(srcDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1329
1622
  } catch {
1330
1623
  log4.warn({ srcDir }, "failed to read built-in skills directory");
1331
1624
  return;
1332
1625
  }
1333
1626
  for (const skillName of entries) {
1334
- const srcSkillMd = join2(srcDir, skillName, "SKILL.md");
1335
- if (!existsSync2(srcSkillMd)) continue;
1336
- const destDir = join2(skillsDir, skillName);
1337
- const destSkillMd = join2(destDir, "SKILL.md");
1338
- const baseSnapshotPath = join2(destDir, ".base.md");
1627
+ const srcSkillMd = join3(srcDir, skillName, "SKILL.md");
1628
+ if (!existsSync3(srcSkillMd)) continue;
1629
+ const destDir = join3(skillsDir, skillName);
1630
+ const destSkillMd = join3(destDir, "SKILL.md");
1631
+ const baseSnapshotPath = join3(destDir, ".base.md");
1339
1632
  let officialContent;
1340
1633
  try {
1341
1634
  officialContent = readFileSync2(srcSkillMd, "utf-8");
@@ -1345,7 +1638,7 @@ function syncBuiltinSkills(rootDir, srcDir) {
1345
1638
  }
1346
1639
  const officialHash = sha256(officialContent);
1347
1640
  const officialVersion = readBuiltinVersion(officialContent);
1348
- if (!existsSync2(destSkillMd)) {
1641
+ if (!existsSync3(destSkillMd)) {
1349
1642
  try {
1350
1643
  mkdirSync(destDir, { recursive: true });
1351
1644
  writeFileSync(destSkillMd, officialContent);
@@ -1360,7 +1653,7 @@ function syncBuiltinSkills(rootDir, srcDir) {
1360
1653
  const userContent = readFileSync2(destSkillMd, "utf-8");
1361
1654
  const userHash = sha256(userContent);
1362
1655
  manifest.refresh(skillName, userHash);
1363
- if (!existsSync2(baseSnapshotPath)) {
1656
+ if (!existsSync3(baseSnapshotPath)) {
1364
1657
  const entry = manifest.load().skills[skillName];
1365
1658
  if (entry && !entry.userModified) {
1366
1659
  try {
@@ -1389,7 +1682,7 @@ function syncBuiltinSkills(rootDir, srcDir) {
1389
1682
  log4.debug({ skill: skillName }, "keeping user-modified skill");
1390
1683
  break;
1391
1684
  case "needs-merge": {
1392
- if (!existsSync2(baseSnapshotPath)) {
1685
+ if (!existsSync3(baseSnapshotPath)) {
1393
1686
  try {
1394
1687
  writeFileSync(
1395
1688
  destSkillMd + ".conflict",
@@ -1472,25 +1765,25 @@ function renderConflictFile(skillName, officialContent, conflicts) {
1472
1765
  return lines.join("\n");
1473
1766
  }
1474
1767
  function ensureSkillsDir() {
1475
- if (!existsSync2(SKILLS_DIR)) {
1768
+ if (!existsSync3(SKILLS_DIR)) {
1476
1769
  mkdirSync(SKILLS_DIR, { recursive: true });
1477
1770
  log4.info({ dir: SKILLS_DIR }, "created skills directory");
1478
1771
  }
1479
1772
  }
1480
1773
  var cachedSkills = [];
1481
1774
  function scanSkills() {
1482
- if (!existsSync2(SKILLS_DIR)) return [];
1775
+ if (!existsSync3(SKILLS_DIR)) return [];
1483
1776
  let dirs;
1484
1777
  try {
1485
- dirs = readdirSync2(SKILLS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1778
+ dirs = readdirSync3(SKILLS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1486
1779
  } catch {
1487
1780
  log4.warn("failed to read skills directory for scanning");
1488
1781
  return [];
1489
1782
  }
1490
1783
  const skills = [];
1491
1784
  for (const dirName of dirs) {
1492
- const skillMd = join2(SKILLS_DIR, dirName, "SKILL.md");
1493
- if (!existsSync2(skillMd)) continue;
1785
+ const skillMd = join3(SKILLS_DIR, dirName, "SKILL.md");
1786
+ if (!existsSync3(skillMd)) continue;
1494
1787
  try {
1495
1788
  const content = readFileSync2(skillMd, "utf-8");
1496
1789
  const parsed = parseFrontmatter(content);
@@ -1512,8 +1805,8 @@ function getSkillList() {
1512
1805
  return cachedSkills;
1513
1806
  }
1514
1807
  function getPendingNotification() {
1515
- const pendingPath = join2(CLAWNET_DIR, ".claude", "pending-evolutions.json");
1516
- if (!existsSync2(pendingPath)) return null;
1808
+ const pendingPath = join3(CLAWNET_DIR, ".claude", "pending-evolutions.json");
1809
+ if (!existsSync3(pendingPath)) return null;
1517
1810
  try {
1518
1811
  const raw = JSON.parse(readFileSync2(pendingPath, "utf-8"));
1519
1812
  const pending = Array.isArray(raw?.pending) ? raw.pending : [];
@@ -1547,7 +1840,7 @@ function ensureMcpConfig() {
1547
1840
  try {
1548
1841
  const req = createRequire(import.meta.url);
1549
1842
  const mcpPkgDir = dirname(req.resolve("@mclawnet/mcp-server/package.json"));
1550
- mcpServerPath = join2(mcpPkgDir, "dist", "server.js");
1843
+ mcpServerPath = join3(mcpPkgDir, "dist", "server.js");
1551
1844
  } catch {
1552
1845
  log4.warn("could not resolve @mclawnet/mcp-server package path, skipping mcp.json generation");
1553
1846
  return;
@@ -1555,7 +1848,7 @@ function ensureMcpConfig() {
1555
1848
  const desired = { command: "node", args: [mcpServerPath] };
1556
1849
  let config = {};
1557
1850
  let fileExists = false;
1558
- if (existsSync2(MCP_CONFIG_PATH)) {
1851
+ if (existsSync3(MCP_CONFIG_PATH)) {
1559
1852
  fileExists = true;
1560
1853
  try {
1561
1854
  config = JSON.parse(readFileSync2(MCP_CONFIG_PATH, "utf-8"));
@@ -2181,19 +2474,19 @@ ${notice.text}`;
2181
2474
 
2182
2475
  // src/start.ts
2183
2476
  import { SwarmCoordinator, initRoles } from "@mclawnet/swarm";
2184
- import { TaskStore } from "@mclawnet/task";
2477
+ import { TaskStore as TaskStore2 } from "@mclawnet/task";
2185
2478
 
2186
2479
  // src/brain-bridge.ts
2187
- import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync3 } from "fs";
2188
- import { join as join3 } from "path";
2480
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync4 } from "fs";
2481
+ import { join as join4 } from "path";
2189
2482
  import { createLogger as createLogger6 } from "@mclawnet/logger";
2190
2483
  var log6 = createLogger6({ module: "brain-bridge" });
2191
2484
  var BrainBridge = class {
2192
2485
  constructor(hub, options) {
2193
2486
  this.hub = hub;
2194
2487
  const home = process.env.HOME || process.env.USERPROFILE || "";
2195
- this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME || join3(home, "BrainData");
2196
- this.brainCorePath = options?.brainCorePath || join3(home, ".brain", "BrainCore");
2488
+ this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME || join4(home, "BrainData");
2489
+ this.brainCorePath = options?.brainCorePath || join4(home, ".brain", "BrainCore");
2197
2490
  this.hub.registerNamespace("brain", (msg) => this.handleRequest(msg));
2198
2491
  log6.info(
2199
2492
  { brainHome: this.brainHome, brainCorePath: this.brainCorePath },
@@ -2220,15 +2513,15 @@ var BrainBridge = class {
2220
2513
  }
2221
2514
  }
2222
2515
  checkSetup() {
2223
- if (!existsSync3(this.brainCorePath)) {
2516
+ if (!existsSync4(this.brainCorePath)) {
2224
2517
  return "not_installed";
2225
2518
  }
2226
2519
  const home = process.env.HOME || process.env.USERPROFILE || "";
2227
- const installJson = join3(home, ".brain", "install.json");
2228
- if (!existsSync3(installJson)) {
2520
+ const installJson = join4(home, ".brain", "install.json");
2521
+ if (!existsSync4(installJson)) {
2229
2522
  return "needs_config";
2230
2523
  }
2231
- if (!existsSync3(this.brainHome)) {
2524
+ if (!existsSync4(this.brainHome)) {
2232
2525
  return "needs_config";
2233
2526
  }
2234
2527
  return "ready";
@@ -2236,18 +2529,18 @@ var BrainBridge = class {
2236
2529
  /** Read the most recent daily briefing report */
2237
2530
  async getBriefing(date) {
2238
2531
  const targetDate = date || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2239
- const reportsDir = join3(this.brainHome, "reports", "daily");
2240
- if (!existsSync3(reportsDir)) {
2532
+ const reportsDir = join4(this.brainHome, "reports", "daily");
2533
+ if (!existsSync4(reportsDir)) {
2241
2534
  log6.info({ reportsDir }, "get_briefing: reports dir not found");
2242
2535
  return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
2243
2536
  }
2244
- const files = readdirSync3(reportsDir).filter((f) => f.includes(targetDate) && f.endsWith(".md")).sort().reverse();
2537
+ const files = readdirSync4(reportsDir).filter((f) => f.includes(targetDate) && f.endsWith(".md")).sort().reverse();
2245
2538
  if (files.length === 0) {
2246
2539
  log6.info({ targetDate }, "get_briefing: no report for date");
2247
2540
  return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
2248
2541
  }
2249
2542
  log6.info({ targetDate, file: files[0] }, "get_briefing: reading report");
2250
- const content = readFileSync3(join3(reportsDir, files[0]), "utf-8");
2543
+ const content = readFileSync3(join4(reportsDir, files[0]), "utf-8");
2251
2544
  const tldrMatch = content.match(/## TL;DR\n([\s\S]*?)(?=\n---|\n## )/);
2252
2545
  const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);
2253
2546
  const actions = this.parseActions(content);
@@ -2446,8 +2739,8 @@ var BrainBridge = class {
2446
2739
  if (!recapPath) {
2447
2740
  return { error: "No recap path provided" };
2448
2741
  }
2449
- const fullPath = join3(this.brainHome, recapPath);
2450
- if (!existsSync3(fullPath)) {
2742
+ const fullPath = join4(this.brainHome, recapPath);
2743
+ if (!existsSync4(fullPath)) {
2451
2744
  log6.warn({ fullPath }, "meeting recap file not found");
2452
2745
  return { error: "Recap file not found" };
2453
2746
  }
@@ -2484,7 +2777,7 @@ var BrainBridge = class {
2484
2777
  };
2485
2778
 
2486
2779
  // src/fs-bridge.ts
2487
- import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
2780
+ import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
2488
2781
  import { extname, isAbsolute } from "path";
2489
2782
  import { createLogger as createLogger7 } from "@mclawnet/logger";
2490
2783
  var log7 = createLogger7({ module: "fs-bridge" });
@@ -2542,7 +2835,7 @@ var FsBridge = class {
2542
2835
  if (!isAbsolute(filePath)) {
2543
2836
  throw new Error(`Access denied: only absolute paths allowed`);
2544
2837
  }
2545
- if (!existsSync4(filePath)) {
2838
+ if (!existsSync5(filePath)) {
2546
2839
  throw new Error(`File not found: ${filePath}`);
2547
2840
  }
2548
2841
  const stat2 = statSync2(filePath);
@@ -2608,6 +2901,7 @@ import {
2608
2901
  AccumulationScanner,
2609
2902
  triggerFromAccumulation
2610
2903
  } from "@mclawnet/skill-manager";
2904
+ import { PROJECTS_RPC_CAPABILITY } from "@mclawnet/shared";
2611
2905
  var log9 = createLogger9({ module: "agent" });
2612
2906
  async function startAgent(options) {
2613
2907
  const config = loadConfig(options.config);
@@ -2623,6 +2917,7 @@ async function startAgent(options) {
2623
2917
  hubUrl: config.hubUrl,
2624
2918
  token: config.token,
2625
2919
  hostname: config.name,
2920
+ capabilities: [PROJECTS_RPC_CAPABILITY],
2626
2921
  onConnect: (agentId) => {
2627
2922
  log9.info({ agentId }, "connected to hub");
2628
2923
  const skills = getSkillList();
@@ -2655,8 +2950,8 @@ async function startAgent(options) {
2655
2950
  }
2656
2951
  });
2657
2952
  let swarmCoordinator;
2658
- const clawnetDir = process.env.CLAWNET_DIR ?? join4(homedir3(), ".clawnet");
2659
- const dbPath = process.env.CLAWNET_MEMORY_DB ?? join4(clawnetDir, "memory.db");
2953
+ const clawnetDir = process.env.CLAWNET_DIR ?? join5(homedir4(), ".clawnet");
2954
+ const dbPath = process.env.CLAWNET_MEMORY_DB ?? join5(clawnetDir, "memory.db");
2660
2955
  let memoryStore = null;
2661
2956
  let embeddingService = null;
2662
2957
  let evolutionPipeline = null;
@@ -2752,18 +3047,18 @@ async function startAgent(options) {
2752
3047
  // PR-C: enable logical-state checkpoint. Lives next to memory.db under
2753
3048
  // CLAWNET_DIR so backup/wipe affects both consistently. Per-call writes
2754
3049
  // are debounced to 5s by SessionManager itself.
2755
- checkpointPath: join4(clawnetDir, "agent-sessions.json")
3050
+ checkpointPath: join5(clawnetDir, "agent-sessions.json")
2756
3051
  });
2757
3052
  swarmCoordinator = new SwarmCoordinator(sessionManager, hub, (workDir) => {
2758
3053
  try {
2759
3054
  const env = process.env.CLAWNET_DIR;
2760
- const home = env ? env.replace(/\/\.clawnet\/?$/, "") : homedir3();
2761
- return new TaskStore({ workDir, home });
3055
+ const home = env ? env.replace(/\/\.clawnet\/?$/, "") : homedir4();
3056
+ return new TaskStore2({ workDir, home });
2762
3057
  } catch (err) {
2763
3058
  log9.warn({ err, workDir }, "TaskStore factory failed");
2764
3059
  return void 0;
2765
3060
  }
2766
- }, process.env.CLAWNET_HOME ?? homedir3());
3061
+ }, process.env.CLAWNET_HOME ?? homedir4());
2767
3062
  hub.setSessionManager(sessionManager);
2768
3063
  hub.setSwarmCoordinator(swarmCoordinator);
2769
3064
  const scheduleRuntime = new ScheduleRuntime({ hub, sessionManager, swarmCoordinator });
@@ -2799,4 +3094,4 @@ export {
2799
3094
  FsBridge,
2800
3095
  startAgent
2801
3096
  };
2802
- //# sourceMappingURL=chunk-WJWCYGLQ.js.map
3097
+ //# sourceMappingURL=chunk-K6CQFAGN.js.map