@mclawnet/agent 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fs-bridge.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-bridge.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/fs-bridge.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/session-manager.test.ts"],"names":[],"mappings":""}
@@ -27,6 +27,8 @@ export interface SpawnOptions {
27
27
  useBrainCore?: boolean;
28
28
  /** Path to MCP config JSON file for --mcp-config */
29
29
  mcpConfigPath?: string;
30
+ /** Memory system role ID. When set, SessionManager auto-injects memory prompt + MCP config */
31
+ roleId?: string;
30
32
  }
31
33
  export interface BackendAdapter {
32
34
  /** Backend type identifier */
@@ -1 +1 @@
1
- {"version":3,"file":"backend-adapter.d.ts","sourceRoot":"","sources":["../src/backend-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEtD,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,6CAA6C;IAC7C,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAEzE,qCAAqC;IACrC,cAAc,CAAC,CACb,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,CAAC,IAAI,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,KAAK,IAAI,GACT,IAAI,CAAC;IAER,6BAA6B;IAC7B,OAAO,CAAC,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E"}
1
+ {"version":3,"file":"backend-adapter.d.ts","sourceRoot":"","sources":["../src/backend-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEtD,qCAAqC;IACrC,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,6CAA6C;IAC7C,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IAEzE,qCAAqC;IACrC,cAAc,CAAC,CACb,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,CAAC,IAAI,EAAE;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD,KAAK,IAAI,GACT,IAAI,CAAC;IAER,6BAA6B;IAC7B,OAAO,CAAC,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E"}
@@ -20,6 +20,14 @@ export declare class BrainBridge {
20
20
  private parseProjects;
21
21
  /** Parse meetings from "### Meetings" subsections */
22
22
  private parseMeetings;
23
+ /** Parse feed items from Teams Chats subsections across all project sections and Announcements */
24
+ private parseFeed;
25
+ /** Extract chat items from a "### Teams Chats" subsection within a body block */
26
+ private extractTeamsChatItems;
27
+ /** Fetch and parse a meeting recap file */
28
+ private getMeetingRecap;
29
+ /** Parse meeting recap markdown into structured sections */
30
+ private parseRecapMarkdown;
23
31
  /** Guess message source from text content */
24
32
  private guessSource;
25
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"brain-bridge.d.ts","sourceRoot":"","sources":["../src/brain-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,cAAc,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAW;IAKpB,OAAO,CAAC,GAAG;IAJb,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAS;gBAGpB,GAAG,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,kBAAkB;IAiBxB,aAAa,CACjB,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAgBnC,UAAU,IAAI,gBAAgB;IAe9B,iDAAiD;YACnC,WAAW;IAkDzB,2DAA2D;IAC3D,OAAO,CAAC,YAAY;IAgDpB,oEAAoE;IACpE,OAAO,CAAC,aAAa;IA6CrB,qDAAqD;IACrD,OAAO,CAAC,aAAa;IAsCrB,6CAA6C;IAC7C,OAAO,CAAC,WAAW;CAQpB"}
1
+ {"version":3,"file":"brain-bridge.d.ts","sourceRoot":"","sources":["../src/brain-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,cAAc,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAW;IAKpB,OAAO,CAAC,GAAG;IAJb,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAS;gBAGpB,GAAG,EAAE,aAAa,EAC1B,OAAO,CAAC,EAAE,kBAAkB;IAiBxB,aAAa,CACjB,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAkBnC,UAAU,IAAI,gBAAgB;IAe9B,iDAAiD;YACnC,WAAW;IAoDzB,2DAA2D;IAC3D,OAAO,CAAC,YAAY;IAgDpB,oEAAoE;IACpE,OAAO,CAAC,aAAa;IA6CrB,qDAAqD;IACrD,OAAO,CAAC,aAAa;IA8CrB,kGAAkG;IAClG,OAAO,CAAC,SAAS;IAyBjB,iFAAiF;IACjF,OAAO,CAAC,qBAAqB;IAsD7B,2CAA2C;YAC7B,eAAe;IAa7B,4DAA4D;IAC5D,OAAO,CAAC,kBAAkB;IA0B1B,6CAA6C;IAC7C,OAAO,CAAC,WAAW;CAQpB"}
@@ -631,8 +631,8 @@ var HubConnection = class {
631
631
  log2.info({ sessionId }, "claude.execute: reusing existing session");
632
632
  this.sessionManager.sendInput(sessionId, content);
633
633
  } else {
634
- log2.info({ sessionId, workDir }, "claude.execute: creating new session");
635
- this.sessionManager.createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore }).then(() => {
634
+ log2.info({ sessionId, workDir, roleId: "role-__assistant__" }, "claude.execute: creating new session with memory injection");
635
+ this.sessionManager.createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore, roleId: "role-__assistant__" }).then(() => {
636
636
  this.sessionManager.sendInput(sessionId, content);
637
637
  }).catch((err) => {
638
638
  this.send({
@@ -645,11 +645,12 @@ var HubConnection = class {
645
645
  return true;
646
646
  }
647
647
  if (msg.type === "session.create") {
648
- log2.info({ sessionId: msg.sessionId }, "session.create");
648
+ log2.info({ sessionId: msg.sessionId, roleId: "role-__assistant__" }, "session.create with memory injection");
649
649
  this.sessionManager.createSession({
650
650
  sessionId: msg.sessionId,
651
651
  workDir: msg.workDir,
652
- resumeId: msg.resumeId
652
+ resumeId: msg.resumeId,
653
+ roleId: "role-__assistant__"
653
654
  }).then((claudeSessionId) => {
654
655
  this.send({
655
656
  type: "session.created",
@@ -745,9 +746,17 @@ var HubConnection = class {
745
746
  };
746
747
 
747
748
  // src/session-manager.ts
749
+ import { writeFileSync as writeFileSync2, unlinkSync } from "fs";
750
+ import { tmpdir } from "os";
751
+ import { join as join3, dirname } from "path";
752
+ import { createRequire } from "module";
753
+ import { createLogger as createLogger3 } from "@mclawnet/logger";
754
+ import { buildMemorySection } from "@mclawnet/memory";
755
+ var log3 = createLogger3({ module: "agent/session-manager" });
748
756
  var SessionManager = class {
749
757
  sessions = /* @__PURE__ */ new Map();
750
758
  conversationBuffer = /* @__PURE__ */ new Map();
759
+ mcpConfigPaths = /* @__PURE__ */ new Map();
751
760
  adapter;
752
761
  onOutput;
753
762
  onTurnComplete;
@@ -764,6 +773,25 @@ var SessionManager = class {
764
773
  if (this.sessions.has(options.sessionId)) {
765
774
  throw new Error(`Session ${options.sessionId} already exists`);
766
775
  }
776
+ if (options.roleId) {
777
+ try {
778
+ const memorySection = buildMemorySection(options.roleId);
779
+ options.systemPrompt = options.systemPrompt ? `${memorySection}
780
+
781
+ ${options.systemPrompt}` : memorySection;
782
+ log3.debug({ roleId: options.roleId, sessionId: options.sessionId }, "memory prompt injected");
783
+ } catch (err) {
784
+ log3.warn({ err, roleId: options.roleId }, "failed to build memory section, proceeding without");
785
+ }
786
+ if (!options.mcpConfigPath) {
787
+ try {
788
+ options.mcpConfigPath = this.createMemoryMcpConfig(options.sessionId, options.roleId);
789
+ log3.debug({ roleId: options.roleId, sessionId: options.sessionId }, "memory MCP config created");
790
+ } catch (err) {
791
+ log3.warn({ err, roleId: options.roleId }, "failed to create memory MCP config, proceeding without");
792
+ }
793
+ }
794
+ }
767
795
  try {
768
796
  const process2 = await this.adapter.spawn(options);
769
797
  this.sessions.set(options.sessionId, process2);
@@ -804,6 +832,7 @@ var SessionManager = class {
804
832
  const process2 = this.sessions.get(sessionId);
805
833
  if (!process2) return;
806
834
  this.conversationBuffer.delete(sessionId);
835
+ this.cleanupMcpConfig(sessionId);
807
836
  this.sessions.delete(sessionId);
808
837
  await this.adapter.stop(process2);
809
838
  }
@@ -816,6 +845,7 @@ var SessionManager = class {
816
845
  });
817
846
  }
818
847
  this.conversationBuffer.delete(sessionId);
848
+ this.cleanupMcpConfig(sessionId);
819
849
  this.sessions.delete(sessionId);
820
850
  await this.adapter.stop(process2);
821
851
  }
@@ -828,6 +858,7 @@ var SessionManager = class {
828
858
  });
829
859
  }
830
860
  this.conversationBuffer.delete(sessionId);
861
+ this.cleanupMcpConfig(sessionId);
831
862
  this.sessions.delete(sessionId);
832
863
  await this.adapter.stop(process2).catch(() => {
833
864
  });
@@ -841,6 +872,40 @@ var SessionManager = class {
841
872
  get activeSessionCount() {
842
873
  return this.sessions.size;
843
874
  }
875
+ // ── Private helpers ─────────────────────────────────────────────────
876
+ /** Generate a temporary MCP config file for the memory server. */
877
+ createMemoryMcpConfig(sessionId, roleId) {
878
+ const req = createRequire(import.meta.url);
879
+ const memoryPkgDir = dirname(req.resolve("@mclawnet/memory/package.json"));
880
+ const mcpServerPath = join3(memoryPkgDir, "dist", "mcp", "server.js");
881
+ const configPath = join3(tmpdir(), `clawnet-mcp-${sessionId.replace(/::/g, "-")}.json`);
882
+ writeFileSync2(
883
+ configPath,
884
+ JSON.stringify({
885
+ mcpServers: {
886
+ "clawnet-memory": {
887
+ command: "node",
888
+ args: [mcpServerPath, "--role-id", roleId]
889
+ }
890
+ }
891
+ })
892
+ );
893
+ this.mcpConfigPaths.set(sessionId, configPath);
894
+ log3.debug({ sessionId, roleId, configPath, mcpServerPath }, "memory MCP config file written");
895
+ return configPath;
896
+ }
897
+ /** Remove temporary MCP config file for a session. */
898
+ cleanupMcpConfig(sessionId) {
899
+ const configPath = this.mcpConfigPaths.get(sessionId);
900
+ if (configPath) {
901
+ try {
902
+ unlinkSync(configPath);
903
+ } catch {
904
+ }
905
+ this.mcpConfigPaths.delete(sessionId);
906
+ log3.debug({ sessionId, configPath }, "memory MCP config file cleaned up");
907
+ }
908
+ }
844
909
  };
845
910
 
846
911
  // src/start.ts
@@ -848,17 +913,17 @@ import { SwarmCoordinator, initRoles } from "@mclawnet/swarm";
848
913
 
849
914
  // src/brain-bridge.ts
850
915
  import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
851
- import { join as join3 } from "path";
852
- import { createLogger as createLogger3 } from "@mclawnet/logger";
853
- var log3 = createLogger3({ module: "brain-bridge" });
916
+ import { join as join4 } from "path";
917
+ import { createLogger as createLogger4 } from "@mclawnet/logger";
918
+ var log4 = createLogger4({ module: "brain-bridge" });
854
919
  var BrainBridge = class {
855
920
  constructor(hub, options) {
856
921
  this.hub = hub;
857
922
  const home = process.env.HOME || process.env.USERPROFILE || "";
858
- this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME || join3(home, "BrainData");
859
- this.brainCorePath = options?.brainCorePath || join3(home, ".brain", "BrainCore");
923
+ this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME || join4(home, "BrainData");
924
+ this.brainCorePath = options?.brainCorePath || join4(home, ".brain", "BrainCore");
860
925
  this.hub.registerNamespace("brain", (msg) => this.handleRequest(msg));
861
- log3.info(
926
+ log4.info(
862
927
  { brainHome: this.brainHome, brainCorePath: this.brainCorePath },
863
928
  "BrainBridge initialized"
864
929
  );
@@ -866,17 +931,19 @@ var BrainBridge = class {
866
931
  brainHome;
867
932
  brainCorePath;
868
933
  async handleRequest(msg) {
869
- log3.info({ action: msg.action, requestId: msg.requestId }, "brain request");
934
+ log4.info({ action: msg.action, requestId: msg.requestId }, "brain request");
870
935
  switch (msg.action) {
871
936
  case "setup_status": {
872
937
  const status = this.checkSetup();
873
- log3.info({ status }, "setup_status result");
938
+ log4.info({ status }, "setup_status result");
874
939
  return { status };
875
940
  }
876
941
  case "get_briefing":
877
942
  return await this.getBriefing(msg.params.date);
943
+ case "get_meeting_recap":
944
+ return await this.getMeetingRecap(msg.params.recapPath);
878
945
  default:
879
- log3.warn({ action: msg.action }, "unknown brain action");
946
+ log4.warn({ action: msg.action }, "unknown brain action");
880
947
  throw new Error(`Unknown brain action: ${msg.action}`);
881
948
  }
882
949
  }
@@ -885,7 +952,7 @@ var BrainBridge = class {
885
952
  return "not_installed";
886
953
  }
887
954
  const home = process.env.HOME || process.env.USERPROFILE || "";
888
- const installJson = join3(home, ".brain", "install.json");
955
+ const installJson = join4(home, ".brain", "install.json");
889
956
  if (!existsSync3(installJson)) {
890
957
  return "needs_config";
891
958
  }
@@ -897,25 +964,26 @@ var BrainBridge = class {
897
964
  /** Read the most recent daily briefing report */
898
965
  async getBriefing(date) {
899
966
  const targetDate = date || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
900
- const reportsDir = join3(this.brainHome, "reports", "daily");
967
+ const reportsDir = join4(this.brainHome, "reports", "daily");
901
968
  if (!existsSync3(reportsDir)) {
902
- log3.info({ reportsDir }, "get_briefing: reports dir not found");
903
- return { briefing: null, actions: [], projects: [], meetings: [] };
969
+ log4.info({ reportsDir }, "get_briefing: reports dir not found");
970
+ return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
904
971
  }
905
972
  const files = readdirSync2(reportsDir).filter((f) => f.includes(targetDate) && f.endsWith(".md")).sort().reverse();
906
973
  if (files.length === 0) {
907
- log3.info({ targetDate }, "get_briefing: no report for date");
908
- return { briefing: null, actions: [], projects: [], meetings: [] };
974
+ log4.info({ targetDate }, "get_briefing: no report for date");
975
+ return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
909
976
  }
910
- log3.info({ targetDate, file: files[0] }, "get_briefing: reading report");
911
- const content = readFileSync3(join3(reportsDir, files[0]), "utf-8");
977
+ log4.info({ targetDate, file: files[0] }, "get_briefing: reading report");
978
+ const content = readFileSync3(join4(reportsDir, files[0]), "utf-8");
912
979
  const tldrMatch = content.match(/## TL;DR\n([\s\S]*?)(?=\n---|\n## )/);
913
980
  const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);
914
981
  const actions = this.parseActions(content);
915
982
  const projects = this.parseProjects(content);
916
983
  const meetings = this.parseMeetings(content);
917
- log3.info(
918
- { actions: actions.length, projects: projects.length, meetings: meetings.length },
984
+ const feed = this.parseFeed(content);
985
+ log4.info(
986
+ { actions: actions.length, projects: projects.length, meetings: meetings.length, feed: feed.length },
919
987
  "get_briefing: parsed"
920
988
  );
921
989
  return {
@@ -926,7 +994,8 @@ var BrainBridge = class {
926
994
  },
927
995
  actions,
928
996
  projects,
929
- meetings
997
+ meetings,
998
+ feed
930
999
  };
931
1000
  }
932
1001
  /** Parse "## Action Required" section into ActionItem[] */
@@ -1031,18 +1100,106 @@ var BrainBridge = class {
1031
1100
  if (statusWord === "missed") status = "completed";
1032
1101
  else if (statusWord === "upcoming") status = "upcoming";
1033
1102
  else if (statusWord.includes("progress")) status = "in_progress";
1034
- const hasRecap = section.includes("Full recap");
1103
+ const meetingEndIdx = section.indexOf("\n####", m.index + m[0].length);
1104
+ const meetingSlice = meetingEndIdx !== -1 ? section.slice(m.index, meetingEndIdx) : section.slice(m.index);
1105
+ const recapMatch = meetingSlice.match(/📎\s*\[Full recap\]\((.+?)\)/);
1106
+ const recapPath = recapMatch ? recapMatch[1] : void 0;
1035
1107
  meetings.push({
1036
1108
  id: `meeting-${++idCounter}`,
1037
1109
  time,
1038
1110
  title,
1039
1111
  status,
1040
- hasRecap
1112
+ hasRecap: !!recapPath,
1113
+ recapPath
1041
1114
  });
1042
1115
  }
1043
1116
  }
1044
1117
  return meetings;
1045
1118
  }
1119
+ /** Parse feed items from Teams Chats subsections across all project sections and Announcements */
1120
+ parseFeed(content) {
1121
+ const items = [];
1122
+ let idCounter = 0;
1123
+ const projectRegex = /## 🔵\s+(.+)\n([\s\S]*?)(?=\n## |$)/g;
1124
+ let projectMatch;
1125
+ while ((projectMatch = projectRegex.exec(content)) !== null) {
1126
+ const projectName = projectMatch[1].trim();
1127
+ const projectBody = projectMatch[2];
1128
+ this.extractTeamsChatItems(projectBody, projectName, items, idCounter);
1129
+ idCounter = items.length;
1130
+ }
1131
+ const announcementMatch = content.match(/## 📢\s+Announcements[^\n]*\n([\s\S]*?)(?=\n## |$)/);
1132
+ if (announcementMatch) {
1133
+ this.extractTeamsChatItems(announcementMatch[1], "", items, idCounter);
1134
+ }
1135
+ return items;
1136
+ }
1137
+ /** Extract chat items from a "### Teams Chats" subsection within a body block */
1138
+ extractTeamsChatItems(body, project, items, _startId) {
1139
+ const teamsChatMatch = body.match(/### Teams Chats\n([\s\S]*?)(?=\n### [^T]|\n---|\n## |$)/);
1140
+ if (!teamsChatMatch) return;
1141
+ const teamsSection = teamsChatMatch[1];
1142
+ const chatRegex = /####\s+(.+?)(?:\s*—\s*(.+))?\n([\s\S]*?)(?=\n####|\n###|\n---|$)/g;
1143
+ let chatMatch;
1144
+ while ((chatMatch = chatRegex.exec(teamsSection)) !== null) {
1145
+ const chatBody = chatMatch[3];
1146
+ const senderMatch = chatBody.match(/\*\*(.+?)\*\*/);
1147
+ const sender = senderMatch ? senderMatch[1].trim() : "Unknown";
1148
+ let contentPreview = "";
1149
+ const lines = chatBody.split("\n").filter((l) => l.trim().length > 0);
1150
+ for (const line of lines) {
1151
+ const cleaned = line.replace(/\*\*.*?\*\*/g, "").replace(/[>*-]/g, "").trim();
1152
+ if (cleaned.length > 10) {
1153
+ contentPreview = cleaned.slice(0, 100);
1154
+ break;
1155
+ }
1156
+ }
1157
+ if (!contentPreview && lines.length > 0) {
1158
+ contentPreview = lines[0].replace(/\*\*/g, "").trim().slice(0, 100);
1159
+ }
1160
+ const timeMatch = chatBody.match(/(\d{1,2}:\d{2})/);
1161
+ const time = timeMatch ? timeMatch[1] : "";
1162
+ items.push({
1163
+ id: `feed-${items.length + 1}`,
1164
+ time,
1165
+ source: "teams",
1166
+ sender,
1167
+ content: contentPreview,
1168
+ project: project || void 0
1169
+ });
1170
+ }
1171
+ }
1172
+ /** Fetch and parse a meeting recap file */
1173
+ async getMeetingRecap(recapPath) {
1174
+ if (!recapPath) {
1175
+ return { error: "No recap path provided" };
1176
+ }
1177
+ const fullPath = join4(this.brainHome, recapPath);
1178
+ if (!existsSync3(fullPath)) {
1179
+ log4.warn({ fullPath }, "meeting recap file not found");
1180
+ return { error: "Recap file not found" };
1181
+ }
1182
+ const content = readFileSync3(fullPath, "utf-8");
1183
+ return { recap: this.parseRecapMarkdown(content) };
1184
+ }
1185
+ /** Parse meeting recap markdown into structured sections */
1186
+ parseRecapMarkdown(content) {
1187
+ const tldrMatch = content.match(/##\s*(?:TL;DR|Summary|概要)\n([\s\S]*?)(?=\n## |\n---|\n$)/);
1188
+ const tldr = tldrMatch ? tldrMatch[1].trim() : "";
1189
+ const relevantMatch = content.match(/##\s*(?:与你相关|Relevant|For You|Action for You)\n([\s\S]*?)(?=\n## |\n---|\n$)/);
1190
+ const relevant = relevantMatch ? relevantMatch[1].trim() : "";
1191
+ const decisionsMatch = content.match(/##\s*(?:决定事项|Decisions|Key Decisions)\n([\s\S]*?)(?=\n## |\n---|\n$)/);
1192
+ const decisions = decisionsMatch ? decisionsMatch[1].trim() : "";
1193
+ const actionsMatch = content.match(/##\s*(?:行动项|Action Items|Next Steps)\n([\s\S]*?)(?=\n## |\n---|\n$)/);
1194
+ const actionItems = actionsMatch ? actionsMatch[1].trim() : "";
1195
+ return {
1196
+ tldr,
1197
+ relevant,
1198
+ decisions,
1199
+ actionItems,
1200
+ rawMarkdown: content
1201
+ };
1202
+ }
1046
1203
  /** Guess message source from text content */
1047
1204
  guessSource(text) {
1048
1205
  const lower = text.toLowerCase();
@@ -1054,30 +1211,112 @@ var BrainBridge = class {
1054
1211
  }
1055
1212
  };
1056
1213
 
1214
+ // src/fs-bridge.ts
1215
+ import { existsSync as existsSync4, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
1216
+ import { extname, resolve } from "path";
1217
+ import { createLogger as createLogger5 } from "@mclawnet/logger";
1218
+ var log5 = createLogger5({ module: "fs-bridge" });
1219
+ var MAX_TEXT_SIZE = 5 * 1024 * 1024;
1220
+ var MIME_MAP = {
1221
+ ".ts": "text/typescript",
1222
+ ".tsx": "text/typescript",
1223
+ ".js": "text/javascript",
1224
+ ".jsx": "text/javascript",
1225
+ ".json": "application/json",
1226
+ ".html": "text/html",
1227
+ ".css": "text/css",
1228
+ ".md": "text/markdown",
1229
+ ".py": "text/x-python",
1230
+ ".sh": "text/x-shellscript",
1231
+ ".yaml": "text/yaml",
1232
+ ".yml": "text/yaml",
1233
+ ".xml": "text/xml",
1234
+ ".sql": "text/x-sql",
1235
+ ".svg": "image/svg+xml",
1236
+ ".png": "image/png",
1237
+ ".jpg": "image/jpeg",
1238
+ ".jpeg": "image/jpeg",
1239
+ ".gif": "image/gif",
1240
+ ".webp": "image/webp",
1241
+ ".mp4": "video/mp4",
1242
+ ".webm": "video/webm",
1243
+ ".mp3": "audio/mpeg",
1244
+ ".wav": "audio/wav"
1245
+ };
1246
+ function getMimeType(filePath) {
1247
+ return MIME_MAP[extname(filePath).toLowerCase()] || "application/octet-stream";
1248
+ }
1249
+ function isTextMime(mime) {
1250
+ return mime.startsWith("text/") || mime === "application/json" || mime === "image/svg+xml";
1251
+ }
1252
+ var FsBridge = class {
1253
+ constructor(hub) {
1254
+ this.hub = hub;
1255
+ this.hub.registerNamespace("fs", (msg) => this.handleRequest(msg));
1256
+ log5.info("FsBridge initialized");
1257
+ }
1258
+ async handleRequest(msg) {
1259
+ log5.info({ action: msg.action, requestId: msg.requestId }, "fs request");
1260
+ switch (msg.action) {
1261
+ case "read":
1262
+ return this.readFile(msg.params);
1263
+ default:
1264
+ throw new Error(`Unknown fs action: ${msg.action}`);
1265
+ }
1266
+ }
1267
+ readFile(params) {
1268
+ const filePath = params.path;
1269
+ if (!filePath) throw new Error("Missing path parameter");
1270
+ const resolved = resolve(filePath);
1271
+ if (resolved !== filePath) {
1272
+ throw new Error(`Access denied: only absolute paths allowed`);
1273
+ }
1274
+ if (!existsSync4(filePath)) {
1275
+ throw new Error(`File not found: ${filePath}`);
1276
+ }
1277
+ const stat2 = statSync2(filePath);
1278
+ if (!stat2.isFile()) {
1279
+ throw new Error(`Not a file: ${filePath}`);
1280
+ }
1281
+ const mimeType = getMimeType(filePath);
1282
+ const totalSize = stat2.size;
1283
+ if (isTextMime(mimeType)) {
1284
+ const raw = readFileSync4(filePath, "utf-8");
1285
+ const truncated2 = raw.length > MAX_TEXT_SIZE;
1286
+ const content = truncated2 ? raw.slice(0, MAX_TEXT_SIZE) : raw;
1287
+ return { content, encoding: "utf-8", size: content.length, totalSize, mimeType, truncated: truncated2 };
1288
+ }
1289
+ const buf = readFileSync4(filePath);
1290
+ const truncated = buf.length > MAX_TEXT_SIZE;
1291
+ const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;
1292
+ return { content: slice.toString("base64"), encoding: "base64", size: slice.length, totalSize, mimeType, truncated };
1293
+ }
1294
+ };
1295
+
1057
1296
  // src/start.ts
1058
- import { createLogger as createLogger4 } from "@mclawnet/logger";
1059
- var log4 = createLogger4({ module: "agent" });
1297
+ import { createLogger as createLogger6 } from "@mclawnet/logger";
1298
+ var log6 = createLogger6({ module: "agent" });
1060
1299
  async function startAgent(options) {
1061
1300
  const config = loadConfig(options.config);
1062
1301
  if (!config.token) {
1063
- log4.error("no token configured \u2014 set CLAWNET_TOKEN or use --token");
1302
+ log6.error("no token configured \u2014 set CLAWNET_TOKEN or use --token");
1064
1303
  process.exit(1);
1065
1304
  }
1066
- log4.info({ backend: options.adapter.type }, "starting agent");
1067
- log4.info({ hubUrl: config.hubUrl }, "connecting to hub");
1305
+ log6.info({ backend: options.adapter.type }, "starting agent");
1306
+ log6.info({ hubUrl: config.hubUrl }, "connecting to hub");
1068
1307
  await initRoles();
1069
1308
  const hub = new HubConnection({
1070
1309
  hubUrl: config.hubUrl,
1071
1310
  token: config.token,
1072
1311
  hostname: config.name,
1073
1312
  onConnect: (agentId) => {
1074
- log4.info({ agentId }, "connected to hub");
1313
+ log6.info({ agentId }, "connected to hub");
1075
1314
  },
1076
1315
  onDisconnect: (code, reason) => {
1077
- log4.info({ code, reason }, "disconnected from hub");
1316
+ log6.info({ code, reason }, "disconnected from hub");
1078
1317
  },
1079
1318
  onError: (err) => {
1080
- log4.error({ err }, "hub connection error");
1319
+ log6.error({ err }, "hub connection error");
1081
1320
  }
1082
1321
  });
1083
1322
  let swarmCoordinator;
@@ -1113,8 +1352,9 @@ async function startAgent(options) {
1113
1352
  hub.setSessionManager(sessionManager);
1114
1353
  hub.setSwarmCoordinator(swarmCoordinator);
1115
1354
  const brainBridge = new BrainBridge(hub);
1355
+ const fsBridge = new FsBridge(hub);
1116
1356
  const shutdown = async () => {
1117
- log4.info("shutting down");
1357
+ log6.info("shutting down");
1118
1358
  await sessionManager.closeAll();
1119
1359
  hub.destroy();
1120
1360
  process.exit(0);
@@ -1122,7 +1362,7 @@ async function startAgent(options) {
1122
1362
  process.on("SIGINT", shutdown);
1123
1363
  process.on("SIGTERM", shutdown);
1124
1364
  hub.connect();
1125
- return { hub, sessionManager, swarmCoordinator, brainBridge };
1365
+ return { hub, sessionManager, swarmCoordinator, brainBridge, fsBridge };
1126
1366
  }
1127
1367
 
1128
1368
  export {
@@ -1131,6 +1371,7 @@ export {
1131
1371
  loadConfig,
1132
1372
  saveConfig,
1133
1373
  BrainBridge,
1374
+ FsBridge,
1134
1375
  startAgent
1135
1376
  };
1136
- //# sourceMappingURL=chunk-MBLHUBHK.js.map
1377
+ //# sourceMappingURL=chunk-UXLBD5IJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/hub-connection.ts","../src/fs-handler.ts","../src/session-manager.ts","../src/start.ts","../src/brain-bridge.ts","../src/fs-bridge.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir, hostname } from \"node:os\";\nimport type { BackendType } from \"@mclawnet/shared\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"config\" });\n\nexport interface EmbeddingConfig {\n /** Embedding provider mode: auto / openai / ollama / hash */\n provider?: string;\n /** OpenAI-compatible API base URL (e.g. http://localhost:4141/v1 for copilot proxy) */\n openaiBaseUrl?: string;\n /** OpenAI API key (use \"dummy\" for copilot proxy) */\n openaiApiKey?: string;\n /** OpenAI embedding model name */\n openaiModel?: string;\n /** Ollama server URL */\n ollamaUrl?: string;\n /** Ollama embedding model name */\n ollamaModel?: string;\n}\n\nexport interface AgentConfig {\n hubUrl: string;\n token: string;\n name: string;\n backendType: BackendType;\n embedding?: EmbeddingConfig;\n}\n\nconst CONFIG_DIR = join(homedir(), \".clawnet\");\nconst SETTINGS_FILE = join(CONFIG_DIR, \"settings.json\");\n\nconst DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || \"ws://localhost:3000/ws/agent\";\n\nconst DEFAULTS: AgentConfig = {\n hubUrl: DEFAULT_HUB_URL,\n token: \"\",\n name: hostname(),\n backendType: \"claude-code\",\n};\n\n/** Ensure hubUrl uses ws(s):// protocol and ends with /ws/agent */\nfunction normalizeHubUrl(url: string): string {\n // Convert http(s):// to ws(s)://\n url = url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\");\n // Default to wss:// if no protocol\n if (!/^wss?:\\/\\//.test(url)) url = \"wss://\" + url;\n if (url.endsWith(\"/ws/agent\")) return url;\n return url.replace(/\\/+$/, \"\") + \"/ws/agent\";\n}\n\n/**\n * Map structured embedding config to CLAWNET_* env vars.\n * Only sets vars that are not already defined in process.env.\n */\nfunction applyEmbeddingConfig(embedding: EmbeddingConfig): void {\n const mapping: Array<[keyof EmbeddingConfig, string]> = [\n [\"provider\", \"CLAWNET_EMBEDDING_PROVIDER\"],\n [\"openaiBaseUrl\", \"CLAWNET_OPENAI_BASE_URL\"],\n [\"openaiApiKey\", \"CLAWNET_OPENAI_API_KEY\"],\n [\"openaiModel\", \"CLAWNET_OPENAI_EMBEDDING_MODEL\"],\n [\"ollamaUrl\", \"CLAWNET_OLLAMA_URL\"],\n [\"ollamaModel\", \"CLAWNET_OLLAMA_MODEL\"],\n ];\n\n for (const [configKey, envKey] of mapping) {\n const value = embedding[configKey];\n if (value !== undefined && process.env[envKey] === undefined) {\n process.env[envKey] = value;\n }\n }\n}\n\n/** Load config: CLI opts > env vars > settings file > defaults */\nexport function loadConfig(cliOpts: Partial<AgentConfig> = {}): AgentConfig {\n let fileConfig: Partial<AgentConfig> = {};\n\n log.info({ path: SETTINGS_FILE }, \"loading config\");\n\n if (existsSync(SETTINGS_FILE)) {\n try {\n fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n log.info(\n { hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },\n \"settings.json loaded\"\n );\n } catch (e) {\n log.warn({ err: e }, \"failed to parse settings.json\");\n }\n } else {\n log.warn(\"settings.json not found\");\n }\n\n // Apply structured embedding config to process.env\n if (fileConfig.embedding) {\n applyEmbeddingConfig(fileConfig.embedding);\n }\n\n const hubUrl =\n cliOpts.hubUrl ??\n process.env.CLAWNET_HUB_URL ??\n fileConfig.hubUrl ??\n DEFAULTS.hubUrl;\n\n const resolved = {\n hubUrl: normalizeHubUrl(hubUrl),\n token:\n cliOpts.token ??\n process.env.CLAWNET_TOKEN ??\n fileConfig.token ??\n DEFAULTS.token,\n name:\n cliOpts.name ??\n process.env.CLAWNET_NAME ??\n fileConfig.name ??\n DEFAULTS.name,\n backendType:\n (cliOpts.backendType as BackendType) ??\n (process.env.CLAWNET_BACKEND_TYPE as BackendType) ??\n (fileConfig.backendType as BackendType) ??\n DEFAULTS.backendType,\n embedding: fileConfig.embedding,\n };\n\n log.info(\n {\n hubUrl: resolved.hubUrl,\n hubUrlSource: cliOpts.hubUrl ? \"cli\" : process.env.CLAWNET_HUB_URL ? \"env\" : fileConfig.hubUrl ? \"file\" : \"default\",\n tokenSource: cliOpts.token ? \"cli\" : process.env.CLAWNET_TOKEN ? \"env\" : fileConfig.token ? \"file\" : \"default\",\n hasToken: !!resolved.token,\n },\n \"config resolved\"\n );\n\n return resolved;\n}\n\n/** Save config to ~/.clawnet/settings.json */\nexport function saveConfig(config: Partial<AgentConfig>): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n\n let existing: Partial<AgentConfig> = {};\n if (existsSync(SETTINGS_FILE)) {\n try {\n existing = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n const merged = { ...existing, ...config };\n writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n","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 } 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.shortName || def.name,\n description: def.description || \"\",\n capabilities: def.capabilities || [],\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 // ── 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?.roles) {\n // Explicit create: crewConfig with roles provided — create new swarm\n log.info({ sessionId, rolesCount: crewConfig.roles.length }, \"swarm.execute: creating new swarm\");\n const roles = crewConfig.roles;\n this.swarmCoordinator.create(sessionId, { workDir, 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 || \"/\";\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 { writeFileSync, unlinkSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { 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\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 via `--append-system-prompt`\n * - Pipeline B: MCP memory server via `--mcp-config`\n */\nexport class SessionManager {\n private sessions = new Map<string, BackendProcess>();\n private conversationBuffer = new Map<string, Array<{ role: string; content: string }>>();\n private mcpConfigPaths = new Map<string, 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 // ── Unified memory injection ──\n if (options.roleId) {\n // Pipeline A: prepend memory section to system prompt\n try {\n const memorySection = buildMemorySection(options.roleId);\n options.systemPrompt = options.systemPrompt\n ? `${memorySection}\\n\\n${options.systemPrompt}`\n : memorySection;\n log.debug({ roleId: options.roleId, sessionId: options.sessionId }, \"memory prompt injected\");\n } catch (err) {\n log.warn({ err, roleId: options.roleId }, \"failed to build memory section, proceeding without\");\n }\n\n // Pipeline B: generate MCP config for memory tools (only if caller didn't provide one)\n if (!options.mcpConfigPath) {\n try {\n options.mcpConfigPath = this.createMemoryMcpConfig(options.sessionId, options.roleId);\n log.debug({ roleId: options.roleId, sessionId: options.sessionId }, \"memory MCP config created\");\n } catch (err) {\n log.warn({ err, roleId: options.roleId }, \"failed to create memory MCP config, proceeding without\");\n }\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 // Kill the process but remove from sessions map — a new process will be\n // lazily created on next claude.execute\n this.conversationBuffer.delete(sessionId);\n this.cleanupMcpConfig(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 this.cleanupMcpConfig(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.cleanupMcpConfig(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 // ── Private helpers ─────────────────────────────────────────────────\n\n /** Generate a temporary MCP config file for the memory server. */\n private createMemoryMcpConfig(sessionId: string, roleId: string): string {\n const req = createRequire(import.meta.url);\n const memoryPkgDir = dirname(req.resolve(\"@mclawnet/memory/package.json\"));\n const mcpServerPath = join(memoryPkgDir, \"dist\", \"mcp\", \"server.js\");\n const configPath = join(tmpdir(), `clawnet-mcp-${sessionId.replace(/::/g, \"-\")}.json`);\n writeFileSync(\n configPath,\n JSON.stringify({\n mcpServers: {\n \"clawnet-memory\": {\n command: \"node\",\n args: [mcpServerPath, \"--role-id\", roleId],\n },\n },\n }),\n );\n this.mcpConfigPaths.set(sessionId, configPath);\n log.debug({ sessionId, roleId, configPath, mcpServerPath }, \"memory MCP config file written\");\n return configPath;\n }\n\n /** Remove temporary MCP config file for a session. */\n private cleanupMcpConfig(sessionId: string): void {\n const configPath = this.mcpConfigPaths.get(sessionId);\n if (configPath) {\n try { unlinkSync(configPath); } catch { /* ignore */ }\n this.mcpConfigPaths.delete(sessionId);\n log.debug({ sessionId, configPath }, \"memory MCP config file cleaned up\");\n }\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 { 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 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, 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, resolve } 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 const resolved = resolve(filePath);\n if (resolved !== 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":["existsSync","readFileSync","homedir","join","createLogger","log","writeFileSync","join","createLogger","log","process","existsSync","readFileSync","readdirSync","join","createLogger","log","existsSync","readFileSync","statSync","createLogger","log","stat","truncated","createLogger","log"]}
@@ -0,0 +1,9 @@
1
+ import type { AgentGenericRequest } from "@mclawnet/shared";
2
+ import type { HubConnection } from "./hub-connection.js";
3
+ export declare class FsBridge {
4
+ private hub;
5
+ constructor(hub: HubConnection);
6
+ handleRequest(msg: AgentGenericRequest): Promise<Record<string, unknown>>;
7
+ private readFile;
8
+ }
9
+ //# sourceMappingURL=fs-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-bridge.d.ts","sourceRoot":"","sources":["../src/fs-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA6BzD,qBAAa,QAAQ;IACP,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAKhC,aAAa,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAU/E,OAAO,CAAC,QAAQ;CAmCjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"hub-connection.d.ts","sourceRoot":"","sources":["../src/hub-connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hub-connection.d.ts","sourceRoot":"","sources":["../src/hub-connection.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,5 +4,6 @@ export { type BackendAdapter, type BackendProcess, type SpawnOptions, } from "./
4
4
  export { loadConfig, saveConfig, type AgentConfig } from "./config.js";
5
5
  export { startAgent, type StartOptions } from "./start.js";
6
6
  export { BrainBridge, type BrainBridgeOptions, type BrainSetupStatus } from "./brain-bridge.js";
7
+ export { FsBridge } from "./fs-bridge.js";
7
8
  export { SwarmCoordinator, type RoleDefinition, loadRole, listRoles, initRoles, buildRolePrompt, } from "@mclawnet/swarm";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGhG,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,QAAQ,EACR,SAAS,EACT,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG1C,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,QAAQ,EACR,SAAS,EACT,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  BrainBridge,
3
+ FsBridge,
3
4
  HubConnection,
4
5
  SessionManager,
5
6
  loadConfig,
6
7
  saveConfig,
7
8
  startAgent
8
- } from "./chunk-MBLHUBHK.js";
9
+ } from "./chunk-UXLBD5IJ.js";
9
10
 
10
11
  // src/index.ts
11
12
  import {
@@ -17,6 +18,7 @@ import {
17
18
  } from "@mclawnet/swarm";
18
19
  export {
19
20
  BrainBridge,
21
+ FsBridge,
20
22
  HubConnection,
21
23
  SessionManager,
22
24
  SwarmCoordinator,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { HubConnection, type HubConnectionOptions } from \"./hub-connection.js\";\nexport { SessionManager } from \"./session-manager.js\";\nexport {\n type BackendAdapter,\n type BackendProcess,\n type SpawnOptions,\n} from \"./backend-adapter.js\";\nexport { loadConfig, saveConfig, type AgentConfig } from \"./config.js\";\nexport { startAgent, type StartOptions } from \"./start.js\";\nexport { BrainBridge, type BrainBridgeOptions, type BrainSetupStatus } from \"./brain-bridge.js\";\n\n// Re-export from @mclawnet/swarm for convenience\nexport {\n SwarmCoordinator,\n type RoleDefinition,\n loadRole,\n listRoles,\n initRoles,\n buildRolePrompt,\n} from \"@mclawnet/swarm\";\n"],"mappings":";;;;;;;;;;AAYA;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { HubConnection, type HubConnectionOptions } from \"./hub-connection.js\";\nexport { SessionManager } from \"./session-manager.js\";\nexport {\n type BackendAdapter,\n type BackendProcess,\n type SpawnOptions,\n} from \"./backend-adapter.js\";\nexport { loadConfig, saveConfig, type AgentConfig } from \"./config.js\";\nexport { startAgent, type StartOptions } from \"./start.js\";\nexport { BrainBridge, type BrainBridgeOptions, type BrainSetupStatus } from \"./brain-bridge.js\";\nexport { FsBridge } from \"./fs-bridge.js\";\n\n// Re-export from @mclawnet/swarm for convenience\nexport {\n SwarmCoordinator,\n type RoleDefinition,\n loadRole,\n listRoles,\n initRoles,\n buildRolePrompt,\n} from \"@mclawnet/swarm\";\n"],"mappings":";;;;;;;;;;;AAaA;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -1,10 +1,15 @@
1
1
  import type { BackendAdapter, SpawnOptions } from "./backend-adapter.js";
2
2
  /**
3
3
  * Manages active sessions, mapping ClawNet session IDs to BackendProcess instances.
4
+ *
5
+ * When `options.roleId` is set, the manager automatically injects:
6
+ * - Pipeline A: memory prompt via `--append-system-prompt`
7
+ * - Pipeline B: MCP memory server via `--mcp-config`
4
8
  */
5
9
  export declare class SessionManager {
6
10
  private sessions;
7
11
  private conversationBuffer;
12
+ private mcpConfigPaths;
8
13
  private adapter;
9
14
  private onOutput;
10
15
  private onTurnComplete;
@@ -35,5 +40,9 @@ export declare class SessionManager {
35
40
  closeAll(): Promise<void>;
36
41
  hasSession(sessionId: string): boolean;
37
42
  get activeSessionCount(): number;
43
+ /** Generate a temporary MCP config file for the memory server. */
44
+ private createMemoryMcpConfig;
45
+ /** Remove temporary MCP config file for a session. */
46
+ private cleanupMcpConfig;
38
47
  }
39
48
  //# sourceMappingURL=session-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzF;;GAEG;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;IA6C3D,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS3C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,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;CACF"}
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAkB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIzF;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,kBAAkB,CAA+D;IACzF,OAAO,CAAC,cAAc,CAA6B;IACnD,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;IAqE3D,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAS3C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB9C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB/B,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAID,kEAAkE;IAClE,OAAO,CAAC,qBAAqB;IAqB7B,sDAAsD;IACtD,OAAO,CAAC,gBAAgB;CAQzB"}
package/dist/start.d.ts CHANGED
@@ -3,6 +3,7 @@ import { HubConnection } from "./hub-connection.js";
3
3
  import { SessionManager } from "./session-manager.js";
4
4
  import { SwarmCoordinator } from "@mclawnet/swarm";
5
5
  import { BrainBridge } from "./brain-bridge.js";
6
+ import { FsBridge } from "./fs-bridge.js";
6
7
  import type { BackendAdapter } from "./backend-adapter.js";
7
8
  export interface StartOptions {
8
9
  config?: Partial<AgentConfig>;
@@ -16,5 +17,6 @@ export declare function startAgent(options: StartOptions): Promise<{
16
17
  sessionManager: SessionManager;
17
18
  swarmCoordinator: SwarmCoordinator;
18
19
  brainBridge: BrainBridge;
20
+ fsBridge: FsBridge;
19
21
  }>;
20
22
  //# sourceMappingURL=start.d.ts.map
@@ -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;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,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;CAC1B,CAAC,CA0FD"}
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;AAC9D,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,CA6FD"}
package/dist/start.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startAgent
3
- } from "./chunk-MBLHUBHK.js";
3
+ } from "./chunk-UXLBD5IJ.js";
4
4
  export {
5
5
  startAgent
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mclawnet/agent",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -18,12 +18,20 @@
18
18
  "publishConfig": {
19
19
  "access": "public"
20
20
  },
21
+ "scripts": {
22
+ "build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist -p tsconfig.build.json",
23
+ "clean": "rm -rf dist",
24
+ "dev": "tsx --env-file=../../../.env.local src/dev.ts",
25
+ "start": "node cli.js start",
26
+ "test": "vitest run"
27
+ },
21
28
  "dependencies": {
22
- "ws": "^8.19.0",
23
- "@mclawnet/logger": "0.1.1",
24
- "@mclawnet/shared": "0.1.0",
25
- "@mclawnet/swarm": "0.1.0",
26
- "@mclawnet/claude-adapter": "0.1.1"
29
+ "@mclawnet/shared": "workspace:*",
30
+ "@mclawnet/logger": "workspace:*",
31
+ "@mclawnet/memory": "workspace:*",
32
+ "@mclawnet/swarm": "workspace:*",
33
+ "@mclawnet/claude-adapter": "workspace:*",
34
+ "ws": "^8.19.0"
27
35
  },
28
36
  "devDependencies": {
29
37
  "@types/node": "^22",
@@ -32,12 +40,5 @@
32
40
  "tsx": "^4.21.0",
33
41
  "typescript": "^5.8.3",
34
42
  "vitest": "^4.0.18"
35
- },
36
- "scripts": {
37
- "build": "tsup && tsc --emitDeclarationOnly --declaration --outDir dist -p tsconfig.build.json",
38
- "clean": "rm -rf dist",
39
- "dev": "tsx --env-file=../../../.env.local src/dev.ts",
40
- "start": "node cli.js start",
41
- "test": "vitest run"
42
43
  }
43
- }
44
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts","../src/hub-connection.ts","../src/fs-handler.ts","../src/session-manager.ts","../src/start.ts","../src/brain-bridge.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir, hostname } from \"node:os\";\nimport type { BackendType } from \"@mclawnet/shared\";\nimport { createLogger } from \"@mclawnet/logger\";\n\nconst log = createLogger({ module: \"config\" });\n\nexport interface EmbeddingConfig {\n /** Embedding provider mode: auto / openai / ollama / hash */\n provider?: string;\n /** OpenAI-compatible API base URL (e.g. http://localhost:4141/v1 for copilot proxy) */\n openaiBaseUrl?: string;\n /** OpenAI API key (use \"dummy\" for copilot proxy) */\n openaiApiKey?: string;\n /** OpenAI embedding model name */\n openaiModel?: string;\n /** Ollama server URL */\n ollamaUrl?: string;\n /** Ollama embedding model name */\n ollamaModel?: string;\n}\n\nexport interface AgentConfig {\n hubUrl: string;\n token: string;\n name: string;\n backendType: BackendType;\n embedding?: EmbeddingConfig;\n}\n\nconst CONFIG_DIR = join(homedir(), \".clawnet\");\nconst SETTINGS_FILE = join(CONFIG_DIR, \"settings.json\");\n\nconst DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || \"ws://localhost:3000/ws/agent\";\n\nconst DEFAULTS: AgentConfig = {\n hubUrl: DEFAULT_HUB_URL,\n token: \"\",\n name: hostname(),\n backendType: \"claude-code\",\n};\n\n/** Ensure hubUrl uses ws(s):// protocol and ends with /ws/agent */\nfunction normalizeHubUrl(url: string): string {\n // Convert http(s):// to ws(s)://\n url = url.replace(/^https:\\/\\//, \"wss://\").replace(/^http:\\/\\//, \"ws://\");\n // Default to wss:// if no protocol\n if (!/^wss?:\\/\\//.test(url)) url = \"wss://\" + url;\n if (url.endsWith(\"/ws/agent\")) return url;\n return url.replace(/\\/+$/, \"\") + \"/ws/agent\";\n}\n\n/**\n * Map structured embedding config to CLAWNET_* env vars.\n * Only sets vars that are not already defined in process.env.\n */\nfunction applyEmbeddingConfig(embedding: EmbeddingConfig): void {\n const mapping: Array<[keyof EmbeddingConfig, string]> = [\n [\"provider\", \"CLAWNET_EMBEDDING_PROVIDER\"],\n [\"openaiBaseUrl\", \"CLAWNET_OPENAI_BASE_URL\"],\n [\"openaiApiKey\", \"CLAWNET_OPENAI_API_KEY\"],\n [\"openaiModel\", \"CLAWNET_OPENAI_EMBEDDING_MODEL\"],\n [\"ollamaUrl\", \"CLAWNET_OLLAMA_URL\"],\n [\"ollamaModel\", \"CLAWNET_OLLAMA_MODEL\"],\n ];\n\n for (const [configKey, envKey] of mapping) {\n const value = embedding[configKey];\n if (value !== undefined && process.env[envKey] === undefined) {\n process.env[envKey] = value;\n }\n }\n}\n\n/** Load config: CLI opts > env vars > settings file > defaults */\nexport function loadConfig(cliOpts: Partial<AgentConfig> = {}): AgentConfig {\n let fileConfig: Partial<AgentConfig> = {};\n\n log.info({ path: SETTINGS_FILE }, \"loading config\");\n\n if (existsSync(SETTINGS_FILE)) {\n try {\n fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n log.info(\n { hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },\n \"settings.json loaded\"\n );\n } catch (e) {\n log.warn({ err: e }, \"failed to parse settings.json\");\n }\n } else {\n log.warn(\"settings.json not found\");\n }\n\n // Apply structured embedding config to process.env\n if (fileConfig.embedding) {\n applyEmbeddingConfig(fileConfig.embedding);\n }\n\n const hubUrl =\n cliOpts.hubUrl ??\n process.env.CLAWNET_HUB_URL ??\n fileConfig.hubUrl ??\n DEFAULTS.hubUrl;\n\n const resolved = {\n hubUrl: normalizeHubUrl(hubUrl),\n token:\n cliOpts.token ??\n process.env.CLAWNET_TOKEN ??\n fileConfig.token ??\n DEFAULTS.token,\n name:\n cliOpts.name ??\n process.env.CLAWNET_NAME ??\n fileConfig.name ??\n DEFAULTS.name,\n backendType:\n (cliOpts.backendType as BackendType) ??\n (process.env.CLAWNET_BACKEND_TYPE as BackendType) ??\n (fileConfig.backendType as BackendType) ??\n DEFAULTS.backendType,\n embedding: fileConfig.embedding,\n };\n\n log.info(\n {\n hubUrl: resolved.hubUrl,\n hubUrlSource: cliOpts.hubUrl ? \"cli\" : process.env.CLAWNET_HUB_URL ? \"env\" : fileConfig.hubUrl ? \"file\" : \"default\",\n tokenSource: cliOpts.token ? \"cli\" : process.env.CLAWNET_TOKEN ? \"env\" : fileConfig.token ? \"file\" : \"default\",\n hasToken: !!resolved.token,\n },\n \"config resolved\"\n );\n\n return resolved;\n}\n\n/** Save config to ~/.clawnet/settings.json */\nexport function saveConfig(config: Partial<AgentConfig>): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n\n let existing: Partial<AgentConfig> = {};\n if (existsSync(SETTINGS_FILE)) {\n try {\n existing = JSON.parse(readFileSync(SETTINGS_FILE, \"utf-8\"));\n } catch {\n // ignore\n }\n }\n\n const merged = { ...existing, ...config };\n writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + \"\\n\");\n}\n","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 } 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.shortName || def.name,\n description: def.description || \"\",\n capabilities: def.capabilities || [],\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 // ── 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?.roles) {\n // Explicit create: crewConfig with roles provided — create new swarm\n log.info({ sessionId, rolesCount: crewConfig.roles.length }, \"swarm.execute: creating new swarm\");\n const roles = crewConfig.roles;\n this.swarmCoordinator.create(sessionId, { workDir, 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 }, \"claude.execute: creating new session\");\n this.sessionManager\n .createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore })\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 }, \"session.create\");\n this.sessionManager\n .createSession({\n sessionId: msg.sessionId,\n workDir: msg.workDir,\n resumeId: msg.resumeId,\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 || \"/\";\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 type { BackendAdapter, BackendProcess, SpawnOptions } from \"./backend-adapter.js\";\n\n/**\n * Manages active sessions, mapping ClawNet session IDs to BackendProcess instances.\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 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 // Kill the process but remove from sessions map — a new process will be\n // lazily created on next claude.execute\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 { BrainBridge } from \"./brain-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}> {\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 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 // 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 };\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 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: [] };\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: [] };\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\n log.info(\n { actions: actions.length, projects: projects.length, meetings: meetings.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 };\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 const hasRecap = section.includes(\"Full recap\");\n\n meetings.push({\n id: `meeting-${++idCounter}`,\n time,\n title,\n status,\n hasRecap,\n });\n }\n }\n\n return meetings;\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"],"mappings":"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","names":["existsSync","readFileSync","homedir","join","createLogger","log","process","existsSync","readFileSync","readdirSync","join","createLogger","log","createLogger","log"]}