@mclawnet/agent 0.6.7 → 0.6.9
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__/skill-loader.test.d.ts +2 -0
- package/dist/__tests__/skill-loader.test.d.ts.map +1 -0
- package/dist/{chunk-GLO5OZAY.js → chunk-JG5PN4V4.js} +108 -16
- package/dist/chunk-JG5PN4V4.js.map +1 -0
- package/dist/hub-connection.d.ts +6 -0
- package/dist/hub-connection.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/session-manager.d.ts +1 -0
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/skill-loader.d.ts +11 -0
- package/dist/skill-loader.d.ts.map +1 -1
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-GLO5OZAY.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/skill-loader.test.ts"],"names":[],"mappings":""}
|
|
@@ -301,6 +301,12 @@ var HubConnection = class {
|
|
|
301
301
|
data
|
|
302
302
|
});
|
|
303
303
|
}
|
|
304
|
+
sendSkillList(skills) {
|
|
305
|
+
this.send({
|
|
306
|
+
type: "skill_list_update",
|
|
307
|
+
skills
|
|
308
|
+
});
|
|
309
|
+
}
|
|
304
310
|
get readyState() {
|
|
305
311
|
return this.ws?.readyState ?? WebSocket.CLOSED;
|
|
306
312
|
}
|
|
@@ -309,7 +315,7 @@ var HubConnection = class {
|
|
|
309
315
|
}
|
|
310
316
|
connect() {
|
|
311
317
|
if (this.destroyed) return;
|
|
312
|
-
this.
|
|
318
|
+
this.cleanupConnection();
|
|
313
319
|
this.authState = "pending";
|
|
314
320
|
this.ws = new WebSocket(this.hubUrl);
|
|
315
321
|
this.ws.on("open", () => {
|
|
@@ -341,6 +347,7 @@ var HubConnection = class {
|
|
|
341
347
|
this.startHeartbeat();
|
|
342
348
|
this.onConnectCb?.(this.agentId);
|
|
343
349
|
this.tryRecoverSwarms();
|
|
350
|
+
this.reportLiveSessions();
|
|
344
351
|
return;
|
|
345
352
|
}
|
|
346
353
|
if (this.authState === "authenticated") {
|
|
@@ -531,12 +538,26 @@ var HubConnection = class {
|
|
|
531
538
|
});
|
|
532
539
|
});
|
|
533
540
|
} else if (this.finishedSwarms.has(sessionId)) {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
541
|
+
if (crewConfig?.templateName || crewConfig?.roles) {
|
|
542
|
+
this.finishedSwarms.delete(sessionId);
|
|
543
|
+
const templateName = crewConfig.templateName;
|
|
544
|
+
const roles = crewConfig.roles;
|
|
545
|
+
log.info({ sessionId, templateName, rolesCount: roles?.length }, "swarm.execute: continuing finished swarm");
|
|
546
|
+
this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content, isContinuation: true }).catch((err) => {
|
|
547
|
+
this.send({
|
|
548
|
+
type: "session.error",
|
|
549
|
+
sessionId,
|
|
550
|
+
error: err instanceof Error ? err.message : String(err)
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
} else {
|
|
554
|
+
log.info({ sessionId }, "swarm.execute ignored: swarm finished, no config to recreate");
|
|
555
|
+
this.send({
|
|
556
|
+
type: "session.error",
|
|
557
|
+
sessionId,
|
|
558
|
+
error: "\u8702\u7FA4\u4EFB\u52A1\u5DF2\u5B8C\u6210\u4E14\u65E0\u6CD5\u6062\u590D\u914D\u7F6E\u3002\u8BF7\u521B\u5EFA\u65B0\u7684\u8702\u7FA4\u4EFB\u52A1\u3002"
|
|
559
|
+
});
|
|
560
|
+
}
|
|
540
561
|
} else if (crewConfig?.templateName || crewConfig?.roles) {
|
|
541
562
|
const templateName = crewConfig.templateName;
|
|
542
563
|
const roles = crewConfig.roles;
|
|
@@ -650,6 +671,19 @@ var HubConnection = class {
|
|
|
650
671
|
log.error({ err }, "swarm recovery failed");
|
|
651
672
|
}
|
|
652
673
|
}
|
|
674
|
+
reportLiveSessions() {
|
|
675
|
+
if (!this.sessionManager) return;
|
|
676
|
+
const ids = this.sessionManager.getActiveSessionIds();
|
|
677
|
+
if (ids.length === 0) return;
|
|
678
|
+
log.info({ count: ids.length }, "reporting live sessions to hub after reconnect");
|
|
679
|
+
for (const sessionId of ids) {
|
|
680
|
+
this.send({
|
|
681
|
+
type: "session.state",
|
|
682
|
+
sessionId,
|
|
683
|
+
processState: "ready"
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
}
|
|
653
687
|
sendRaw(data) {
|
|
654
688
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;
|
|
655
689
|
this.ws.send(JSON.stringify(data));
|
|
@@ -676,9 +710,12 @@ var HubConnection = class {
|
|
|
676
710
|
this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);
|
|
677
711
|
}
|
|
678
712
|
cleanup() {
|
|
679
|
-
this.
|
|
713
|
+
this.cleanupConnection();
|
|
680
714
|
this.sessionManager?.closeAll().catch(() => {
|
|
681
715
|
});
|
|
716
|
+
}
|
|
717
|
+
cleanupConnection() {
|
|
718
|
+
this.stopHeartbeat();
|
|
682
719
|
if (this.reconnectTimer) {
|
|
683
720
|
clearTimeout(this.reconnectTimer);
|
|
684
721
|
this.reconnectTimer = null;
|
|
@@ -812,13 +849,16 @@ ${options.systemPrompt}` : `${memorySection}${roleHint}`;
|
|
|
812
849
|
get activeSessionCount() {
|
|
813
850
|
return this.sessions.size;
|
|
814
851
|
}
|
|
852
|
+
getActiveSessionIds() {
|
|
853
|
+
return Array.from(this.sessions.keys());
|
|
854
|
+
}
|
|
815
855
|
};
|
|
816
856
|
|
|
817
857
|
// src/start.ts
|
|
818
858
|
import { SwarmCoordinator, initRoles } from "@mclawnet/swarm";
|
|
819
859
|
|
|
820
860
|
// src/skill-loader.ts
|
|
821
|
-
import { existsSync as existsSync2, mkdirSync, copyFileSync, readdirSync as readdirSync2, writeFileSync } from "fs";
|
|
861
|
+
import { existsSync as existsSync2, mkdirSync, copyFileSync, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
822
862
|
import { join as join2, dirname } from "path";
|
|
823
863
|
import { homedir as homedir2 } from "os";
|
|
824
864
|
import { createRequire } from "module";
|
|
@@ -832,6 +872,7 @@ async function initSkills() {
|
|
|
832
872
|
ensureSkillsDir();
|
|
833
873
|
copyBuiltinSkills();
|
|
834
874
|
ensureMcpConfig();
|
|
875
|
+
scanSkills();
|
|
835
876
|
}
|
|
836
877
|
function ensureSkillsDir() {
|
|
837
878
|
if (!existsSync2(SKILLS_DIR)) {
|
|
@@ -871,6 +912,52 @@ function copyBuiltinSkills() {
|
|
|
871
912
|
}
|
|
872
913
|
}
|
|
873
914
|
}
|
|
915
|
+
var cachedSkills = [];
|
|
916
|
+
function scanSkills() {
|
|
917
|
+
if (!existsSync2(SKILLS_DIR)) return [];
|
|
918
|
+
let dirs;
|
|
919
|
+
try {
|
|
920
|
+
dirs = readdirSync2(SKILLS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
921
|
+
} catch {
|
|
922
|
+
log3.warn("failed to read skills directory for scanning");
|
|
923
|
+
return [];
|
|
924
|
+
}
|
|
925
|
+
const skills = [];
|
|
926
|
+
for (const dirName of dirs) {
|
|
927
|
+
const skillMd = join2(SKILLS_DIR, dirName, "SKILL.md");
|
|
928
|
+
if (!existsSync2(skillMd)) continue;
|
|
929
|
+
try {
|
|
930
|
+
const content = readFileSync2(skillMd, "utf-8");
|
|
931
|
+
const parsed = parseFrontmatter(content);
|
|
932
|
+
if (parsed.name) {
|
|
933
|
+
skills.push({
|
|
934
|
+
name: parsed.name,
|
|
935
|
+
description: parsed.description || dirName
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
} catch (err) {
|
|
939
|
+
log3.debug({ skill: dirName, err }, "failed to parse SKILL.md frontmatter");
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
cachedSkills = skills;
|
|
943
|
+
log3.info({ count: skills.length }, "scanned skills");
|
|
944
|
+
return skills;
|
|
945
|
+
}
|
|
946
|
+
function getSkillList() {
|
|
947
|
+
return cachedSkills;
|
|
948
|
+
}
|
|
949
|
+
function parseFrontmatter(content) {
|
|
950
|
+
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
951
|
+
if (!match) return { name: "", description: "" };
|
|
952
|
+
const yaml = match[1];
|
|
953
|
+
const nameMatch = yaml.match(/^name:\s*(.+)$/m);
|
|
954
|
+
const descMatch = yaml.match(/^description:\s*(.+)$/m);
|
|
955
|
+
const strip = (s) => s.trim().replace(/^["']|["']$/g, "");
|
|
956
|
+
return {
|
|
957
|
+
name: strip(nameMatch?.[1] ?? ""),
|
|
958
|
+
description: strip(descMatch?.[1] ?? "")
|
|
959
|
+
};
|
|
960
|
+
}
|
|
874
961
|
function ensureMcpConfig() {
|
|
875
962
|
if (existsSync2(MCP_CONFIG_PATH)) {
|
|
876
963
|
log3.debug("mcp.json already exists, skipping");
|
|
@@ -903,7 +990,7 @@ function ensureMcpConfig() {
|
|
|
903
990
|
}
|
|
904
991
|
|
|
905
992
|
// src/brain-bridge.ts
|
|
906
|
-
import { existsSync as existsSync3, readFileSync as
|
|
993
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync3 } from "fs";
|
|
907
994
|
import { join as join3 } from "path";
|
|
908
995
|
import { createLogger as createLogger4 } from "@mclawnet/logger";
|
|
909
996
|
var log4 = createLogger4({ module: "brain-bridge" });
|
|
@@ -966,7 +1053,7 @@ var BrainBridge = class {
|
|
|
966
1053
|
return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
|
|
967
1054
|
}
|
|
968
1055
|
log4.info({ targetDate, file: files[0] }, "get_briefing: reading report");
|
|
969
|
-
const content =
|
|
1056
|
+
const content = readFileSync3(join3(reportsDir, files[0]), "utf-8");
|
|
970
1057
|
const tldrMatch = content.match(/## TL;DR\n([\s\S]*?)(?=\n---|\n## )/);
|
|
971
1058
|
const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);
|
|
972
1059
|
const actions = this.parseActions(content);
|
|
@@ -1170,7 +1257,7 @@ var BrainBridge = class {
|
|
|
1170
1257
|
log4.warn({ fullPath }, "meeting recap file not found");
|
|
1171
1258
|
return { error: "Recap file not found" };
|
|
1172
1259
|
}
|
|
1173
|
-
const content =
|
|
1260
|
+
const content = readFileSync3(fullPath, "utf-8");
|
|
1174
1261
|
return { recap: this.parseRecapMarkdown(content) };
|
|
1175
1262
|
}
|
|
1176
1263
|
/** Parse meeting recap markdown into structured sections */
|
|
@@ -1203,7 +1290,7 @@ var BrainBridge = class {
|
|
|
1203
1290
|
};
|
|
1204
1291
|
|
|
1205
1292
|
// src/fs-bridge.ts
|
|
1206
|
-
import { existsSync as existsSync4, readFileSync as
|
|
1293
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
1207
1294
|
import { extname, isAbsolute } from "path";
|
|
1208
1295
|
import { createLogger as createLogger5 } from "@mclawnet/logger";
|
|
1209
1296
|
var log5 = createLogger5({ module: "fs-bridge" });
|
|
@@ -1271,12 +1358,12 @@ var FsBridge = class {
|
|
|
1271
1358
|
const mimeType = getMimeType(filePath);
|
|
1272
1359
|
const totalSize = stat2.size;
|
|
1273
1360
|
if (isTextMime(mimeType)) {
|
|
1274
|
-
const raw =
|
|
1361
|
+
const raw = readFileSync4(filePath, "utf-8");
|
|
1275
1362
|
const truncated2 = raw.length > MAX_TEXT_SIZE;
|
|
1276
1363
|
const content = truncated2 ? raw.slice(0, MAX_TEXT_SIZE) : raw;
|
|
1277
1364
|
return { content, encoding: "utf-8", size: content.length, totalSize, mimeType, truncated: truncated2 };
|
|
1278
1365
|
}
|
|
1279
|
-
const buf =
|
|
1366
|
+
const buf = readFileSync4(filePath);
|
|
1280
1367
|
const truncated = buf.length > MAX_TEXT_SIZE;
|
|
1281
1368
|
const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;
|
|
1282
1369
|
return { content: slice.toString("base64"), encoding: "base64", size: slice.length, totalSize, mimeType, truncated };
|
|
@@ -1302,6 +1389,11 @@ async function startAgent(options) {
|
|
|
1302
1389
|
hostname: config.name,
|
|
1303
1390
|
onConnect: (agentId) => {
|
|
1304
1391
|
log6.info({ agentId }, "connected to hub");
|
|
1392
|
+
const skills = getSkillList();
|
|
1393
|
+
if (skills.length > 0) {
|
|
1394
|
+
hub.sendSkillList(skills);
|
|
1395
|
+
log6.info({ count: skills.length }, "pushed skill list to hub");
|
|
1396
|
+
}
|
|
1305
1397
|
},
|
|
1306
1398
|
onDisconnect: (code, reason) => {
|
|
1307
1399
|
log6.info({ code, reason }, "disconnected from hub");
|
|
@@ -1363,4 +1455,4 @@ export {
|
|
|
1363
1455
|
FsBridge,
|
|
1364
1456
|
startAgent
|
|
1365
1457
|
};
|
|
1366
|
-
//# sourceMappingURL=chunk-
|
|
1458
|
+
//# sourceMappingURL=chunk-JG5PN4V4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hub-connection.ts","../src/fs-handler.ts","../src/session-manager.ts","../src/start.ts","../src/skill-loader.ts","../src/brain-bridge.ts","../src/fs-bridge.ts"],"sourcesContent":["import { hostname as osHostname } from \"node:os\";\nimport WebSocket from \"ws\";\nimport {\n HEARTBEAT_INTERVAL_MS,\n DEFAULT_RECONNECT_MS,\n MAX_RECONNECT_MS,\n WS_CLOSE_INVALID_TOKEN,\n} from \"@mclawnet/shared\";\nimport type {\n AgentServerMessage,\n AgentClientMessage,\n AgentGenericRequest,\n} from \"@mclawnet/shared\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { SwarmCoordinator } from \"@mclawnet/swarm\";\nimport { listRecoverableSwarms, recoverSwarm, listRoles, loadRole, listRecoverableSwarmIds, deleteSwarmSnapshot, listTemplates, loadTemplate } from \"@mclawnet/swarm\";\nimport { handleListDir, handleListFolders, handleListHistorySessions, handleLoadSessionHistory } from \"./fs-handler.js\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface HubConnectionOptions {\n hubUrl: string;\n token: string;\n hostname?: string;\n version?: string;\n capabilities?: string[];\n heartbeatInterval?: number;\n reconnectDelay?: number;\n maxReconnectDelay?: number;\n onMessage?: (data: unknown) => void;\n onConnect?: (agentId: string) => void;\n onDisconnect?: (code: number, reason: string) => void;\n onError?: (err: Error) => void;\n}\n\ntype AuthState = \"pending\" | \"authenticating\" | \"authenticated\";\n\nexport class HubConnection {\n private ws: WebSocket | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectDelay: number;\n private destroyed = false;\n private authState: AuthState = \"pending\";\n\n readonly hubUrl: string;\n readonly token: string;\n readonly hostname: string;\n readonly version: string | undefined;\n readonly capabilities: string[] | undefined;\n readonly heartbeatInterval: number;\n readonly maxReconnectDelay: number;\n\n /** Agent ID assigned by Hub after successful auth */\n agentId: string | null = null;\n\n /** Swarm IDs that have been completed/failed — prevents accidental recreation */\n private finishedSwarms = new Set<string>();\n\n /** Session manager — set after construction via setSessionManager() */\n private sessionManager: SessionManager | null = null;\n\n /** Swarm coordinator — set after construction via setSwarmCoordinator() */\n private swarmCoordinator: SwarmCoordinator | null = null;\n\n /** Namespace-based generic message handlers */\n private namespaceHandlers = new Map<\n string,\n (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n >();\n\n private onMessage?: (data: unknown) => void;\n private onConnectCb?: (agentId: string) => void;\n private onDisconnect?: (code: number, reason: string) => void;\n private onError?: (err: Error) => void;\n\n constructor(opts: HubConnectionOptions) {\n this.hubUrl = opts.hubUrl;\n this.token = opts.token;\n this.hostname = opts.hostname ?? osHostname();\n this.version = opts.version;\n this.capabilities = opts.capabilities;\n this.heartbeatInterval = opts.heartbeatInterval ?? HEARTBEAT_INTERVAL_MS;\n this.reconnectDelay = opts.reconnectDelay ?? DEFAULT_RECONNECT_MS;\n this.maxReconnectDelay = opts.maxReconnectDelay ?? MAX_RECONNECT_MS;\n this.onMessage = opts.onMessage;\n this.onConnectCb = opts.onConnect;\n this.onDisconnect = opts.onDisconnect;\n this.onError = opts.onError;\n }\n\n setSessionManager(manager: SessionManager): void {\n this.sessionManager = manager;\n }\n\n setSwarmCoordinator(coordinator: SwarmCoordinator): void {\n this.swarmCoordinator = coordinator;\n }\n\n registerNamespace(\n namespace: string,\n handler: (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n ) {\n this.namespaceHandlers.set(namespace, handler);\n }\n\n sendPush(namespace: string, event: string, data: Record<string, unknown>) {\n this.send({\n type: \"generic.push\",\n namespace,\n event,\n data,\n });\n }\n\n sendSkillList(skills: Array<{ name: string; description: string }>) {\n this.send({\n type: \"skill_list_update\",\n skills,\n });\n }\n\n get readyState(): number {\n return this.ws?.readyState ?? WebSocket.CLOSED;\n }\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.authState === \"authenticated\";\n }\n\n connect(): void {\n if (this.destroyed) return;\n this.cleanupConnection();\n this.authState = \"pending\";\n\n this.ws = new WebSocket(this.hubUrl);\n\n this.ws.on(\"open\", () => {\n this.reconnectDelay = DEFAULT_RECONNECT_MS;\n });\n\n this.ws.on(\"message\", (raw) => {\n let data: AgentServerMessage;\n try {\n data = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n // Step 1: Hub sends auth_required → reply with auth\n if (this.authState === \"pending\" && data.type === \"auth_required\") {\n log.info(\"hub requires auth, sending credentials\");\n this.authState = \"authenticating\";\n this.sendRaw({\n type: \"auth\",\n token: this.token,\n hostname: this.hostname,\n version: this.version,\n capabilities: this.capabilities,\n });\n return;\n }\n\n // Step 2: Hub sends registered → auth complete\n if (this.authState === \"authenticating\" && data.type === \"registered\") {\n log.info({ agentId: data.agentId }, \"registered with hub\");\n this.authState = \"authenticated\";\n this.agentId = data.agentId ?? null;\n this.startHeartbeat();\n this.onConnectCb?.(this.agentId!);\n\n // Attempt to recover any persisted swarms\n this.tryRecoverSwarms();\n\n // Report any sessions that survived reconnect to Hub\n this.reportLiveSessions();\n return;\n }\n\n // Post-auth message handling\n if (this.authState === \"authenticated\") {\n if (this.handleSessionMessage(data)) return;\n this.onMessage?.(data);\n }\n });\n\n this.ws.on(\"close\", (code, reason) => {\n log.warn({ code, reason: reason.toString() }, \"disconnected from hub\");\n this.stopHeartbeat();\n this.authState = \"pending\";\n this.onDisconnect?.(code, reason.toString());\n if (code === WS_CLOSE_INVALID_TOKEN) {\n log.error(\"auth failed — not reconnecting, check your token\");\n return;\n }\n this.scheduleReconnect();\n });\n\n this.ws.on(\"error\", (err) => {\n log.error({ err }, \"ws connection error\");\n this.onError?.(err);\n });\n }\n\n send(data: AgentClientMessage): boolean {\n // Track swarm completion to prevent accidental recreation\n const msg = data as any;\n if (msg.type === \"swarm.status\" && (msg.swarmStatus === \"completed\" || msg.swarmStatus === \"failed\")) {\n this.finishedSwarms.add(msg.sessionId);\n }\n return this.sendRaw(data);\n }\n\n destroy(): void {\n this.destroyed = true;\n this.cleanup();\n }\n\n // ── Session message handling ─────────────────────────────────────\n\n private handleSessionMessage(msg: AgentServerMessage): boolean {\n // ── Filesystem / history requests (no sessionManager needed) ─────\n\n if (msg.type === \"fs.list_dir\") {\n log.info({ path: msg.path }, \"fs.list_dir\");\n handleListDir(msg.path)\n .then((result) => {\n this.send({ type: \"fs.list_dir_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, path: msg.path }, \"fs.list_dir failed\");\n this.send({\n type: \"fs.list_dir_result\",\n requestId: msg.requestId,\n path: msg.path || \"/\",\n entries: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"list_folders\") {\n log.info(\"list_folders\");\n handleListFolders()\n .then((result) => {\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err }, \"list_folders failed\");\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, folders: [] });\n });\n return true;\n }\n\n if (msg.type === \"list_history_sessions\") {\n log.info({ workDir: msg.workDir }, \"list_history_sessions\");\n handleListHistorySessions(msg.workDir)\n .then((result) => {\n this.send({ type: \"history_sessions_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, workDir: msg.workDir }, \"list_history_sessions failed\");\n this.send({\n type: \"history_sessions_result\",\n requestId: msg.requestId,\n workDir: msg.workDir,\n sessions: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"load_session_history\") {\n log.info({ workDir: msg.workDir, claudeSessionId: msg.claudeSessionId }, \"load_session_history\");\n handleLoadSessionHistory(msg.workDir, msg.claudeSessionId)\n .then((result) => {\n this.send({ type: \"session_history_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, workDir: msg.workDir }, \"load_session_history failed\");\n this.send({ type: \"session_history_result\", requestId: msg.requestId, messages: [] });\n });\n return true;\n }\n\n // ── Swarm handling (requires swarmCoordinator) ──────────────────────\n\n if (msg.type === \"list_roles\") {\n log.info(\"list_roles\");\n const roleNames = listRoles();\n const roles = roleNames.map((name) => {\n try {\n const def = loadRole(name);\n return {\n name: def.name,\n displayName: def.displayName || def.description || def.name,\n description: def.description || \"\",\n capabilities: def.capabilities || [],\n type: def.type,\n color: def.color,\n promptBody: def.promptBody || \"\",\n };\n } catch {\n return { name, displayName: name, description: \"\", capabilities: [], promptBody: \"\" };\n }\n });\n this.send({\n type: \"roles_list_result\",\n sessionId: (msg as any).sessionId,\n roles,\n } as any);\n return true;\n }\n\n if (msg.type === \"list_templates\") {\n log.info(\"list_templates\");\n try {\n const names = listTemplates();\n const templates = names.map((name) => {\n const tpl = loadTemplate(name);\n return {\n name: tpl.name,\n displayName: tpl.displayName,\n description: tpl.description,\n icon: tpl.icon,\n roles: tpl.roles,\n };\n });\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates,\n } as any);\n } catch (err) {\n log.error({ err }, \"list_templates failed\");\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates: [],\n } as any);\n }\n return true;\n }\n\n // ── Generic request: dispatch to registered namespace handlers ──\n if (msg.type === \"generic.request\") {\n const handler = this.namespaceHandlers.get(msg.namespace);\n if (handler) {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request received\");\n handler(msg)\n .then((result) => {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request handled OK\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: result,\n requestId: msg.requestId,\n });\n })\n .catch((err) => {\n log.error({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId, err }, \"generic.request handler error\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n return true;\n }\n log.warn({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request unknown namespace\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: `Unknown namespace: ${msg.namespace}`,\n });\n return true;\n }\n\n if (msg.type === \"swarm.execute\" && this.swarmCoordinator) {\n const { sessionId, content, workDir, targetInstance, crewConfig } = msg;\n\n if (this.swarmCoordinator.hasSwarm(sessionId)) {\n // Existing swarm — forward user message\n log.info({ sessionId, targetInstance }, \"swarm.execute: forwarding to existing swarm\");\n this.swarmCoordinator.handleUserMessage(sessionId, content, targetInstance).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else if (this.finishedSwarms.has(sessionId)) {\n // Swarm completed/failed — recreate to continue if config available\n if (crewConfig?.templateName || crewConfig?.roles) {\n this.finishedSwarms.delete(sessionId);\n const templateName = crewConfig.templateName;\n const roles = crewConfig.roles;\n log.info({ sessionId, templateName, rolesCount: roles?.length }, \"swarm.execute: continuing finished swarm\");\n this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content, isContinuation: true }).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else {\n log.info({ sessionId }, \"swarm.execute ignored: swarm finished, no config to recreate\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"蜂群任务已完成且无法恢复配置。请创建新的蜂群任务。\",\n });\n }\n } else if (crewConfig?.templateName || crewConfig?.roles) {\n // Create new swarm: template-based or direct roles\n const templateName = crewConfig.templateName;\n const roles = crewConfig.roles;\n log.info({ sessionId, templateName, rolesCount: roles?.length }, \"swarm.execute: creating new swarm\");\n this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content }).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else {\n // No swarm and no crewConfig — shouldn't happen normally\n log.info({ sessionId }, \"swarm.execute ignored: swarm not found, no config\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"蜂群任务已完成,无法继续操作。请创建新的蜂群任务。\",\n });\n }\n return true;\n }\n\n // ── Session management (requires sessionManager) ─────────────────\n\n if (!this.sessionManager) return false;\n\n if (msg.type === \"abort_execution\") {\n const { sessionId } = msg;\n log.info({ sessionId }, \"abort_execution\");\n if (this.sessionManager?.hasSession(sessionId)) {\n this.sessionManager.abortSession(sessionId).then(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }).catch(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n });\n } else {\n // No active session — just acknowledge\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }\n return true;\n }\n\n // claude.execute — auto-create session if needed, then send input\n if (msg.type === \"claude.execute\") {\n const { sessionId, content, workDir, claudeSessionId, useBrainCore } = msg;\n if (this.sessionManager.hasSession(sessionId)) {\n log.info({ sessionId }, \"claude.execute: reusing existing session\");\n this.sessionManager.sendInput(sessionId, content);\n } else {\n log.info({ sessionId, workDir, roleId: \"role-__assistant__\" }, \"claude.execute: creating new session with memory injection\");\n this.sessionManager\n .createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore, roleId: \"role-__assistant__\" })\n .then(() => {\n this.sessionManager!.sendInput(sessionId, content);\n })\n .catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n return true;\n }\n\n if (msg.type === \"session.create\") {\n log.info({ sessionId: msg.sessionId, roleId: \"role-__assistant__\" }, \"session.create with memory injection\");\n this.sessionManager\n .createSession({\n sessionId: msg.sessionId,\n workDir: msg.workDir,\n resumeId: msg.resumeId,\n roleId: \"role-__assistant__\",\n })\n .then((claudeSessionId) => {\n this.send({\n type: \"session.created\",\n sessionId: msg.sessionId,\n claudeSessionId,\n });\n })\n .catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId: msg.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n return true;\n }\n\n if (msg.type === \"session.close\") {\n log.info({ sessionId: msg.sessionId }, \"session.close\");\n this.sessionManager.closeSession(msg.sessionId).catch(() => {});\n return true;\n }\n\n if (msg.type === \"claude.input\") {\n log.info({ sessionId: msg.sessionId }, \"claude.input\");\n this.sessionManager.sendInput(msg.sessionId, msg.content);\n return true;\n }\n\n return false;\n }\n\n // ── Internal helpers ─────────────────────────────────────────────\n\n private tryRecoverSwarms(): void {\n if (!this.swarmCoordinator) return;\n try {\n const allIds = listRecoverableSwarmIds();\n const snapshots = listRecoverableSwarms();\n const recoverableIds = new Set(snapshots.map((s) => s.id));\n\n // Clean up expired/completed/failed snapshots\n for (const id of allIds) {\n if (!recoverableIds.has(id)) {\n deleteSwarmSnapshot(id);\n log.info({ swarmId: id }, \"cleaned up non-recoverable swarm snapshot\");\n }\n }\n\n for (const snap of snapshots) {\n log.info({ swarmId: snap.id }, \"recovering swarm\");\n recoverSwarm(this.swarmCoordinator, snap).catch((err) => {\n log.error({ err, swarmId: snap.id }, \"failed to recover swarm\");\n });\n }\n } catch (err) {\n log.error({ err }, \"swarm recovery failed\");\n }\n }\n\n private reportLiveSessions(): void {\n if (!this.sessionManager) return;\n const ids = this.sessionManager.getActiveSessionIds();\n if (ids.length === 0) return;\n log.info({ count: ids.length }, \"reporting live sessions to hub after reconnect\");\n for (const sessionId of ids) {\n this.send({\n type: \"session.state\",\n sessionId,\n processState: \"ready\",\n });\n }\n }\n\n private sendRaw(data: unknown): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n this.ws.send(JSON.stringify(data));\n return true;\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.send({ type: \"heartbeat\", ts: Date.now() });\n }, this.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private scheduleReconnect(): void {\n if (this.destroyed) return;\n log.warn({ delayMs: this.reconnectDelay }, \"reconnecting to hub...\");\n this.reconnectTimer = setTimeout(() => {\n this.connect();\n }, this.reconnectDelay);\n this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);\n }\n\n private cleanup(): void {\n this.cleanupConnection();\n this.sessionManager?.closeAll().catch(() => {});\n }\n\n private cleanupConnection(): void {\n this.stopHeartbeat();\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n this.ws.removeAllListeners();\n if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {\n this.ws.close();\n }\n this.ws = null;\n }\n }\n}\n","import { readdir, stat, readFile } from \"node:fs/promises\";\nimport { existsSync, readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\".git\", \"node_modules\", \"__pycache__\", \".next\", \".nuxt\", \".cache\"]);\n\n// ── fs.list_dir ─────────────────────────────────────────────────────\n\nexport async function handleListDir(\n path: string,\n): Promise<{ path: string; entries: Array<{ name: string; type: \"directory\" | \"file\" }> }> {\n const target = path || homedir();\n const dirents = await readdir(target, { withFileTypes: true });\n\n const entries = dirents\n .filter((d) => !(d.isDirectory() && SKIP_DIRS.has(d.name)))\n .map((d) => ({\n name: d.name,\n type: (d.isDirectory() ? \"directory\" : \"file\") as \"directory\" | \"file\",\n }))\n .sort((a, b) => {\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n\n return { path: target, entries };\n}\n\n// ── list_folders (scan ~/.claude/projects/) ──────────────────────────\n\nfunction getClaudeProjectsDir(): string {\n return join(homedir(), \".claude\", \"projects\");\n}\n\nfunction pathToProjectFolder(workDir: string): string {\n return workDir.replace(/:/g, \"-\").replace(/[/\\\\]/g, \"-\");\n}\n\nfunction extractWorkDirFromSessionFile(filePath: string): string | null {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n for (const line of lines.slice(0, 5)) {\n try {\n const data = JSON.parse(line);\n if (data.cwd) return data.cwd.replace(/\\\\/g, \"/\");\n } catch {}\n }\n } catch {}\n return null;\n}\n\nfunction getWorkDirFromProjectFolder(folderPath: string, folderName: string): string {\n try {\n const files = readdirSync(folderPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n const workDir = extractWorkDirFromSessionFile(join(folderPath, file));\n if (workDir) return workDir;\n }\n }\n } catch {}\n\n // Fallback: simple conversion\n if (/^[A-Za-z]--/.test(folderName)) {\n return folderName.replace(/^([A-Za-z])--/, \"$1:/\").replace(/-/g, \"/\");\n }\n if (folderName.startsWith(\"-\")) {\n return \"/\" + folderName.substring(1).replace(/-/g, \"/\");\n }\n return folderName.replace(/-/g, \"/\");\n}\n\nexport async function handleListFolders(): Promise<{\n folders: Array<{ path: string; sessionCount: number; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const folders: Array<{ path: string; sessionCount: number; lastModified?: number }> = [];\n\n if (!existsSync(projectsDir)) return { folders };\n\n const entries = readdirSync(projectsDir);\n for (const entry of entries) {\n const entryPath = join(projectsDir, entry);\n let entryStat;\n try {\n entryStat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!entryStat.isDirectory()) continue;\n\n // Skip crew role directories\n if (entry.includes(\"--crew-roles-\")) continue;\n\n const originalPath = getWorkDirFromProjectFolder(entryPath, entry);\n\n let sessionCount = 0;\n let lastModified = entryStat.mtime.getTime();\n\n try {\n const files = readdirSync(entryPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n sessionCount++;\n try {\n const fileStats = statSync(join(entryPath, file));\n if (fileStats.mtime.getTime() > lastModified) {\n lastModified = fileStats.mtime.getTime();\n }\n } catch {}\n }\n }\n } catch {}\n\n folders.push({ path: originalPath, sessionCount, lastModified });\n }\n\n folders.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { folders };\n}\n\n// ── list_history_sessions ───────────────────────────────────────────\n\nexport async function handleListHistorySessions(workDir: string): Promise<{\n workDir: string;\n sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const projectFolder = pathToProjectFolder(workDir);\n const projectPath = join(projectsDir, projectFolder);\n\n if (!existsSync(projectPath)) {\n return { workDir, sessions: [] };\n }\n\n const sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }> = [];\n const files = readdirSync(projectPath);\n\n for (const file of files) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const sessionId = file.replace(\".jsonl\", \"\");\n const filePath = join(projectPath, file);\n let fileStats;\n try {\n fileStats = statSync(filePath);\n } catch {\n continue;\n }\n\n let title = \"\";\n let hasUserMessage = false;\n let customTitle = \"\";\n let jsonlSummary = \"\";\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line);\n if (!hasUserMessage && data.type === \"user\" && data.message?.content) {\n const text =\n typeof data.message.content === \"string\"\n ? data.message.content\n : data.message.content[0]?.text || \"\";\n if (text.trim()) {\n title = text.substring(0, 100);\n hasUserMessage = true;\n }\n }\n if (data.type === \"custom-title\" && data.customTitle) {\n customTitle = data.customTitle;\n }\n if (data.type === \"summary\" && data.summary) {\n jsonlSummary = data.summary;\n }\n } catch {}\n }\n } catch {}\n\n if (hasUserMessage) {\n sessions.push({\n sessionId,\n title: customTitle || jsonlSummary || title || sessionId.slice(0, 8),\n workDir,\n lastModified: fileStats.mtime.getTime(),\n });\n }\n }\n\n sessions.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { workDir, sessions };\n}\n\n// ── load_session_history ────────────────────────────────────────────\n\ninterface HistoryMessage {\n role: \"user\" | \"assistant\";\n content: string;\n toolCalls?: Array<{ name: string; input?: string; output?: string; status: string }>;\n thinking?: string;\n}\n\nexport async function handleLoadSessionHistory(\n workDir: string,\n claudeSessionId: string,\n): Promise<{ messages: HistoryMessage[] }> {\n const projectsDir = getClaudeProjectsDir();\n const projectFolder = pathToProjectFolder(workDir);\n const filePath = join(projectsDir, projectFolder, `${claudeSessionId}.jsonl`);\n\n if (!existsSync(filePath)) {\n return { messages: [] };\n }\n\n const messages: HistoryMessage[] = [];\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line);\n\n if (data.type === \"user\" && data.message?.content) {\n const blocks = Array.isArray(data.message.content)\n ? data.message.content\n : [{ type: \"text\", text: String(data.message.content) }];\n\n // Extract user text (only text blocks, skip tool_result etc.)\n const textParts: string[] = [];\n for (const block of blocks) {\n if (block.type === \"text\" && block.text?.trim()) {\n textParts.push(block.text);\n }\n }\n if (textParts.length > 0) {\n messages.push({ role: \"user\", content: textParts.join(\"\\n\") });\n }\n\n // Attach tool_result outputs to the last assistant's toolCalls\n const lastAssistant = messages.length > 0\n ? [...messages].reverse().find((m) => m.role === \"assistant\" && m.toolCalls?.length)\n : undefined;\n if (lastAssistant?.toolCalls) {\n for (const block of blocks) {\n if (block.type === \"tool_result\") {\n // Match by tool_use_id or just fill the next pending one\n const pending = lastAssistant.toolCalls.find((tc) => !tc.output);\n if (pending) {\n pending.output = typeof block.content === \"string\"\n ? block.content\n : Array.isArray(block.content)\n ? block.content.map((c: any) => c.text ?? \"\").join(\"\")\n : JSON.stringify(block.content);\n pending.status = block.is_error ? \"error\" : \"done\";\n }\n }\n }\n }\n }\n\n if (data.type === \"assistant\" && data.message?.content) {\n let text = \"\";\n const toolCalls: HistoryMessage[\"toolCalls\"] = [];\n let thinking = \"\";\n\n for (const block of data.message.content) {\n if (block.type === \"text\") {\n text += block.text;\n } else if (block.type === \"tool_use\") {\n toolCalls.push({\n name: block.name,\n input: typeof block.input === \"string\" ? block.input : JSON.stringify(block.input, null, 2),\n status: \"done\",\n });\n } else if (block.type === \"thinking\") {\n thinking += block.thinking ?? \"\";\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n thinking: thinking || undefined,\n });\n }\n } catch {}\n }\n } catch {}\n\n // Return last 50 messages to avoid overloading\n return { messages: messages.slice(-50) };\n}\n","import { createLogger } from \"@mclawnet/logger\";\nimport { buildMemorySection } from \"@mclawnet/memory\";\nimport type { BackendAdapter, BackendProcess, SpawnOptions } from \"./backend-adapter.js\";\n\nconst log = createLogger({ module: \"agent/session-manager\" });\n\nconst DEFAULT_MAX_PROCESSES = 10;\nconst MAX_PROCESSES = Number(process.env.CLAWNET_MAX_PROCESSES) || DEFAULT_MAX_PROCESSES;\n\n/**\n * Manages active sessions, mapping ClawNet session IDs to BackendProcess instances.\n *\n * When `options.roleId` is set, the manager automatically injects:\n * - Pipeline A: memory prompt + roleId hint via `--append-system-prompt`\n *\n * Note: MCP config is now handled globally via ~/.clawnet/mcp.json\n * (mounted by ClaudeCodeAdapter), no longer generated per-session.\n */\nexport class SessionManager {\n private sessions = new Map<string, BackendProcess>();\n private conversationBuffer = new Map<string, Array<{ role: string; content: string }>>();\n private adapter: BackendAdapter;\n private onOutput: (sessionId: string, data: unknown) => void;\n private onTurnComplete: (\n sessionId: string,\n info: {\n claudeSessionId?: string;\n cost?: number;\n duration?: number;\n contextUsage?: { used: number; total: number };\n },\n ) => void;\n private onSessionError: (sessionId: string, error: string) => void;\n private onBeforeClose?: (sessionId: string, messages: Array<{ role: string; content: string }>) => Promise<void>;\n\n constructor(options: {\n adapter: BackendAdapter;\n onOutput: (sessionId: string, data: unknown) => void;\n onTurnComplete: (\n sessionId: string,\n info: {\n claudeSessionId?: string;\n cost?: number;\n duration?: number;\n contextUsage?: { used: number; total: number };\n },\n ) => void;\n onSessionError: (sessionId: string, error: string) => void;\n onBeforeClose?: (sessionId: string, messages: Array<{ role: string; content: string }>) => Promise<void>;\n }) {\n this.adapter = options.adapter;\n this.onOutput = options.onOutput;\n this.onTurnComplete = options.onTurnComplete;\n this.onSessionError = options.onSessionError;\n this.onBeforeClose = options.onBeforeClose;\n }\n\n async createSession(options: SpawnOptions): Promise<string> {\n if (this.sessions.has(options.sessionId)) {\n throw new Error(`Session ${options.sessionId} already exists`);\n }\n\n if (this.sessions.size >= MAX_PROCESSES) {\n throw new Error(`Process limit reached (${MAX_PROCESSES}). Cannot create new session.`);\n }\n\n // ── Unified memory injection ──\n if (options.roleId) {\n // Pipeline A: prepend memory section + roleId hint to system prompt\n try {\n const memorySection = buildMemorySection(options.roleId);\n const roleHint = `\\n\\n[Memory Context] Your roleId is \"${options.roleId}\". Always use this roleId when calling memory_search, memory_store, memory_stats, or memory_reflect.`;\n options.systemPrompt = options.systemPrompt\n ? `${memorySection}${roleHint}\\n\\n${options.systemPrompt}`\n : `${memorySection}${roleHint}`;\n log.debug({ roleId: options.roleId, sessionId: options.sessionId }, \"memory prompt + roleId hint injected\");\n } catch (err) {\n log.warn({ err, roleId: options.roleId }, \"failed to build memory section, proceeding without\");\n }\n }\n\n try {\n const process = await this.adapter.spawn(options);\n this.sessions.set(options.sessionId, process);\n\n // Wire up output handler\n this.adapter.onOutput(process, (data) => {\n // Accumulate assistant text messages for distillation\n const msg = data as any;\n if (msg?.type === \"assistant\" && msg?.message?.content) {\n const buf = this.conversationBuffer.get(options.sessionId) ?? [];\n // Extract text from content blocks\n const text = Array.isArray(msg.message.content)\n ? msg.message.content.filter((b: any) => b.type === \"text\").map((b: any) => b.text).join(\"\\n\")\n : String(msg.message.content);\n if (text) {\n buf.push({ role: \"assistant\", content: text });\n this.conversationBuffer.set(options.sessionId, buf);\n }\n }\n this.onOutput(options.sessionId, data);\n });\n\n // Wire up turn-complete handler\n this.adapter.onTurnComplete?.(process, (info) => {\n this.onTurnComplete(options.sessionId, info);\n });\n\n // Wire up error handler\n this.adapter.onError?.(process, (error) => {\n this.onSessionError(options.sessionId, error.message);\n });\n\n return process.id;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.onSessionError(options.sessionId, message);\n throw err;\n }\n }\n\n sendInput(sessionId: string, input: string): void {\n const process = this.sessions.get(sessionId);\n if (!process) {\n this.onSessionError(sessionId, `No active session: ${sessionId}`);\n return;\n }\n this.adapter.send(process, input);\n }\n\n async abortSession(sessionId: string): Promise<void> {\n const process = this.sessions.get(sessionId);\n if (!process) return;\n this.conversationBuffer.delete(sessionId);\n this.sessions.delete(sessionId);\n await this.adapter.stop(process);\n }\n\n async closeSession(sessionId: string): Promise<void> {\n const process = this.sessions.get(sessionId);\n if (!process) return;\n\n // Trigger distillation before closing\n const messages = this.conversationBuffer.get(sessionId);\n if (this.onBeforeClose && messages?.length) {\n await this.onBeforeClose(sessionId, messages).catch(() => {});\n }\n this.conversationBuffer.delete(sessionId);\n\n this.sessions.delete(sessionId);\n await this.adapter.stop(process);\n }\n\n async closeAll(): Promise<void> {\n const promises = Array.from(this.sessions.entries()).map(\n async ([sessionId, process]) => {\n // Trigger distillation before closing\n const messages = this.conversationBuffer.get(sessionId);\n if (this.onBeforeClose && messages?.length) {\n await this.onBeforeClose(sessionId, messages).catch(() => {});\n }\n this.conversationBuffer.delete(sessionId);\n this.sessions.delete(sessionId);\n await this.adapter.stop(process).catch(() => {});\n },\n );\n await Promise.all(promises);\n }\n\n hasSession(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n get activeSessionCount(): number {\n return this.sessions.size;\n }\n\n getActiveSessionIds(): string[] {\n return Array.from(this.sessions.keys());\n }\n}\n","import { loadConfig, type AgentConfig } from \"./config.js\";\nimport { HubConnection } from \"./hub-connection.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { SwarmCoordinator, initRoles } from \"@mclawnet/swarm\";\nimport { initSkills, getSkillList } from \"./skill-loader.js\";\nimport { BrainBridge } from \"./brain-bridge.js\";\nimport { FsBridge } from \"./fs-bridge.js\";\nimport type { BackendAdapter } from \"./backend-adapter.js\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface StartOptions {\n config?: Partial<AgentConfig>;\n adapter: BackendAdapter;\n}\n\n/**\n * Start the ClawNet agent: connect to Hub and register a BackendAdapter.\n */\nexport async function startAgent(options: StartOptions): Promise<{\n hub: HubConnection;\n sessionManager: SessionManager;\n swarmCoordinator: SwarmCoordinator;\n brainBridge: BrainBridge;\n fsBridge: FsBridge;\n}> {\n const config = loadConfig(options.config);\n\n if (!config.token) {\n log.error(\"no token configured — set CLAWNET_TOKEN or use --token\");\n process.exit(1);\n }\n\n log.info({ backend: options.adapter.type }, \"starting agent\");\n log.info({ hubUrl: config.hubUrl }, \"connecting to hub\");\n\n // Initialize role templates\n await initRoles();\n\n // Initialize skill system (copy built-in skills + ensure mcp.json)\n await initSkills();\n\n const hub = new HubConnection({\n hubUrl: config.hubUrl,\n token: config.token,\n hostname: config.name,\n onConnect: (agentId) => {\n log.info({ agentId }, \"connected to hub\");\n // Push available skills to browsers via Hub\n const skills = getSkillList();\n if (skills.length > 0) {\n hub.sendSkillList(skills);\n log.info({ count: skills.length }, \"pushed skill list to hub\");\n }\n },\n onDisconnect: (code, reason) => {\n log.info({ code, reason }, \"disconnected from hub\");\n },\n onError: (err) => {\n log.error({ err }, \"hub connection error\");\n },\n });\n\n // Create SwarmCoordinator (needs hub reference; sessionManager set after construction)\n // We use a lazy reference so the coordinator can be created before sessionManager\n let swarmCoordinator: SwarmCoordinator;\n\n const sessionManager = new SessionManager({\n adapter: options.adapter,\n onOutput: (sessionId, data) => {\n // Intercept swarm role output\n if (swarmCoordinator.handleRoleOutput(sessionId, data)) return;\n\n // Normal (non-swarm) session output\n hub.send({\n type: \"claude.output\",\n sessionId,\n data,\n });\n },\n onTurnComplete: (sessionId, info) => {\n // Intercept swarm role turn completion\n if (swarmCoordinator.handleRoleTurnComplete(sessionId, info)) return;\n\n // Normal (non-swarm) session\n hub.send({\n type: \"claude.turn_complete\",\n sessionId,\n cost: info.cost,\n duration: info.duration,\n contextUsage: info.contextUsage,\n });\n },\n onSessionError: (sessionId, error) => {\n hub.send({\n type: \"session.error\",\n sessionId,\n error,\n });\n },\n });\n\n swarmCoordinator = new SwarmCoordinator(sessionManager, hub);\n\n hub.setSessionManager(sessionManager);\n hub.setSwarmCoordinator(swarmCoordinator);\n\n // Initialize BrainBridge (registers \"brain\" namespace handler)\n const brainBridge = new BrainBridge(hub);\n\n // Initialize FsBridge (registers \"fs\" namespace handler)\n const fsBridge = new FsBridge(hub);\n\n // Graceful shutdown\n const shutdown = async () => {\n log.info(\"shutting down\");\n await sessionManager.closeAll();\n hub.destroy();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n hub.connect();\n\n return { hub, sessionManager, swarmCoordinator, brainBridge, fsBridge };\n}\n","import { existsSync, mkdirSync, copyFileSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent/skill-loader\" });\n\n/** ~/.clawnet base directory */\nconst CLAWNET_DIR = join(homedir(), \".clawnet\");\n/** Skill target directory: ~/.clawnet/.claude/skills/ */\nconst SKILLS_DIR = join(CLAWNET_DIR, \".claude\", \"skills\");\n/** MCP config file: ~/.clawnet/mcp.json */\nconst MCP_CONFIG_PATH = join(CLAWNET_DIR, \"mcp.json\");\n\n/**\n * Initialize ClawNet skill system:\n * 1. Ensure skill directory exists\n * 2. Copy built-in skills (don't overwrite existing)\n * 3. Ensure MCP config exists\n */\nexport async function initSkills(): Promise<void> {\n ensureSkillsDir();\n copyBuiltinSkills();\n ensureMcpConfig();\n scanSkills();\n}\n\n/** Create ~/.clawnet/.claude/skills/ if it doesn't exist. */\nfunction ensureSkillsDir(): void {\n if (!existsSync(SKILLS_DIR)) {\n mkdirSync(SKILLS_DIR, { recursive: true });\n log.info({ dir: SKILLS_DIR }, \"created skills directory\");\n }\n}\n\n/** Copy built-in skills from agent package to ~/.clawnet/.claude/skills/. */\nfunction copyBuiltinSkills(): void {\n // Built-in skills are in packages/@clawnet/agent/skills/\n const thisFile = fileURLToPath(import.meta.url);\n const srcDir = join(dirname(thisFile), \"..\", \"skills\");\n\n if (!existsSync(srcDir)) {\n log.debug({ srcDir }, \"no built-in skills directory found, skipping\");\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(srcDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch {\n log.warn({ srcDir }, \"failed to read built-in skills directory\");\n return;\n }\n\n for (const skillName of entries) {\n const srcSkillMd = join(srcDir, skillName, \"SKILL.md\");\n const destDir = join(SKILLS_DIR, skillName);\n const destSkillMd = join(destDir, \"SKILL.md\");\n\n if (!existsSync(srcSkillMd)) continue;\n if (existsSync(destSkillMd)) {\n log.debug({ skill: skillName }, \"skill already exists, skipping\");\n continue;\n }\n\n try {\n mkdirSync(destDir, { recursive: true });\n copyFileSync(srcSkillMd, destSkillMd);\n log.info({ skill: skillName }, \"copied built-in skill\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to copy built-in skill\");\n }\n }\n}\n\nexport interface SkillInfo {\n name: string;\n description: string;\n}\n\n/** Cached skill list, populated by scanSkills(). */\nlet cachedSkills: SkillInfo[] = [];\n\n/**\n * Scan ~/.clawnet/.claude/skills/ and parse SKILL.md frontmatter\n * to build a list of { name, description }.\n */\nexport function scanSkills(): SkillInfo[] {\n if (!existsSync(SKILLS_DIR)) return [];\n\n let dirs: string[];\n try {\n dirs = readdirSync(SKILLS_DIR, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch {\n log.warn(\"failed to read skills directory for scanning\");\n return [];\n }\n\n const skills: SkillInfo[] = [];\n for (const dirName of dirs) {\n const skillMd = join(SKILLS_DIR, dirName, \"SKILL.md\");\n if (!existsSync(skillMd)) continue;\n\n try {\n const content = readFileSync(skillMd, \"utf-8\");\n const parsed = parseFrontmatter(content);\n if (parsed.name) {\n skills.push({\n name: parsed.name,\n description: parsed.description || dirName,\n });\n }\n } catch (err) {\n log.debug({ skill: dirName, err }, \"failed to parse SKILL.md frontmatter\");\n }\n }\n\n cachedSkills = skills;\n log.info({ count: skills.length }, \"scanned skills\");\n return skills;\n}\n\n/** Get the cached skill list (call scanSkills() first). */\nexport function getSkillList(): SkillInfo[] {\n return cachedSkills;\n}\n\n/** Parse YAML frontmatter from SKILL.md content. */\nfunction parseFrontmatter(content: string): { name: string; description: string } {\n const match = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!match) return { name: \"\", description: \"\" };\n\n const yaml = match[1];\n const nameMatch = yaml.match(/^name:\\s*(.+)$/m);\n const descMatch = yaml.match(/^description:\\s*(.+)$/m);\n const strip = (s: string) => s.trim().replace(/^[\"']|[\"']$/g, \"\");\n return {\n name: strip(nameMatch?.[1] ?? \"\"),\n description: strip(descMatch?.[1] ?? \"\"),\n };\n}\n\n/** Generate ~/.clawnet/mcp.json with default memory MCP config if it doesn't exist. */\nfunction ensureMcpConfig(): void {\n if (existsSync(MCP_CONFIG_PATH)) {\n log.debug(\"mcp.json already exists, skipping\");\n return;\n }\n\n // Resolve the memory MCP server.js path from the installed package\n let mcpServerPath: string;\n try {\n const req = createRequire(import.meta.url);\n const memoryPkgDir = dirname(req.resolve(\"@mclawnet/memory/package.json\"));\n mcpServerPath = join(memoryPkgDir, \"dist\", \"mcp\", \"server.js\");\n } catch {\n log.warn(\"could not resolve @mclawnet/memory package path, skipping mcp.json generation\");\n return;\n }\n\n const config = {\n mcpServers: {\n \"clawnet-memory\": {\n command: \"node\",\n args: [mcpServerPath],\n },\n },\n };\n\n try {\n // Ensure ~/.clawnet/ exists\n mkdirSync(CLAWNET_DIR, { recursive: true });\n writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\");\n log.info({ path: MCP_CONFIG_PATH }, \"generated default mcp.json\");\n } catch (err) {\n log.warn({ err }, \"failed to generate mcp.json\");\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"brain-bridge\" });\n\nexport type BrainSetupStatus = \"not_installed\" | \"needs_config\" | \"ready\";\n\nexport interface BrainBridgeOptions {\n brainHomePath?: string;\n brainCorePath?: string;\n}\n\nexport class BrainBridge {\n private brainHome: string;\n private brainCorePath: string;\n\n constructor(\n private hub: HubConnection,\n options?: BrainBridgeOptions\n ) {\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n this.brainHome =\n options?.brainHomePath ||\n process.env.BRAIN_HOME ||\n join(home, \"BrainData\");\n this.brainCorePath =\n options?.brainCorePath || join(home, \".brain\", \"BrainCore\");\n\n this.hub.registerNamespace(\"brain\", (msg) => this.handleRequest(msg));\n log.info(\n { brainHome: this.brainHome, brainCorePath: this.brainCorePath },\n \"BrainBridge initialized\"\n );\n }\n\n async handleRequest(\n msg: AgentGenericRequest\n ): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"brain request\");\n switch (msg.action) {\n case \"setup_status\": {\n const status = this.checkSetup();\n log.info({ status }, \"setup_status result\");\n return { status };\n }\n case \"get_briefing\":\n return await this.getBriefing(msg.params.date as string | undefined);\n case \"get_meeting_recap\":\n return await this.getMeetingRecap(msg.params.recapPath as string);\n default:\n log.warn({ action: msg.action }, \"unknown brain action\");\n throw new Error(`Unknown brain action: ${msg.action}`);\n }\n }\n\n checkSetup(): BrainSetupStatus {\n if (!existsSync(this.brainCorePath)) {\n return \"not_installed\";\n }\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n const installJson = join(home, \".brain\", \"install.json\");\n if (!existsSync(installJson)) {\n return \"needs_config\";\n }\n if (!existsSync(this.brainHome)) {\n return \"needs_config\";\n }\n return \"ready\";\n }\n\n /** Read the most recent daily briefing report */\n private async getBriefing(\n date?: string\n ): Promise<Record<string, unknown>> {\n const targetDate = date || new Date().toISOString().slice(0, 10);\n const reportsDir = join(this.brainHome, \"reports\", \"daily\");\n\n if (!existsSync(reportsDir)) {\n log.info({ reportsDir }, \"get_briefing: reports dir not found\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n const files = readdirSync(reportsDir)\n .filter((f: string) => f.includes(targetDate) && f.endsWith(\".md\"))\n .sort()\n .reverse();\n\n if (files.length === 0) {\n log.info({ targetDate }, \"get_briefing: no report for date\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n log.info({ targetDate, file: files[0] }, \"get_briefing: reading report\");\n\n const content = readFileSync(join(reportsDir, files[0]), \"utf-8\");\n\n // Extract TL;DR\n const tldrMatch = content.match(/## TL;DR\\n([\\s\\S]*?)(?=\\n---|\\n## )/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);\n\n const actions = this.parseActions(content);\n const projects = this.parseProjects(content);\n const meetings = this.parseMeetings(content);\n const feed = this.parseFeed(content);\n\n log.info(\n { actions: actions.length, projects: projects.length, meetings: meetings.length, feed: feed.length },\n \"get_briefing: parsed\"\n );\n\n return {\n briefing: {\n date: targetDate,\n tldr,\n generatedAt: new Date().toISOString(),\n },\n actions,\n projects,\n meetings,\n feed,\n };\n }\n\n /** Parse \"## Action Required\" section into ActionItem[] */\n private parseActions(content: string): Array<Record<string, unknown>> {\n const sectionMatch = content.match(/## Action Required\\n([\\s\\S]*?)(?=\\n---|\\n## [^A])/);\n if (!sectionMatch) return [];\n\n const section = sectionMatch[1];\n const items: Array<Record<string, unknown>> = [];\n let currentPriority: string = \"p3\";\n let idCounter = 0;\n\n for (const line of section.split(\"\\n\")) {\n // Detect priority headers\n if (line.includes(\"🔴 Today\")) { currentPriority = \"p1\"; continue; }\n if (line.includes(\"🟡 This Week\")) { currentPriority = \"p2\"; continue; }\n if (line.includes(\"⚪ FYI\") || line.includes(\"FYI —\")) { currentPriority = \"p4\"; continue; }\n\n // Numbered items: \"1. **Title** → description\"\n const numberedMatch = line.match(/^\\d+\\.\\s+\\*\\*(.+?)\\*\\*\\s*[→—–-]\\s*(.+)/);\n if (numberedMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: currentPriority,\n title: `${numberedMatch[1].trim()} — ${numberedMatch[2].trim()}`,\n source: this.guessSource(numberedMatch[2]),\n timeAgo: \"\",\n done: false,\n });\n continue;\n }\n\n // Bullet items under FYI: \"- description\"\n if (currentPriority === \"p4\") {\n const bulletMatch = line.match(/^-\\s+(.+)/);\n if (bulletMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: \"p4\",\n title: bulletMatch[1].replace(/\\*\\*/g, \"\").trim(),\n source: this.guessSource(bulletMatch[1]),\n timeAgo: \"\",\n done: false,\n });\n }\n }\n }\n\n return items;\n }\n\n /** Parse project sections \"## 🔵 ProjectName\" with Status tables */\n private parseProjects(content: string): Array<Record<string, unknown>> {\n const projects: Array<Record<string, unknown>> = [];\n // Match \"## 🔵 ProjectName\" sections\n const projectRegex = /## 🔵\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let match;\n\n while ((match = projectRegex.exec(content)) !== null) {\n const name = match[1].trim();\n const body = match[2];\n\n // Parse status table: | 🟡 At Risk | ... | or | 🟢 On Track | ... |\n let status: string = \"on_track\";\n const statusMatch = body.match(/\\|\\s*(🟡|🔴|🟢)\\s*(.*?)\\s*\\|/);\n if (statusMatch) {\n const icon = statusMatch[1];\n if (icon === \"🔴\") status = \"blocked\";\n else if (icon === \"🟡\") status = \"blocked\";\n else if (icon === \"🟢\") status = \"good\";\n }\n\n // Count \"Teams Chats\" subsections (#### headers under ### Teams Chats)\n const teamsSection = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n let newMessages = 0;\n if (teamsSection) {\n const chatHeaders = teamsSection[1].match(/^####/gm);\n newMessages = chatHeaders ? chatHeaders.length : 0;\n }\n\n // Count \"Key Decisions\" items\n let pendingDecisions = 0;\n const decisionsMatches = body.match(/\\*\\*\\[(?:Decided|Leaning)\\]\\*\\*/g);\n if (decisionsMatches) pendingDecisions = decisionsMatches.length;\n\n projects.push({\n slug: name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\"),\n name,\n status,\n newMessages,\n pendingDecisions,\n });\n }\n\n return projects;\n }\n\n /** Parse meetings from \"### Meetings\" subsections */\n private parseMeetings(content: string): Array<Record<string, unknown>> {\n const meetings: Array<Record<string, unknown>> = [];\n // Find all \"#### MeetingTitle\" under \"### Meetings\" sections\n const meetingSectionRegex = /### Meetings\\n([\\s\\S]*?)(?=\\n### [^M]|\\n---|\\n## |$)/g;\n let sectionMatch;\n let idCounter = 0;\n\n while ((sectionMatch = meetingSectionRegex.exec(content)) !== null) {\n const section = sectionMatch[1];\n // Each meeting: \"#### Title\\n\\n📅 time | status | participants | host\"\n const meetingRegex = /####\\s+(.+)\\n\\n📅\\s*(\\S+)\\s+\\w+\\s*\\|\\s*(\\w+)/g;\n let m;\n\n while ((m = meetingRegex.exec(section)) !== null) {\n const title = m[1].trim();\n const time = m[2].trim();\n const statusWord = m[3].toLowerCase();\n\n let status = \"completed\";\n if (statusWord === \"missed\") status = \"completed\"; // still show recap\n else if (statusWord === \"upcoming\") status = \"upcoming\";\n else if (statusWord.includes(\"progress\")) status = \"in_progress\";\n\n // Get the text slice for this specific meeting (from current match to next #### or section end)\n const meetingEndIdx = section.indexOf(\"\\n####\", m.index + m[0].length);\n const meetingSlice = meetingEndIdx !== -1\n ? section.slice(m.index, meetingEndIdx)\n : section.slice(m.index);\n\n const recapMatch = meetingSlice.match(/📎\\s*\\[Full recap\\]\\((.+?)\\)/);\n const recapPath = recapMatch ? recapMatch[1] : undefined;\n\n meetings.push({\n id: `meeting-${++idCounter}`,\n time,\n title,\n status,\n hasRecap: !!recapPath,\n recapPath,\n });\n }\n }\n\n return meetings;\n }\n\n /** Parse feed items from Teams Chats subsections across all project sections and Announcements */\n private parseFeed(content: string): Array<Record<string, unknown>> {\n const items: Array<Record<string, unknown>> = [];\n let idCounter = 0;\n\n // 1) Extract feed items from \"### Teams Chats\" under \"## 🔵 ProjectName\" sections\n const projectRegex = /## 🔵\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let projectMatch;\n\n while ((projectMatch = projectRegex.exec(content)) !== null) {\n const projectName = projectMatch[1].trim();\n const projectBody = projectMatch[2];\n\n this.extractTeamsChatItems(projectBody, projectName, items, idCounter);\n idCounter = items.length;\n }\n\n // 2) Extract feed items from \"## 📢 Announcements & FYI\" section (no project)\n const announcementMatch = content.match(/## 📢\\s+Announcements[^\\n]*\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (announcementMatch) {\n this.extractTeamsChatItems(announcementMatch[1], \"\", items, idCounter);\n }\n\n return items;\n }\n\n /** Extract chat items from a \"### Teams Chats\" subsection within a body block */\n private extractTeamsChatItems(\n body: string,\n project: string,\n items: Array<Record<string, unknown>>,\n _startId: number\n ): void {\n // Find \"### Teams Chats\" subsection\n const teamsChatMatch = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n if (!teamsChatMatch) return;\n\n const teamsSection = teamsChatMatch[1];\n\n // Find \"#### ChatTitle — Priority\" headers and their content\n const chatRegex = /####\\s+(.+?)(?:\\s*—\\s*(.+))?\\n([\\s\\S]*?)(?=\\n####|\\n###|\\n---|$)/g;\n let chatMatch;\n\n while ((chatMatch = chatRegex.exec(teamsSection)) !== null) {\n const chatBody = chatMatch[3];\n\n // Extract bold names like **Person Name** as sender\n const senderMatch = chatBody.match(/\\*\\*(.+?)\\*\\*/);\n const sender = senderMatch ? senderMatch[1].trim() : \"Unknown\";\n\n // Extract content: first meaningful line after the sender, or first sentence\n let contentPreview = \"\";\n const lines = chatBody.split(\"\\n\").filter((l: string) => l.trim().length > 0);\n for (const line of lines) {\n // Skip lines that are just metadata (timestamps, status indicators)\n const cleaned = line.replace(/\\*\\*.*?\\*\\*/g, \"\").replace(/[>*-]/g, \"\").trim();\n if (cleaned.length > 10) {\n contentPreview = cleaned.slice(0, 100);\n break;\n }\n }\n // Fallback: use the entire chat body trimmed\n if (!contentPreview && lines.length > 0) {\n contentPreview = lines[0].replace(/\\*\\*/g, \"\").trim().slice(0, 100);\n }\n\n // Try to extract a time from the body (e.g., \"10:30\" or \"14:23\")\n const timeMatch = chatBody.match(/(\\d{1,2}:\\d{2})/);\n const time = timeMatch ? timeMatch[1] : \"\";\n\n items.push({\n id: `feed-${items.length + 1}`,\n time,\n source: \"teams\",\n sender,\n content: contentPreview,\n project: project || undefined,\n });\n }\n }\n\n /** Fetch and parse a meeting recap file */\n private async getMeetingRecap(recapPath: string): Promise<Record<string, unknown>> {\n if (!recapPath) {\n return { error: \"No recap path provided\" };\n }\n const fullPath = join(this.brainHome, recapPath);\n if (!existsSync(fullPath)) {\n log.warn({ fullPath }, \"meeting recap file not found\");\n return { error: \"Recap file not found\" };\n }\n const content = readFileSync(fullPath, \"utf-8\");\n return { recap: this.parseRecapMarkdown(content) };\n }\n\n /** Parse meeting recap markdown into structured sections */\n private parseRecapMarkdown(content: string): Record<string, unknown> {\n // Extract TL;DR / Summary section\n const tldrMatch = content.match(/##\\s*(?:TL;DR|Summary|概要)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : \"\";\n\n // Extract \"Relevant to You\" / \"与你相关\" section\n const relevantMatch = content.match(/##\\s*(?:与你相关|Relevant|For You|Action for You)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const relevant = relevantMatch ? relevantMatch[1].trim() : \"\";\n\n // Extract \"Decisions\" / \"决定事项\" / \"Key Decisions\" section\n const decisionsMatch = content.match(/##\\s*(?:决定事项|Decisions|Key Decisions)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const decisions = decisionsMatch ? decisionsMatch[1].trim() : \"\";\n\n // Extract \"Action Items\" / \"行动项\" section\n const actionsMatch = content.match(/##\\s*(?:行动项|Action Items|Next Steps)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const actionItems = actionsMatch ? actionsMatch[1].trim() : \"\";\n\n return {\n tldr,\n relevant,\n decisions,\n actionItems,\n rawMarkdown: content,\n };\n }\n\n /** Guess message source from text content */\n private guessSource(text: string): string {\n const lower = text.toLowerCase();\n if (lower.includes(\"teams\")) return \"teams\";\n if (lower.includes(\"email\") || lower.includes(\"mail\")) return \"email\";\n if (lower.includes(\"meeting\") || lower.includes(\"sync\")) return \"meeting\";\n if (lower.includes(\"pr\") || lower.includes(\"ado\") || lower.includes(\"work item\")) return \"ado\";\n return \"teams\";\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { extname, isAbsolute } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"fs-bridge\" });\n\nconst MAX_TEXT_SIZE = 5 * 1024 * 1024; // 5MB\n\nconst MIME_MAP: Record<string, string> = {\n \".ts\": \"text/typescript\", \".tsx\": \"text/typescript\",\n \".js\": \"text/javascript\", \".jsx\": \"text/javascript\",\n \".json\": \"application/json\", \".html\": \"text/html\",\n \".css\": \"text/css\", \".md\": \"text/markdown\",\n \".py\": \"text/x-python\", \".sh\": \"text/x-shellscript\",\n \".yaml\": \"text/yaml\", \".yml\": \"text/yaml\",\n \".xml\": \"text/xml\", \".sql\": \"text/x-sql\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\", \".jpg\": \"image/jpeg\", \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\", \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\", \".webm\": \"video/webm\",\n \".mp3\": \"audio/mpeg\", \".wav\": \"audio/wav\",\n};\n\nfunction getMimeType(filePath: string): string {\n return MIME_MAP[extname(filePath).toLowerCase()] || \"application/octet-stream\";\n}\n\nfunction isTextMime(mime: string): boolean {\n return mime.startsWith(\"text/\") || mime === \"application/json\" || mime === \"image/svg+xml\";\n}\n\nexport class FsBridge {\n constructor(private hub: HubConnection) {\n this.hub.registerNamespace(\"fs\", (msg) => this.handleRequest(msg));\n log.info(\"FsBridge initialized\");\n }\n\n async handleRequest(msg: AgentGenericRequest): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"fs request\");\n switch (msg.action) {\n case \"read\":\n return this.readFile(msg.params);\n default:\n throw new Error(`Unknown fs action: ${msg.action}`);\n }\n }\n\n private readFile(params: Record<string, unknown>): Record<string, unknown> {\n const filePath = params.path as string;\n if (!filePath) throw new Error(\"Missing path parameter\");\n\n // Security: only allow absolute paths (no relative traversal tricks)\n if (!isAbsolute(filePath)) {\n throw new Error(`Access denied: only absolute paths allowed`);\n }\n\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n const stat = statSync(filePath);\n if (!stat.isFile()) {\n throw new Error(`Not a file: ${filePath}`);\n }\n\n const mimeType = getMimeType(filePath);\n const totalSize = stat.size;\n\n if (isTextMime(mimeType)) {\n const raw = readFileSync(filePath, \"utf-8\");\n const truncated = raw.length > MAX_TEXT_SIZE;\n const content = truncated ? raw.slice(0, MAX_TEXT_SIZE) : raw;\n return { content, encoding: \"utf-8\", size: content.length, totalSize, mimeType, truncated };\n }\n\n // Binary: base64\n const buf = readFileSync(filePath);\n const truncated = buf.length > MAX_TEXT_SIZE;\n const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;\n return { content: slice.toString(\"base64\"), encoding: \"base64\", size: slice.length, totalSize, mimeType, truncated };\n }\n}\n"],"mappings":"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","names":["createLogger","log","process","existsSync","readdirSync","readFileSync","join","homedir","createLogger","log","existsSync","readFileSync","readdirSync","join","createLogger","log","existsSync","readFileSync","statSync","createLogger","log","stat","truncated","createLogger","log"]}
|
package/dist/hub-connection.d.ts
CHANGED
|
@@ -48,6 +48,10 @@ export declare class HubConnection {
|
|
|
48
48
|
setSwarmCoordinator(coordinator: SwarmCoordinator): void;
|
|
49
49
|
registerNamespace(namespace: string, handler: (msg: AgentGenericRequest) => Promise<Record<string, unknown>>): void;
|
|
50
50
|
sendPush(namespace: string, event: string, data: Record<string, unknown>): void;
|
|
51
|
+
sendSkillList(skills: Array<{
|
|
52
|
+
name: string;
|
|
53
|
+
description: string;
|
|
54
|
+
}>): void;
|
|
51
55
|
get readyState(): number;
|
|
52
56
|
get isConnected(): boolean;
|
|
53
57
|
connect(): void;
|
|
@@ -55,10 +59,12 @@ export declare class HubConnection {
|
|
|
55
59
|
destroy(): void;
|
|
56
60
|
private handleSessionMessage;
|
|
57
61
|
private tryRecoverSwarms;
|
|
62
|
+
private reportLiveSessions;
|
|
58
63
|
private sendRaw;
|
|
59
64
|
private startHeartbeat;
|
|
60
65
|
private stopHeartbeat;
|
|
61
66
|
private scheduleReconnect;
|
|
62
67
|
private cleanup;
|
|
68
|
+
private cleanupConnection;
|
|
63
69
|
}
|
|
64
70
|
//# sourceMappingURL=hub-connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hub-connection.d.ts","sourceRoot":"","sources":["../src/hub-connection.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAOxD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAwB;IAEzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAEnC,qDAAqD;IACrD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE9B,iFAAiF;IACjF,OAAO,CAAC,cAAc,CAAqB;IAE3C,uEAAuE;IACvE,OAAO,CAAC,cAAc,CAA+B;IAErD,2EAA2E;IAC3E,OAAO,CAAC,gBAAgB,CAAiC;IAEzD,+CAA+C;IAC/C,OAAO,CAAC,iBAAiB,CAGrB;IAEJ,OAAO,CAAC,SAAS,CAAC,CAA0B;IAC5C,OAAO,CAAC,WAAW,CAAC,CAA4B;IAChD,OAAO,CAAC,YAAY,CAAC,CAAyC;IAC9D,OAAO,CAAC,OAAO,CAAC,CAAuB;gBAE3B,IAAI,EAAE,oBAAoB;IAetC,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIhD,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI;IAIxD,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAKzE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IASxE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"hub-connection.d.ts","sourceRoot":"","sources":["../src/hub-connection.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzF;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,kBAAkB,CAA+D;IACzF,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAA6C;IAC7D,OAAO,CAAC,cAAc,CAQZ;IACV,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,aAAa,CAAC,CAA2F;gBAErG,OAAO,EAAE;QACnB,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;QACrD,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;YACJ,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,YAAY,CAAC,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,CAAC;SAChD,KACE,IAAI,CAAC;QACV,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3D,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1G;IAQK,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgE3D,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS3C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,IAAI,kBAAkB,IAAI,MAAM,CAE/B;
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOzF;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,kBAAkB,CAA+D;IACzF,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAA6C;IAC7D,OAAO,CAAC,cAAc,CAQZ;IACV,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,aAAa,CAAC,CAA2F;gBAErG,OAAO,EAAE;QACnB,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;QACrD,cAAc,EAAE,CACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;YACJ,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,YAAY,CAAC,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,CAAC;SAChD,KACE,IAAI,CAAC;QACV,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3D,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC1G;IAQK,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgE3D,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS3C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,mBAAmB,IAAI,MAAM,EAAE;CAGhC"}
|
package/dist/skill-loader.d.ts
CHANGED
|
@@ -5,4 +5,15 @@
|
|
|
5
5
|
* 3. Ensure MCP config exists
|
|
6
6
|
*/
|
|
7
7
|
export declare function initSkills(): Promise<void>;
|
|
8
|
+
export interface SkillInfo {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Scan ~/.clawnet/.claude/skills/ and parse SKILL.md frontmatter
|
|
14
|
+
* to build a list of { name, description }.
|
|
15
|
+
*/
|
|
16
|
+
export declare function scanSkills(): SkillInfo[];
|
|
17
|
+
/** Get the cached skill list (call scanSkills() first). */
|
|
18
|
+
export declare function getSkillList(): SkillInfo[];
|
|
8
19
|
//# sourceMappingURL=skill-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhD;AAoDD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,SAAS,EAAE,CAmCxC;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,IAAI,SAAS,EAAE,CAE1C"}
|
package/dist/start.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAa,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC;IAC/D,GAAG,EAAE,aAAa,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC,
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAa,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC;IAC/D,GAAG,EAAE,aAAa,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC,CAsGD"}
|
package/dist/start.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mclawnet/agent",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"commander": "^14.0.3",
|
|
24
24
|
"ws": "^8.19.0",
|
|
25
|
-
"@mclawnet/claude-adapter": "0.1.
|
|
26
|
-
"@mclawnet/memory": "0.1.1",
|
|
25
|
+
"@mclawnet/claude-adapter": "0.1.6",
|
|
27
26
|
"@mclawnet/logger": "0.1.2",
|
|
27
|
+
"@mclawnet/memory": "0.1.1",
|
|
28
28
|
"@mclawnet/shared": "0.1.1",
|
|
29
29
|
"@mclawnet/swarm": "0.1.1"
|
|
30
30
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hub-connection.ts","../src/fs-handler.ts","../src/session-manager.ts","../src/start.ts","../src/skill-loader.ts","../src/brain-bridge.ts","../src/fs-bridge.ts"],"sourcesContent":["import { hostname as osHostname } from \"node:os\";\nimport WebSocket from \"ws\";\nimport {\n HEARTBEAT_INTERVAL_MS,\n DEFAULT_RECONNECT_MS,\n MAX_RECONNECT_MS,\n WS_CLOSE_INVALID_TOKEN,\n} from \"@mclawnet/shared\";\nimport type {\n AgentServerMessage,\n AgentClientMessage,\n AgentGenericRequest,\n} from \"@mclawnet/shared\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport type { SwarmCoordinator } from \"@mclawnet/swarm\";\nimport { listRecoverableSwarms, recoverSwarm, listRoles, loadRole, listRecoverableSwarmIds, deleteSwarmSnapshot, listTemplates, loadTemplate } from \"@mclawnet/swarm\";\nimport { handleListDir, handleListFolders, handleListHistorySessions, handleLoadSessionHistory } from \"./fs-handler.js\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface HubConnectionOptions {\n hubUrl: string;\n token: string;\n hostname?: string;\n version?: string;\n capabilities?: string[];\n heartbeatInterval?: number;\n reconnectDelay?: number;\n maxReconnectDelay?: number;\n onMessage?: (data: unknown) => void;\n onConnect?: (agentId: string) => void;\n onDisconnect?: (code: number, reason: string) => void;\n onError?: (err: Error) => void;\n}\n\ntype AuthState = \"pending\" | \"authenticating\" | \"authenticated\";\n\nexport class HubConnection {\n private ws: WebSocket | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private reconnectDelay: number;\n private destroyed = false;\n private authState: AuthState = \"pending\";\n\n readonly hubUrl: string;\n readonly token: string;\n readonly hostname: string;\n readonly version: string | undefined;\n readonly capabilities: string[] | undefined;\n readonly heartbeatInterval: number;\n readonly maxReconnectDelay: number;\n\n /** Agent ID assigned by Hub after successful auth */\n agentId: string | null = null;\n\n /** Swarm IDs that have been completed/failed — prevents accidental recreation */\n private finishedSwarms = new Set<string>();\n\n /** Session manager — set after construction via setSessionManager() */\n private sessionManager: SessionManager | null = null;\n\n /** Swarm coordinator — set after construction via setSwarmCoordinator() */\n private swarmCoordinator: SwarmCoordinator | null = null;\n\n /** Namespace-based generic message handlers */\n private namespaceHandlers = new Map<\n string,\n (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n >();\n\n private onMessage?: (data: unknown) => void;\n private onConnectCb?: (agentId: string) => void;\n private onDisconnect?: (code: number, reason: string) => void;\n private onError?: (err: Error) => void;\n\n constructor(opts: HubConnectionOptions) {\n this.hubUrl = opts.hubUrl;\n this.token = opts.token;\n this.hostname = opts.hostname ?? osHostname();\n this.version = opts.version;\n this.capabilities = opts.capabilities;\n this.heartbeatInterval = opts.heartbeatInterval ?? HEARTBEAT_INTERVAL_MS;\n this.reconnectDelay = opts.reconnectDelay ?? DEFAULT_RECONNECT_MS;\n this.maxReconnectDelay = opts.maxReconnectDelay ?? MAX_RECONNECT_MS;\n this.onMessage = opts.onMessage;\n this.onConnectCb = opts.onConnect;\n this.onDisconnect = opts.onDisconnect;\n this.onError = opts.onError;\n }\n\n setSessionManager(manager: SessionManager): void {\n this.sessionManager = manager;\n }\n\n setSwarmCoordinator(coordinator: SwarmCoordinator): void {\n this.swarmCoordinator = coordinator;\n }\n\n registerNamespace(\n namespace: string,\n handler: (msg: AgentGenericRequest) => Promise<Record<string, unknown>>\n ) {\n this.namespaceHandlers.set(namespace, handler);\n }\n\n sendPush(namespace: string, event: string, data: Record<string, unknown>) {\n this.send({\n type: \"generic.push\",\n namespace,\n event,\n data,\n });\n }\n\n get readyState(): number {\n return this.ws?.readyState ?? WebSocket.CLOSED;\n }\n\n get isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN && this.authState === \"authenticated\";\n }\n\n connect(): void {\n if (this.destroyed) return;\n this.cleanup();\n this.authState = \"pending\";\n\n this.ws = new WebSocket(this.hubUrl);\n\n this.ws.on(\"open\", () => {\n this.reconnectDelay = DEFAULT_RECONNECT_MS;\n });\n\n this.ws.on(\"message\", (raw) => {\n let data: AgentServerMessage;\n try {\n data = JSON.parse(raw.toString());\n } catch {\n return;\n }\n\n // Step 1: Hub sends auth_required → reply with auth\n if (this.authState === \"pending\" && data.type === \"auth_required\") {\n log.info(\"hub requires auth, sending credentials\");\n this.authState = \"authenticating\";\n this.sendRaw({\n type: \"auth\",\n token: this.token,\n hostname: this.hostname,\n version: this.version,\n capabilities: this.capabilities,\n });\n return;\n }\n\n // Step 2: Hub sends registered → auth complete\n if (this.authState === \"authenticating\" && data.type === \"registered\") {\n log.info({ agentId: data.agentId }, \"registered with hub\");\n this.authState = \"authenticated\";\n this.agentId = data.agentId ?? null;\n this.startHeartbeat();\n this.onConnectCb?.(this.agentId!);\n\n // Attempt to recover any persisted swarms\n this.tryRecoverSwarms();\n return;\n }\n\n // Post-auth message handling\n if (this.authState === \"authenticated\") {\n if (this.handleSessionMessage(data)) return;\n this.onMessage?.(data);\n }\n });\n\n this.ws.on(\"close\", (code, reason) => {\n log.warn({ code, reason: reason.toString() }, \"disconnected from hub\");\n this.stopHeartbeat();\n this.authState = \"pending\";\n this.onDisconnect?.(code, reason.toString());\n if (code === WS_CLOSE_INVALID_TOKEN) {\n log.error(\"auth failed — not reconnecting, check your token\");\n return;\n }\n this.scheduleReconnect();\n });\n\n this.ws.on(\"error\", (err) => {\n log.error({ err }, \"ws connection error\");\n this.onError?.(err);\n });\n }\n\n send(data: AgentClientMessage): boolean {\n // Track swarm completion to prevent accidental recreation\n const msg = data as any;\n if (msg.type === \"swarm.status\" && (msg.swarmStatus === \"completed\" || msg.swarmStatus === \"failed\")) {\n this.finishedSwarms.add(msg.sessionId);\n }\n return this.sendRaw(data);\n }\n\n destroy(): void {\n this.destroyed = true;\n this.cleanup();\n }\n\n // ── Session message handling ─────────────────────────────────────\n\n private handleSessionMessage(msg: AgentServerMessage): boolean {\n // ── Filesystem / history requests (no sessionManager needed) ─────\n\n if (msg.type === \"fs.list_dir\") {\n log.info({ path: msg.path }, \"fs.list_dir\");\n handleListDir(msg.path)\n .then((result) => {\n this.send({ type: \"fs.list_dir_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, path: msg.path }, \"fs.list_dir failed\");\n this.send({\n type: \"fs.list_dir_result\",\n requestId: msg.requestId,\n path: msg.path || \"/\",\n entries: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"list_folders\") {\n log.info(\"list_folders\");\n handleListFolders()\n .then((result) => {\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err }, \"list_folders failed\");\n this.send({ type: \"folders_list_result\", requestId: msg.requestId, folders: [] });\n });\n return true;\n }\n\n if (msg.type === \"list_history_sessions\") {\n log.info({ workDir: msg.workDir }, \"list_history_sessions\");\n handleListHistorySessions(msg.workDir)\n .then((result) => {\n this.send({ type: \"history_sessions_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, workDir: msg.workDir }, \"list_history_sessions failed\");\n this.send({\n type: \"history_sessions_result\",\n requestId: msg.requestId,\n workDir: msg.workDir,\n sessions: [],\n });\n });\n return true;\n }\n\n if (msg.type === \"load_session_history\") {\n log.info({ workDir: msg.workDir, claudeSessionId: msg.claudeSessionId }, \"load_session_history\");\n handleLoadSessionHistory(msg.workDir, msg.claudeSessionId)\n .then((result) => {\n this.send({ type: \"session_history_result\", requestId: msg.requestId, ...result });\n })\n .catch((err: any) => {\n log.error({ err, workDir: msg.workDir }, \"load_session_history failed\");\n this.send({ type: \"session_history_result\", requestId: msg.requestId, messages: [] });\n });\n return true;\n }\n\n // ── Swarm handling (requires swarmCoordinator) ──────────────────────\n\n if (msg.type === \"list_roles\") {\n log.info(\"list_roles\");\n const roleNames = listRoles();\n const roles = roleNames.map((name) => {\n try {\n const def = loadRole(name);\n return {\n name: def.name,\n displayName: def.displayName || def.description || def.name,\n description: def.description || \"\",\n capabilities: def.capabilities || [],\n type: def.type,\n color: def.color,\n promptBody: def.promptBody || \"\",\n };\n } catch {\n return { name, displayName: name, description: \"\", capabilities: [], promptBody: \"\" };\n }\n });\n this.send({\n type: \"roles_list_result\",\n sessionId: (msg as any).sessionId,\n roles,\n } as any);\n return true;\n }\n\n if (msg.type === \"list_templates\") {\n log.info(\"list_templates\");\n try {\n const names = listTemplates();\n const templates = names.map((name) => {\n const tpl = loadTemplate(name);\n return {\n name: tpl.name,\n displayName: tpl.displayName,\n description: tpl.description,\n icon: tpl.icon,\n roles: tpl.roles,\n };\n });\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates,\n } as any);\n } catch (err) {\n log.error({ err }, \"list_templates failed\");\n this.send({\n type: \"templates_list_result\",\n sessionId: (msg as any).sessionId,\n templates: [],\n } as any);\n }\n return true;\n }\n\n // ── Generic request: dispatch to registered namespace handlers ──\n if (msg.type === \"generic.request\") {\n const handler = this.namespaceHandlers.get(msg.namespace);\n if (handler) {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request received\");\n handler(msg)\n .then((result) => {\n log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request handled OK\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: result,\n requestId: msg.requestId,\n });\n })\n .catch((err) => {\n log.error({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId, err }, \"generic.request handler error\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n return true;\n }\n log.warn({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, \"generic.request unknown namespace\");\n this.send({\n type: \"generic.response\",\n namespace: msg.namespace,\n action: msg.action,\n data: {},\n requestId: msg.requestId,\n error: `Unknown namespace: ${msg.namespace}`,\n });\n return true;\n }\n\n if (msg.type === \"swarm.execute\" && this.swarmCoordinator) {\n const { sessionId, content, workDir, targetInstance, crewConfig } = msg;\n\n if (this.swarmCoordinator.hasSwarm(sessionId)) {\n // Existing swarm — forward user message\n log.info({ sessionId, targetInstance }, \"swarm.execute: forwarding to existing swarm\");\n this.swarmCoordinator.handleUserMessage(sessionId, content, targetInstance).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else if (this.finishedSwarms.has(sessionId)) {\n // Swarm already completed/failed — don't recreate\n log.info({ sessionId }, \"swarm.execute ignored: swarm already finished\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"蜂群任务已完成,无法继续操作。请创建新的蜂群任务。\",\n });\n } else if (crewConfig?.templateName || crewConfig?.roles) {\n // Create new swarm: template-based or direct roles\n const templateName = crewConfig.templateName;\n const roles = crewConfig.roles;\n log.info({ sessionId, templateName, rolesCount: roles?.length }, \"swarm.execute: creating new swarm\");\n this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content }).catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } else {\n // No swarm and no crewConfig — shouldn't happen normally\n log.info({ sessionId }, \"swarm.execute ignored: swarm not found, no config\");\n this.send({\n type: \"session.error\",\n sessionId,\n error: \"蜂群任务已完成,无法继续操作。请创建新的蜂群任务。\",\n });\n }\n return true;\n }\n\n // ── Session management (requires sessionManager) ─────────────────\n\n if (!this.sessionManager) return false;\n\n if (msg.type === \"abort_execution\") {\n const { sessionId } = msg;\n log.info({ sessionId }, \"abort_execution\");\n if (this.sessionManager?.hasSession(sessionId)) {\n this.sessionManager.abortSession(sessionId).then(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }).catch(() => {\n this.send({ type: \"execution_aborted\", sessionId } as any);\n });\n } else {\n // No active session — just acknowledge\n this.send({ type: \"execution_aborted\", sessionId } as any);\n }\n return true;\n }\n\n // claude.execute — auto-create session if needed, then send input\n if (msg.type === \"claude.execute\") {\n const { sessionId, content, workDir, claudeSessionId, useBrainCore } = msg;\n if (this.sessionManager.hasSession(sessionId)) {\n log.info({ sessionId }, \"claude.execute: reusing existing session\");\n this.sessionManager.sendInput(sessionId, content);\n } else {\n log.info({ sessionId, workDir, roleId: \"role-__assistant__\" }, \"claude.execute: creating new session with memory injection\");\n this.sessionManager\n .createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore, roleId: \"role-__assistant__\" })\n .then(() => {\n this.sessionManager!.sendInput(sessionId, content);\n })\n .catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n return true;\n }\n\n if (msg.type === \"session.create\") {\n log.info({ sessionId: msg.sessionId, roleId: \"role-__assistant__\" }, \"session.create with memory injection\");\n this.sessionManager\n .createSession({\n sessionId: msg.sessionId,\n workDir: msg.workDir,\n resumeId: msg.resumeId,\n roleId: \"role-__assistant__\",\n })\n .then((claudeSessionId) => {\n this.send({\n type: \"session.created\",\n sessionId: msg.sessionId,\n claudeSessionId,\n });\n })\n .catch((err) => {\n this.send({\n type: \"session.error\",\n sessionId: msg.sessionId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n return true;\n }\n\n if (msg.type === \"session.close\") {\n log.info({ sessionId: msg.sessionId }, \"session.close\");\n this.sessionManager.closeSession(msg.sessionId).catch(() => {});\n return true;\n }\n\n if (msg.type === \"claude.input\") {\n log.info({ sessionId: msg.sessionId }, \"claude.input\");\n this.sessionManager.sendInput(msg.sessionId, msg.content);\n return true;\n }\n\n return false;\n }\n\n // ── Internal helpers ─────────────────────────────────────────────\n\n private tryRecoverSwarms(): void {\n if (!this.swarmCoordinator) return;\n try {\n const allIds = listRecoverableSwarmIds();\n const snapshots = listRecoverableSwarms();\n const recoverableIds = new Set(snapshots.map((s) => s.id));\n\n // Clean up expired/completed/failed snapshots\n for (const id of allIds) {\n if (!recoverableIds.has(id)) {\n deleteSwarmSnapshot(id);\n log.info({ swarmId: id }, \"cleaned up non-recoverable swarm snapshot\");\n }\n }\n\n for (const snap of snapshots) {\n log.info({ swarmId: snap.id }, \"recovering swarm\");\n recoverSwarm(this.swarmCoordinator, snap).catch((err) => {\n log.error({ err, swarmId: snap.id }, \"failed to recover swarm\");\n });\n }\n } catch (err) {\n log.error({ err }, \"swarm recovery failed\");\n }\n }\n\n private sendRaw(data: unknown): boolean {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return false;\n this.ws.send(JSON.stringify(data));\n return true;\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.send({ type: \"heartbeat\", ts: Date.now() });\n }, this.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private scheduleReconnect(): void {\n if (this.destroyed) return;\n log.warn({ delayMs: this.reconnectDelay }, \"reconnecting to hub...\");\n this.reconnectTimer = setTimeout(() => {\n this.connect();\n }, this.reconnectDelay);\n this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxReconnectDelay);\n }\n\n private cleanup(): void {\n this.stopHeartbeat();\n this.sessionManager?.closeAll().catch(() => {});\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n if (this.ws) {\n this.ws.removeAllListeners();\n if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {\n this.ws.close();\n }\n this.ws = null;\n }\n }\n}\n","import { readdir, stat, readFile } from \"node:fs/promises\";\nimport { existsSync, readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\".git\", \"node_modules\", \"__pycache__\", \".next\", \".nuxt\", \".cache\"]);\n\n// ── fs.list_dir ─────────────────────────────────────────────────────\n\nexport async function handleListDir(\n path: string,\n): Promise<{ path: string; entries: Array<{ name: string; type: \"directory\" | \"file\" }> }> {\n const target = path || homedir();\n const dirents = await readdir(target, { withFileTypes: true });\n\n const entries = dirents\n .filter((d) => !(d.isDirectory() && SKIP_DIRS.has(d.name)))\n .map((d) => ({\n name: d.name,\n type: (d.isDirectory() ? \"directory\" : \"file\") as \"directory\" | \"file\",\n }))\n .sort((a, b) => {\n if (a.type !== b.type) return a.type === \"directory\" ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n\n return { path: target, entries };\n}\n\n// ── list_folders (scan ~/.claude/projects/) ──────────────────────────\n\nfunction getClaudeProjectsDir(): string {\n return join(homedir(), \".claude\", \"projects\");\n}\n\nfunction pathToProjectFolder(workDir: string): string {\n return workDir.replace(/:/g, \"-\").replace(/[/\\\\]/g, \"-\");\n}\n\nfunction extractWorkDirFromSessionFile(filePath: string): string | null {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n for (const line of lines.slice(0, 5)) {\n try {\n const data = JSON.parse(line);\n if (data.cwd) return data.cwd.replace(/\\\\/g, \"/\");\n } catch {}\n }\n } catch {}\n return null;\n}\n\nfunction getWorkDirFromProjectFolder(folderPath: string, folderName: string): string {\n try {\n const files = readdirSync(folderPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n const workDir = extractWorkDirFromSessionFile(join(folderPath, file));\n if (workDir) return workDir;\n }\n }\n } catch {}\n\n // Fallback: simple conversion\n if (/^[A-Za-z]--/.test(folderName)) {\n return folderName.replace(/^([A-Za-z])--/, \"$1:/\").replace(/-/g, \"/\");\n }\n if (folderName.startsWith(\"-\")) {\n return \"/\" + folderName.substring(1).replace(/-/g, \"/\");\n }\n return folderName.replace(/-/g, \"/\");\n}\n\nexport async function handleListFolders(): Promise<{\n folders: Array<{ path: string; sessionCount: number; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const folders: Array<{ path: string; sessionCount: number; lastModified?: number }> = [];\n\n if (!existsSync(projectsDir)) return { folders };\n\n const entries = readdirSync(projectsDir);\n for (const entry of entries) {\n const entryPath = join(projectsDir, entry);\n let entryStat;\n try {\n entryStat = statSync(entryPath);\n } catch {\n continue;\n }\n if (!entryStat.isDirectory()) continue;\n\n // Skip crew role directories\n if (entry.includes(\"--crew-roles-\")) continue;\n\n const originalPath = getWorkDirFromProjectFolder(entryPath, entry);\n\n let sessionCount = 0;\n let lastModified = entryStat.mtime.getTime();\n\n try {\n const files = readdirSync(entryPath);\n for (const file of files) {\n if (file.endsWith(\".jsonl\")) {\n sessionCount++;\n try {\n const fileStats = statSync(join(entryPath, file));\n if (fileStats.mtime.getTime() > lastModified) {\n lastModified = fileStats.mtime.getTime();\n }\n } catch {}\n }\n }\n } catch {}\n\n folders.push({ path: originalPath, sessionCount, lastModified });\n }\n\n folders.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { folders };\n}\n\n// ── list_history_sessions ───────────────────────────────────────────\n\nexport async function handleListHistorySessions(workDir: string): Promise<{\n workDir: string;\n sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }>;\n}> {\n const projectsDir = getClaudeProjectsDir();\n const projectFolder = pathToProjectFolder(workDir);\n const projectPath = join(projectsDir, projectFolder);\n\n if (!existsSync(projectPath)) {\n return { workDir, sessions: [] };\n }\n\n const sessions: Array<{ sessionId: string; title: string; workDir?: string; lastModified?: number }> = [];\n const files = readdirSync(projectPath);\n\n for (const file of files) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const sessionId = file.replace(\".jsonl\", \"\");\n const filePath = join(projectPath, file);\n let fileStats;\n try {\n fileStats = statSync(filePath);\n } catch {\n continue;\n }\n\n let title = \"\";\n let hasUserMessage = false;\n let customTitle = \"\";\n let jsonlSummary = \"\";\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line);\n if (!hasUserMessage && data.type === \"user\" && data.message?.content) {\n const text =\n typeof data.message.content === \"string\"\n ? data.message.content\n : data.message.content[0]?.text || \"\";\n if (text.trim()) {\n title = text.substring(0, 100);\n hasUserMessage = true;\n }\n }\n if (data.type === \"custom-title\" && data.customTitle) {\n customTitle = data.customTitle;\n }\n if (data.type === \"summary\" && data.summary) {\n jsonlSummary = data.summary;\n }\n } catch {}\n }\n } catch {}\n\n if (hasUserMessage) {\n sessions.push({\n sessionId,\n title: customTitle || jsonlSummary || title || sessionId.slice(0, 8),\n workDir,\n lastModified: fileStats.mtime.getTime(),\n });\n }\n }\n\n sessions.sort((a, b) => (b.lastModified ?? 0) - (a.lastModified ?? 0));\n return { workDir, sessions };\n}\n\n// ── load_session_history ────────────────────────────────────────────\n\ninterface HistoryMessage {\n role: \"user\" | \"assistant\";\n content: string;\n toolCalls?: Array<{ name: string; input?: string; output?: string; status: string }>;\n thinking?: string;\n}\n\nexport async function handleLoadSessionHistory(\n workDir: string,\n claudeSessionId: string,\n): Promise<{ messages: HistoryMessage[] }> {\n const projectsDir = getClaudeProjectsDir();\n const projectFolder = pathToProjectFolder(workDir);\n const filePath = join(projectsDir, projectFolder, `${claudeSessionId}.jsonl`);\n\n if (!existsSync(filePath)) {\n return { messages: [] };\n }\n\n const messages: HistoryMessage[] = [];\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const lines = content.split(\"\\n\").filter((l) => l.trim());\n\n for (const line of lines) {\n try {\n const data = JSON.parse(line);\n\n if (data.type === \"user\" && data.message?.content) {\n const blocks = Array.isArray(data.message.content)\n ? data.message.content\n : [{ type: \"text\", text: String(data.message.content) }];\n\n // Extract user text (only text blocks, skip tool_result etc.)\n const textParts: string[] = [];\n for (const block of blocks) {\n if (block.type === \"text\" && block.text?.trim()) {\n textParts.push(block.text);\n }\n }\n if (textParts.length > 0) {\n messages.push({ role: \"user\", content: textParts.join(\"\\n\") });\n }\n\n // Attach tool_result outputs to the last assistant's toolCalls\n const lastAssistant = messages.length > 0\n ? [...messages].reverse().find((m) => m.role === \"assistant\" && m.toolCalls?.length)\n : undefined;\n if (lastAssistant?.toolCalls) {\n for (const block of blocks) {\n if (block.type === \"tool_result\") {\n // Match by tool_use_id or just fill the next pending one\n const pending = lastAssistant.toolCalls.find((tc) => !tc.output);\n if (pending) {\n pending.output = typeof block.content === \"string\"\n ? block.content\n : Array.isArray(block.content)\n ? block.content.map((c: any) => c.text ?? \"\").join(\"\")\n : JSON.stringify(block.content);\n pending.status = block.is_error ? \"error\" : \"done\";\n }\n }\n }\n }\n }\n\n if (data.type === \"assistant\" && data.message?.content) {\n let text = \"\";\n const toolCalls: HistoryMessage[\"toolCalls\"] = [];\n let thinking = \"\";\n\n for (const block of data.message.content) {\n if (block.type === \"text\") {\n text += block.text;\n } else if (block.type === \"tool_use\") {\n toolCalls.push({\n name: block.name,\n input: typeof block.input === \"string\" ? block.input : JSON.stringify(block.input, null, 2),\n status: \"done\",\n });\n } else if (block.type === \"thinking\") {\n thinking += block.thinking ?? \"\";\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n thinking: thinking || undefined,\n });\n }\n } catch {}\n }\n } catch {}\n\n // Return last 50 messages to avoid overloading\n return { messages: messages.slice(-50) };\n}\n","import { createLogger } from \"@mclawnet/logger\";\nimport { buildMemorySection } from \"@mclawnet/memory\";\nimport type { BackendAdapter, BackendProcess, SpawnOptions } from \"./backend-adapter.js\";\n\nconst log = createLogger({ module: \"agent/session-manager\" });\n\nconst DEFAULT_MAX_PROCESSES = 10;\nconst MAX_PROCESSES = Number(process.env.CLAWNET_MAX_PROCESSES) || DEFAULT_MAX_PROCESSES;\n\n/**\n * Manages active sessions, mapping ClawNet session IDs to BackendProcess instances.\n *\n * When `options.roleId` is set, the manager automatically injects:\n * - Pipeline A: memory prompt + roleId hint via `--append-system-prompt`\n *\n * Note: MCP config is now handled globally via ~/.clawnet/mcp.json\n * (mounted by ClaudeCodeAdapter), no longer generated per-session.\n */\nexport class SessionManager {\n private sessions = new Map<string, BackendProcess>();\n private conversationBuffer = new Map<string, Array<{ role: string; content: string }>>();\n private adapter: BackendAdapter;\n private onOutput: (sessionId: string, data: unknown) => void;\n private onTurnComplete: (\n sessionId: string,\n info: {\n claudeSessionId?: string;\n cost?: number;\n duration?: number;\n contextUsage?: { used: number; total: number };\n },\n ) => void;\n private onSessionError: (sessionId: string, error: string) => void;\n private onBeforeClose?: (sessionId: string, messages: Array<{ role: string; content: string }>) => Promise<void>;\n\n constructor(options: {\n adapter: BackendAdapter;\n onOutput: (sessionId: string, data: unknown) => void;\n onTurnComplete: (\n sessionId: string,\n info: {\n claudeSessionId?: string;\n cost?: number;\n duration?: number;\n contextUsage?: { used: number; total: number };\n },\n ) => void;\n onSessionError: (sessionId: string, error: string) => void;\n onBeforeClose?: (sessionId: string, messages: Array<{ role: string; content: string }>) => Promise<void>;\n }) {\n this.adapter = options.adapter;\n this.onOutput = options.onOutput;\n this.onTurnComplete = options.onTurnComplete;\n this.onSessionError = options.onSessionError;\n this.onBeforeClose = options.onBeforeClose;\n }\n\n async createSession(options: SpawnOptions): Promise<string> {\n if (this.sessions.has(options.sessionId)) {\n throw new Error(`Session ${options.sessionId} already exists`);\n }\n\n if (this.sessions.size >= MAX_PROCESSES) {\n throw new Error(`Process limit reached (${MAX_PROCESSES}). Cannot create new session.`);\n }\n\n // ── Unified memory injection ──\n if (options.roleId) {\n // Pipeline A: prepend memory section + roleId hint to system prompt\n try {\n const memorySection = buildMemorySection(options.roleId);\n const roleHint = `\\n\\n[Memory Context] Your roleId is \"${options.roleId}\". Always use this roleId when calling memory_search, memory_store, memory_stats, or memory_reflect.`;\n options.systemPrompt = options.systemPrompt\n ? `${memorySection}${roleHint}\\n\\n${options.systemPrompt}`\n : `${memorySection}${roleHint}`;\n log.debug({ roleId: options.roleId, sessionId: options.sessionId }, \"memory prompt + roleId hint injected\");\n } catch (err) {\n log.warn({ err, roleId: options.roleId }, \"failed to build memory section, proceeding without\");\n }\n }\n\n try {\n const process = await this.adapter.spawn(options);\n this.sessions.set(options.sessionId, process);\n\n // Wire up output handler\n this.adapter.onOutput(process, (data) => {\n // Accumulate assistant text messages for distillation\n const msg = data as any;\n if (msg?.type === \"assistant\" && msg?.message?.content) {\n const buf = this.conversationBuffer.get(options.sessionId) ?? [];\n // Extract text from content blocks\n const text = Array.isArray(msg.message.content)\n ? msg.message.content.filter((b: any) => b.type === \"text\").map((b: any) => b.text).join(\"\\n\")\n : String(msg.message.content);\n if (text) {\n buf.push({ role: \"assistant\", content: text });\n this.conversationBuffer.set(options.sessionId, buf);\n }\n }\n this.onOutput(options.sessionId, data);\n });\n\n // Wire up turn-complete handler\n this.adapter.onTurnComplete?.(process, (info) => {\n this.onTurnComplete(options.sessionId, info);\n });\n\n // Wire up error handler\n this.adapter.onError?.(process, (error) => {\n this.onSessionError(options.sessionId, error.message);\n });\n\n return process.id;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.onSessionError(options.sessionId, message);\n throw err;\n }\n }\n\n sendInput(sessionId: string, input: string): void {\n const process = this.sessions.get(sessionId);\n if (!process) {\n this.onSessionError(sessionId, `No active session: ${sessionId}`);\n return;\n }\n this.adapter.send(process, input);\n }\n\n async abortSession(sessionId: string): Promise<void> {\n const process = this.sessions.get(sessionId);\n if (!process) return;\n this.conversationBuffer.delete(sessionId);\n this.sessions.delete(sessionId);\n await this.adapter.stop(process);\n }\n\n async closeSession(sessionId: string): Promise<void> {\n const process = this.sessions.get(sessionId);\n if (!process) return;\n\n // Trigger distillation before closing\n const messages = this.conversationBuffer.get(sessionId);\n if (this.onBeforeClose && messages?.length) {\n await this.onBeforeClose(sessionId, messages).catch(() => {});\n }\n this.conversationBuffer.delete(sessionId);\n\n this.sessions.delete(sessionId);\n await this.adapter.stop(process);\n }\n\n async closeAll(): Promise<void> {\n const promises = Array.from(this.sessions.entries()).map(\n async ([sessionId, process]) => {\n // Trigger distillation before closing\n const messages = this.conversationBuffer.get(sessionId);\n if (this.onBeforeClose && messages?.length) {\n await this.onBeforeClose(sessionId, messages).catch(() => {});\n }\n this.conversationBuffer.delete(sessionId);\n this.sessions.delete(sessionId);\n await this.adapter.stop(process).catch(() => {});\n },\n );\n await Promise.all(promises);\n }\n\n hasSession(sessionId: string): boolean {\n return this.sessions.has(sessionId);\n }\n\n get activeSessionCount(): number {\n return this.sessions.size;\n }\n}\n","import { loadConfig, type AgentConfig } from \"./config.js\";\nimport { HubConnection } from \"./hub-connection.js\";\nimport { SessionManager } from \"./session-manager.js\";\nimport { SwarmCoordinator, initRoles } from \"@mclawnet/swarm\";\nimport { initSkills } from \"./skill-loader.js\";\nimport { BrainBridge } from \"./brain-bridge.js\";\nimport { FsBridge } from \"./fs-bridge.js\";\nimport type { BackendAdapter } from \"./backend-adapter.js\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent\" });\n\nexport interface StartOptions {\n config?: Partial<AgentConfig>;\n adapter: BackendAdapter;\n}\n\n/**\n * Start the ClawNet agent: connect to Hub and register a BackendAdapter.\n */\nexport async function startAgent(options: StartOptions): Promise<{\n hub: HubConnection;\n sessionManager: SessionManager;\n swarmCoordinator: SwarmCoordinator;\n brainBridge: BrainBridge;\n fsBridge: FsBridge;\n}> {\n const config = loadConfig(options.config);\n\n if (!config.token) {\n log.error(\"no token configured — set CLAWNET_TOKEN or use --token\");\n process.exit(1);\n }\n\n log.info({ backend: options.adapter.type }, \"starting agent\");\n log.info({ hubUrl: config.hubUrl }, \"connecting to hub\");\n\n // Initialize role templates\n await initRoles();\n\n // Initialize skill system (copy built-in skills + ensure mcp.json)\n await initSkills();\n\n const hub = new HubConnection({\n hubUrl: config.hubUrl,\n token: config.token,\n hostname: config.name,\n onConnect: (agentId) => {\n log.info({ agentId }, \"connected to hub\");\n },\n onDisconnect: (code, reason) => {\n log.info({ code, reason }, \"disconnected from hub\");\n },\n onError: (err) => {\n log.error({ err }, \"hub connection error\");\n },\n });\n\n // Create SwarmCoordinator (needs hub reference; sessionManager set after construction)\n // We use a lazy reference so the coordinator can be created before sessionManager\n let swarmCoordinator: SwarmCoordinator;\n\n const sessionManager = new SessionManager({\n adapter: options.adapter,\n onOutput: (sessionId, data) => {\n // Intercept swarm role output\n if (swarmCoordinator.handleRoleOutput(sessionId, data)) return;\n\n // Normal (non-swarm) session output\n hub.send({\n type: \"claude.output\",\n sessionId,\n data,\n });\n },\n onTurnComplete: (sessionId, info) => {\n // Intercept swarm role turn completion\n if (swarmCoordinator.handleRoleTurnComplete(sessionId, info)) return;\n\n // Normal (non-swarm) session\n hub.send({\n type: \"claude.turn_complete\",\n sessionId,\n cost: info.cost,\n duration: info.duration,\n contextUsage: info.contextUsage,\n });\n },\n onSessionError: (sessionId, error) => {\n hub.send({\n type: \"session.error\",\n sessionId,\n error,\n });\n },\n });\n\n swarmCoordinator = new SwarmCoordinator(sessionManager, hub);\n\n hub.setSessionManager(sessionManager);\n hub.setSwarmCoordinator(swarmCoordinator);\n\n // Initialize BrainBridge (registers \"brain\" namespace handler)\n const brainBridge = new BrainBridge(hub);\n\n // Initialize FsBridge (registers \"fs\" namespace handler)\n const fsBridge = new FsBridge(hub);\n\n // Graceful shutdown\n const shutdown = async () => {\n log.info(\"shutting down\");\n await sessionManager.closeAll();\n hub.destroy();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n hub.connect();\n\n return { hub, sessionManager, swarmCoordinator, brainBridge, fsBridge };\n}\n","import { existsSync, mkdirSync, copyFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"agent/skill-loader\" });\n\n/** ~/.clawnet base directory */\nconst CLAWNET_DIR = join(homedir(), \".clawnet\");\n/** Skill target directory: ~/.clawnet/.claude/skills/ */\nconst SKILLS_DIR = join(CLAWNET_DIR, \".claude\", \"skills\");\n/** MCP config file: ~/.clawnet/mcp.json */\nconst MCP_CONFIG_PATH = join(CLAWNET_DIR, \"mcp.json\");\n\n/**\n * Initialize ClawNet skill system:\n * 1. Ensure skill directory exists\n * 2. Copy built-in skills (don't overwrite existing)\n * 3. Ensure MCP config exists\n */\nexport async function initSkills(): Promise<void> {\n ensureSkillsDir();\n copyBuiltinSkills();\n ensureMcpConfig();\n}\n\n/** Create ~/.clawnet/.claude/skills/ if it doesn't exist. */\nfunction ensureSkillsDir(): void {\n if (!existsSync(SKILLS_DIR)) {\n mkdirSync(SKILLS_DIR, { recursive: true });\n log.info({ dir: SKILLS_DIR }, \"created skills directory\");\n }\n}\n\n/** Copy built-in skills from agent package to ~/.clawnet/.claude/skills/. */\nfunction copyBuiltinSkills(): void {\n // Built-in skills are in packages/@clawnet/agent/skills/\n const thisFile = fileURLToPath(import.meta.url);\n const srcDir = join(dirname(thisFile), \"..\", \"skills\");\n\n if (!existsSync(srcDir)) {\n log.debug({ srcDir }, \"no built-in skills directory found, skipping\");\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(srcDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch {\n log.warn({ srcDir }, \"failed to read built-in skills directory\");\n return;\n }\n\n for (const skillName of entries) {\n const srcSkillMd = join(srcDir, skillName, \"SKILL.md\");\n const destDir = join(SKILLS_DIR, skillName);\n const destSkillMd = join(destDir, \"SKILL.md\");\n\n if (!existsSync(srcSkillMd)) continue;\n if (existsSync(destSkillMd)) {\n log.debug({ skill: skillName }, \"skill already exists, skipping\");\n continue;\n }\n\n try {\n mkdirSync(destDir, { recursive: true });\n copyFileSync(srcSkillMd, destSkillMd);\n log.info({ skill: skillName }, \"copied built-in skill\");\n } catch (err) {\n log.warn({ skill: skillName, err }, \"failed to copy built-in skill\");\n }\n }\n}\n\n/** Generate ~/.clawnet/mcp.json with default memory MCP config if it doesn't exist. */\nfunction ensureMcpConfig(): void {\n if (existsSync(MCP_CONFIG_PATH)) {\n log.debug(\"mcp.json already exists, skipping\");\n return;\n }\n\n // Resolve the memory MCP server.js path from the installed package\n let mcpServerPath: string;\n try {\n const req = createRequire(import.meta.url);\n const memoryPkgDir = dirname(req.resolve(\"@mclawnet/memory/package.json\"));\n mcpServerPath = join(memoryPkgDir, \"dist\", \"mcp\", \"server.js\");\n } catch {\n log.warn(\"could not resolve @mclawnet/memory package path, skipping mcp.json generation\");\n return;\n }\n\n const config = {\n mcpServers: {\n \"clawnet-memory\": {\n command: \"node\",\n args: [mcpServerPath],\n },\n },\n };\n\n try {\n // Ensure ~/.clawnet/ exists\n mkdirSync(CLAWNET_DIR, { recursive: true });\n writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\");\n log.info({ path: MCP_CONFIG_PATH }, \"generated default mcp.json\");\n } catch (err) {\n log.warn({ err }, \"failed to generate mcp.json\");\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"brain-bridge\" });\n\nexport type BrainSetupStatus = \"not_installed\" | \"needs_config\" | \"ready\";\n\nexport interface BrainBridgeOptions {\n brainHomePath?: string;\n brainCorePath?: string;\n}\n\nexport class BrainBridge {\n private brainHome: string;\n private brainCorePath: string;\n\n constructor(\n private hub: HubConnection,\n options?: BrainBridgeOptions\n ) {\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n this.brainHome =\n options?.brainHomePath ||\n process.env.BRAIN_HOME ||\n join(home, \"BrainData\");\n this.brainCorePath =\n options?.brainCorePath || join(home, \".brain\", \"BrainCore\");\n\n this.hub.registerNamespace(\"brain\", (msg) => this.handleRequest(msg));\n log.info(\n { brainHome: this.brainHome, brainCorePath: this.brainCorePath },\n \"BrainBridge initialized\"\n );\n }\n\n async handleRequest(\n msg: AgentGenericRequest\n ): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"brain request\");\n switch (msg.action) {\n case \"setup_status\": {\n const status = this.checkSetup();\n log.info({ status }, \"setup_status result\");\n return { status };\n }\n case \"get_briefing\":\n return await this.getBriefing(msg.params.date as string | undefined);\n case \"get_meeting_recap\":\n return await this.getMeetingRecap(msg.params.recapPath as string);\n default:\n log.warn({ action: msg.action }, \"unknown brain action\");\n throw new Error(`Unknown brain action: ${msg.action}`);\n }\n }\n\n checkSetup(): BrainSetupStatus {\n if (!existsSync(this.brainCorePath)) {\n return \"not_installed\";\n }\n const home = process.env.HOME || process.env.USERPROFILE || \"\";\n const installJson = join(home, \".brain\", \"install.json\");\n if (!existsSync(installJson)) {\n return \"needs_config\";\n }\n if (!existsSync(this.brainHome)) {\n return \"needs_config\";\n }\n return \"ready\";\n }\n\n /** Read the most recent daily briefing report */\n private async getBriefing(\n date?: string\n ): Promise<Record<string, unknown>> {\n const targetDate = date || new Date().toISOString().slice(0, 10);\n const reportsDir = join(this.brainHome, \"reports\", \"daily\");\n\n if (!existsSync(reportsDir)) {\n log.info({ reportsDir }, \"get_briefing: reports dir not found\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n const files = readdirSync(reportsDir)\n .filter((f: string) => f.includes(targetDate) && f.endsWith(\".md\"))\n .sort()\n .reverse();\n\n if (files.length === 0) {\n log.info({ targetDate }, \"get_briefing: no report for date\");\n return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };\n }\n\n log.info({ targetDate, file: files[0] }, \"get_briefing: reading report\");\n\n const content = readFileSync(join(reportsDir, files[0]), \"utf-8\");\n\n // Extract TL;DR\n const tldrMatch = content.match(/## TL;DR\\n([\\s\\S]*?)(?=\\n---|\\n## )/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);\n\n const actions = this.parseActions(content);\n const projects = this.parseProjects(content);\n const meetings = this.parseMeetings(content);\n const feed = this.parseFeed(content);\n\n log.info(\n { actions: actions.length, projects: projects.length, meetings: meetings.length, feed: feed.length },\n \"get_briefing: parsed\"\n );\n\n return {\n briefing: {\n date: targetDate,\n tldr,\n generatedAt: new Date().toISOString(),\n },\n actions,\n projects,\n meetings,\n feed,\n };\n }\n\n /** Parse \"## Action Required\" section into ActionItem[] */\n private parseActions(content: string): Array<Record<string, unknown>> {\n const sectionMatch = content.match(/## Action Required\\n([\\s\\S]*?)(?=\\n---|\\n## [^A])/);\n if (!sectionMatch) return [];\n\n const section = sectionMatch[1];\n const items: Array<Record<string, unknown>> = [];\n let currentPriority: string = \"p3\";\n let idCounter = 0;\n\n for (const line of section.split(\"\\n\")) {\n // Detect priority headers\n if (line.includes(\"🔴 Today\")) { currentPriority = \"p1\"; continue; }\n if (line.includes(\"🟡 This Week\")) { currentPriority = \"p2\"; continue; }\n if (line.includes(\"⚪ FYI\") || line.includes(\"FYI —\")) { currentPriority = \"p4\"; continue; }\n\n // Numbered items: \"1. **Title** → description\"\n const numberedMatch = line.match(/^\\d+\\.\\s+\\*\\*(.+?)\\*\\*\\s*[→—–-]\\s*(.+)/);\n if (numberedMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: currentPriority,\n title: `${numberedMatch[1].trim()} — ${numberedMatch[2].trim()}`,\n source: this.guessSource(numberedMatch[2]),\n timeAgo: \"\",\n done: false,\n });\n continue;\n }\n\n // Bullet items under FYI: \"- description\"\n if (currentPriority === \"p4\") {\n const bulletMatch = line.match(/^-\\s+(.+)/);\n if (bulletMatch) {\n items.push({\n id: `action-${++idCounter}`,\n priority: \"p4\",\n title: bulletMatch[1].replace(/\\*\\*/g, \"\").trim(),\n source: this.guessSource(bulletMatch[1]),\n timeAgo: \"\",\n done: false,\n });\n }\n }\n }\n\n return items;\n }\n\n /** Parse project sections \"## 🔵 ProjectName\" with Status tables */\n private parseProjects(content: string): Array<Record<string, unknown>> {\n const projects: Array<Record<string, unknown>> = [];\n // Match \"## 🔵 ProjectName\" sections\n const projectRegex = /## 🔵\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let match;\n\n while ((match = projectRegex.exec(content)) !== null) {\n const name = match[1].trim();\n const body = match[2];\n\n // Parse status table: | 🟡 At Risk | ... | or | 🟢 On Track | ... |\n let status: string = \"on_track\";\n const statusMatch = body.match(/\\|\\s*(🟡|🔴|🟢)\\s*(.*?)\\s*\\|/);\n if (statusMatch) {\n const icon = statusMatch[1];\n if (icon === \"🔴\") status = \"blocked\";\n else if (icon === \"🟡\") status = \"blocked\";\n else if (icon === \"🟢\") status = \"good\";\n }\n\n // Count \"Teams Chats\" subsections (#### headers under ### Teams Chats)\n const teamsSection = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n let newMessages = 0;\n if (teamsSection) {\n const chatHeaders = teamsSection[1].match(/^####/gm);\n newMessages = chatHeaders ? chatHeaders.length : 0;\n }\n\n // Count \"Key Decisions\" items\n let pendingDecisions = 0;\n const decisionsMatches = body.match(/\\*\\*\\[(?:Decided|Leaning)\\]\\*\\*/g);\n if (decisionsMatches) pendingDecisions = decisionsMatches.length;\n\n projects.push({\n slug: name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\"),\n name,\n status,\n newMessages,\n pendingDecisions,\n });\n }\n\n return projects;\n }\n\n /** Parse meetings from \"### Meetings\" subsections */\n private parseMeetings(content: string): Array<Record<string, unknown>> {\n const meetings: Array<Record<string, unknown>> = [];\n // Find all \"#### MeetingTitle\" under \"### Meetings\" sections\n const meetingSectionRegex = /### Meetings\\n([\\s\\S]*?)(?=\\n### [^M]|\\n---|\\n## |$)/g;\n let sectionMatch;\n let idCounter = 0;\n\n while ((sectionMatch = meetingSectionRegex.exec(content)) !== null) {\n const section = sectionMatch[1];\n // Each meeting: \"#### Title\\n\\n📅 time | status | participants | host\"\n const meetingRegex = /####\\s+(.+)\\n\\n📅\\s*(\\S+)\\s+\\w+\\s*\\|\\s*(\\w+)/g;\n let m;\n\n while ((m = meetingRegex.exec(section)) !== null) {\n const title = m[1].trim();\n const time = m[2].trim();\n const statusWord = m[3].toLowerCase();\n\n let status = \"completed\";\n if (statusWord === \"missed\") status = \"completed\"; // still show recap\n else if (statusWord === \"upcoming\") status = \"upcoming\";\n else if (statusWord.includes(\"progress\")) status = \"in_progress\";\n\n // Get the text slice for this specific meeting (from current match to next #### or section end)\n const meetingEndIdx = section.indexOf(\"\\n####\", m.index + m[0].length);\n const meetingSlice = meetingEndIdx !== -1\n ? section.slice(m.index, meetingEndIdx)\n : section.slice(m.index);\n\n const recapMatch = meetingSlice.match(/📎\\s*\\[Full recap\\]\\((.+?)\\)/);\n const recapPath = recapMatch ? recapMatch[1] : undefined;\n\n meetings.push({\n id: `meeting-${++idCounter}`,\n time,\n title,\n status,\n hasRecap: !!recapPath,\n recapPath,\n });\n }\n }\n\n return meetings;\n }\n\n /** Parse feed items from Teams Chats subsections across all project sections and Announcements */\n private parseFeed(content: string): Array<Record<string, unknown>> {\n const items: Array<Record<string, unknown>> = [];\n let idCounter = 0;\n\n // 1) Extract feed items from \"### Teams Chats\" under \"## 🔵 ProjectName\" sections\n const projectRegex = /## 🔵\\s+(.+)\\n([\\s\\S]*?)(?=\\n## |$)/g;\n let projectMatch;\n\n while ((projectMatch = projectRegex.exec(content)) !== null) {\n const projectName = projectMatch[1].trim();\n const projectBody = projectMatch[2];\n\n this.extractTeamsChatItems(projectBody, projectName, items, idCounter);\n idCounter = items.length;\n }\n\n // 2) Extract feed items from \"## 📢 Announcements & FYI\" section (no project)\n const announcementMatch = content.match(/## 📢\\s+Announcements[^\\n]*\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (announcementMatch) {\n this.extractTeamsChatItems(announcementMatch[1], \"\", items, idCounter);\n }\n\n return items;\n }\n\n /** Extract chat items from a \"### Teams Chats\" subsection within a body block */\n private extractTeamsChatItems(\n body: string,\n project: string,\n items: Array<Record<string, unknown>>,\n _startId: number\n ): void {\n // Find \"### Teams Chats\" subsection\n const teamsChatMatch = body.match(/### Teams Chats\\n([\\s\\S]*?)(?=\\n### [^T]|\\n---|\\n## |$)/);\n if (!teamsChatMatch) return;\n\n const teamsSection = teamsChatMatch[1];\n\n // Find \"#### ChatTitle — Priority\" headers and their content\n const chatRegex = /####\\s+(.+?)(?:\\s*—\\s*(.+))?\\n([\\s\\S]*?)(?=\\n####|\\n###|\\n---|$)/g;\n let chatMatch;\n\n while ((chatMatch = chatRegex.exec(teamsSection)) !== null) {\n const chatBody = chatMatch[3];\n\n // Extract bold names like **Person Name** as sender\n const senderMatch = chatBody.match(/\\*\\*(.+?)\\*\\*/);\n const sender = senderMatch ? senderMatch[1].trim() : \"Unknown\";\n\n // Extract content: first meaningful line after the sender, or first sentence\n let contentPreview = \"\";\n const lines = chatBody.split(\"\\n\").filter((l: string) => l.trim().length > 0);\n for (const line of lines) {\n // Skip lines that are just metadata (timestamps, status indicators)\n const cleaned = line.replace(/\\*\\*.*?\\*\\*/g, \"\").replace(/[>*-]/g, \"\").trim();\n if (cleaned.length > 10) {\n contentPreview = cleaned.slice(0, 100);\n break;\n }\n }\n // Fallback: use the entire chat body trimmed\n if (!contentPreview && lines.length > 0) {\n contentPreview = lines[0].replace(/\\*\\*/g, \"\").trim().slice(0, 100);\n }\n\n // Try to extract a time from the body (e.g., \"10:30\" or \"14:23\")\n const timeMatch = chatBody.match(/(\\d{1,2}:\\d{2})/);\n const time = timeMatch ? timeMatch[1] : \"\";\n\n items.push({\n id: `feed-${items.length + 1}`,\n time,\n source: \"teams\",\n sender,\n content: contentPreview,\n project: project || undefined,\n });\n }\n }\n\n /** Fetch and parse a meeting recap file */\n private async getMeetingRecap(recapPath: string): Promise<Record<string, unknown>> {\n if (!recapPath) {\n return { error: \"No recap path provided\" };\n }\n const fullPath = join(this.brainHome, recapPath);\n if (!existsSync(fullPath)) {\n log.warn({ fullPath }, \"meeting recap file not found\");\n return { error: \"Recap file not found\" };\n }\n const content = readFileSync(fullPath, \"utf-8\");\n return { recap: this.parseRecapMarkdown(content) };\n }\n\n /** Parse meeting recap markdown into structured sections */\n private parseRecapMarkdown(content: string): Record<string, unknown> {\n // Extract TL;DR / Summary section\n const tldrMatch = content.match(/##\\s*(?:TL;DR|Summary|概要)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const tldr = tldrMatch ? tldrMatch[1].trim() : \"\";\n\n // Extract \"Relevant to You\" / \"与你相关\" section\n const relevantMatch = content.match(/##\\s*(?:与你相关|Relevant|For You|Action for You)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const relevant = relevantMatch ? relevantMatch[1].trim() : \"\";\n\n // Extract \"Decisions\" / \"决定事项\" / \"Key Decisions\" section\n const decisionsMatch = content.match(/##\\s*(?:决定事项|Decisions|Key Decisions)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const decisions = decisionsMatch ? decisionsMatch[1].trim() : \"\";\n\n // Extract \"Action Items\" / \"行动项\" section\n const actionsMatch = content.match(/##\\s*(?:行动项|Action Items|Next Steps)\\n([\\s\\S]*?)(?=\\n## |\\n---|\\n$)/);\n const actionItems = actionsMatch ? actionsMatch[1].trim() : \"\";\n\n return {\n tldr,\n relevant,\n decisions,\n actionItems,\n rawMarkdown: content,\n };\n }\n\n /** Guess message source from text content */\n private guessSource(text: string): string {\n const lower = text.toLowerCase();\n if (lower.includes(\"teams\")) return \"teams\";\n if (lower.includes(\"email\") || lower.includes(\"mail\")) return \"email\";\n if (lower.includes(\"meeting\") || lower.includes(\"sync\")) return \"meeting\";\n if (lower.includes(\"pr\") || lower.includes(\"ado\") || lower.includes(\"work item\")) return \"ado\";\n return \"teams\";\n }\n}\n","import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { extname, isAbsolute } from \"node:path\";\nimport { createLogger } from \"@mclawnet/logger\";\nimport type { AgentGenericRequest } from \"@mclawnet/shared\";\nimport type { HubConnection } from \"./hub-connection.js\";\n\nconst log = createLogger({ module: \"fs-bridge\" });\n\nconst MAX_TEXT_SIZE = 5 * 1024 * 1024; // 5MB\n\nconst MIME_MAP: Record<string, string> = {\n \".ts\": \"text/typescript\", \".tsx\": \"text/typescript\",\n \".js\": \"text/javascript\", \".jsx\": \"text/javascript\",\n \".json\": \"application/json\", \".html\": \"text/html\",\n \".css\": \"text/css\", \".md\": \"text/markdown\",\n \".py\": \"text/x-python\", \".sh\": \"text/x-shellscript\",\n \".yaml\": \"text/yaml\", \".yml\": \"text/yaml\",\n \".xml\": \"text/xml\", \".sql\": \"text/x-sql\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\", \".jpg\": \"image/jpeg\", \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\", \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\", \".webm\": \"video/webm\",\n \".mp3\": \"audio/mpeg\", \".wav\": \"audio/wav\",\n};\n\nfunction getMimeType(filePath: string): string {\n return MIME_MAP[extname(filePath).toLowerCase()] || \"application/octet-stream\";\n}\n\nfunction isTextMime(mime: string): boolean {\n return mime.startsWith(\"text/\") || mime === \"application/json\" || mime === \"image/svg+xml\";\n}\n\nexport class FsBridge {\n constructor(private hub: HubConnection) {\n this.hub.registerNamespace(\"fs\", (msg) => this.handleRequest(msg));\n log.info(\"FsBridge initialized\");\n }\n\n async handleRequest(msg: AgentGenericRequest): Promise<Record<string, unknown>> {\n log.info({ action: msg.action, requestId: msg.requestId }, \"fs request\");\n switch (msg.action) {\n case \"read\":\n return this.readFile(msg.params);\n default:\n throw new Error(`Unknown fs action: ${msg.action}`);\n }\n }\n\n private readFile(params: Record<string, unknown>): Record<string, unknown> {\n const filePath = params.path as string;\n if (!filePath) throw new Error(\"Missing path parameter\");\n\n // Security: only allow absolute paths (no relative traversal tricks)\n if (!isAbsolute(filePath)) {\n throw new Error(`Access denied: only absolute paths allowed`);\n }\n\n if (!existsSync(filePath)) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n const stat = statSync(filePath);\n if (!stat.isFile()) {\n throw new Error(`Not a file: ${filePath}`);\n }\n\n const mimeType = getMimeType(filePath);\n const totalSize = stat.size;\n\n if (isTextMime(mimeType)) {\n const raw = readFileSync(filePath, \"utf-8\");\n const truncated = raw.length > MAX_TEXT_SIZE;\n const content = truncated ? raw.slice(0, MAX_TEXT_SIZE) : raw;\n return { content, encoding: \"utf-8\", size: content.length, totalSize, mimeType, truncated };\n }\n\n // Binary: base64\n const buf = readFileSync(filePath);\n const truncated = buf.length > MAX_TEXT_SIZE;\n const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;\n return { content: slice.toString(\"base64\"), encoding: \"base64\", size: slice.length, totalSize, mimeType, truncated };\n }\n}\n"],"mappings":"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","names":["createLogger","log","process","existsSync","readdirSync","join","homedir","createLogger","log","existsSync","readFileSync","readdirSync","join","createLogger","log","existsSync","readFileSync","statSync","createLogger","log","stat","truncated","createLogger","log"]}
|