@mclawnet/agent 0.6.24 → 0.6.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/__tests__/projects-handler.test.d.ts +2 -0
- package/dist/__tests__/projects-handler.test.d.ts.map +1 -0
- package/dist/{chunk-WJWCYGLQ.js → chunk-K6CQFAGN.js} +351 -56
- package/dist/chunk-K6CQFAGN.js.map +1 -0
- package/dist/hub-connection.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/projects-handler.d.ts +126 -0
- package/dist/projects-handler.d.ts.map +1 -0
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +1 -1
- package/package.json +8 -8
- package/dist/chunk-WJWCYGLQ.js.map +0 -1
|
@@ -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
|
|
7
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
1292
|
-
import { homedir as
|
|
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 =
|
|
1299
|
-
var SKILLS_DIR =
|
|
1300
|
-
var MCP_CONFIG_PATH =
|
|
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
|
|
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 =
|
|
1320
|
-
if (!
|
|
1321
|
-
if (!
|
|
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 =
|
|
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 =
|
|
1335
|
-
if (!
|
|
1336
|
-
const destDir =
|
|
1337
|
-
const destSkillMd =
|
|
1338
|
-
const baseSnapshotPath =
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
1775
|
+
if (!existsSync3(SKILLS_DIR)) return [];
|
|
1483
1776
|
let dirs;
|
|
1484
1777
|
try {
|
|
1485
|
-
dirs =
|
|
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 =
|
|
1493
|
-
if (!
|
|
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 =
|
|
1516
|
-
if (!
|
|
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 =
|
|
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 (
|
|
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
|
|
2188
|
-
import { join as
|
|
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 ||
|
|
2196
|
-
this.brainCorePath = options?.brainCorePath ||
|
|
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 (!
|
|
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 =
|
|
2228
|
-
if (!
|
|
2520
|
+
const installJson = join4(home, ".brain", "install.json");
|
|
2521
|
+
if (!existsSync4(installJson)) {
|
|
2229
2522
|
return "needs_config";
|
|
2230
2523
|
}
|
|
2231
|
-
if (!
|
|
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 =
|
|
2240
|
-
if (!
|
|
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 =
|
|
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(
|
|
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 =
|
|
2450
|
-
if (!
|
|
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
|
|
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 (!
|
|
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 ??
|
|
2659
|
-
const dbPath = process.env.CLAWNET_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:
|
|
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\/?$/, "") :
|
|
2761
|
-
return new
|
|
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 ??
|
|
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-
|
|
3097
|
+
//# sourceMappingURL=chunk-K6CQFAGN.js.map
|